diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 0e5219042b700d..f6ec0a4e1da7e2 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.22067.1", + "version": "1.0.0-prerelease.22074.1", "commands": [ "xharness" ] diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 31ff731b029117..2634a9528f1eea 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,3 +10,12 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ build-essential python curl git lldb-6.0 liblldb-6.0-dev \ libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev \ libssl-dev libnuma-dev libkrb5-dev zlib1g-dev ninja-build + +# Install V8 Engine +SHELL ["/bin/bash", "-c"] + +RUN curl -sSL "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/linux/chromium-v8/v8-linux64-rel-8.5.183.zip" -o ./v8.zip \ + && unzip ./v8.zip -d /usr/local/v8 \ + && echo $'#!/usr/bin/env bash\n\ +"/usr/local/v8/d8" --snapshot_blob="/usr/local/v8/snapshot_blob.bin" "$@"\n' > /usr/local/bin/v8 \ + && chmod +x /usr/local/bin/v8 \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 41e9c94c00deee..d7b5a8b0efb57a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "name": "C# (.NET)", "build": { "dockerfile": "Dockerfile", - "args": { + "args": { // Update 'VARIANT' to pick a .NET Core version: 2.1, 3.1, 5.0 "VARIANT": "5.0", } @@ -32,11 +32,22 @@ // Add the locally installed dotnet to the path to ensure that it is activated // This allows developers to just use 'dotnet build' on the command-line, and the local dotnet version will be used. + // Add the global tools dir to the PATH so that globally installed tools will work "remoteEnv": { - "PATH": "${containerWorkspaceFolder}/.dotnet:${containerEnv:PATH}", - "DOTNET_MULTILEVEL_LOOKUP": "0" + "PATH": "${containerWorkspaceFolder}/.dotnet:${containerWorkspaceFolder}/.dotnet-tools-global:${containerEnv:PATH}", + "DOTNET_MULTILEVEL_LOOKUP": "0", + // Path to provisioned Emscripten SDK, for rebuilding the wasm runtime + "EMSDK_PATH": "${containerWorkspaceFolder}/src/mono/wasm/emsdk", }, // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" + "remoteUser": "vscode", + + // Forward mono samples port + "forwardPorts": [8000], + "portsAttributes": { + "8000": { + "label": "mono wasm samples (8000)", + } + } } diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index faf7cb08d1afae..48850f5f00b719 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -7,5 +7,13 @@ set -e # restore libs tests so that the project is ready to be loaded by OmniSharp ./build.sh libs.tests -restore +# prebuild for WASM, so it is ready for wasm development +make -C src/mono/wasm provision-wasm +export EMSDK_PATH=$PWD/src/mono/wasm/emsdk +./build.sh mono+libs -os Browser -c release + +# install dotnet-serve for running wasm samples +./dotnet.sh tool install dotnet-serve --tool-path ./.dotnet-tools-global + # save the commit hash of the currently built assemblies, so developers know which version was built git rev-parse HEAD > ./artifacts/prebuild.sha diff --git a/.github/fabricbot.json b/.github/fabricbot.json index 723e3f5c493f2f..accae195f26ee0 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -13,8 +13,7 @@ ], "mentionees": [ "dotnet/area-system-security", - "vcsjones", - "krwq" + "vcsjones" ] }, { @@ -33,8 +32,7 @@ "area-System.Linq.Parallel" ], "mentionees": [ - "dotnet/area-system-linq-parallel", - "tarekgh" + "dotnet/area-system-linq-parallel" ] }, { @@ -42,8 +40,7 @@ "area-System.Text.Encoding" ], "mentionees": [ - "dotnet/area-system-text-encoding", - "tarekgh" + "dotnet/area-system-text-encoding" ] }, { @@ -51,8 +48,7 @@ "area-System.Text.Encodings.Web" ], "mentionees": [ - "dotnet/area-system-text-encodings-web", - "tarekgh" + "dotnet/area-system-text-encodings-web" ] }, { @@ -175,8 +171,7 @@ "area-System.Buffers" ], "mentionees": [ - "dotnet/area-system-buffers", - "GrabYourPitchforks" + "dotnet/area-system-buffers" ] }, { @@ -377,8 +372,7 @@ "area-Extensions-FileSystem" ], "mentionees": [ - "dotnet/area-extensions-filesystem", - "maryamariyan" + "dotnet/area-extensions-filesystem" ] }, { @@ -776,8 +770,7 @@ "area-System.Resources" ], "mentionees": [ - "dotnet/area-system-resources", - "tarekgh" + "dotnet/area-system-resources" ] }, { @@ -996,7 +989,7 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "Replace `needs-author-action` label with `needs further triage` label when the author comments on an issue", + "taskName": "Replace `needs-author-action` label with `needs-further-triage` label when the author comments on an issue", "conditions": { "operator": "and", "operands": [ @@ -1030,7 +1023,7 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -1052,7 +1045,7 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "Remove `no recent activity` label from issues when issue is modified", + "taskName": "Remove `no-recent-activity` label from issues when issue is modified", "conditions": { "operator": "and", "operands": [ @@ -1070,7 +1063,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1079,7 +1072,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1090,7 +1083,7 @@ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1107,14 +1100,14 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "Remove `no recent activity` label when an issue is commented on", + "taskName": "Remove `no-recent-activity` label when an issue is commented on", "conditions": { "operator": "and", "operands": [ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1123,7 +1116,7 @@ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1149,7 +1142,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1158,7 +1151,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1171,12 +1164,12 @@ "issues", "project_card" ], - "taskName": "Remove `no recent activity` label from PRs when modified", + "taskName": "Remove `no-recent-activity` label from PRs when modified", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1194,7 +1187,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1207,12 +1200,12 @@ "eventNames": [ "issue_comment" ], - "taskName": "Remove `no recent activity` label from PRs when commented on", + "taskName": "Remove `no-recent-activity` label from PRs when commented on", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1230,7 +1223,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1243,12 +1236,12 @@ "eventNames": [ "pull_request_review" ], - "taskName": "Remove `no recent activity` label from PRs when new review is added", + "taskName": "Remove `no-recent-activity` label from PRs when new review is added", "actions": [ { "name": "removeLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -1345,7 +1338,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1359,7 +1352,7 @@ { "name": "addReply", "parameters": { - "comment": "This issue will now be closed since it had been marked `no recent activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days." + "comment": "This issue will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days." } }, { @@ -1375,7 +1368,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Close PRs with no recent activity", + "taskName": "Close PRs with no-recent-activity", "frequency": [ { "weekDay": 0, @@ -1460,7 +1453,7 @@ { "name": "hasLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { @@ -1474,7 +1467,7 @@ { "name": "addReply", "parameters": { - "comment": "This pull request will now be closed since it had been marked `no recent activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days." + "comment": "This pull request will now be closed since it had been marked `no-recent-activity` but received no further activity in the past 14 days. It is still possible to reopen or comment on the pull request, but please note that it will be locked if it remains inactive for another 30 days." } }, { @@ -1490,7 +1483,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Add no recent activity label to issues", + "taskName": "Add no-recent-activity label to issues", "frequency": [ { "weekDay": 0, @@ -1587,7 +1580,7 @@ { "name": "noLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1595,13 +1588,13 @@ { "name": "addLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { "name": "addReply", "parameters": { - "comment": "This issue has been automatically marked `no recent activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no recent activity`." + "comment": "This issue has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`." } } ] @@ -1614,7 +1607,7 @@ "subCapability": "ScheduledSearch", "version": "1.1", "config": { - "taskName": "Add no recent activity label to PRs", + "taskName": "Add no-recent-activity label to PRs", "frequency": [ { "weekDay": 0, @@ -1711,7 +1704,7 @@ { "name": "noLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ], @@ -1719,13 +1712,13 @@ { "name": "addLabel", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } }, { "name": "addReply", "parameters": { - "comment": "This pull request has been automatically marked `no recent activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no recent activity`." + "comment": "This pull request has been automatically marked `no-recent-activity` because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove `no-recent-activity`." } } ] @@ -1742,7 +1735,7 @@ "inPrLabelText": "Status: In PR", "fixedLabelText": "Status: Fixed", "fixedLabelEnabled": false, - "label_inPr": "in pr" + "label_inPr": "in-pr" } }, { @@ -2239,7 +2232,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2267,7 +2260,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2280,7 +2273,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2502,7 +2495,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2524,7 +2517,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -2543,7 +2536,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2625,7 +2618,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -2928,7 +2921,7 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3006,7 +2999,7 @@ { "name": "addLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3130,7 +3123,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3152,7 +3145,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3171,7 +3164,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3258,7 +3251,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3280,7 +3273,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3299,7 +3292,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3369,7 +3362,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3398,7 +3391,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -3837,7 +3830,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -3989,7 +3982,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4018,7 +4011,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4029,7 +4022,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -4210,7 +4203,7 @@ { "name": "labelAdded", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -4317,7 +4310,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4350,7 +4343,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -4369,7 +4362,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -5159,7 +5152,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5187,7 +5180,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5215,7 +5208,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5287,7 +5280,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5315,7 +5308,7 @@ { "name": "hasLabel", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } } ] @@ -5328,7 +5321,7 @@ { "name": "labelRemoved", "parameters": { - "label": "needs further triage" + "label": "needs-further-triage" } }, { @@ -5383,7 +5376,7 @@ { "name": "labelAdded", "parameters": { - "label": "no recent activity" + "label": "no-recent-activity" } } ] @@ -8524,5 +8517,1457 @@ } ] } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Add new issue to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isCloseAndComment", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "write" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Needs Further Triage", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Remove relabeled issues", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - Issue Triage] Move to Triaged Column", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Carlos / Santi - PRs] Remove relabeled PRs", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Carlos / Santi - PRs", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Add new issue to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isCloseAndComment", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "write" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Needs Further Triage", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Remove relabeled issues", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - Issue Triage] Move to Triaged Column", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - PRs] Add new PR to Board", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ] + } + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + } + ] + } + ] + }, + "eventType": "pull_request", + "eventNames": [ + "pull_request", + "issues", + "project_card" + ], + "taskName": "[Area Pod: Adam / David - PRs] Remove relabeled PRs", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + } } ] \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6627d2c2d0a75b..a4848da2e9ca5c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ syntax: glob # instead of directories), git will still ignore them. .dotnet .dotnet-mono +.dotnet-tools-global .packages .tools diff --git a/Directory.Build.props b/Directory.Build.props index e9e6fc4e362346..d862ee091fe81b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -29,6 +29,7 @@ <_hostArch>$([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture.ToString().ToLowerInvariant) $(_hostArch) arm + armv6 armel arm64 loongarch64 diff --git a/NuGet.config b/NuGet.config index f74e0c4a70248a..01da6689762612 100644 --- a/NuGet.config +++ b/NuGet.config @@ -15,6 +15,7 @@ + diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index e38f6ef907d430..55329a8b022944 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -697,6 +697,35 @@ License for fastmod (https://github.com/lemire/fastmod) and ibm-fpgen (https://g See the License for the specific language governing permissions and limitations under the License. +License for sse4-strstr (https://github.com/WojciechMula/sse4-strstr) +-------------------------------------- + + Copyright (c) 2008-2016, Wojciech Muła + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + License notice for The C++ REST SDK ----------------------------------- diff --git a/docs/coding-guidelines/libraries-packaging.md b/docs/coding-guidelines/libraries-packaging.md index 9e07a0683fd8d0..66909e4df855cf 100644 --- a/docs/coding-guidelines/libraries-packaging.md +++ b/docs/coding-guidelines/libraries-packaging.md @@ -86,5 +86,12 @@ In the analyzer project make sure to do the following. Ensure it only targets `n ``` +In order to mitigate design-time/build-time performance issues with source generators, we generate build logic to allow the end user to disable the source generator from the package. By default, the MSBuild property an end user can set is named `Disable{PackageId}SourceGenerator`. If a package needs a custom property name, this can be overriden by setting the following property in the project that produces the package +```xml + + CustomPropertyName + +``` + ### .NETFramework RID specific assets When targeting .NETFramework, RID specific assets are automatically added to the package if the project contains other compatible RID specific assets, mainly `netstandard2.0-windows`. diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 1c52fedd4d84ce..6e1900c1dc6bd0 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -13,6 +13,7 @@ This is a list of additions and edits to be made in ECMA-335 specifications. It - [Static Interface Methods](#static-interface-methods) - [Covariant Return Types](#covariant-return-types) - [Unsigned data conversion with overflow detection](#unsigned-data-conversion-with-overflow-detection) +- [Rules for IL rewriters](#rules-for-il-rewriters) ## Signatures @@ -948,3 +949,12 @@ Conversions from floating-point numbers to integral values truncate the number t on the top of the stack is reinterpreted as an unsigned value before the conversion. Note that integer values of less than 4 bytes are extended to int32 (not native int) on the evaluation stack. + +## Rules for IL Rewriters + +There are apis such as `System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan(...)` which require that the PE file have a particular structure. In particular, that api requires that the associated RVA of a FieldDef which is used to create a span must be naturally aligned over the data type that `CreateSpan` is instantiated over. There are 2 major concerns. + +1. That the RVA be aligned when the PE file is constructed. This may be achieved by whatever means is most convenient for the compiler. +2. That in the presence of IL rewriters that the RVA remains aligned. This section descibes metadata which will be processed by IL rewriters in order to maintain the required alignment. + +In order to maintain alignment, if the field needs alignment to be preserved, the field must be of a type locally defined within the module which has a Pack (§II.10.7) value of the desired alignment. Unlike other uses of the .pack directive, in this circumstance the .pack specifies a minimum alignment. diff --git a/docs/design/specs/PortablePdb-Metadata.md b/docs/design/specs/PortablePdb-Metadata.md index 811af00510bea7..c1d8e3c4420660 100644 --- a/docs/design/specs/PortablePdb-Metadata.md +++ b/docs/design/specs/PortablePdb-Metadata.md @@ -64,6 +64,8 @@ There shall be no duplicate rows in the _Document_ table, based upon document na _Name_ shall not be nil. It can however encode an empty name string. +_Hash_ is the file content hashed using the specified _HashAlgorithm_. It is used to validate that a source file matches the one used by the compiler when compiling the source code. + The values for which field _Language_ has a defined meaning are listed in the following tables along with the corresponding interpretation: | _Language_ field value | language | diff --git a/docs/project/glossary.md b/docs/project/glossary.md index 9104049e947ec1..28fed9e8e160d5 100644 --- a/docs/project/glossary.md +++ b/docs/project/glossary.md @@ -187,8 +187,7 @@ by Mono runtime in environments that allow fallback to JIT or need IL interprete [Native AOT](https://github.com/dotnet/designs/blob/main/accepted/2020/form-factors.md#native-aot-form-factors) is a .NET runtime form factor with key performance characteristics (startup time, binary size and steady state throughput and predictability) -competitive with statically compiled languages. A .NET runtime flavor based on CoreCLR with these characteristics is being developed as -experimental project in [dotnet/runtimelab](https://github.com/dotnet/runtimelab/tree/feature/NativeAOT) repo. +competitive with statically compiled languages. ## Frameworks diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md index 968bb5fa892435..3206fc7349c200 100644 --- a/docs/workflow/building/coreclr/nativeaot.md +++ b/docs/workflow/building/coreclr/nativeaot.md @@ -21,7 +21,7 @@ The executable looks like a native executable, in the sense that it can be debug ## Building - [Install pre-requisites](../../README.md#build-requirements) -- Run `build[.cmd|.sh] clr+libs -rc [Debug|Release] -lc Release` from the repo root. This will restore nuget packages required for building and build the parts of the repo required for general CoreCLR development. Alternatively, instead of specifying `clr+libs`, you can specify `clr.jit+clr.tools+clr.nativeaotlibs+libs` which is more targeted and builds faster. Replace `clr.jit` with `clr.alljits` if you need to crosscompile. +- Run `build[.cmd|.sh] clr+libs -rc [Debug|Release] -lc Release` from the repo root. This will restore nuget packages required for building and build the parts of the repo required for general CoreCLR development. Alternatively, instead of specifying `clr+libs`, you can specify `clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs` which is more targeted and builds faster. Replace `clr.jit` with `clr.alljits` if you need to crosscompile. - [NOT PORTED OVER YET] The build will place the toolchain packages at `artifacts\packages\[Debug|Release]\Shipping`. To publish your project using these packages: - [NOT PORTED OVER YET] Add the package directory to your `nuget.config` file. For example, replace `dotnet-experimental` line in `samples\HelloWorld\nuget.config` with `` - [NOT PORTED OVER YET] Run `dotnet publish --packages pkg -r [win-x64|linux-x64|osx-64] -c [Debug|Release]` to publish your project. `--packages pkg` option restores the package into a local directory that is easy to cleanup once you are done. It avoids polluting the global nuget cache with your locally built dev package. diff --git a/docs/workflow/debugging/libraries/debugging-corelib.md b/docs/workflow/debugging/libraries/debugging-corelib.md new file mode 100644 index 00000000000000..9dd817d5bf7ff7 --- /dev/null +++ b/docs/workflow/debugging/libraries/debugging-corelib.md @@ -0,0 +1,7 @@ +Debugging System.Private.CoreLib +========================== + +`System.Console.Write`/`System.Console.WriteLine` cannot be used in `System.Private.CoreLib`. Instead, use `Internal.Console.Write` to add temporary logging for printf-style debugging. + +### Android +The logs can be found through the generated Android Debug Bridge log or viewed directly through ADB logcat. diff --git a/docs/workflow/debugging/mono/wasm-debugging.md b/docs/workflow/debugging/mono/wasm-debugging.md index cfc98c1be2dbd7..4e7945ce515b6d 100644 --- a/docs/workflow/debugging/mono/wasm-debugging.md +++ b/docs/workflow/debugging/mono/wasm-debugging.md @@ -2,7 +2,7 @@ WASM runtime debugging ====================== -- Disable symbol stripping by setting the `WasmNativeStrip` msbuild property to `false`. +- Disable symbol stripping by setting the `WasmNativeStrip` msbuild property to `false`. See also, [collecting stack traces with symbols in Blazor](#collecting-stack-traces-with-symbols-in-blazor) - Emscripten generates dwarf debug info and Chrome 80 and later can use it. @@ -133,3 +133,131 @@ These kinds of faults usually happen because the mono runtime has some helper fu never meant to be reached, i.e. `no_gsharedvt_in_wrapper` or `no_llvmonly_interp_method_pointer`. These functions are used as placeholders for function pointers with different signatures, so if they do end up being called due to a bug, a signature mismatch error happens. + +# Collecting stack traces with symbols in Blazor + +When debugging a native crash in a .NET 6 Blazor app or another WebAssembly +framework that uses our default `dotnet.wasm`, the native stack frames will not +have C symbol names, but will instead look like `$func1234`. + +For example this Razor page will crash when a user clicks on the `Crash` button + +```csharp + + +@code { + private void Crash () + { + IntPtr p = (IntPtr)0x01; + Console.WriteLine ("About to crash"); + System.Runtime.InteropServices.Marshal.FreeHGlobal(p); + } +} +``` + +Clicking on the `Crash` button will produce the following output in the console (the function indices may be different): + +```console +dotnet.wasm:0x1d8355 Uncaught (in promise) RuntimeError: memory access out of bounds + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm + at _framework/dotnet.wasm +$free @ dotnet.wasm:0x1d8355 +$func4027 @ dotnet.wasm:0xead6a +$func219 @ dotnet.wasm:0x1a03a +$func167 @ dotnet.wasm:0xcaf7 +$func166 @ dotnet.wasm:0xba0a +$func2810 @ dotnet.wasm:0xabacf +$func1615 @ dotnet.wasm:0x6f8eb +$func1613 @ dotnet.wasm:0x6f85d +$func966 @ dotnet.wasm:0x502dc +$func219 @ dotnet.wasm:0x1a0e2 +$func167 @ dotnet.wasm:0xcaf7 +$func166 @ dotnet.wasm:0xba0a +$func2810 @ dotnet.wasm:0xabacf +$func1615 @ dotnet.wasm:0x6f8eb +$func1619 @ dotnet.wasm:0x6ff58 +$mono_wasm_invoke_method @ dotnet.wasm:0x96c9 +Module._mono_wasm_invoke_method @ dotnet.6.0.1.hopd7ipo8x.js:1 +managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19 +beginInvokeDotNetFromJS @ blazor.webassembly.js:1 +b @ blazor.webassembly.js:1 +invokeMethodAsync @ blazor.webassembly.js:1 +(anonymous) @ blazor.webassembly.js:1 +invokeWhenHeapUnlocked @ blazor.webassembly.js:1 +S @ blazor.webassembly.js:1 +C @ blazor.webassembly.js:1 +dispatchGlobalEventToAllElements @ blazor.webassembly.js:1 +onGlobalEvent @ blazor.webassembly.js:1 +``` + +In order to get symbols, the user should: + +1. Install the `wasm-tools` workload using `dotnet workload install wasm-tools` +2. Set these additional properties in their `.csproj` file: + + ```xml + + + true + false + + ``` + +3. Delete the `bin` and `obj` folders, re-build the project and run it again. + +Now clicking on the `Crash` button will produce a stack trace with symbols: + +```console +dotnet.wasm:0x224878 Uncaught (in promise) RuntimeError: memory access out of bounds + at dlfree (dotnet.wasm:0x224878) + at SystemNative_Free (dotnet.wasm:0x20f0e2) + at do_icall (dotnet.wasm:0x190f9) + at do_icall_wrapper (dotnet.wasm:0x18429) + at interp_exec_method (dotnet.wasm:0xa56c) + at interp_runtime_invoke (dotnet.wasm:0x943a) + at mono_jit_runtime_invoke (dotnet.wasm:0x1dec32) + at do_runtime_invoke (dotnet.wasm:0x95fca) + at mono_runtime_invoke_checked (dotnet.wasm:0x95f57) + at mono_runtime_try_invoke_array (dotnet.wasm:0x9a87e) +$dlfree @ dotnet.wasm:0x224878 +$SystemNative_Free @ dotnet.wasm:0x20f0e2 +$do_icall @ dotnet.wasm:0x190f9 +$do_icall_wrapper @ dotnet.wasm:0x18429 +$interp_exec_method @ dotnet.wasm:0xa56c +$interp_runtime_invoke @ dotnet.wasm:0x943a +$mono_jit_runtime_invoke @ dotnet.wasm:0x1dec32 +$do_runtime_invoke @ dotnet.wasm:0x95fca +$mono_runtime_invoke_checked @ dotnet.wasm:0x95f57 +$mono_runtime_try_invoke_array @ dotnet.wasm:0x9a87e +$mono_runtime_invoke_array_checked @ dotnet.wasm:0x9af17 +$ves_icall_InternalInvoke @ dotnet.wasm:0x702ed +$ves_icall_InternalInvoke_raw @ dotnet.wasm:0x7777f +$do_icall @ dotnet.wasm:0x191c5 +$do_icall_wrapper @ dotnet.wasm:0x18429 +$interp_exec_method @ dotnet.wasm:0xa56c +$interp_runtime_invoke @ dotnet.wasm:0x943a +$mono_jit_runtime_invoke @ dotnet.wasm:0x1dec32 +$do_runtime_invoke @ dotnet.wasm:0x95fca +$mono_runtime_try_invoke @ dotnet.wasm:0x966fe +$mono_runtime_invoke @ dotnet.wasm:0x98982 +$mono_wasm_invoke_method @ dotnet.wasm:0x227de2 +Module._mono_wasm_invoke_method @ dotnet..y6ggkhlo8e.js:9927 +managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet @ managed__Microsoft_AspNetCore_Components_WebAssembly__Microsoft_AspNetCore_Components_WebAssembly_Services_DefaultWebAssemblyJSRuntime_BeginInvokeDotNet:19 +beginInvokeDotNetFromJS @ blazor.webassembly.js:1 +b @ blazor.webassembly.js:1 +invokeMethodAsync @ blazor.webassembly.js:1 +(anonymous) @ blazor.webassembly.js:1 +invokeWhenHeapUnlocked @ blazor.webassembly.js:1 +S @ blazor.webassembly.js:1 +C @ blazor.webassembly.js:1 +dispatchGlobalEventToAllElements @ blazor.webassembly.js:1 +onGlobalEvent @ blazor.webassembly.js:1 +``` diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index 0fc9bf8e5a7eeb..e5ae41903b5a76 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -152,10 +152,10 @@ dotnet_diagnostic.CA1064.severity = none dotnet_diagnostic.CA1065.severity = none # CA1066: Implement IEquatable when overriding Object.Equals -dotnet_diagnostic.CA1066.severity = none +dotnet_diagnostic.CA1066.severity = warning # CA1067: Override Object.Equals(object) when implementing IEquatable -dotnet_diagnostic.CA1067.severity = none +dotnet_diagnostic.CA1067.severity = warning # CA1068: CancellationToken parameters must come last dotnet_diagnostic.CA1068.severity = none diff --git a/eng/Subsets.props b/eng/Subsets.props index 5ce54174451364..5ea1ff48e23f4a 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -27,7 +27,7 @@ flavor is used to decide when to build the hosts and installers. --> CoreCLR - Mono + Mono @@ -106,7 +106,8 @@ - + + @@ -203,7 +204,7 @@ $(ClrRuntimeBuildSubsets);ClrILToolsSubset=true - + $(ClrRuntimeBuildSubsets);ClrNativeAotSubset=true @@ -363,6 +364,7 @@ + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index af284815b19ecb..3da43d2ed21e24 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,258 +1,258 @@ - + https://github.com/dotnet/icu - 4170ccfbbcada3e22aa4428a84524fabef006e38 + 80a658fa6aa6601d67bfe5a294e0d1b7e1184a5c https://github.com/dotnet/msquic a7213b4676c1803bb251771291a525482d42e511 - + https://github.com/dotnet/emsdk - 4eb953d7051890da4f36167125c6b41e06d7f56d + aaa56a6622c4991cf65d553250af3c0ade1320bc https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/llvm-project - fe77708023f3d8a51c1548b86487a692897227ec + afc9070f64d110ce2bf029a4a624b9dd1c6dbffd - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/llvm-project - 79a6d232058e2c2f1d9e833355b72f07fe342a3b + 44adf6c047663fe20c388bfb769e18dd3c91f7e0 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 - + https://github.com/dotnet/runtime - ae2f60c950cc021921fce83c796cbcb5ff96c658 + 09ff1acdad2e7789908b5db9bb89896144c13042 https://github.com/dotnet/linker e485816b48273d03bd6266a64dad9bea97f861d5 - + https://github.com/dotnet/xharness - 3060cda4543b80824a9238bcd176bb1a5af72044 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/xharness - 3060cda4543b80824a9238bcd176bb1a5af72044 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/xharness - 3060cda4543b80824a9238bcd176bb1a5af72044 + 0137095821e2e5a9e030d97248503387b8d72a18 - + https://github.com/dotnet/arcade - 9ffc76ac9f5799de9b28ee59f9bfbe0f8844d0d7 + 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -270,13 +270,13 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 91d6b3c1f51888d166701510189505f35714665c - + https://github.com/dotnet/hotreload-utils - b6504c8dca937ff1a59d3283374241eacf26684a + d3e96c2e8ed4d58de217c44423c9ba3b90333724 - + https://github.com/dotnet/runtime-assets - a597df23119faf540d95cebab14b82f084c47384 + 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7 https://github.com/dotnet/roslyn-analyzers diff --git a/eng/Versions.props b/eng/Versions.props index 04f7adea4cff9d..aae2d08e090181 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -7,8 +7,8 @@ 0 0 7.0.100 - alpha - 1 + preview + 2 $(MajorVersion).$(MinorVersion).0.0 @@ -54,38 +54,38 @@ 2.0.0-alpha.1.21525.11 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 2.5.1-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 - 7.0.0-beta.22068.3 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 2.5.1-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 + 7.0.0-beta.22075.6 6.0.0-preview.1.102 - 7.0.0-alpha.1.22066.4 - 7.0.0-alpha.1.22066.4 - 7.0.0-alpha.1.22066.4 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 3.1.0 - 7.0.0-alpha.1.22066.4 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 - 1.0.0-alpha.1.22070.1 + 7.0.0-alpha.1.22073.5 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 + 1.0.0-alpha.1.22073.1 5.0.0 4.3.0 @@ -114,30 +114,30 @@ 4.3.0 4.3.0 4.3.0 - 6.0.0-rc.2.21454.1 + 6.0.0 4.3.1 5.0.0 5.0.0 5.0.0 4.9.0-rc2.21473.1 - 7.0.0-alpha.1.22066.4 - 7.0.0-alpha.1.22066.4 + 7.0.0-alpha.1.22073.5 + 7.0.0-alpha.1.22073.5 4.5.4 4.5.0 - 7.0.0-alpha.1.22066.4 + 7.0.0-alpha.1.22073.5 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 - 7.0.0-beta.22060.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 + 7.0.0-beta.22075.1 1.0.0-prerelease.21577.2 1.0.0-prerelease.21577.2 @@ -160,10 +160,10 @@ 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.22067.1 - 1.0.0-prerelease.22067.1 - 1.0.0-prerelease.22067.1 - 1.0.2-alpha.0.22069.1 + 1.0.0-prerelease.22074.1 + 1.0.0-prerelease.22074.1 + 1.0.0-prerelease.22074.1 + 1.0.2-alpha.0.22074.1 2.4.2-pre.22 0.12.0-pre.20 2.4.2 @@ -175,25 +175,25 @@ 7.0.100-alpha.1.21528.1 1.1.1-beta1.21467.5 - 6.0.0-preview-20211019.1 + 6.0.0-preview-20220104.1 7.0.100-1.22063.2 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-alpha.1.22067.1 + 7.0.0-preview.2.22074.5 7.0.0-alpha.1.21529.3 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 - 11.1.0-alpha.1.22067.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 + 11.1.0-alpha.1.22074.2 - 7.0.0-alpha.1.21601.1 + 7.0.0-alpha.2.22071.3 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) 1.1.87-gba258badda diff --git a/eng/build.sh b/eng/build.sh index ea8e3089e95f4d..167f8e2014182e 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -17,7 +17,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" usage() { echo "Common settings:" - echo " --arch (-a) Target platform: x86, x64, arm, armel, arm64, loongarch64, s390x or wasm." + echo " --arch (-a) Target platform: x86, x64, arm, armv6, armel, arm64, loongarch64, s390x or wasm." echo " [Default: Your machine's architecture.]" echo " --binaryLog (-bl) Output binary log." echo " --cross Optional argument to signify cross compilation." @@ -206,12 +206,12 @@ while [[ $# > 0 ]]; do fi passedArch="$(echo "$2" | tr "[:upper:]" "[:lower:]")" case "$passedArch" in - x64|x86|arm|armel|arm64|loongarch64|s390x|wasm) + x64|x86|arm|armv6|armel|arm64|loongarch64|s390x|wasm) arch=$passedArch ;; *) echo "Unsupported target architecture '$2'." - echo "The allowed values are x86, x64, arm, armel, arm64, loongarch64, s390x, and wasm." + echo "The allowed values are x86, x64, arm, armv6, armel, arm64, loongarch64, s390x, and wasm." exit 1 ;; esac diff --git a/eng/common/cross/arm/tizen-build-rootfs.sh b/eng/common/cross/arm/tizen-build-rootfs.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/arm/tizen-fetch.sh b/eng/common/cross/arm/tizen-fetch.sh old mode 100644 new mode 100755 diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh index e94d13d62ef64d..f97dca77054089 100755 --- a/eng/common/cross/build-rootfs.sh +++ b/eng/common/cross/build-rootfs.sh @@ -7,7 +7,7 @@ usage() echo "Usage: $0 [BuildArch] [CodeName] [lldbx.y] [--skipunmount] --rootfsdir ]" echo "BuildArch can be: arm(default), armel, arm64, x86" echo "CodeName - optional, Code name for Linux, can be: xenial(default), zesty, bionic, alpine, alpine3.13 or alpine3.14. If BuildArch is armel, LinuxCodeName is jessie(default) or tizen." - echo " for FreeBSD can be: freebsd11, freebsd12, freebsd13" + echo " for FreeBSD can be: freebsd12, freebsd13" echo " for illumos can be: illumos." echo "lldbx.y - optional, LLDB version, can be: lldb3.9(default), lldb4.0, lldb5.0, lldb6.0 no-lldb. Ignored for alpine and FreeBSD" echo "--skipunmount - optional, will skip the unmount of rootfs folder." @@ -60,13 +60,13 @@ __AlpinePackages+=" krb5-dev" __AlpinePackages+=" openssl-dev" __AlpinePackages+=" zlib-dev" -__FreeBSDBase="12.2-RELEASE" -__FreeBSDPkg="1.12.0" +__FreeBSDBase="12.3-RELEASE" +__FreeBSDPkg="1.17.0" __FreeBSDABI="12" __FreeBSDPackages="libunwind" __FreeBSDPackages+=" icu" __FreeBSDPackages+=" libinotify" -__FreeBSDPackages+=" lttng-ust" +__FreeBSDPackages+=" openssl" __FreeBSDPackages+=" krb5" __FreeBSDPackages+=" terminfo-db" @@ -206,10 +206,6 @@ while :; do __AlpineVersion=3.14 __AlpinePackages+=" llvm11-libs" ;; - freebsd11) - __FreeBSDBase="11.3-RELEASE" - __FreeBSDABI="11" - ;& freebsd12) __CodeName=freebsd __BuildArch=x64 diff --git a/eng/common/internal/NuGet.config b/eng/common/internal/NuGet.config new file mode 100644 index 00000000000000..769650362f4aa4 --- /dev/null +++ b/eng/common/internal/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 8cf772b3cbf812..24cec0424e5d64 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -29,14 +29,6 @@ parameters: # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, # not pipeline artifacts, so doesn't affect the use of this parameter. pipelineArtifactNames: [] - # Optional: location and ID of the AzDO build that the build/pipeline artifacts should be - # downloaded from. By default, uses runtime expressions to decide based on the variables set by - # the 'setupMaestroVars' dependency. Overriding this parameter is necessary if SDL tasks are - # running without Maestro++/BAR involved, or to download artifacts from a specific existing build - # to iterate quickly on SDL changes. - AzDOProjectName: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - AzDOPipelineId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - AzDOBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] jobs: - job: Run_SDL @@ -55,11 +47,20 @@ jobs: - name: GuardianVersion value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} pool: - vmImage: windows-2019 + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: - checkout: self clean: true + - template: /eng/common/templates/post-build/setup-maestro-vars.yml + - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - ${{ if ne(parameters.artifactNames, '') }}: - ${{ each artifactName in parameters.artifactNames }}: diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index c4fc18b3ee77aa..9d1e3042d8a6c0 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -3,9 +3,8 @@ parameters: dependsOn: '' # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: - vmImage: 'windows-2019' - + pool: '' + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) @@ -31,7 +30,18 @@ jobs: displayName: OneLocBuild - pool: ${{ parameters.pool }} + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 variables: - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index ff4ab75c886dc7..554e71cfc436dd 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -83,7 +83,15 @@ jobs: - ${{ if eq(parameters.enableSourceBuild, true) }}: - Source_Build_Complete pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + runAsPublic: ${{ parameters.runAsPublic }} publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index c99fd7503767cd..c830e6f277606e 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,54 +4,6 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - - # .NET Core 3.1 Dev - - name: PublicDevRelease_31_Channel_Id - value: 128 - - # .NET 5 Dev - - name: Net_5_Dev_Channel_Id - value: 131 - - # .NET Eng - Validation - - name: Net_Eng_Validation_Channel_Id - value: 9 - - # .NET Eng - Latest - - name: Net_Eng_Latest_Channel_Id - value: 2 - - # .NET 3 Eng - Validation - - name: NET_3_Eng_Validation_Channel_Id - value: 390 - - # .NET 3 Eng - - name: NetCore_3_Tools_Channel_Id - value: 344 - - # .NET Core 3.0 Internal Servicing - - name: InternalServicing_30_Channel_Id - value: 184 - - # .NET Core 3.0 Release - - name: PublicRelease_30_Channel_Id - value: 19 - - # .NET Core 3.1 Release - - name: PublicRelease_31_Channel_Id - value: 129 - - # General Testing - - name: GeneralTesting_Channel_Id - value: 529 - - # .NET Core 3.1 Blazor Features - - name: NetCore_31_Blazor_Features_Channel_Id - value: 531 - - # .NET Core Experimental - - name: NetCore_Experimental_Channel_Id - value: 562 # Whether the build is internal or not - name: IsInternalBuild @@ -70,27 +22,6 @@ variables: - name: SymbolToolVersion value: 1.0.1 - # Feed Configurations - # These should include the suffix "/index.json" - - # Default locations for Installers and checksums - # Public Locations - - name: ChecksumsBlobFeedUrl - value: https://dotnetclichecksums.blob.core.windows.net/dotnet/index.json - - name: InstallersBlobFeedUrl - value: https://dotnetcli.blob.core.windows.net/dotnet/index.json - - # Private Locations - - name: InternalChecksumsBlobFeedUrl - value: https://dotnetclichecksumsmsrc.blob.core.windows.net/dotnet/index.json - - name: InternalChecksumsBlobFeedKey - value: $(dotnetclichecksumsmsrc-storage-key) - - - name: InternalInstallersBlobFeedUrl - value: https://dotnetclimsrc.blob.core.windows.net/dotnet/index.json - - name: InternalInstallersBlobFeedKey - value: $(dotnetclimsrc-access-key) - # Skip component governance and codesign validation for SDL. These jobs # create no content. - name: skipComponentGovernanceDetection diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 8985b429c85437..2f176571f020cf 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -90,25 +90,25 @@ stages: variables: - template: common-variables.yml jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - job: displayName: NuGet Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableNugetValidation }}, 'true') pool: - vmImage: 'windows-2019' - variables: - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -129,19 +129,22 @@ stages: - job: displayName: Signing Validation - dependsOn: setupMaestroVars condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -186,19 +189,22 @@ stages: - job: displayName: SourceLink Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: @@ -224,7 +230,6 @@ stages: - template: /eng/common/templates/job/execute-sdl.yml parameters: enable: ${{ parameters.SDLValidationParameters.enable }} - dependsOn: setupMaestroVars additionalParameters: ${{ parameters.SDLValidationParameters.params }} continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} @@ -239,21 +244,26 @@ stages: variables: - template: common-variables.yml jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - job: displayName: Publish Using Darc - dependsOn: setupMaestroVars timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + + - task: NuGetAuthenticate@0 + - task: PowerShell@2 displayName: Publish Using Darc inputs: diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 4a22b2e6f6de79..0c87f149a4ad77 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -2,77 +2,69 @@ parameters: BARBuildId: '' PromoteToChannelIds: '' -jobs: -- job: setupMaestroVars - displayName: Setup Maestro Vars - variables: - - template: common-variables.yml - pool: - vmImage: 'windows-2019' - steps: - - checkout: none - - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars +steps: + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs inputs: - targetType: inline - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 + - task: PowerShell@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + targetType: inline + pwsh: true + script: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } + $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $apiHeaders.Add('Accept', 'application/json') + $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels;isOutput=true]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" + $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + + $BarId = $Env:BARBuildId + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" - Write-Host "##vso[task.setvariable variable=AzDOProjectName;isOutput=true]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId;isOutput=true]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId;isOutput=true]$AzureDevOpsBuildId" + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + MAESTRO_API_TOKEN: $(MaestroApiAccessToken) + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 373091b13a0014..294e9832ad3105 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -197,7 +197,7 @@ usage() echo "" echo "Common Options:" echo "" - echo "BuildArch can be: -arm, -armel, -arm64, -loongarch64, -s390x, x64, x86, -wasm" + echo "BuildArch can be: -arm, -armv6, -armel, -arm64, -loongarch64, -s390x, x64, x86, -wasm" echo "BuildType can be: -debug, -checked, -release" echo "-os: target OS (defaults to running OS)" echo "-bindir: output directory (defaults to $__ProjectRoot/artifacts)" @@ -270,6 +270,10 @@ while :; do __BuildArch=arm ;; + armv6|-armv6) + __BuildArch=armv6 + ;; + arm64|-arm64) __BuildArch=arm64 ;; diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index fad1ac58d39c88..b67594cb60fb2a 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -213,6 +213,9 @@ elseif (CLR_CMAKE_HOST_ARCH_I386) elseif (CLR_CMAKE_HOST_ARCH_ARM) set(ARCH_HOST_NAME arm) add_definitions(-DHOST_ARM) +elseif (CLR_CMAKE_HOST_ARCH_ARMV6) + set(ARCH_HOST_NAME armv6) + add_definitions(-DHOST_ARMV6) elseif (CLR_CMAKE_HOST_ARCH_ARM64) set(ARCH_HOST_NAME arm64) add_definitions(-DHOST_ARM64 -DHOST_64BIT) @@ -238,6 +241,8 @@ if (CLR_CMAKE_HOST_UNIX) message("Detected Linux x86_64") elseif(CLR_CMAKE_HOST_UNIX_ARM) message("Detected Linux ARM") + elseif(CLR_CMAKE_HOST_UNIX_ARMV6) + message("Detected Linux ARMv6") elseif(CLR_CMAKE_HOST_UNIX_ARM64) message("Detected Linux ARM64") elseif(CLR_CMAKE_HOST_UNIX_LOONGARCH64) @@ -301,6 +306,12 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM) set(ARCH_TARGET_NAME arm) add_compile_definitions($<$>>:TARGET_ARM>) add_compile_definitions($<$>>:TARGET_32BIT>) +elseif (CLR_CMAKE_TARGET_ARCH_ARMV6) + set(ARCH_SOURCES_DIR arm) + set(ARCH_TARGET_NAME armv6) + add_compile_definitions($<$>>:TARGET_ARM>) + add_compile_definitions($<$>>:TARGET_ARMV6>) + add_compile_definitions($<$>>:TARGET_32BIT>) elseif (CLR_CMAKE_TARGET_ARCH_I386) set(ARCH_TARGET_NAME x86) set(ARCH_SOURCES_DIR i386) @@ -507,6 +518,14 @@ if(CLR_CMAKE_HOST_UNIX_ARM) endif(ARM_SOFTFP) endif(CLR_CMAKE_HOST_UNIX_ARM) +if(CLR_CMAKE_HOST_UNIX_ARMV6) + add_compile_options(-mfpu=vfp) + add_definitions(-DCLR_ARM_FPU_CAPABILITY=0x0) + add_compile_options(-march=armv6zk) + add_compile_options(-mcpu=arm1176jzf-s) + add_compile_options(-mfloat-abi=hard) +endif(CLR_CMAKE_HOST_UNIX_ARMV6) + if(CLR_CMAKE_HOST_UNIX_X86) add_compile_options(-msse2) endif() diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index cdf33430b49f11..ecf10a8d4c39ef 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -41,6 +41,8 @@ if(CLR_CMAKE_HOST_OS STREQUAL Linux) set(CLR_CMAKE_HOST_UNIX_ARMV7L 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL armv7-a) set(CLR_CMAKE_HOST_UNIX_ARM 1) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL armv6 OR CMAKE_SYSTEM_PROCESSOR STREQUAL armv6l) + set(CLR_CMAKE_HOST_UNIX_ARMV6 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm64) set(CLR_CMAKE_HOST_UNIX_ARM64 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL loongarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL loongarch64) @@ -217,6 +219,13 @@ if(CLR_CMAKE_HOST_UNIX_ARM) if(CLR_CMAKE_HOST_UNIX_ARMV7L) set(CLR_CMAKE_HOST_ARCH_ARMV7L 1) endif() +elseif(CLR_CMAKE_HOST_UNIX_ARMV6) + set(CLR_CMAKE_HOST_ARCH_ARMV6 1) + set(CLR_CMAKE_HOST_ARCH "armv6") + + if(CLR_CMAKE_HOST_UNIX_ARMV6L) + set(CLR_CMAKE_HOST_ARCH_ARMV6L 1) + endif() elseif(CLR_CMAKE_HOST_UNIX_ARM64) set(CLR_CMAKE_HOST_ARCH_ARM64 1) set(CLR_CMAKE_HOST_ARCH "arm64") @@ -277,6 +286,8 @@ if (CLR_CMAKE_TARGET_ARCH STREQUAL x64) set(CLR_CMAKE_TARGET_ARCH_LOONGARCH64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) set(CLR_CMAKE_TARGET_ARCH_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armv6) + set(CLR_CMAKE_TARGET_ARCH_ARMV6 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armel) set(CLR_CMAKE_TARGET_ARCH_ARM 1) set(CLR_CMAKE_TARGET_ARCH_ARMV7L 1) @@ -379,6 +390,8 @@ if(CLR_CMAKE_TARGET_UNIX) set(CLR_CMAKE_TARGET_UNIX_ARM 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm) set(CLR_CMAKE_TARGET_UNIX_ARM 1) + elseif(CLR_CMAKE_TARGET_ARCH STREQUAL armv6) + set(CLR_CMAKE_TARGET_UNIX_ARMV6 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL arm64) set(CLR_CMAKE_TARGET_UNIX_ARM64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL loongarch64) diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index 136cd67925d0cb..860e46427b6b08 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -7,15 +7,15 @@ if (CMAKE_C_COMPILER MATCHES "-?[0-9]+(\.[0-9]+)?$") endif() if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(CMAKE_C_COMPILER_ID MATCHES "Clang") if(APPLE) set(TOOLSET_PREFIX "") else() set(TOOLSET_PREFIX "llvm-") endif() - elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU") if(CMAKE_CROSSCOMPILING) - set(TOOLSET_PREFIX "${CMAKE_CXX_COMPILER_TARGET}-") + set(TOOLSET_PREFIX "${CMAKE_C_COMPILER_TARGET}-") else() set(TOOLSET_PREFIX "") endif() @@ -52,8 +52,8 @@ if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) if(CLR_CMAKE_TARGET_ANDROID) set(TOOLSET_PREFIX ${ANDROID_TOOLCHAIN_PREFIX}) - elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR - CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm OR CMAKE_SYSTEM_PROCESSOR STREQUAL s390x)) + elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND + CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7l|armv6l|aarch64|arm|s390x)$") set(TOOLSET_PREFIX "${TOOLCHAIN}-") else() set(TOOLSET_PREFIX "") diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index c4af68ba7dc610..0c28f75706de19 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -4,7 +4,7 @@ function(clr_unknown_arch) elseif(CLR_CROSS_COMPONENTS_BUILD) message(FATAL_ERROR "Only AMD64, I386 host are supported for linux cross-architecture component. Found: ${CMAKE_SYSTEM_PROCESSOR}") else() - message(FATAL_ERROR "Only AMD64, ARM64, LOONGARCH64 and ARM are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Only AMD64, ARMV6, ARM64, LOONGARCH64 and ARM are supported. Found: ${CMAKE_SYSTEM_PROCESSOR}") endif() endfunction() @@ -155,6 +155,10 @@ function(find_unwind_libs UnwindLibs) find_library(UNWIND_ARCH NAMES unwind-arm) endif() + if(CLR_CMAKE_HOST_ARCH_ARMV6) + find_library(UNWIND_ARCH NAMES unwind-arm) + endif() + if(CLR_CMAKE_HOST_ARCH_ARM64) find_library(UNWIND_ARCH NAMES unwind-aarch64) endif() diff --git a/eng/native/init-os-and-arch.sh b/eng/native/init-os-and-arch.sh index 586534be1c8aa9..eda07a5feebbdf 100644 --- a/eng/native/init-os-and-arch.sh +++ b/eng/native/init-os-and-arch.sh @@ -53,6 +53,10 @@ case "$CPUName" in fi ;; + armv6l) + arch=armv6 + ;; + i[3-6]86) echo "Unsupported CPU $CPUName detected, build might not succeed!" arch=x86 diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index e8a04c5698ad35..fca410fcb4b42f 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -68,7 +68,7 @@ if(DARWIN) else() message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm64 or x64 is supported for OSX cross build!") endif() -elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|arm64|loongarch64|s390x|x86)$" OR FREEBSD OR ILLUMOS) +elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|s390x|x86)$" OR FREEBSD OR ILLUMOS) set_cache_value(FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE 1) set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 0) set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) @@ -146,9 +146,9 @@ elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|arm64|loongarch64|s390x|x86)$" OR F set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) endif() else() - message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64, loongarch64, s390x and x86 are supported!") + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, armv6, arm64, loongarch64, s390x and x86 are supported!") endif() -if(TARGET_ARCH_NAME STREQUAL "x86" OR TARGET_ARCH_NAME STREQUAL "s390x" OR TARGET_ARCH_NAME STREQUAL "loongarch64") +if(TARGET_ARCH_NAME STREQUAL "x86" OR TARGET_ARCH_NAME STREQUAL "s390x" OR TARGET_ARCH_NAME STREQUAL "armv6" OR TARGET_ARCH_NAME STREQUAL "loongarch64") set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) endif() diff --git a/eng/packaging.targets b/eng/packaging.targets index 667837fbff1067..c305c64dd94090 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -162,19 +162,18 @@ <_MultiTargetRoslynComponentTargetPrefix>$(PackageId.Replace('.', '_')) - <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>Disable$(PackageId.Replace('.', ''))SourceGenerator - <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>$(_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName.Replace('Abstractions', '')) + Disable$(PackageId.Replace('.', ''))SourceGenerator diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 282fa567550812..4f0200380bc9f7 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -52,6 +52,31 @@ jobs: crossrootfsDir: '/crossrootfs/arm' ${{ insert }}: ${{ parameters.jobParameters }} +# Linux armv6 +- ${{ if or(containsValue(parameters.platforms, 'Linux_armv6'), or(and(ne(parameters.runtimeFlavor, 'mono'), in(parameters.platformGroup, 'gcstress')), and(eq(parameters.runtimeFlavor, 'mono'), in(parameters.platformGroup, 'all', 'gcstress')))) }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: Linux + archType: armv6 + targetRid: linux-armv6 + platform: Linux_armv6 + container: + image: ubuntu-20.04-cross-armv6-raspbian-10-20211208135931-e6e3ac4 + 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/armv6' + ${{ insert }}: ${{ parameters.jobParameters }} + # Linux arm64 - ${{ if or(containsValue(parameters.platforms, 'Linux_arm64'), in(parameters.platformGroup, 'all', 'gcstress')) }}: diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index 6aa8a54f24c0f8..f944ad47ba2037 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -319,7 +319,7 @@ jobs: - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) $(runtimeVariantArg) displayName: "LLVM AOT compile CoreCLR tests" - ${{ if eq(parameters.archType, 'arm64') }}: - - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) cross $(runtimeVariantArg) + - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(logRootNameArg)MonoAot $(monoAotBuildshCommand) $(buildConfig) $(archType) cross $(runtimeVariantArg) -maxcpucount:2 displayName: "LLVM AOT cross-compile CoreCLR tests" env: __MonoToolPrefix: aarch64-linux-gnu- diff --git a/eng/pipelines/coreclr/templates/build-jit-job.yml b/eng/pipelines/coreclr/templates/build-jit-job.yml index 2022a8c53a24fd..b5ff3df213af30 100644 --- a/eng/pipelines/coreclr/templates/build-jit-job.yml +++ b/eng/pipelines/coreclr/templates/build-jit-job.yml @@ -118,7 +118,7 @@ jobs: - script: $(PipScript) install --user --upgrade pip && $(PipScript) install --user azure.storage.blob==12.5.0 --force-reinstall displayName: Upgrade Pip to latest and install azure-storage-blob Python package - - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/jitrollingbuild.py upload -build_type $(buildConfig) -arch $(archType) -host_os $(osGroup) -git_hash $(Build.SourceVersion) + - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/jitrollingbuild.py upload -build_type $(buildConfig) -arch $(archType) -host_os $(osGroup) -git_hash $(Build.SourceVersion) --use_latest_jit_change displayName: Upload JIT to Azure Storage env: CLRJIT_AZ_KEY: $(clrjit_key1) # secret key stored as variable in pipeline diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index 713882250e627a..9048e8ed4fe8a2 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -212,7 +212,7 @@ jobs: # Build CoreCLR Managed Components - ${{ if or(ne(parameters.osGroup, 'Linux'), ne(parameters.archType, 'x86')) }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib+clr.nativecorelib+clr.tools+clr.packages+clr.paltestlist $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci + - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib+clr.nativecorelib+clr.nativeaotlibs+clr.tools+clr.packages+clr.paltestlist $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci displayName: Build managed product components and packages - ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.archType, 'x86')) }}: - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.corelib $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(pgoInstrumentArg) $(officialBuildIdArg) -ci diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index dec87138ed4563..f82e09c9e0a124 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -33,6 +33,11 @@ jobs: - (Debian.10.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 - (Debian.11.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 + # Linux armv6 + - ${{ if eq(parameters.platform, 'Linux_armv6') }}: +# - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - (Raspbian.10.Armv6.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:raspbian-10-helix-arm32v6-20211215185610-60748cc + # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index d864487760908b..0f2070a49bfbf7 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -191,4 +191,8 @@ jobs: - fullpgo_random_gdv - fullpgo_random_edge - fullpgo_random_gdv_edge + - jitosr + - jitosr_stress + - jitosr_stress_random + - jitosr_pgo diff --git a/eng/pipelines/runtime-extra-platforms.yml b/eng/pipelines/runtime-extra-platforms.yml index d9121f4b8027a0..a0642f4ab521c7 100644 --- a/eng/pipelines/runtime-extra-platforms.yml +++ b/eng/pipelines/runtime-extra-platforms.yml @@ -177,7 +177,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: ConsoleBrowserTests + nameSuffix: LibraryTests buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows timeoutInMinutes: 180 condition: >- @@ -221,7 +221,7 @@ jobs: jobParameters: isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: AllSubsets_Mono_EAT + nameSuffix: LibraryTests_EAT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false timeoutInMinutes: 180 condition: >- @@ -265,7 +265,7 @@ jobs: jobParameters: isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} testGroup: innerloop - nameSuffix: AllSubsets_Mono_AOT + nameSuffix: LibraryTests_AOT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true /p:BrowserHost=$(_hostedOs) timeoutInMinutes: 180 condition: >- @@ -288,43 +288,6 @@ jobs: eq(variables['monoContainsChange'], true), eq(variables['isRollingBuild'], true)) -# -# Build the whole product using Mono and run runtime tests -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml - buildConfig: Release - runtimeFlavor: mono - platforms: - - Browser_wasm - variables: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: pr/dotnet/runtime/$(Build.SourceBranch) - - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: - - name: _HelixSource - value: ci/dotnet/runtime/$(Build.SourceBranch) - - name: timeoutPerTestInMinutes - value: 10 - - name: timeoutPerTestCollectionInMinutes - value: 200 - jobParameters: - testGroup: innerloop - nameSuffix: AllSubsets_Mono_RuntimeTests - buildArgs: -s mono+libs -c $(_BuildConfig) - timeoutInMinutes: 180 - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), - eq(variables['isRollingBuild'], true)) - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) - # # Build the whole product using Mono and run libraries tests # @@ -562,7 +525,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: Windows_wasm_DebuggerTests + nameSuffix: Mono_DebuggerTests buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows timeoutInMinutes: 180 condition: >- diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index 42803677d00371..c51d639d29f0f2 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -234,6 +234,41 @@ jobs: eq(variables['monoContainsChange'], true), eq(variables['isRollingBuild'], true)) +# +# 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_armv6 + 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: + testScope: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+clr+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 120 + 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['isRollingBuild'], true)) + ${{ if eq(variables['isRollingBuild'], true) }}: + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + # # Build the whole product using Mono and run runtime tests with the JIT. # @@ -273,6 +308,180 @@ jobs: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig) +# +# Build the whole product using Mono and run libraries tests, for Wasm.Build.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: + - Browser_wasm_win + variables: + # map dependencies variables to local variables + - name: wasmbuildtestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] + jobParameters: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} + testGroup: innerloop + nameSuffix: WasmBuildTests + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs) + timeoutInMinutes: 180 + condition: >- + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:BrowserHost=$(_hostedOs) + scenarios: + - buildwasmapps + condition: >- + eq(variables['wasmbuildtestsContainsChange'], true) + +# +# Build Browser_wasm, on windows, run console and browser 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: + - Browser_wasm_win + 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: LibraryTests + buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows + 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)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Windows_wasm_$(_BuildConfig) + extraHelixArguments: /p:BrowserHost=windows + scenarios: + - normal + - wasmtestonbrowser + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isRollingBuild'], true)) + +# +# Build for Browser/wasm with RunAOTCompilation=true +# +- 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: + - Browser_wasm_win + 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: + isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }} + testGroup: innerloop + nameSuffix: LibraryTests_AOT + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true /p:BrowserHost=$(_hostedOs) + 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)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_AOT_$(_BuildConfig)_$(_hostedOs) + extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) /p:BrowserHost=$(_hostedOs) + scenarios: + - normal + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true)) + +# Wasm debugger tests - windows +- 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: + - Browser_wasm_win + variables: + # map dependencies variables to local variables + - name: wasmdebuggertestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: Mono_DebuggerTests + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows + timeoutInMinutes: 180 + condition: >- + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + extraHelixArguments: /p:BrowserHost=windows + scenarios: + - wasmdebuggertests + +# Wasm debugger 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: + - Browser_wasm + variables: + # map dependencies variables to local variables + - name: wasmdebuggertestsContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: Mono_DebuggerTests + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false + timeoutInMinutes: 180 + condition: >- + eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + scenarios: + - wasmdebuggertests + # # Build the whole product using Mono for Android and run runtime tests with Android devices # diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index cfc899e8d808de..9d3bbfe477d8e0 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -211,7 +211,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -233,7 +233,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -257,7 +257,7 @@ jobs: testGroup: innerloop timeoutInMinutes: 120 nameSuffix: NativeAOT - buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+libs -rc $(_BuildConfig) -lc Release + buildArgs: -s clr.jit+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs -rc $(_BuildConfig) -lc Release extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml condition: >- or( @@ -364,7 +364,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono + nameSuffix: LibraryTests buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true timeoutInMinutes: 180 condition: >- @@ -404,7 +404,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_WasmBuildTests + nameSuffix: WasmBuildTests buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false timeoutInMinutes: 180 condition: >- @@ -442,7 +442,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_EAT + nameSuffix: LibraryTests_EAT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false timeoutInMinutes: 180 condition: >- @@ -484,7 +484,7 @@ jobs: value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] jobParameters: testGroup: innerloop - nameSuffix: AllSubsets_Mono_AOT + nameSuffix: LibraryTests_AOT buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true timeoutInMinutes: 180 condition: >- @@ -507,6 +507,43 @@ jobs: eq(variables['monoContainsChange'], true), eq(variables['isRollingBuild'], true)) +# +# Build the whole product using Mono and run runtime tests +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Browser_wasm + variables: + - ${{ if and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: pr/dotnet/runtime/$(Build.SourceBranch) + - ${{ if and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}: + - name: _HelixSource + value: ci/dotnet/runtime/$(Build.SourceBranch) + - name: timeoutPerTestInMinutes + value: 10 + - name: timeoutPerTestCollectionInMinutes + value: 200 + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono_RuntimeTests + buildArgs: -s mono+libs -c $(_BuildConfig) + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true), + eq(variables['isRollingBuild'], true)) + extraStepsTemplate: /eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + # Build and test libraries under single-file publishing - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -1073,8 +1110,7 @@ jobs: runtimeFlavor: mono platforms: - Linux_x64 - # Disabled pending outcome of https://github.com/dotnet/runtime/issues/60234 investigation - #- Linux_arm64 + - Linux_arm64 helixQueueGroup: pr helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: diff --git a/eng/targetingpacks.targets b/eng/targetingpacks.targets index 4213c84e709d9c..150ddf7401c9ea 100644 --- a/eng/targetingpacks.targets +++ b/eng/targetingpacks.targets @@ -43,13 +43,13 @@ RuntimeFrameworkName="$(LocalFrameworkOverrideName)" LatestRuntimeFrameworkVersion="$(ProductVersion)" RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.Mono.**RID**" - RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-loongarch64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;browser-wasm;ios-arm64;ios-arm;iossimulator-arm64;iossimulator-x64;iossimulator-x86;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" + RuntimePackRuntimeIdentifiers="linux-arm;linux-armv6;linux-arm64;linux-musl-arm64;linux-loongarch64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;browser-wasm;ios-arm64;ios-arm;iossimulator-arm64;iossimulator-x64;iossimulator-x86;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" RuntimePackLabels="Mono" Condition="'@(KnownRuntimePack)' == '' or !@(KnownRuntimePack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))"/> - - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs deleted file mode 100644 index dc2a0a05708c16..00000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** -** Represents address Kinds used with local variables, parameters, and -** fields. -** -** -===========================================================*/ -// Only statics, does not need to be marked with the serializable attribute - -namespace System.Diagnostics.SymbolStore -{ - internal enum SymAddressKind - { - // ILOffset: addr1 = IL local var or param index. - ILOffset = 1, - - // NativeRVA: addr1 = RVA into module. - NativeRVA = 2, - - // NativeRegister: addr1 = register the var is stored in. - NativeRegister = 3, - - // NativeRegisterRelative: addr1 = register, addr2 = offset. - NativeRegisterRelative = 4, - - // NativeOffset: addr1 = offset from start of parent. - NativeOffset = 5, - - // NativeRegisterRegister: addr1 = reg low, addr2 = reg high. - NativeRegisterRegister = 6, - - // NativeRegisterStack: addr1 = reg low, addr2 = reg stk, addr3 = offset. - NativeRegisterStack = 7, - - // NativeStackRegister: addr1 = reg stk, addr2 = offset, addr3 = reg high. - NativeStackRegister = 8, - - // BitField: addr1 = field start, addr = field length. - BitField = 9, - - // NativeSectionOffset: addr1 = section, addr = offset - NativeSectionOffset = 10, - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs deleted file mode 100644 index fbd9f7e4bc1ae9..00000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** Small value class used by the SymbolStore package for passing -** around metadata tokens. -** -===========================================================*/ - -using System.Diagnostics.CodeAnalysis; - -namespace System.Diagnostics.SymbolStore -{ - internal struct SymbolToken - { - internal int m_token; - - public SymbolToken(int val) { m_token = val; } - - public int GetToken() { return m_token; } - - public override int GetHashCode() { return m_token; } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is SymbolToken) - return Equals((SymbolToken)obj); - else - return false; - } - - public bool Equals(SymbolToken obj) - { - return obj.m_token == m_token; - } - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs index f45b3837abdd93..bfe5bcce8db998 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs @@ -11,18 +11,6 @@ namespace System.Reflection { public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable { - public AssemblyName(string assemblyName) - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - nInit(); - } - internal AssemblyName(string? name, byte[]? publicKey, byte[]? publicKeyToken, @@ -44,23 +32,6 @@ internal AssemblyName(string? name, _flags = flags; } - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern void nInit(); - - // This call opens and closes the file, but does not add the - // assembly to the domain. - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern AssemblyName nGetFileInformation(string s); - - internal static AssemblyName GetFileInformationCore(string assemblyFile) - { - string fullPath = Path.GetFullPath(assemblyFile); - return nGetFileInformation(fullPath); - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern byte[]? ComputePublicKeyToken(); - internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) { #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 70cd4fb988f088..9def7541aa4c6a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -314,14 +314,7 @@ public ModuleBuilder DefineDynamicModule(string name) private ModuleBuilder DefineDynamicModuleInternalNoLock(string name) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') { throw new ArgumentException(SR.Argument_InvalidName, nameof(name)); @@ -467,14 +460,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers /// The name of module for the look up. private ModuleBuilder? GetDynamicModuleNoLock(string name) { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); for (int i = 0; i < _assemblyData._moduleBuilderList.Count; i++) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs index e4c35c9dbbc034..c3e22c5d340719 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs @@ -20,17 +20,12 @@ public sealed class FieldBuilder : FieldInfo internal FieldBuilder(TypeBuilder typeBuilder, string fieldName, Type type, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, FieldAttributes attributes) { - if (fieldName == null) - throw new ArgumentNullException(nameof(fieldName)); - - if (fieldName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(fieldName)); + ArgumentException.ThrowIfNullOrEmpty(fieldName); if (fieldName[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(fieldName)); - if (type == null) - throw new ArgumentNullException(nameof(type)); + ArgumentNullException.ThrowIfNull(type); if (type == typeof(void)) throw new ArgumentException(SR.Argument_BadFieldType); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index 275cecbead57a6..1b35f5cdbb15f0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -1273,11 +1273,7 @@ public virtual void UsingNamespace(string usingNamespace) // Specifying the namespace to be used in evaluating locals and watches // for the current active lexical scope. - if (usingNamespace == null) - throw new ArgumentNullException(nameof(usingNamespace)); - - if (usingNamespace.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(usingNamespace)); + ArgumentException.ThrowIfNullOrEmpty(usingNamespace); MethodBuilder? methodBuilder = m_methodBuilder as MethodBuilder; if (methodBuilder == null) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs index 176f5a3fd37296..9d11aacaf53ea8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs @@ -61,24 +61,18 @@ internal MethodBuilder(string name, MethodAttributes attributes, CallingConventi Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers, ModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TypeBuilder type) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); - if (mod == null) - throw new ArgumentNullException(nameof(mod)); + ArgumentNullException.ThrowIfNull(mod); if (parameterTypes != null) { foreach (Type t in parameterTypes) { - if (t == null) - throw new ArgumentNullException(nameof(parameterTypes)); + ArgumentNullException.ThrowIfNull(t, nameof(parameterTypes)); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index fe5da8367cdd43..cbe0a7b39dde5b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -233,7 +233,7 @@ private int GetTypeRefNested(Type type, Module? refedModule, string? strRefedMod typeName = UnmangleTypeName(typeName); } - Debug.Assert(!type.IsByRef, "Must not be ByRef."); + Debug.Assert(!type.IsByRef, "Must not be ByRef. Get token from TypeSpec."); Debug.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments."); ModuleBuilder thisModule = this; @@ -948,14 +948,7 @@ private MethodBuilder DefineGlobalMethodNoLock(string name, MethodAttributes att { throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated); } - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); if ((attributes & MethodAttributes.Static) == 0) { throw new ArgumentException(SR.Argument_GlobalFunctionHasToBeStatic); @@ -1081,19 +1074,16 @@ private int GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition) // instructions. Tokens are always relative to the Module. For example, // the token value for System.String is likely to be different from // Module to Module. Calling GetTypeToken will cause a reference to be - // added to the Module. This reference becomes a perminate part of the Module, - // multiple calles to this method with the same class have no additional side affects. - // This function is optimized to use the TypeDef token if Type is within the same module. - // We should also be aware of multiple dynamic modules and multiple implementation of Type!!! - if (type.IsByRef) - { - throw new ArgumentException(SR.Argument_CannotGetTypeTokenForByRef); - } - - if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) || - type.IsGenericParameter || - type.IsArray || - type.IsPointer) + // added to the Module. This reference becomes a permanent part of the Module, + // multiple calls to this method with the same class have no additional side-effects. + // This function is optimized to use the TypeDef token if the Type is within the + // same module. We should also be aware of multiple dynamic modules and multiple + // implementations of a Type. + if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) + || type.IsGenericParameter + || type.IsArray + || type.IsPointer + || type.IsByRef) { byte[] sig = SignatureHelper.GetTypeSigToken(this, type).InternalGetSignature(out int length); return GetTokenFromTypeSpec(sig, length); @@ -1355,18 +1345,8 @@ internal int GetArrayMethodToken(Type arrayClass, string methodName, CallingConv private int GetArrayMethodTokenNoLock(Type arrayClass, string methodName, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes) { - if (arrayClass == null) - { - throw new ArgumentNullException(nameof(arrayClass)); - } - if (methodName == null) - { - throw new ArgumentNullException(nameof(methodName)); - } - if (methodName.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyName, nameof(methodName)); - } + ArgumentNullException.ThrowIfNull(arrayClass); + ArgumentException.ThrowIfNullOrEmpty(methodName); if (!arrayClass.IsArray) { throw new ArgumentException(SR.Argument_HasToBeArrayClass); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs index ae6e704b2a5c87..89accc39caeb98 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs @@ -34,10 +34,7 @@ internal PropertyBuilder( int prToken, // the metadata token for this property TypeBuilder containingType) // the containing type { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs index 6d9b8121fa6b42..ad80acad078350 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs @@ -480,11 +480,7 @@ internal TypeBuilder( string fullname, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, ModuleBuilder module, PackingSize iPackingSize, int iTypeSize, TypeBuilder? enclosingType) { - if (fullname == null) - throw new ArgumentNullException(nameof(fullname)); - - if (fullname.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(fullname)); + ArgumentException.ThrowIfNullOrEmpty(fullname); if (fullname[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(fullname)); @@ -581,11 +577,7 @@ private FieldBuilder DefineDataHelper(string name, byte[]? data, int size, Field FieldBuilder fdBuilder; TypeAttributes typeAttributes; - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (size <= 0 || size >= 0x003f0000) throw new ArgumentException(SR.Argument_BadSizeForData); @@ -1282,11 +1274,7 @@ private MethodBuilder DefineMethodNoLock(string name, MethodAttributes attribute Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); AssemblyBuilder.CheckContext(returnType); AssemblyBuilder.CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes); @@ -1374,23 +1362,9 @@ private MethodBuilder DefinePInvokeMethodHelper( lock (SyncRoot) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); - - if (dllName == null) - throw new ArgumentNullException(nameof(dllName)); - - if (dllName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(dllName)); - - if (importName == null) - throw new ArgumentNullException(nameof(importName)); - - if (importName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(importName)); + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(dllName); + ArgumentException.ThrowIfNullOrEmpty(importName); if ((attributes & MethodAttributes.Abstract) != 0) throw new ArgumentException(SR.Argument_BadPInvokeMethod); @@ -1792,10 +1766,7 @@ private PropertyBuilder DefinePropertyNoLock(string name, PropertyAttributes att Type returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); AssemblyBuilder.CheckContext(returnType); AssemblyBuilder.CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes); @@ -1847,10 +1818,7 @@ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type ev private EventBuilder DefineEventNoLock(string name, EventAttributes attributes, Type eventtype) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); if (name[0] == '\0') throw new ArgumentException(SR.Argument_IllegalName, nameof(name)); @@ -1922,7 +1890,9 @@ private EventBuilder DefineEventNoLock(string name, EventAttributes attributes, int tkParent = 0; if (m_typeParent != null) + { tkParent = m_module.GetTypeTokenInternal(m_typeParent); + } ModuleBuilder module = m_module; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index 9368fc25d340b8..cdc15dc8fb6e08 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -194,7 +194,9 @@ public int this[int index] } } +#pragma warning disable CA1066 // IEquatable interface implementation isn't used internal readonly struct MetadataImport +#pragma warning restore CA1067 { private readonly IntPtr m_metadataImport2; private readonly object? m_keepalive; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 977d73e5c3b990..3708e71cb4510b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -558,8 +558,7 @@ private static partial void GetTypeByName(string name, bool throwOnError, bool i internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule scope) { - if (string.IsNullOrEmpty(name)) - throw new ArgumentException(null, nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); RuntimeType? type = null; GetTypeByNameUsingCARules(name, new QCallModule(ref scope), ObjectHandleOnStack.Create(ref type)); @@ -1246,7 +1245,7 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) } } - public unsafe partial struct ModuleHandle + public unsafe partial struct ModuleHandle : IEquatable { #region Public Static Members public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index a0d7026b544078..bf83df6c0f9751 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -1941,7 +1941,7 @@ private static PropertyInfo GetPropertyInfo(RuntimeType reflectedType, int tkPro } Debug.Fail("Unreachable code"); - throw new SystemException(); + throw new UnreachableException(); } internal static void ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception? e) diff --git a/src/coreclr/binder/inc/assemblyidentity.hpp b/src/coreclr/binder/inc/assemblyidentity.hpp index cc0916c8780afa..ef4768d3b8cd9b 100644 --- a/src/coreclr/binder/inc/assemblyidentity.hpp +++ b/src/coreclr/binder/inc/assemblyidentity.hpp @@ -30,12 +30,9 @@ namespace BINDER_SPACE IDENTITY_FLAG_PUBLIC_KEY_TOKEN = 0x004, IDENTITY_FLAG_PUBLIC_KEY = 0x008, IDENTITY_FLAG_CULTURE = 0x010, - IDENTITY_FLAG_LANGUAGE = 0x020, IDENTITY_FLAG_PROCESSOR_ARCHITECTURE = 0x040, IDENTITY_FLAG_RETARGETABLE = 0x080, IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL = 0x100, - IDENTITY_FLAG_CUSTOM = 0x200, - IDENTITY_FLAG_CUSTOM_NULL = 0x400, IDENTITY_FLAG_CONTENT_TYPE = 0x800, IDENTITY_FLAG_FULL_NAME = (IDENTITY_FLAG_SIMPLE_NAME | IDENTITY_FLAG_VERSION) @@ -50,7 +47,6 @@ namespace BINDER_SPACE // Need to pre-populate SBuffers because of bogus asserts static const BYTE byteArr[] = { 0 }; m_publicKeyOrTokenBLOB.SetImmutable(byteArr, sizeof(byteArr)); - m_customBLOB.SetImmutable(byteArr, sizeof(byteArr)); } ~AssemblyIdentity() { @@ -83,7 +79,6 @@ namespace BINDER_SPACE SBuffer m_publicKeyOrTokenBLOB; PEKIND m_kProcessorArchitecture; AssemblyContentType m_kContentType; - SBuffer m_customBLOB; DWORD m_dwIdentityFlags; }; diff --git a/src/coreclr/binder/inc/stringlexer.hpp b/src/coreclr/binder/inc/stringlexer.hpp index 41af7e7baa18d7..f08e046982c566 100644 --- a/src/coreclr/binder/inc/stringlexer.hpp +++ b/src/coreclr/binder/inc/stringlexer.hpp @@ -55,32 +55,28 @@ namespace BINDER_SPACE inline StringLexer(); inline ~StringLexer(); - inline void Init(SString &inputString, BOOL fSupportEscaping); + inline void Init(SString &inputString); static inline BOOL IsWhitespace(WCHAR wcChar); static inline BOOL IsEOS(WCHAR wcChar); static inline BOOL IsQuoteCharacter(WCHAR wcChar); - virtual BOOL IsSeparatorChar(WCHAR wcChar) = NULL; - virtual LEXEME_TYPE GetLexemeType(WCHAR wcChar) = NULL; + BOOL IsSeparatorChar(WCHAR wcChar); + LEXEME_TYPE GetLexemeType(WCHAR wcChar); protected: static const WCHAR INVALID_CHARACTER = -1; - LEXEME_TYPE GetNextLexeme(SString ¤tString, BOOL fPermitUnescapedQuotes = FALSE); + LEXEME_TYPE GetNextLexeme(SString ¤tString); inline WCHAR PopCharacter(BOOL *pfIsEscaped); inline void PushCharacter(WCHAR wcCurrentChar, BOOL fIsEscaped); inline WCHAR GetRawCharacter(); - inline void PushRawCharacter(); - inline WCHAR DecodeUTF16Character(); inline WCHAR GetNextCharacter(BOOL *pfIsEscaped); - inline WCHAR ParseUnicode(); - LEXEME_TYPE ParseString(SString ¤tString, - BOOL fPermitUnescapeQuotes); + LEXEME_TYPE ParseString(SString ¤tString); void TrimTrailingWhiteSpaces(SString ¤tString); @@ -89,8 +85,6 @@ namespace BINDER_SPACE WCHAR m_wcCurrentChar; BOOL m_fCurrentCharIsEscaped; - BOOL m_fSupportEscaping; - BOOL m_fReadRawCharacter; }; #include "stringlexer.inl" diff --git a/src/coreclr/binder/inc/stringlexer.inl b/src/coreclr/binder/inc/stringlexer.inl index bfe4bddeaa4c18..42f7f73ed0bbc2 100644 --- a/src/coreclr/binder/inc/stringlexer.inl +++ b/src/coreclr/binder/inc/stringlexer.inl @@ -25,12 +25,10 @@ StringLexer::~StringLexer() // Nothing to do here } -void StringLexer::Init(SString &inputString, BOOL fSupportEscaping) +void StringLexer::Init(SString &inputString) { m_cursor = inputString.Begin(); m_end = inputString.End(); - m_fSupportEscaping = fSupportEscaping; - m_fReadRawCharacter = FALSE; } BOOL StringLexer::IsWhitespace(WCHAR wcChar) @@ -55,6 +53,7 @@ WCHAR StringLexer::PopCharacter(BOOL *pfIsEscaped) { m_wcCurrentChar = INVALID_CHARACTER; *pfIsEscaped = m_fCurrentCharIsEscaped; + m_cursor++; } else { @@ -71,172 +70,63 @@ void StringLexer::PushCharacter(WCHAR wcCurrentChar, m_wcCurrentChar = wcCurrentChar; m_fCurrentCharIsEscaped = fIsEscaped; + m_cursor--; } WCHAR StringLexer::GetRawCharacter() { WCHAR wcCurrentChar = 0; - if (m_cursor <= m_end) + if (m_cursor < m_end) { wcCurrentChar = m_cursor[0]; - m_fReadRawCharacter = TRUE; m_cursor++; - } - else - { - m_fReadRawCharacter = FALSE; - } - - return wcCurrentChar; -} - -void StringLexer::PushRawCharacter() -{ - if (m_fReadRawCharacter) - { - m_cursor--; - m_fReadRawCharacter = FALSE; - } -} -WCHAR StringLexer::DecodeUTF16Character() -{ - // See http://www.ietf.org/rfc/rfc2781.txt for details on UTF-16 encoding. - - WCHAR wcCurrentChar = 0; - SCOUNT_T nCharacters = m_end - m_cursor + 1; - WCHAR wcChar1 = GetRawCharacter(); - - if (wcChar1 < 0xd800) - { - wcCurrentChar = wcChar1; + // do not allow \0 anywhere in the string. + if (wcCurrentChar == 0) + { + wcCurrentChar = INVALID_CHARACTER; + } } else { - // StringLexer is not designed to handle UTF-16 characters beyond the Basic Multilingual Plane, - // since it stores all characters in 16-bit WCHARs. - // However, since the vast majority of the time, we (Microsoft) produce the manifests, - // this is likely a non-scenario, as the other Unicode planes would never be used in practice. - - if (wcChar1 <= 0xdbff) // 0xd800 - 0xdbff indicates the first WCHAR of a surrogate pair - { - if (nCharacters >= 2) - { - GetRawCharacter(); // Skip the second WCHAR of the surrogate pair - } - } - // Otherwise, the character is either in the 0xdc00 - 0xdfff range, indicating the second WCHAR of a surrogate pair, - // or in the 0xE000 - 0xFFFF range, which has within it ranges of invalid characters, and which we conservatively treat - // as invalid. - - wcCurrentChar = INVALID_CHARACTER; + // EOS + wcCurrentChar = 0; } return wcCurrentChar; } - WCHAR StringLexer::GetNextCharacter(BOOL *pfIsEscaped) { *pfIsEscaped = FALSE; - WCHAR wcCurrentChar = GetRawCharacter(); // DecodeUTF16Character() + WCHAR wcCurrentChar = GetRawCharacter(); if (wcCurrentChar == L'\\') { - WCHAR wcTempChar = GetRawCharacter(); // DecodeUTF16Character() + WCHAR wcTempChar = GetRawCharacter(); - if (m_fSupportEscaping) - { - // Handle standard escapes - switch (wcTempChar) - { - case L'"': - case L'\'': - case L',': - case L'\\': - case L'/': - case L'=': - break; - case L't': - wcTempChar = 9; - break; - case L'n': - wcTempChar = 10; - break; - case L'r': - wcTempChar = 13; - break; - case L'u': - wcTempChar = ParseUnicode(); - break; - default: - return INVALID_CHARACTER; - } - - *pfIsEscaped = TRUE; - wcCurrentChar = wcTempChar; - } - else - { - // Do not handle escapes except for quotes - switch (wcTempChar) - { - case L'"': - case L'\'': - *pfIsEscaped = TRUE; - wcCurrentChar = wcTempChar; - break; - default: - PushRawCharacter(); - break; - } - } - } - - return wcCurrentChar; -} - -WCHAR StringLexer::ParseUnicode() -{ - int nCharacters = 0; - WCHAR wcUnicodeChar = 0; - - for(;;) - { - WCHAR wcCurrentChar = DecodeUTF16Character(); - nCharacters++; - - if (wcCurrentChar == L';') + // Handle standard escapes + switch (wcTempChar) { + case L'"': + case L'\'': + case L',': + case L'\\': + case L'=': + case L't': + case L'n': + case L'r': break; - } - else if ((wcCurrentChar == INVALID_CHARACTER) || (nCharacters >= 9)) - { + default: return INVALID_CHARACTER; } - wcUnicodeChar <<= 4; - - if ((wcCurrentChar >= L'0') && (wcCurrentChar <= L'9')) - { - wcUnicodeChar += (wcCurrentChar - L'0'); - } - else if ((wcCurrentChar >= L'a') && (wcCurrentChar <= L'f')) - { - wcUnicodeChar += (wcCurrentChar - L'a') + 10; - } - else if ((wcCurrentChar >= L'A') && (wcCurrentChar <= L'F')) - { - wcUnicodeChar += (wcCurrentChar - L'A') + 10; - } - else - { - return INVALID_CHARACTER; - } + *pfIsEscaped = TRUE; + wcCurrentChar = wcTempChar; } - return wcUnicodeChar; + return wcCurrentChar; } #endif diff --git a/src/coreclr/binder/inc/textualidentityparser.hpp b/src/coreclr/binder/inc/textualidentityparser.hpp index a5187d254a6522..2b60c3110f37f7 100644 --- a/src/coreclr/binder/inc/textualidentityparser.hpp +++ b/src/coreclr/binder/inc/textualidentityparser.hpp @@ -28,12 +28,9 @@ namespace BINDER_SPACE TextualIdentityParser(AssemblyIdentity *pAssemblyIdentity); ~TextualIdentityParser(); - virtual BOOL IsSeparatorChar(WCHAR wcChar); - virtual StringLexer::LEXEME_TYPE GetLexemeType(WCHAR wcChar); - static HRESULT Parse(/* in */ SString &textualIdentity, - /* out */ AssemblyIdentity *pAssemblyIdentity, - /* in */ BOOL fPermitUnescapedQuotes = FALSE); + /* out */ AssemblyIdentity *pAssemblyIdentity); + static HRESULT ToString(/* in */ AssemblyIdentity *pAssemblyIdentity, /* in */ DWORD dwIdentityFlags, /* out */ SString &textualIdentity); @@ -45,6 +42,7 @@ namespace BINDER_SPACE /* in */ BOOL fValidateHex, /* in */ BOOL fIsToken, /* out */ SBuffer &publicKeyOrTokenBLOB); + static void BlobToHex(/* in */ SBuffer &publicKeyOrTokenBLOB, /* out */ SString &publicKeyOrToken); @@ -52,8 +50,7 @@ namespace BINDER_SPACE /* out */ SString &contentString); protected: - BOOL Parse(/* in */ SString &textualIdentity, - /* in */ BOOL fPermitUnescapedQuotes = FALSE); + BOOL Parse(/* in */ SString &textualIdentity); BOOL PopulateAssemblyIdentity(/* in */ SString &attributeString, /* in */ SString &valueString); diff --git a/src/coreclr/binder/stringlexer.cpp b/src/coreclr/binder/stringlexer.cpp index b6b722fa77ab9f..44ec23e3b517cd 100644 --- a/src/coreclr/binder/stringlexer.cpp +++ b/src/coreclr/binder/stringlexer.cpp @@ -19,7 +19,7 @@ namespace BINDER_SPACE { StringLexer::LEXEME_TYPE - StringLexer::GetNextLexeme(SString ¤tString, BOOL fPermitUnescapedQuotes) + StringLexer::GetNextLexeme(SString ¤tString) { BOOL fIsEscaped = FALSE; WCHAR wcCurrentChar = INVALID_CHARACTER; @@ -43,11 +43,11 @@ namespace BINDER_SPACE // First character of string lexeme; push it back PushCharacter(wcCurrentChar, fIsEscaped); - return ParseString(currentString, fPermitUnescapedQuotes); + return ParseString(currentString); } StringLexer::LEXEME_TYPE - StringLexer::ParseString(SString ¤tString, BOOL fPermitUnescapedQuotes) + StringLexer::ParseString(SString ¤tString) { BOOL fIsFirstCharacter = TRUE; WCHAR wcCurrentChar = INVALID_CHARACTER; @@ -99,7 +99,7 @@ namespace BINDER_SPACE break; } - if (!fPermitUnescapedQuotes && !fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote)) + if (!fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote)) { // Unescaped quotes in the middle of the string are an error return LEXEME_TYPE_INVALID; @@ -147,4 +147,24 @@ namespace BINDER_SPACE currentString.Truncate(cursor + 1); } } + + BOOL StringLexer::IsSeparatorChar(WCHAR wcChar) + { + return ((wcChar == W(',')) || (wcChar == W('='))); + } + + StringLexer::LEXEME_TYPE StringLexer::GetLexemeType(WCHAR wcChar) + { + switch (wcChar) + { + case W('='): + return LEXEME_TYPE_EQUALS; + case W(','): + return LEXEME_TYPE_COMMA; + case 0: + return LEXEME_TYPE_END_OF_STREAM; + default: + return LEXEME_TYPE_STRING; + } + } }; diff --git a/src/coreclr/binder/textualidentityparser.cpp b/src/coreclr/binder/textualidentityparser.cpp index f69e0bf66b202b..35587df3cb7e4d 100644 --- a/src/coreclr/binder/textualidentityparser.cpp +++ b/src/coreclr/binder/textualidentityparser.cpp @@ -200,30 +200,9 @@ namespace BINDER_SPACE // Nothing to do here } - BOOL TextualIdentityParser::IsSeparatorChar(WCHAR wcChar) - { - return ((wcChar == W(',')) || (wcChar == W('='))); - } - - StringLexer::LEXEME_TYPE TextualIdentityParser::GetLexemeType(WCHAR wcChar) - { - switch (wcChar) - { - case W('='): - return LEXEME_TYPE_EQUALS; - case W(','): - return LEXEME_TYPE_COMMA; - case 0: - return LEXEME_TYPE_END_OF_STREAM; - default: - return LEXEME_TYPE_STRING; - } - } - /* static */ HRESULT TextualIdentityParser::Parse(SString &textualIdentity, - AssemblyIdentity *pAssemblyIdentity, - BOOL fPermitUnescapedQuotes) + AssemblyIdentity *pAssemblyIdentity) { HRESULT hr = S_OK; @@ -233,7 +212,7 @@ namespace BINDER_SPACE { TextualIdentityParser identityParser(pAssemblyIdentity); - if (!identityParser.Parse(textualIdentity, fPermitUnescapedQuotes)) + if (!identityParser.Parse(textualIdentity)) { IF_FAIL_GO(FUSION_E_INVALID_NAME); } @@ -335,18 +314,6 @@ namespace BINDER_SPACE textualIdentity.Append(ContentTypeToString(pAssemblyIdentity->m_kContentType)); } - if (AssemblyIdentity::Have(dwIdentityFlags, AssemblyIdentity::IDENTITY_FLAG_CUSTOM)) - { - textualIdentity.Append(W(", Custom=")); - tmpString.Clear(); - BlobToHex(pAssemblyIdentity->m_customBLOB, tmpString); - textualIdentity.Append(tmpString); - } - else if (AssemblyIdentity::Have(dwIdentityFlags, - AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL)) - { - textualIdentity.Append(W(", Custom=null")); - } } EX_CATCH_HRESULT(hr); @@ -486,19 +453,19 @@ namespace BINDER_SPACE publicKeyOrToken.CloseBuffer(cbPublicKeyOrTokenBLOB * 2); } - BOOL TextualIdentityParser::Parse(SString &textualIdentity, BOOL fPermitUnescapedQuotes) + BOOL TextualIdentityParser::Parse(SString &textualIdentity) { BOOL fIsValid = TRUE; SString unicodeTextualIdentity; // Lexer modifies input string textualIdentity.ConvertToUnicode(unicodeTextualIdentity); - Init(unicodeTextualIdentity, TRUE /* fSupportEscaping */); + Init(unicodeTextualIdentity); SmallStackSString currentString; // Identity format is simple name (, attr = value)* - GO_IF_NOT_EXPECTED(GetNextLexeme(currentString, fPermitUnescapedQuotes), LEXEME_TYPE_STRING); + GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING); m_pAssemblyIdentity->m_simpleName.Set(currentString); m_pAssemblyIdentity->m_simpleName.Normalize(); m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_SIMPLE_NAME); @@ -532,7 +499,7 @@ namespace BINDER_SPACE // Lexer modifies input string textualString.ConvertToUnicode(unicodeTextualString); - Init(unicodeTextualString, TRUE /* fSupportEscaping */); + Init(unicodeTextualString); SmallStackSString currentString; GO_IF_NOT_EXPECTED(GetNextLexeme(currentString), LEXEME_TYPE_STRING); @@ -549,8 +516,7 @@ namespace BINDER_SPACE { BOOL fIsValid = TRUE; - if (EqualsCaseInsensitive(attributeString, W("culture")) || - EqualsCaseInsensitive(attributeString, W("language"))) + if (EqualsCaseInsensitive(attributeString, W("culture"))) { GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CULTURE); GO_IF_WILDCARD(valueString); @@ -586,8 +552,7 @@ namespace BINDER_SPACE GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); GO_IF_WILDCARD(valueString); - if (!EqualsCaseInsensitive(valueString, W("null")) && - !EqualsCaseInsensitive(valueString, W("neutral"))) + if (!EqualsCaseInsensitive(valueString, W("null"))) { GO_IF_VALIDATE_FAILED(ValidatePublicKeyToken, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); @@ -606,8 +571,7 @@ namespace BINDER_SPACE GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY_TOKEN); GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY); - if (!EqualsCaseInsensitive(valueString, W("null")) && - !EqualsCaseInsensitive(valueString, W("neutral"))) + if (!EqualsCaseInsensitive(valueString, W("null"))) { GO_IF_VALIDATE_FAILED(ValidatePublicKey, AssemblyIdentity::IDENTITY_FLAG_PUBLIC_KEY); HexToBlob(valueString, @@ -661,23 +625,6 @@ namespace BINDER_SPACE fIsValid = FALSE; } } - else if (EqualsCaseInsensitive(attributeString, W("custom"))) - { - GO_IF_SEEN(AssemblyIdentity::IDENTITY_FLAG_CUSTOM); - - if (EqualsCaseInsensitive(valueString, W("null"))) - { - m_pAssemblyIdentity->SetHave(AssemblyIdentity::IDENTITY_FLAG_CUSTOM_NULL); - } - else - { - GO_IF_VALIDATE_FAILED(ValidateHex, AssemblyIdentity::IDENTITY_FLAG_CUSTOM); - HexToBlob(valueString, - FALSE /* fValidateHex */, - FALSE /* fIsToken */, - m_pAssemblyIdentity->m_customBLOB); - } - } Exit: return fIsValid; diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index d5fc9f5e1ee8e5..533d5255002b49 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -92,7 +92,6 @@ endif(CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_BASICFREEZE) add_definitions(-DFEATURE_CORECLR) -add_definitions(-DFEATURE_CORESYSTEM) if(FEATURE_DBGIPC) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_DI) add_definitions(-DFEATURE_DBGIPC_TRANSPORT_VM) diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 9aaf6e6e4cb171..7936b3a1279a8c 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -6542,61 +6542,6 @@ bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEAssembly *pPEAssembly, return true; } -#if defined(FEATURE_CORESYSTEM) -/* static */ -// We extract "ni.dll from the NGEN image name to obtain the IL image name. -// In the end we add given ilExtension. -// This dependecy is based on Apollo installer behavior. -bool ClrDataAccess::GetILImageNameFromNgenImage( LPCWSTR ilExtension, - _Out_writes_(cchFilePath) LPWSTR wszFilePath, - const DWORD cchFilePath) -{ - if (wszFilePath == NULL || cchFilePath == 0) - { - return false; - } - - _wcslwr_s(wszFilePath, cchFilePath); - // Find the "ni.dll" extension. - // If none exists use NGEN image name. - // - const WCHAR* ngenExtension = W("ni.dll"); - - if (wcslen(ilExtension) <= wcslen(ngenExtension)) - { - LPWSTR wszFileExtension = wcsstr(wszFilePath, ngenExtension); - if (wszFileExtension != 0) - { - LPWSTR wszNextFileExtension = wszFileExtension; - // Find last occurrence - do - { - wszFileExtension = wszNextFileExtension; - wszNextFileExtension = wcsstr(wszFileExtension + 1, ngenExtension); - } while (wszNextFileExtension != 0); - - // Overwrite ni.dll with ilExtension - if (!memcpy_s(wszFileExtension, - wcslen(ngenExtension)*sizeof(WCHAR), - ilExtension, - wcslen(ilExtension)*sizeof(WCHAR))) - { - wszFileExtension[wcslen(ilExtension)] = '\0'; - return true; - } - } - } - - //Use ngen filename if there is no ".ni" - if (wcsstr(wszFilePath, W(".ni")) == 0) - { - return true; - } - - return false; -} -#endif // FEATURE_CORESYSTEM - void * ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, bool* isAlternate) @@ -6705,7 +6650,6 @@ ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, goto ErrExit; } -#if defined(FEATURE_CORESYSTEM) const WCHAR* ilExtension = W("dll"); WCHAR ngenImageName[MAX_LONGPATH] = {0}; if (wcscpy_s(ngenImageName, ARRAY_SIZE(ngenImageName), uniPath) != 0) @@ -6716,12 +6660,6 @@ ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, { goto ErrExit; } - // Transform NGEN image name into IL Image name - if (!GetILImageNameFromNgenImage(ilExtension, uniPath, ARRAY_SIZE(uniPath))) - { - goto ErrExit; - } -#endif//FEATURE_CORESYSTEM // RVA size in ngen image and IL image is the same. Because the only // different is in RVA. That is 4 bytes column fixed. @@ -6943,11 +6881,6 @@ bool ClrDataAccess::TargetConsistencyAssertsEnabled() return m_fEnableTargetConsistencyAsserts; } -#ifdef FEATURE_CORESYSTEM -#define ctime_s _ctime32_s -#define time_t __time32_t -#endif - // // VerifyDlls - Validate that the mscorwks in the target matches this version of mscordacwks // Only done on Windows and Mac builds at the moment. @@ -7503,34 +7436,8 @@ BOOL OutOfProcessExceptionEventGetProcessIdAndThreadId(HANDLE hProcess, HANDLE h *pPId = (DWORD)(SIZE_T)hProcess; *pThreadId = (DWORD)(SIZE_T)hThread; #else -#if !defined(FEATURE_CORESYSTEM) - HMODULE hKernel32 = WszGetModuleHandle(W("kernel32.dll")); -#else - HMODULE hKernel32 = WszGetModuleHandle(W("api-ms-win-core-processthreads-l1-1-1.dll")); -#endif - if (hKernel32 == NULL) - { - return FALSE; - } - - typedef WINBASEAPI DWORD (WINAPI GET_PROCESSID_OF_THREAD)(HANDLE); - GET_PROCESSID_OF_THREAD * pGetProcessIdOfThread; - - typedef WINBASEAPI DWORD (WINAPI GET_THREADID)(HANDLE); - GET_THREADID * pGetThreadId; - - pGetProcessIdOfThread = (GET_PROCESSID_OF_THREAD *)GetProcAddress(hKernel32, "GetProcessIdOfThread"); - pGetThreadId = (GET_THREADID *)GetProcAddress(hKernel32, "GetThreadId"); - - // OOP callbacks are used on Win7 or later. We should have having below two APIs available. - _ASSERTE((pGetProcessIdOfThread != NULL) && (pGetThreadId != NULL)); - if ((pGetProcessIdOfThread == NULL) || (pGetThreadId == NULL)) - { - return FALSE; - } - - *pPId = (*pGetProcessIdOfThread)(hThread); - *pThreadId = (*pGetThreadId)(hThread); + *pPId = GetProcessIdOfThread(hThread); + *pThreadId = GetThreadId(hThread); #endif // TARGET_UNIX return TRUE; } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 4efcd8a8323b4f..1ff143cf7cce16 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -657,21 +657,21 @@ void DacDbiInterfaceImpl::GetAppDomainFullName( // Get the values of the JIT Optimization and EnC flags. void DacDbiInterfaceImpl::GetCompilerFlags ( - VMPTR_DomainFile vmDomainFile, + VMPTR_DomainAssembly vmDomainAssembly, BOOL *pfAllowJITOpts, BOOL *pfEnableEnC) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - if (pDomainFile == NULL) + if (pDomainAssembly == NULL) { ThrowHR(E_FAIL); } // Get the underlying module - none of this is AppDomain specific - Module * pModule = pDomainFile->GetModule(); + Module * pModule = pDomainAssembly->GetModule(); DWORD dwBits = pModule->GetDebuggerInfoBits(); *pfAllowJITOpts = !CORDisableJITOptimizations(dwBits); *pfEnableEnC = pModule->IsEditAndContinueEnabled(); @@ -712,15 +712,15 @@ bool DacDbiInterfaceImpl::CanSetEnCBits(Module * pModule) } // DacDbiInterfaceImpl::SetEnCBits // Set the values of the JIT optimization and EnC flags. -HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainFile vmDomainFile, +HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC) { DD_ENTER_MAY_THROW; DWORD dwBits = 0; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); HRESULT hr = S_OK; @@ -1082,15 +1082,15 @@ ULONG DacDbiInterfaceImpl::TranslateInstrumentedILOffsetToOriginal(ULONG // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // -void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, TargetBuffer * pCodeInfo, mdToken * pLocalSigToken) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); RVA methodRVA = 0; DWORD implFlags; @@ -1323,7 +1323,7 @@ void DacDbiInterfaceImpl::GetMethodRegionInfo(MethodDesc * pMethodDe // isn't currently available. In this case, all values in pCodeInfo will be // cleared. -void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, NativeCodeFunctionData * pCodeInfo) { @@ -1334,8 +1334,8 @@ void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainFile vmDomainFil // pre-initialize: pCodeInfo->Clear(); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); MethodDesc* pMethodDesc = FindLoadedMethodRefOrDef(pModule, functionToken); pCodeInfo->vmNativeCodeMethodDescToken.SetHostPtr(pMethodDesc); @@ -1760,7 +1760,7 @@ void DacDbiInterfaceImpl::GetClassInfo(VMPTR_AppDomain vmAppDomain, } // DacDbiInterfaceImpl::GetClassInfo // DacDbi API: Get field information and object size for an instantiated generic type -void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, +void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, DacDbiArrayList * pFieldList, @@ -1768,9 +1768,9 @@ void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainFile { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - _ASSERTE(pDomainFile != NULL); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + _ASSERTE(pDomainAssembly != NULL); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); TypeHandle thExact; TypeHandle thApprox; @@ -2503,11 +2503,11 @@ void DacDbiInterfaceImpl::GetClassTypeInfo(TypeHandle typeH pTypeInfo->ClassTypeData.vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule)); if (pAppDomain) { - pTypeInfo->ClassTypeData.vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile())); + pTypeInfo->ClassTypeData.vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainAssembly())); } else { - pTypeInfo->ClassTypeData.vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->ClassTypeData.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); } } // DacDbiInterfaceImpl::GetClassTypeInfo @@ -2567,7 +2567,7 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle case ELEMENT_TYPE_BYREF: pTypeInfo->vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); pTypeInfo->metadataToken = mdTokenNil; - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); break; case ELEMENT_TYPE_CLASS: @@ -2590,11 +2590,11 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle pTypeInfo->vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule)); if (pAppDomain) { - pTypeInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile())); + pTypeInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainAssembly())); } else { - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); } break; } @@ -2602,7 +2602,7 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle default: pTypeInfo->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); pTypeInfo->metadataToken = mdTokenNil; - pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr(); + pTypeInfo->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); break; } return; @@ -2889,8 +2889,8 @@ TypeHandle DacDbiInterfaceImpl::GetClassOrValueTypeHandle(DebuggerIPCE_BasicType // otherwise, have the loader look it up using the metadata token and domain file else { - DomainFile * pDomainFile = pData->vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pData->vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, pData->metadataToken); if (typeHandle.IsNull()) @@ -3292,7 +3292,7 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, CorElementType simpleType, mdTypeDef *pMetadataToken, VMPTR_Module *pVmModule, - VMPTR_DomainFile *pVmDomainFile) + VMPTR_DomainAssembly *pVmDomainAssembly) { DD_ENTER_MAY_THROW; @@ -3300,8 +3300,8 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, // if we fail to get either a valid type handle or module, we will want to send back // a NULL domain file too, so we'll to preinitialize this here. - _ASSERTE(pVmDomainFile != NULL); - *pVmDomainFile = VMPTR_DomainFile::NullPtr(); + _ASSERTE(pVmDomainAssembly != NULL); + *pVmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); // FindLoadedElementType will return NULL if the type hasn't been loaded yet. TypeHandle typeHandle = FindLoadedElementType(simpleType); @@ -3322,8 +3322,8 @@ void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, if (pAppDomain) { - pVmDomainFile->SetHostPtr(pModule->GetDomainFile()); - if (pVmDomainFile->IsNull()) + pVmDomainAssembly->SetHostPtr(pModule->GetDomainAssembly()); + if (pVmDomainAssembly->IsNull()) ThrowHR(CORDBG_E_TARGET_INCONSISTENT); } } @@ -3483,7 +3483,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateType(VMPTR_Object delegateObject, Delega HRESULT DacDbiInterfaceImpl::GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef) { DD_ENTER_MAY_THROW; @@ -3514,7 +3514,7 @@ HRESULT DacDbiInterfaceImpl::GetDelegateFunctionData( if (hr != S_OK) return hr; - ppFunctionDomainFile->SetDacTargetPtr(dac_cast(pMD.GetDacPtr()->GetModule()->GetDomainFile())); + ppFunctionDomainAssembly->SetDacTargetPtr(dac_cast(pMD.GetDacPtr()->GetModule()->GetDomainAssembly())); *pMethodDef = pMD.GetDacPtr()->GetMemberDef(); return hr; @@ -3725,17 +3725,17 @@ void DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, Dac BaseDomain* pBaseDomain = currentElement.pFunc->GetAssembly()->GetDomain(); AppDomain* pDomain = NULL; - DomainFile* pDomainFile = NULL; + DomainAssembly* pDomainAssembly = NULL; pDomain = pBaseDomain->AsAppDomain(); _ASSERTE(pDomain != NULL); - pDomainFile = pModule->GetDomainFile(); - _ASSERTE(pDomainFile != NULL); + pDomainAssembly = pModule->GetDomainAssembly(); + _ASSERTE(pDomainAssembly != NULL); currentFrame.vmAppDomain.SetHostPtr(pDomain); - currentFrame.vmDomainFile.SetHostPtr(pDomainFile); + currentFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); currentFrame.ip = currentElement.ip; currentFrame.methodDef = currentElement.pFunc->GetMemberDef(); currentFrame.isLastForeignExceptionFrame = (currentElement.flags & STEF_LAST_FRAME_FROM_FOREIGN_STACK_TRACE) != 0; @@ -3879,8 +3879,8 @@ FieldDesc * DacDbiInterfaceImpl::GetEnCFieldDesc(const EnCHangingFieldInfo * pEn { FieldDesc * pFD = NULL; - DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pEnCFieldInfo->GetObjectTypeData().vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); // get the type handle for the object TypeHandle typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, @@ -3918,8 +3918,8 @@ PTR_CBYTE DacDbiInterfaceImpl::GetPtrToEnCField(FieldDesc * pFD, const EnCHangin #else PTR_EditAndContinueModule pEnCModule; - DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr(); - Module * pModule = pDomainFile->GetModule(); + DomainAssembly * pDomainAssembly = pEnCFieldInfo->GetObjectTypeData().vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetModule(); // make sure we actually have an EditAndContinueModule _ASSERTE(pModule->IsEditAndContinueCapable()); @@ -4066,7 +4066,7 @@ BOOL DacDbiInterfaceImpl::GetAssemblyPath( // Get the manifest module for this assembly Assembly * pAssembly = vmAssembly.GetDacPtr(); - Module * pManifestModule = pAssembly->GetManifestModule(); + Module * pManifestModule = pAssembly->GetModule(); // Get the path for the manifest module. // since we no longer support Win9x, we assume all paths will be in unicode format already @@ -4090,8 +4090,8 @@ void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, TypeRefData * pTargetRefInfo) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = pTypeRefInfo->vmDomainFile.GetDacPtr(); - Module * pReferencingModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = pTypeRefInfo->vmDomainAssembly.GetDacPtr(); + Module * pReferencingModule = pDomainAssembly->GetModule(); BOOL fSuccess = FALSE; // Resolve the type ref @@ -4117,9 +4117,9 @@ void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, _ASSERTE(pTargetModule != NULL); _ASSERTE( TypeFromToken(targetTypeDef) == mdtTypeDef ); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); - pTargetRefInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainFile())); + pTargetRefInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainAssembly())); pTargetRefInfo->typeToken = targetTypeDef; } else @@ -4347,19 +4347,19 @@ void DacDbiInterfaceImpl::GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * -void DacDbiInterfaceImpl::GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule) +void DacDbiInterfaceImpl::GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) { DD_ENTER_MAY_THROW; _ASSERTE(pModule != NULL); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - pModule->SetHostPtr(pDomainFile->GetModule()); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + pModule->SetHostPtr(pDomainAssembly->GetModule()); } -// Implement IDacDbiInterface::GetDomainFileData -void DacDbiInterfaceImpl::GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData) +// Implement IDacDbiInterface::GetDomainAssemblyData +void DacDbiInterfaceImpl::GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData) { DD_ENTER_MAY_THROW; @@ -4367,12 +4367,11 @@ void DacDbiInterfaceImpl::GetDomainFileData(VMPTR_DomainFile vmDomainFile, Domai ZeroMemory(pData, sizeof(*pData)); - DomainFile * pDomainFile = vmDomainFile.GetDacPtr(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); // @dbgtodo - is this efficient DAC usage (perhaps a dac-cop rule)? Are we round-tripping the pointer? - // Should we have a GetDomainAssembly() that returns a PTR_DomainAssembly? - pData->vmDomainAssembly.SetHostPtr(pDomainFile->GetDomainAssembly()); + pData->vmDomainAssembly.SetHostPtr(pDomainAssembly); pData->vmAppDomain.SetHostPtr(pAppDomain); } @@ -4494,41 +4493,30 @@ void DacDbiInterfaceImpl::EnumerateModulesInAssembly( DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr(); - // If the domain is not yet fully-loaded, don't advertise it yet. - // It's not ready to be inspected. - DomainModuleIterator iterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - - while (iterator.Next()) + // Debugger isn't notified of Resource / Inspection-only modules. + if (pDomainAssembly->GetModule()->IsVisibleToDebugger()) { - DomainFile * pDomainFile = iterator.GetDomainFile(); + _ASSERTE(pDomainAssembly->IsLoaded()); - // Debugger isn't notified of Resource / Inspection-only modules. - if (!pDomainFile->GetModule()->IsVisibleToDebugger()) - { - continue; - } - - _ASSERTE(pDomainFile->IsLoaded()); - - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); - vmDomainFile.SetHostPtr(pDomainFile); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + vmDomainAssembly.SetHostPtr(pDomainAssembly); - fpCallback(vmDomainFile, pUserData); + fpCallback(vmDomainAssembly, pUserData); } } // Implementation of IDacDbiInterface::ResolveAssembly // Returns NULL if not found. VMPTR_DomainAssembly DacDbiInterfaceImpl::ResolveAssembly( - VMPTR_DomainFile vmScope, + VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef) { DD_ENTER_MAY_THROW; - DomainFile * pDomainFile = vmScope.GetDacPtr(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); - Module * pModule = pDomainFile->GetCurrentModule(); + DomainAssembly * pDomainAssembly = vmScope.GetDacPtr(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); + Module * pModule = pDomainAssembly->GetModule(); VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); @@ -6068,7 +6056,7 @@ void DacDbiInterfaceImpl::GetTypedByRefInfo(CORDB_ADDRESS pTypedByRe "ref=0x%08x, cls=0x%08x, mod=0x%p\n", pObjectData->objRef, pObjectData->typedByrefType.metadataToken, - pObjectData->typedByrefType.vmDomainFile.GetDacPtr())); + pObjectData->typedByrefType.vmDomainAssembly.GetDacPtr())); } // DacDbiInterfaceImpl::GetTypedByRefInfo // Get the string data associated withn obj and put it into the pointers @@ -7025,7 +7013,7 @@ bool DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS addr) } bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_AppDomain * pAppDomain, - OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *pDomainFile) + OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *pDomainAssembly) { DD_ENTER_MAY_THROW; @@ -7045,7 +7033,7 @@ bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_Ap { pAppDomain->SetDacTargetPtr(PTR_HOST_TO_TADDR(baseDomain->AsAppDomain())); pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module)); - pDomainFile->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainFile())); + pDomainAssembly->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainAssembly())); } else { diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index e484a28008b0cf..e885703113197e 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -96,7 +96,7 @@ class DacDbiInterfaceImpl : IStringHolder * pStrName); // Get the values of the JIT Optimization and EnC flags. - void GetCompilerFlags (VMPTR_DomainFile vmDomainFile, + void GetCompilerFlags (VMPTR_DomainAssembly vmDomainAssembly, BOOL * pfAllowJITOpts, BOOL * pfEnableEnC); @@ -104,7 +104,7 @@ class DacDbiInterfaceImpl : bool CanSetEnCBits(Module * pModule); // Set the values of the JIT optimization and EnC flags. - HRESULT SetCompilerFlags(VMPTR_DomainFile vmDomainFile, + HRESULT SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC); @@ -133,7 +133,7 @@ class DacDbiInterfaceImpl : bool IsValidObject(CORDB_ADDRESS obj); - bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *mod); + bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *mod); @@ -218,7 +218,7 @@ class DacDbiInterfaceImpl : // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // - void GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, + void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, TargetBuffer * pCodeInfo, mdToken * pLocalSigToken); @@ -229,7 +229,7 @@ class DacDbiInterfaceImpl : // whether it's an instantiated generic // its EnC version number // hot and cold region information. - void GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, + void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, NativeCodeFunctionData * pCodeInfo); @@ -260,7 +260,7 @@ class DacDbiInterfaceImpl : ClassInfo * pData); // get field information and object size for an instantiated generic type - void GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, + void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, DacDbiArrayList * pFieldList, @@ -336,7 +336,7 @@ class DacDbiInterfaceImpl : CorElementType simpleType, mdTypeDef * pMetadataToken, VMPTR_Module * pVmModule, - VMPTR_DomainFile * pVmDomainFile); + VMPTR_DomainAssembly * pVmDomainAssembly); BOOL IsExceptionObject(VMPTR_Object vmObject); @@ -352,7 +352,7 @@ class DacDbiInterfaceImpl : HRESULT GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef); HRESULT GetDelegateTargetObject( @@ -730,10 +730,10 @@ class DacDbiInterfaceImpl : // Gets properties for a module void GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData); - // Gets properties for a domainfile - void GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData); + // Gets properties for a domain assembly + void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData); - void GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule); + void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule); // Yields true if the address is a CLR stub. BOOL IsTransitionStub(CORDB_ADDRESS address); @@ -829,8 +829,8 @@ class DacDbiInterfaceImpl : // Return the current appdomain the specified thread is in. VMPTR_AppDomain GetCurrentAppDomain(VMPTR_Thread vmThread); - // Given an assembly ref token and metadata scope (via the DomainFile), resolve the assembly. - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainFile vmScope, mdToken tkAssemblyRef); + // Given an assembly ref token and metadata scope (via the DomainAssembly), resolve the assembly. + VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef); // Hijack the thread diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 251b5dde74fdfc..b8a84043b396f9 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -514,7 +514,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread #endif // FEATURE_COMINTEROP Module * pModule = (pMD ? pMD->GetModule() : NULL); - DomainFile * pDomainFile = (pModule ? pModule->GetDomainFile() : NULL); + DomainAssembly * pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); if (frameData.stubFrame.frameType == STUBFRAME_FUNC_EVAL) { @@ -522,14 +522,14 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread DebuggerEval * pDE = pFEF->GetDebuggerEval(); frameData.stubFrame.funcMetadataToken = pDE->m_methodToken; - frameData.stubFrame.vmDomainFile.SetHostPtr( - pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainFile() : NULL); + frameData.stubFrame.vmDomainAssembly.SetHostPtr( + pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainAssembly() : NULL); frameData.stubFrame.vmMethodDesc = VMPTR_MethodDesc::NullPtr(); } else { frameData.stubFrame.funcMetadataToken = (pMD == NULL ? NULL : pMD->GetMemberDef()); - frameData.stubFrame.vmDomainFile.SetHostPtr(pDomainFile); + frameData.stubFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD); } @@ -702,11 +702,11 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter, // Although MiniDumpNormal tries to dump all AppDomains, it's possible // target corruption will keep one from being present. This should mean // we'll just fail later, but struggle on for now. - DomainFile *pDomainFile = NULL; + DomainAssembly *pDomainAssembly = NULL; EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY { - pDomainFile = (pModule ? pModule->GetDomainFile() : NULL); - _ASSERTE(pDomainFile != NULL); + pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); + _ASSERTE(pDomainAssembly != NULL); } EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY @@ -783,7 +783,7 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter, // pFuncData->funcMetadataToken = pMD->GetMemberDef(); - pFuncData->vmDomainFile.SetHostPtr(pDomainFile); + pFuncData->vmDomainAssembly.SetHostPtr(pDomainAssembly); // PERF: this is expensive to get so I stopped fetching it eagerly // It is only needed if we haven't already got a cached copy diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 57a4dc1bbab8fc..7a03d984e3ac70 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -14,14 +14,11 @@ #define __DACIMPL_H__ #include "gcinterface.dac.h" - -#if defined(TARGET_ARM) || defined(FEATURE_CORESYSTEM) // @ARMTODO: STL breaks the build with current VC headers //--------------------------------------------------------------------------------------- // Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for // storing code:DAC_INSTANCE . Otherwise, the DAC uses the STL unordered_map to. #define DAC_HASHTABLE -#endif // TARGET_ARM|| FEATURE_CORESYSTEM #ifndef DAC_HASHTABLE #pragma push_macro("return") @@ -509,7 +506,6 @@ struct ProcessModIter bool m_nextDomain; AppDomain::AssemblyIterator m_assemIter; Assembly* m_curAssem; - Assembly::ModuleIterator m_modIter; ProcessModIter(void) : m_domainIter(FALSE) @@ -545,7 +541,7 @@ struct ProcessModIter } // Note: DAC doesn't need to keep the assembly alive - see code:CollectibleAssemblyHolder#CAH_DAC - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); return pAssembly; } return NULL; @@ -554,27 +550,13 @@ struct ProcessModIter Module* NextModule(void) { SUPPORTS_DAC; - for (;;) + m_curAssem = NextAssem(); + if (!m_curAssem) { - if (!m_curAssem) - { - m_curAssem = NextAssem(); - if (!m_curAssem) - { - return NULL; - } - - m_modIter = m_curAssem->IterateModules(); - } - - if (!m_modIter.Next()) - { - m_curAssem = NULL; - continue; - } - - return m_modIter.GetModule(); + return NULL; } + + return m_curAssem->GetModule(); } }; @@ -1520,11 +1502,6 @@ class ClrDataAccess DWORD &dwSize, _Out_writes_(cchPath) LPWSTR wszPath, const DWORD cchPath); -#if defined(FEATURE_CORESYSTEM) - static bool GetILImageNameFromNgenImage(LPCWSTR ilExtension, - _Out_writes_(cchFilePath) LPWSTR wszFilePath, - const DWORD cchFilePath); -#endif // FEATURE_CORESYSTEM }; extern ClrDataAccess* g_dacImpl; diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 1e327721f4a92d..cd81cde5ac69ee 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2607,10 +2607,7 @@ ClrDataAccess::GetAssemblyData(CLRDATA_ADDRESS cdBaseDomainPtr, CLRDATA_ADDRESS assemblyData->ModuleCount = 0; assemblyData->isDomainNeutral = FALSE; - pAssembly->GetManifestFile(); - - ModuleIterator mi = pAssembly->IterateModules(); - while (mi.Next()) + if (pAssembly->GetModule()) { assemblyData->ModuleCount++; } @@ -2628,17 +2625,17 @@ ClrDataAccess::GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, _In if (name) name[0] = 0; - if (!pAssembly->GetManifestFile()->GetPath().IsEmpty()) + if (!pAssembly->GetPEAssembly()->GetPath().IsEmpty()) { - if (!pAssembly->GetManifestFile()->GetPath().DacGetUnicode(count, name, pNeeded)) + if (!pAssembly->GetPEAssembly()->GetPath().DacGetUnicode(count, name, pNeeded)) hr = E_FAIL; else if (name) name[count-1] = 0; } - else if (!pAssembly->GetManifestFile()->IsDynamic()) + else if (!pAssembly->GetPEAssembly()->IsDynamic()) { StackSString displayName; - pAssembly->GetManifestFile()->GetDisplayName(displayName, 0); + pAssembly->GetPEAssembly()->GetDisplayName(displayName, 0); const WCHAR *val = displayName.GetUnicode(); @@ -2673,9 +2670,9 @@ ClrDataAccess::GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, _Inout_u Assembly* pAssembly = PTR_Assembly(TO_TADDR(assembly)); // Turn from bytes to wide characters - if (!pAssembly->GetManifestFile()->GetPath().IsEmpty()) + if (!pAssembly->GetPEAssembly()->GetPath().IsEmpty()) { - if (!pAssembly->GetManifestFile()->GetPath(). + if (!pAssembly->GetPEAssembly()->GetPath(). DacGetUnicode(count, location, pNeeded)) { hr = E_FAIL; @@ -2703,21 +2700,14 @@ ClrDataAccess::GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int coun SOSDacEnter(); Assembly* pAssembly = PTR_Assembly(TO_TADDR(assembly)); - ModuleIterator mi = pAssembly->IterateModules(); - unsigned int n = 0; if (modules) { - while (mi.Next() && n < count) - modules[n++] = HOST_CDADDR(mi.GetModule()); - } - else - { - while (mi.Next()) - n++; + if (pAssembly->GetModule() && count > 0) + modules[0] = HOST_CDADDR(pAssembly->GetModule()); } if (pNeeded) - *pNeeded = n; + *pNeeded = 1; SOSDacLeave(); return hr; diff --git a/src/coreclr/debug/daccess/task.cpp b/src/coreclr/debug/daccess/task.cpp index 30abc5e090cc9e..319d3506b9b889 100644 --- a/src/coreclr/debug/daccess/task.cpp +++ b/src/coreclr/debug/daccess/task.cpp @@ -948,6 +948,11 @@ ClrDataAssembly::Release(THIS) return newRefs; } +struct TrivialModuleIterator +{ + Module* m_module; +}; + HRESULT STDMETHODCALLTYPE ClrDataAssembly::StartEnumModules( /* [out] */ CLRDATA_ENUM* handle) @@ -958,11 +963,10 @@ ClrDataAssembly::StartEnumModules( EX_TRY { - Assembly::ModuleIterator* iter = new (nothrow) - Assembly::ModuleIterator; + TrivialModuleIterator* iter = new (nothrow) TrivialModuleIterator; if (iter) { - *iter = m_assembly->IterateModules(); + iter->m_module = m_assembly->GetModule(); *handle = TO_CDENUM(iter); status = S_OK; } @@ -995,12 +999,13 @@ ClrDataAssembly::EnumModule( EX_TRY { - Assembly::ModuleIterator* iter = - FROM_CDENUM(Assembly::ModuleIterator, *handle); - if (iter->Next()) + TrivialModuleIterator* iter = FROM_CDENUM(TrivialModuleIterator, *handle); + if (iter->m_module) { *mod = new (nothrow) - ClrDataModule(m_dac, iter->GetModule()); + ClrDataModule(m_dac, iter->m_module); + + iter->m_module = NULL; status = *mod ? S_OK : E_OUTOFMEMORY; } else @@ -1031,8 +1036,7 @@ ClrDataAssembly::EndEnumModules( EX_TRY { - Assembly::ModuleIterator* iter = - FROM_CDENUM(Assembly::ModuleIterator, handle); + TrivialModuleIterator* iter = FROM_CDENUM(TrivialModuleIterator, handle); delete iter; status = S_OK; } @@ -1170,7 +1174,7 @@ ClrDataAssembly::GetFileName( { COUNT_T _nameLen; - if (m_assembly->GetManifestFile()->GetPath(). + if (m_assembly->GetPEAssembly()->GetPath(). DacGetUnicode(bufLen, name, &_nameLen)) { if (nameLen) diff --git a/src/coreclr/debug/di/breakpoint.cpp b/src/coreclr/debug/di/breakpoint.cpp index eb156c49e04d9c..ad45df5c618ace 100644 --- a/src/coreclr/debug/di/breakpoint.cpp +++ b/src/coreclr/debug/di/breakpoint.cpp @@ -201,7 +201,7 @@ HRESULT CordbFunctionBreakpoint::Activate(BOOL fActivate) pProcess->InitIPCEvent(pEvent, DB_IPCE_BREAKPOINT_ADD, true, pAppDomain->GetADToken()); pEvent->BreakpointData.funcMetadataToken = m_code->GetMetadataToken(); - pEvent->BreakpointData.vmDomainFile = m_code->GetModule()->GetRuntimeDomainFile(); + pEvent->BreakpointData.vmDomainAssembly = m_code->GetModule()->GetRuntimeDomainAssembly(); pEvent->BreakpointData.encVersion = m_code->GetVersion(); BOOL codeIsIL = m_code->IsIL(); diff --git a/src/coreclr/debug/di/cordb.cpp b/src/coreclr/debug/di/cordb.cpp index e195f3731a9e6f..2f014d1fa587c0 100644 --- a/src/coreclr/debug/di/cordb.cpp +++ b/src/coreclr/debug/di/cordb.cpp @@ -84,16 +84,6 @@ //***************************************************************************** STDAPI CreateCordbObject(int iDebuggerVersion, IUnknown ** ppCordb) { -#if !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - // This API should not be called for Windows CoreCLR unless we are doing interop-debugging - // (which is only supported internally). Use code:CoreCLRCreateCordbObject instead. - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) - { - _ASSERTE(!"Deprecated entry point CreateCordbObject() is called on Windows CoreCLR\n"); - return E_NOTIMPL; - } -#endif // !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - if (ppCordb == NULL) { return E_INVALIDARG; diff --git a/src/coreclr/debug/di/divalue.cpp b/src/coreclr/debug/di/divalue.cpp index b8c9e745260db2..5e79a5ee1c92bc 100644 --- a/src/coreclr/debug/di/divalue.cpp +++ b/src/coreclr/debug/di/divalue.cpp @@ -2464,7 +2464,7 @@ HRESULT CordbObjectValue::EnumerateExceptionCallStack(ICorDebugExceptionObjectCa CorDebugExceptionObjectStackFrame& currentStackFrame = pStackFrames[index]; CordbAppDomain* pAppDomain = GetProcess()->LookupOrCreateAppDomain(currentDacFrame.vmAppDomain); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(currentDacFrame.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(currentDacFrame.vmDomainAssembly); hr = pModule->QueryInterface(IID_ICorDebugModule, reinterpret_cast(¤tStackFrame.pModule)); _ASSERTE(SUCCEEDED(hr)); @@ -2653,18 +2653,18 @@ HRESULT CordbObjectValue::GetFunctionHelper(ICorDebugFunction **ppFunction) return hr; mdMethodDef functionMethodDef = 0; - VMPTR_DomainFile functionDomainFile; + VMPTR_DomainAssembly functionDomainAssembly; NativeCodeFunctionData nativeCodeForDelFunc; - hr = pDAC->GetDelegateFunctionData(delType, pDelegateObj, &functionDomainFile, &functionMethodDef); + hr = pDAC->GetDelegateFunctionData(delType, pDelegateObj, &functionDomainAssembly, &functionMethodDef); if (hr != S_OK) return hr; // TODO: How to ensure results are sanitized? // Also, this is expensive. Do we really care that much about this? - pDAC->GetNativeCodeInfo(functionDomainFile, functionMethodDef, &nativeCodeForDelFunc); + pDAC->GetNativeCodeInfo(functionDomainAssembly, functionMethodDef, &nativeCodeForDelFunc); - RSSmartPtr funcModule(GetProcess()->LookupOrCreateModule(functionDomainFile)); + RSSmartPtr funcModule(GetProcess()->LookupOrCreateModule(functionDomainAssembly)); RSSmartPtr func; { RSLockHolder lockHolder(GetProcess()->GetProcessLock()); diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index 6d6a7a55befa2e..55f9e8a29c87de 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -48,17 +48,17 @@ STDAPI ReOpenMetaDataWithMemoryEx( // // Arguments: // pProcess - process that this module lives in -// vmDomainFile - CLR cookie for module. +// vmDomainAssembly - CLR cookie for module. CordbModule::CordbModule( CordbProcess * pProcess, VMPTR_Module vmModule, - VMPTR_DomainFile vmDomainFile) -: CordbBase(pProcess, vmDomainFile.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainFile), enumCordbModule), + VMPTR_DomainAssembly vmDomainAssembly) +: CordbBase(pProcess, vmDomainAssembly.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainAssembly), enumCordbModule), m_pAssembly(0), m_pAppDomain(0), m_classes(11), m_functions(101), - m_vmDomainFile(vmDomainFile), + m_vmDomainAssembly(vmDomainAssembly), m_vmModule(vmModule), m_EnCCount(0), m_fForceMetaDataSerialize(FALSE), @@ -84,11 +84,11 @@ CordbModule::CordbModule( m_fInMemory = modInfo.fInMemory; m_vmPEFile = modInfo.vmPEAssembly; - if (!vmDomainFile.IsNull()) + if (!vmDomainAssembly.IsNull()) { - DomainFileInfo dfInfo; + DomainAssemblyInfo dfInfo; - pProcess->GetDAC()->GetDomainFileData(vmDomainFile, &dfInfo); // throws + pProcess->GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &dfInfo); // throws m_pAppDomain = pProcess->LookupOrCreateAppDomain(dfInfo.vmAppDomain); m_pAssembly = m_pAppDomain->LookupOrCreateAssembly(dfInfo.vmDomainAssembly); @@ -115,21 +115,21 @@ CordbModule::CordbModule( // Callback helper for code:CordbModule::DbgAssertModuleDeleted // // Arguments -// vmDomainFile - domain file in the enumeration +// vmDomainAssembly - domain file in the enumeration // pUserData - pointer to the CordbModule that we just got an exit event for. // -void DbgAssertModuleDeletedCallback(VMPTR_DomainFile vmDomainFile, void * pUserData) +void DbgAssertModuleDeletedCallback(VMPTR_DomainAssembly vmDomainAssembly, void * pUserData) { CordbModule * pThis = reinterpret_cast(pUserData); INTERNAL_DAC_CALLBACK(pThis->GetProcess()); - if (!pThis->m_vmDomainFile.IsNull()) + if (!pThis->m_vmDomainAssembly.IsNull()) { - VMPTR_DomainFile vmDomainFileDeleted = pThis->m_vmDomainFile; + VMPTR_DomainAssembly vmDomainAssemblyDeleted = pThis->m_vmDomainAssembly; - CONSISTENCY_CHECK_MSGF((vmDomainFileDeleted != vmDomainFile), - ("A Module Unload event was sent for a module, but it still shows up in the enumeration.\n vmDomainFileDeleted=%p\n", - VmPtrToCookie(vmDomainFileDeleted))); + CONSISTENCY_CHECK_MSGF((vmDomainAssemblyDeleted != vmDomainAssembly), + ("A Module Unload event was sent for a module, but it still shows up in the enumeration.\n vmDomainAssemblyDeleted=%p\n", + VmPtrToCookie(vmDomainAssemblyDeleted))); } } @@ -1499,7 +1499,7 @@ HRESULT CordbModule::EnableClassLoadCallbacks(BOOL bClassLoadCallbacks) if (m_fDynamic && !bClassLoadCallbacks) return E_INVALIDARG; - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; // Send a Set Class Load Flag event to the left side. There is no need to wait for a response, and this can be @@ -1511,7 +1511,7 @@ HRESULT CordbModule::EnableClassLoadCallbacks(BOOL bClassLoadCallbacks) DB_IPCE_SET_CLASS_LOAD_FLAG, false, (GetAppDomain()->GetADToken())); - event.SetClassLoad.vmDomainFile = this->m_vmDomainFile; + event.SetClassLoad.vmDomainAssembly = this->m_vmDomainAssembly; event.SetClassLoad.flag = (bClassLoadCallbacks == TRUE); HRESULT hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, @@ -2041,7 +2041,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) return E_INVALIDARG; } - if (m_vmDomainFile.IsNull() || m_pAppDomain == NULL) + if (m_vmDomainAssembly.IsNull() || m_pAppDomain == NULL) { return E_UNEXPECTED; } @@ -2050,7 +2050,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) *ppClass = NULL; EX_TRY { - TypeRefData inData = {m_vmDomainFile, token}; + TypeRefData inData = {m_vmDomainAssembly, token}; TypeRefData outData; { @@ -2058,7 +2058,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) pProcess->GetDAC()->ResolveTypeReference(&inData, &outData); } - CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainFile); + CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainAssembly); IfFailThrow(pModule->LookupClassByToken(outData.typeToken, ppClass)); } EX_CATCH_HRESULT(hr); @@ -2271,7 +2271,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, FAIL_IF_NEUTERED(this); INTERNAL_SYNC_API_ENTRY(this->GetProcess()); // - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; #ifdef FEATURE_ENC_SUPPORTED @@ -2288,7 +2288,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, DebuggerIPCEvent event; GetProcess()->InitIPCEvent(&event, DB_IPCE_APPLY_CHANGES, false, VMPTR_AppDomain::NullPtr()); - event.ApplyChanges.vmDomainFile = this->m_vmDomainFile; + event.ApplyChanges.vmDomainAssembly = this->m_vmDomainAssembly; // Have the left-side create a buffer for us to store the delta into ULONG cbSize = cbMetaData+cbIL; @@ -2354,7 +2354,7 @@ HRESULT CordbModule::ApplyChangesInternal(ULONG cbMetaData, CordbModule* pModule = NULL; - pModule = pAppDomain->LookupOrCreateModule(retEvent->EnCUpdate.vmDomainFile); // throws + pModule = pAppDomain->LookupOrCreateModule(retEvent->EnCUpdate.vmDomainAssembly); // throws _ASSERTE(pModule != NULL); // update to the newest version @@ -2412,7 +2412,7 @@ HRESULT CordbModule::SetJMCStatus( FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); - if (m_vmDomainFile.IsNull()) + if (m_vmDomainAssembly.IsNull()) return E_UNEXPECTED; // @todo -allow the other parameters. These are functions that have default status @@ -2431,7 +2431,7 @@ HRESULT CordbModule::SetJMCStatus( // Tell the LS that this module is/is not user code DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_SET_MODULE_JMC_STATUS, true, this->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_vmDomainFile; + event.SetJMCFunctionStatus.vmDomainAssembly = m_vmDomainAssembly; event.SetJMCFunctionStatus.dwStatus = fIsUserCode; @@ -2520,10 +2520,10 @@ CordbAssembly * CordbModule::ResolveAssemblyInternal(mdToken tkAssemblyRef) CordbAssembly * pAssembly = NULL; - if (!m_vmDomainFile.IsNull()) + if (!m_vmDomainAssembly.IsNull()) { // Get DAC to do the real work to resolve the assembly - VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainFile, tkAssemblyRef); + VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainAssembly, tkAssemblyRef); // now find the ICorDebugAssembly corresponding to it if (!vmDomainAssembly.IsNull() && m_pAppDomain != NULL) @@ -2694,7 +2694,7 @@ HRESULT CordbModule::SetJITCompilerFlags(DWORD dwFlags) if (SUCCEEDED(hr)) { // DD interface will check if it's a valid time to change the flags. - hr = pProcess->GetDAC()->SetCompilerFlags(GetRuntimeDomainFile(), fAllowJitOpts, fEnableEnC); + hr = pProcess->GetDAC()->SetCompilerFlags(GetRuntimeDomainAssembly(), fAllowJitOpts, fEnableEnC); } } } @@ -2730,7 +2730,7 @@ HRESULT CordbModule::GetJITCompilerFlags(DWORD *pdwFlags ) BOOL fEnableEnC; pProcess->GetDAC()->GetCompilerFlags ( - GetRuntimeDomainFile(), + GetRuntimeDomainAssembly(), &fAllowJitOpts, &fEnableEnC); @@ -5169,8 +5169,8 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffsetImpl(Instantiation *currentInst int skipBytes = 0; -#if defined(TARGET_X86) && defined(FEATURE_CORESYSTEM) - // Skip nop sleds on x86 coresystem. The JIT adds these instructions as a security measure, +#if defined(PSEUDORANDOM_NOP_INSERTION) + // Skip nop sleds the JIT adds. These instructions as a security measure, // and incorrectly reports to us the wrong offset of the call instruction. const BYTE nop_opcode = 0x90; while (fetched && nativeBuffer[0] == nop_opcode) diff --git a/src/coreclr/debug/di/nativepipeline.h b/src/coreclr/debug/di/nativepipeline.h index f1b973ea5967ca..fc03b277724744 100644 --- a/src/coreclr/debug/di/nativepipeline.h +++ b/src/coreclr/debug/di/nativepipeline.h @@ -146,28 +146,6 @@ class INativeEventPipeline virtual BOOL TerminateProcess(UINT32 exitCode) = 0; - // - // Resume any suspended threads in the currend process. - // This decreases the suspend count of each thread by at most 1. - // Call multiple times until it returns S_FALSE if you want to really ensure - // all threads are running. - // - // Notes: - // On Windows the OS may suspend threads when continuing a 2nd-chance exception. - // Call this to get them resumed again. On other platforms this - // will typically be a no-op, so I provide a default implementation to avoid - // everyone having to override this. - // - // Return Value: - // S_OK if at least one thread was resumed from a suspended state - // S_FALSE if nothing was done - // An error code indicating why we were not able to attempt this - - virtual HRESULT EnsureThreadsRunning() - { - return S_FALSE; - } - #ifdef TARGET_UNIX // Used by debugger side (RS) to cleanup the target (LS) named pipes // and semaphores when the debugger detects the debuggee process exited. diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index 59af4cc8d9c649..1abed121f3e5ad 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -414,7 +414,6 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( WCHAR *mutableFilePath = (WCHAR *)filePath; -#if defined(FEATURE_CORESYSTEM) size_t pathLen = wcslen(mutableFilePath); const WCHAR *nidll = W(".ni.dll"); @@ -429,7 +428,6 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( { wcscpy_s(mutableFilePath+pathLen-dllLen, dllLen, W(".exe")); } -#endif//FEATURE_CORESYSTEM ALLOW_DATATARGET_MISSING_MEMORY( pMDII = LookupMetaDataFromDebuggerForSingleFile(pModule, mutableFilePath, dwImageTimeStamp, dwImageSize); @@ -2564,10 +2562,10 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbAppDomain* pAppD { VMPTR_AppDomain appDomain; VMPTR_Module mod; - VMPTR_DomainFile domainFile; + VMPTR_DomainAssembly domainAssembly; HRESULT hr = E_FAIL; - if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainFile)) + if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainAssembly)) { if (pAppDomainOverride) { @@ -4431,15 +4429,15 @@ class ShimModuleCallbackData // Callback invoked from DAC enumeration. // // arguments: - // vmDomainFile - VMPTR for Module + // vmDomainAssembly - VMPTR for Module // pData - a 'this' pointer // - static void Callback(VMPTR_DomainFile vmDomainFile, void * pData) + static void Callback(VMPTR_DomainAssembly vmDomainAssembly, void * pData) { ShimModuleCallbackData * pThis = static_cast (pData); INTERNAL_DAC_CALLBACK(pThis->m_pProcess); - CordbModule * pModule = pThis->m_pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainFile); + CordbModule * pModule = pThis->m_pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainAssembly); pThis->SetAndMoveNext(pModule); } @@ -5065,7 +5063,7 @@ void CordbProcess::RawDispatchEvent( case DB_IPCE_METADATA_UPDATE: { - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->MetadataUpdateData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->MetadataUpdateData.vmDomainAssembly); pModule->RefreshMetaData(); } break; @@ -5073,7 +5071,7 @@ void CordbProcess::RawDispatchEvent( case DB_IPCE_LOAD_MODULE: { _ASSERTE (pAppDomain != NULL); - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadModuleData.vmDomainAssembly); { pModule->SetLoadEventContinueMarker(); @@ -5125,12 +5123,12 @@ void CordbProcess::RawDispatchEvent( { STRESS_LOG3(LF_CORDB, LL_INFO100, "RCET::HRCE: unload module on thread %#x Mod:0x%x AD:0x%08x\n", dwVolatileThreadId, - VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile), + VmPtrToCookie(pEvent->UnloadModuleData.vmDomainAssembly), VmPtrToCookie(pEvent->vmAppDomain)); PREFIX_ASSUME (pAppDomain != NULL); - CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainFile); + CordbModule *module = pAppDomain->LookupOrCreateModule(pEvent->UnloadModuleData.vmDomainAssembly); if (module == NULL) { @@ -5151,7 +5149,7 @@ void CordbProcess::RawDispatchEvent( pCallback1->UnloadModule(pAppDomain, module); } - pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainFile)); + pAppDomain->m_modules.RemoveBase(VmPtrToCookie(pEvent->UnloadModuleData.vmDomainAssembly)); } break; @@ -5163,13 +5161,13 @@ void CordbProcess::RawDispatchEvent( "RCET::HRCE: load class on thread %#x Tok:0x%08x Mod:0x%08x Asm:0x%08x AD:0x%08x\n", dwVolatileThreadId, pEvent->LoadClass.classMetadataToken, - VmPtrToCookie(pEvent->LoadClass.vmDomainFile), + VmPtrToCookie(pEvent->LoadClass.vmDomainAssembly), LsPtrToCookie(pEvent->LoadClass.classDebuggerAssemblyToken), VmPtrToCookie(pEvent->vmAppDomain))); _ASSERTE (pAppDomain != NULL); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadClass.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->LoadClass.vmDomainAssembly); if (pModule == NULL) { LOG((LF_CORDB, LL_INFO100, "Load Class on not-loaded Module - continue()ing!" )); @@ -5221,13 +5219,13 @@ void CordbProcess::RawDispatchEvent( "RCET::HRCE: unload class on thread %#x Tok:0x%08x Mod:0x%08x AD:0x%08x\n", dwVolatileThreadId, pEvent->UnloadClass.classMetadataToken, - VmPtrToCookie(pEvent->UnloadClass.vmDomainFile), + VmPtrToCookie(pEvent->UnloadClass.vmDomainAssembly), VmPtrToCookie(pEvent->vmAppDomain))); // get the appdomain object _ASSERTE (pAppDomain != NULL); - CordbModule *pModule = pAppDomain->LookupOrCreateModule(pEvent->UnloadClass.vmDomainFile); + CordbModule *pModule = pAppDomain->LookupOrCreateModule(pEvent->UnloadClass.vmDomainAssembly); if (pModule == NULL) { LOG((LF_CORDB, LL_INFO100, "Unload Class on not-loaded Module - continue()ing!" )); @@ -5304,7 +5302,7 @@ void CordbProcess::RawDispatchEvent( // determine first whether custom notifications for this type are enabled -- if not // we just return without doing anything. CordbClass * pNotificationClass = LookupClass(pAppDomain, - pEvent->CustomNotification.vmDomainFile, + pEvent->CustomNotification.vmDomainAssembly, pEvent->CustomNotification.classToken); // if the class is NULL, that means the debugger never enabled notifications for it. Otherwise, @@ -5580,7 +5578,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE (pAppDomain != NULL); // Find the Right Side module for this module. - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->UpdateModuleSymsData.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->UpdateModuleSymsData.vmDomainAssembly); _ASSERTE(pModule != NULL); // This is a legacy event notification for updated PDBs. @@ -5654,7 +5652,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE(NULL != pAppDomain); - CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile); + CordbModule * pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); CordbFunction * pCurFunction = NULL; @@ -5710,7 +5708,7 @@ void CordbProcess::RawDispatchEvent( _ASSERTE(NULL != pAppDomain); - CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainFile); + CordbModule* pModule = pAppDomain->LookupOrCreateModule(pEvent->EnCRemap.vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); // Find the function we're remapping to, which must be the latest version @@ -7626,27 +7624,7 @@ HRESULT CordbProcess::GetRuntimeOffsets() { -#if !defined FEATURE_CORESYSTEM - // kernel32!OpenThread does not exist on all platforms (missing on Win98). - // So we need to delay load it. - typedef HANDLE (WINAPI *FPOPENTHREAD)(DWORD dwDesiredAccess, - BOOL bInheritHandle, - DWORD dwThreadId); - - - - HMODULE mod = WszGetModuleHandle(W("kernel32.dll")); - - _ASSERTE(mod != NULL); // can't fail since Kernel32.dll is already loaded. - - const FPOPENTHREAD pfnOpenThread = (FPOPENTHREAD)GetProcAddress(mod, "OpenThread"); - - if (pfnOpenThread != NULL) - { - m_hHelperThread = pfnOpenThread(SYNCHRONIZE, FALSE, dwHelperTid); - CONSISTENCY_CHECK_MSGF(m_hHelperThread != NULL, ("Failed to get helper-thread handle. tid=0x%x\n", dwHelperTid)); - } -#elif TARGET_UNIX +#if TARGET_UNIX m_hHelperThread = NULL; //RS is supposed to be able to live without a helper thread handle. #else m_hHelperThread = OpenThread(SYNCHRONIZE, FALSE, dwHelperTid); @@ -7673,8 +7651,6 @@ HRESULT CordbProcess::GetRuntimeOffsets() m_runtimeOffsets.m_excepNotForRuntimeBPAddr)); LOG((LF_CORDB, LL_INFO10000, " m_notifyRSOfSyncCompleteBPAddr= 0x%p\n", m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr)); - LOG((LF_CORDB, LL_INFO10000, " m_raiseException= 0x%p\n", - m_runtimeOffsets.m_raiseExceptionAddr)); LOG((LF_CORDB, LL_INFO10000, " m_debuggerWordTLSIndex= 0x%08x\n", m_runtimeOffsets.m_debuggerWordTLSIndex)); #endif // FEATURE_INTEROP_DEBUGGING @@ -9819,27 +9795,22 @@ HRESULT CordbProcess::EnsureClrInstanceIdSet() // If we didn't expect a specific CLR, then attempt to attach to any. if (m_clrInstanceId == 0) { - -#ifdef FEATURE_CORESYSTEM + // The only case in which we were allowed to request the "default" CLR instance + // ID is when we're running in V2 mode. In V3, the client is required to pass + // a non-zero value to OpenVirtualProcess. Since V2 is no longer supported we + // no longer attempt to find it. if(m_cordb->GetTargetCLR() != 0) { m_clrInstanceId = PTR_TO_CORDB_ADDRESS(m_cordb->GetTargetCLR()); return S_OK; } -#endif - // The only case in which we're allowed to request the "default" CLR instance - // ID is when we're running in V2 mode. In V3, the client is required to pass - // a non-zero value to OpenVirtualProcess. + // In V3, the client is required to pass a non-zero value to OpenVirtualProcess. + // In V2 mode we should be setting target CLR up front but return an error + // if we haven't. _ASSERTE(m_pShim != NULL); + return E_UNEXPECTED; - HRESULT hr = m_pShim->FindLoadedCLR(&m_clrInstanceId); - if (FAILED(hr)) - { - // Couldn't find a loaded clr - no CLR instance ID yet - _ASSERTE(m_clrInstanceId == 0); - return hr; - } } // We've (now) got a valid CLR instance id @@ -14910,26 +14881,6 @@ HRESULT CordbProcess::IsReadyForDetach() pAppDomain = m_appDomains.FindNext(&foundAppDomain); } - // If we're using the shim, give a chance to early-out if the OS doesn't support detach - // so that the user can continue to debug in that case. - // Ideally we'd just rely on the failure from DebugActiveProcessStop, but by then it's too late - // to recover. This function is our only chance to distinguish between graceful detach failures - // and hard detach failures (after which the process object is neutered). - if (m_pShim != NULL) - { -#if !defined(FEATURE_CORESYSTEM) // CORESYSTEM TODO - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - typedef BOOL (*DebugActiveProcessStopSig) (DWORD); - DebugActiveProcessStopSig pDebugActiveProcessStop = - reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); - if (pDebugActiveProcessStop == NULL) - return COR_E_PLATFORMNOTSUPPORTED; -#endif - } - return S_OK; } @@ -14976,16 +14927,16 @@ void CordbProcess::UpdateThreadsForAdUnload(CordbAppDomain * pAppDomain) // CordbProcess::LookupClass // Looks up a previously constructed CordbClass instance without creating. May return NULL if the // CordbClass instance doesn't exist. -// Argument: (in) vmDomainFile - pointer to the domainfile for the module +// Argument: (in) vmDomainAssembly - pointer to the domain assembly for the module // (in) mdTypeDef - metadata token for the class // Return value: pointer to a previously created CordbClass instance or NULL in none exists -CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken) +CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainAssembly vmDomainAssembly, mdTypeDef classToken) { _ASSERTE(ThreadHoldsProcessLock()); if (pAppDomain != NULL) { - CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmDomainFile)); + CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmDomainAssembly)); if (pModule != NULL) { return pModule->LookupClass(classToken); @@ -14998,7 +14949,7 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do // Look for a specific module in the process. // // Arguments: -// vmDomainFile - non-null module to lookup +// vmDomainAssembly - non-null module to lookup // // Returns: // a CordbModule object for the given cookie. Object may be from the cache, or created @@ -15006,23 +14957,23 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do // Never returns null. Throws on error. // // Notes: -// A VMPTR_DomainFile has appdomain affinity, but is ultimately scoped to a process. -// So if we get a raw VMPTR_DomainFile (eg, from the stackwalker or from some other +// A VMPTR_DomainAssembly has appdomain affinity, but is ultimately scoped to a process. +// So if we get a raw VMPTR_DomainAssembly (eg, from the stackwalker or from some other // lookup function), then we need to do a process wide lookup since we don't know which // appdomain it's in. If you know the appdomain, you can use code:CordbAppDomain::LookupOrCreateModule. // -CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); RSLockHolder lockHolder(GetProcess()->GetProcessLock()); - _ASSERTE(!vmDomainFile.IsNull()); + _ASSERTE(!vmDomainAssembly.IsNull()); - DomainFileInfo data; - GetDAC()->GetDomainFileData(vmDomainFile, &data); // throws + DomainAssemblyInfo data; + GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &data); // throws CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(data.vmAppDomain); - return pAppDomain->LookupOrCreateModule(vmDomainFile); + return pAppDomain->LookupOrCreateModule(vmDomainAssembly); } //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/debug/di/publish.cpp b/src/coreclr/debug/di/publish.cpp index 1d7741fb9ea75b..d27e28a4abc37c 100644 --- a/src/coreclr/debug/di/publish.cpp +++ b/src/coreclr/debug/di/publish.cpp @@ -43,54 +43,8 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, { HandleHolder hSnapshotHolder; -#if !defined(FEATURE_CORESYSTEM) - // Load the dll "kernel32.dll". - HModuleHolder hDll = WszLoadLibrary(W("kernel32")); - _ASSERTE(hDll != NULL); - - if (hDll == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to load the dll for enumerating processes. " - "LoadLibrary (kernel32.dll) failed.\n")); - return FALSE; - } -#else - // Load the dll "api-ms-win-obsolete-kernel32-l1-1-0.dll". - HModuleHolder hDll = WszLoadLibrary(W("api-ms-win-obsolete-kernel32-l1-1-0.dll")); - _ASSERTE(hDll != NULL); - - if (hDll == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to load the dll for enumerating processes. " - "LoadLibrary (api-ms-win-obsolete-kernel32-l1-1-0.dll) failed.\n")); - return FALSE; - } -#endif - - // Create the Process' Snapshot - // Get the pointer to the requested function - FARPROC pProcAddr = GetProcAddress(hDll, "CreateToolhelp32Snapshot"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (CreateToolhelp32Snapshot) failed.\n")); - return FALSE; - } - - - - // Handle from CreateToolHelp32Snapshot must be freed via CloseHandle(). - typedef HANDLE CREATETOOLHELP32SNAPSHOT(DWORD, DWORD); - - HANDLE hSnapshot = - ((CREATETOOLHELP32SNAPSHOT *)pProcAddr)(TH32CS_SNAPPROCESS, NULL); - + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (hSnapshot == INVALID_HANDLE_VALUE) { LOG((LF_CORDB, LL_INFO1000, @@ -101,29 +55,13 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. hSnapshotHolder.Assign(hSnapshot); - // Get the first process in the process list - // Get the pointer to the requested function - pProcAddr = GetProcAddress(hDll, "Process32First"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (Process32First) failed.\n")); - return FALSE; - } - PROCESSENTRY32 PE32; // need to initialize the dwSize field before calling Process32First PE32.dwSize = sizeof (PROCESSENTRY32); - typedef BOOL PROCESS32FIRST(HANDLE, LPPROCESSENTRY32); - - BOOL succ = - ((PROCESS32FIRST *)pProcAddr)(hSnapshot, &PE32); - + // Get the first process in the process list + BOOL succ = Process32First(hSnapshot, &PE32); if (succ != TRUE) { LOG((LF_CORDB, LL_INFO1000, @@ -132,29 +70,14 @@ BOOL GetAllProcessesInSystem(DWORD *ProcessId, return FALSE; } - // Loop over and get all the remaining processes - // Get the pointer to the requested function - pProcAddr = GetProcAddress(hDll, "Process32Next"); - - // If the proc address was not found, return error - if (pProcAddr == NULL) - { - LOG((LF_CORDB, LL_INFO1000, - "Unable to enumerate processes in the system. " - "GetProcAddr (Process32Next) failed.\n")); - return FALSE; - } - - typedef BOOL PROCESS32NEXT(HANDLE, LPPROCESSENTRY32); - int iIndex = 0; do { ProcessId [iIndex++] = PE32.th32ProcessID; - succ = ((PROCESS32NEXT *)pProcAddr)(hSnapshot, &PE32); + succ = Process32Next(hSnapshot, &PE32); } while ((succ == TRUE) && (iIndex < (int)dwArraySize)); @@ -177,16 +100,12 @@ const DWORD SAFETY_TIMEOUT = 2000; // ****************************************** CorpubPublish::CorpubPublish() - : CordbCommonBase(0), - m_fpGetModuleFileNameEx(NULL) + : CordbCommonBase(0) + , m_fpGetModuleFileNameEx(NULL) { // Try to get psapi!GetModuleFileNameExW once, and then every process object can use it. // If we can't get it, then we'll fallback to getting information from the IPC block. -#if !defined(FEATURE_CORESYSTEM) - m_hPSAPIdll = WszLoadLibrary(W("psapi.dll")); -#else m_hPSAPIdll = WszLoadLibrary(W("api-ms-win-obsolete-psapi-l1-1-0.dll")); -#endif if (m_hPSAPIdll != NULL) { diff --git a/src/coreclr/debug/di/rsappdomain.cpp b/src/coreclr/debug/di/rsappdomain.cpp index 081baa95216d5b..e140b8a77f13fb 100644 --- a/src/coreclr/debug/di/rsappdomain.cpp +++ b/src/coreclr/debug/di/rsappdomain.cpp @@ -829,7 +829,7 @@ CordbAssembly * CordbAppDomain::LookupOrCreateAssembly(VMPTR_Assembly vmAssembly // Lookup or create a module within the appdomain // // Arguments: -// vmDomainFile - non-null module to lookup +// vmDomainAssembly - non-null module to lookup // // Returns: // a CordbModule object for the given cookie. Object may be from the cache, or created @@ -839,26 +839,26 @@ CordbAssembly * CordbAppDomain::LookupOrCreateAssembly(VMPTR_Assembly vmAssembly // Notes: // If you don't know which appdomain the module is in, use code:CordbProcess::LookupOrCreateModule. // -CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_DomainFile vmDomainFile) +CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); CordbModule * pModule; RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // @dbgtodo locking: push this up. - _ASSERTE(!vmDomainFile.IsNull() || !vmModule.IsNull()); + _ASSERTE(!vmDomainAssembly.IsNull() || !vmModule.IsNull()); // check to see if the module is present in this app domain - pModule = m_modules.GetBase(vmDomainFile.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainFile)); + pModule = m_modules.GetBase(vmDomainAssembly.IsNull() ? VmPtrToCookie(vmModule) : VmPtrToCookie(vmDomainAssembly)); if (pModule != NULL) { return pModule; } if (vmModule.IsNull()) - GetProcess()->GetDAC()->GetModuleForDomainFile(vmDomainFile, &vmModule); + GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule); - RSInitHolder pModuleInit(new CordbModule(GetProcess(), vmModule, vmDomainFile)); + RSInitHolder pModuleInit(new CordbModule(GetProcess(), vmModule, vmDomainAssembly)); pModule = pModuleInit.TransferOwnershipToHash(&m_modules); // The appdomains should match. @@ -868,12 +868,12 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_D } -CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { INTERNAL_API_ENTRY(this); - _ASSERTE(!vmDomainFile.IsNull()); - return LookupOrCreateModule(VMPTR_Module::NullPtr(), vmDomainFile); + _ASSERTE(!vmDomainAssembly.IsNull()); + return LookupOrCreateModule(VMPTR_Module::NullPtr(), vmDomainAssembly); } @@ -890,7 +890,7 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) // invokes this callback. // static -void CordbAppDomain::ModuleEnumerationCallback(VMPTR_DomainFile vmModule, void * pUserData) +void CordbAppDomain::ModuleEnumerationCallback(VMPTR_DomainAssembly vmModule, void * pUserData) { CONTRACTL { diff --git a/src/coreclr/debug/di/rsclass.cpp b/src/coreclr/debug/di/rsclass.cpp index 40d886de9935e5..4fe8930712a4ed 100644 --- a/src/coreclr/debug/di/rsclass.cpp +++ b/src/coreclr/debug/di/rsclass.cpp @@ -781,11 +781,11 @@ void CordbClass::Init(ClassLoadLevel desiredLoadLevel) if(desiredLoadLevel == FullInfo) { VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); - VMPTR_DomainFile vmDomainFile = m_pModule->GetRuntimeDomainFile(); - if (!vmDomainFile.IsNull()) + VMPTR_DomainAssembly vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); + if (!vmDomainAssembly.IsNull()) { - DomainFileInfo info; - pDac->GetDomainFileData(vmDomainFile, &info); + DomainAssemblyInfo info; + pDac->GetDomainAssemblyData(vmDomainAssembly, &info); vmAppDomain = info.vmAppDomain; } pDac->GetClassInfo(vmAppDomain, vmTypeHandle, &m_classInfo); @@ -941,7 +941,7 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, fieldToken, ELEMENT_TYPE_MAX, classToken, - m_pModule->GetRuntimeDomainFile()); + m_pModule->GetRuntimeDomainAssembly()); } else { @@ -966,7 +966,7 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, // This is used only for log messages, and could // be removed. classToken, // metadata token for the class - m_pModule->GetRuntimeDomainFile()); // Domain file for the class + m_pModule->GetRuntimeDomainAssembly()); // Domain file for the class } } // CordbClass::InitFieldData diff --git a/src/coreclr/debug/di/rsfunction.cpp b/src/coreclr/debug/di/rsfunction.cpp index b901a1ded88fea..f2384411bc0f2a 100644 --- a/src/coreclr/debug/di/rsfunction.cpp +++ b/src/coreclr/debug/di/rsfunction.cpp @@ -705,7 +705,7 @@ HRESULT CordbFunction::GetILCodeAndSigToken() // and we also fallback on creating an empty ILCode object. // See issue DD 273199 for cases where IL and NGEN metadata mismatch (different RVAs). ALLOW_DATATARGET_MISSING_OR_INCONSISTENT_MEMORY( - pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainFile(), + pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo, &localVarSigToken); @@ -782,7 +782,7 @@ HRESULT CordbFunction::InitParentClassOfFunction() } mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile = m_pModule->GetRuntimeDomainFile(); + VMPTR_DomainAssembly vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); classMetadataToken = InitParentClassOfFunctionHelper(m_MDToken); @@ -795,7 +795,7 @@ HRESULT CordbFunction::InitParentClassOfFunction() CordbAssembly *pAssembly = m_pModule->GetCordbAssembly(); PREFIX_ASSUME(pAssembly != NULL); - CordbModule* pClassModule = pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainFile); + CordbModule* pClassModule = pAssembly->GetAppDomain()->LookupOrCreateModule(vmDomainAssembly); PREFIX_ASSUME(pClassModule != NULL); CordbClass *pClass; @@ -850,7 +850,7 @@ HRESULT CordbFunction::InitNativeCodeInfo() // All we actually need is the start address and method desc which are cheap to get relative // to some of the other members. So far this doesn't appear to be a perf hotspot, but if it // shows up in some scenario it wouldn't be too hard to improve it - pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainFile(), m_MDToken, &codeInfo); + pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo); } // populate the m_nativeCode pointer with the code info we found @@ -904,7 +904,7 @@ HRESULT CordbFunction::SetJMCStatus(BOOL fIsUserCode) DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_SET_METHOD_JMC_STATUS, true, m_pModule->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_pModule->GetRuntimeDomainFile(); + event.SetJMCFunctionStatus.vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); event.SetJMCFunctionStatus.funcMetadataToken = m_MDToken; event.SetJMCFunctionStatus.dwStatus = fIsUserCode; @@ -956,7 +956,7 @@ HRESULT CordbFunction::GetJMCStatus(BOOL * pfIsUserCode) // Ask the left-side if a method is user code or not. DebuggerIPCEvent event; pProcess->InitIPCEvent(&event, DB_IPCE_GET_METHOD_JMC_STATUS, true, m_pModule->GetAppDomain()->GetADToken()); - event.SetJMCFunctionStatus.vmDomainFile = m_pModule->GetRuntimeDomainFile(); + event.SetJMCFunctionStatus.vmDomainAssembly = m_pModule->GetRuntimeDomainAssembly(); event.SetJMCFunctionStatus.funcMetadataToken = m_MDToken; diff --git a/src/coreclr/debug/di/rsmain.cpp b/src/coreclr/debug/di/rsmain.cpp index 5594b299e2d125..cc30e2c84136e3 100644 --- a/src/coreclr/debug/di/rsmain.cpp +++ b/src/coreclr/debug/di/rsmain.cpp @@ -961,15 +961,12 @@ Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion) } Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion, const ProcessDescriptor& pd) - : CordbBase(NULL, 0, enumCordb), - m_processes(11), - m_initialized(false), - m_debuggerSpecifiedVersion(iDebuggerVersion), - m_pd(pd) -#ifdef FEATURE_CORESYSTEM - , - m_targetCLR(0) -#endif + : CordbBase(NULL, 0, enumCordb) + , m_processes(11) + , m_initialized(false) + , m_debuggerSpecifiedVersion(iDebuggerVersion) + , m_pd(pd) + , m_targetCLR(0) { g_pRSDebuggingInfo->m_Cordb = this; @@ -1420,10 +1417,7 @@ HRESULT Cordb::SetTargetCLR(HMODULE hmodTargetCLR) if (m_initialized) return E_FAIL; -#ifdef FEATURE_CORESYSTEM m_targetCLR = hmodTargetCLR; -#endif - return S_OK; } @@ -1528,16 +1522,6 @@ bool Cordb::IsInteropDebuggingSupported() // We explicitly refrain from checking the unmanaged callback. See comment in // ICorDebug::SetUnmanagedHandler for details. #ifdef FEATURE_INTEROP_DEBUGGING - -#if !defined(FEATURE_CORESYSTEM) - // Interop debugging is only supported internally on CoreCLR. - // Check if the special reg key is set. If not, then we don't allow interop debugging. - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgEnableMixedModeDebugging) == 0) - { - return false; - } -#endif // FEATURE_CORESYSTEM - return true; #else return false; diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index 690917c2795a91..acb8d4c32473cd 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -2324,9 +2324,7 @@ class Cordb : public CordbBase, public ICorDebug, public ICorDebugRemote CorDebugInterfaceVersion GetDebuggerVersion() const; -#ifdef FEATURE_CORESYSTEM HMODULE GetTargetCLR() { return m_targetCLR; } -#endif private: bool IsCreateProcessSupported(); @@ -2347,11 +2345,7 @@ class Cordb : public CordbBase, public ICorDebug, public ICorDebugRemote // Store information about the process to be debugged ProcessDescriptor m_pd; -//Note - this code could be useful outside coresystem, but keeping the change localized -// because we are late in the win8 release -#ifdef FEATURE_CORESYSTEM HMODULE m_targetCLR; -#endif }; @@ -2511,13 +2505,13 @@ class CordbAppDomain : public CordbBase, CordbModule * GetModuleFromMetaDataInterface(IUnknown *pIMetaData); // Lookup a module from the cache. Create and to the cache if needed. - CordbModule * LookupOrCreateModule(VMPTR_Module vmModuleToken, VMPTR_DomainFile vmDomainFileToken); + CordbModule * LookupOrCreateModule(VMPTR_Module vmModuleToken, VMPTR_DomainAssembly vmDomainAssemblyToken); // Lookup a module from the cache. Create and to the cache if needed. - CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFileToken); + CordbModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssemblyToken); // Callback from DAC for module enumeration - static void ModuleEnumerationCallback(VMPTR_DomainFile vmModule, void * pUserData); + static void ModuleEnumerationCallback(VMPTR_DomainAssembly vmModule, void * pUserData); // Use DAC to add any modules for this assembly. void PrepopulateModules(); @@ -2549,7 +2543,7 @@ class CordbAppDomain : public CordbBase, // Cache of modules in this appdomain. In the VM, modules live in an assembly. // This cache lives on the appdomain because we generally want to do appdomain (or process) // wide lookup. - // This is indexed by VMPTR_DomainFile, which has appdomain affinity. + // This is indexed by VMPTR_DomainAssembly, which has appdomain affinity. // This is populated by code:CordbAppDomain::LookupOrCreateModule (which may be invoked // anytime the RS gets hold of a VMPTR), and are removed at the unload event. CordbSafeHashTable m_modules; @@ -3460,9 +3454,9 @@ class CordbProcess : // Looks up a previously constructed CordbClass instance without creating. May return NULL if the // CordbClass instance doesn't exist. - CordbClass * LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainFile vmDomainFile, mdTypeDef classToken); + CordbClass * LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_DomainAssembly vmDomainAssembly, mdTypeDef classToken); - CordbModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFile); + CordbModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly); #ifdef FEATURE_INTEROP_DEBUGGING CordbUnmanagedThread *GetUnmanagedThread(DWORD dwThreadId) @@ -4147,7 +4141,7 @@ class CordbModule : public CordbBase, public: CordbModule(CordbProcess * process, VMPTR_Module vmModule, - VMPTR_DomainFile vmDomainFile); + VMPTR_DomainAssembly vmDomainAssembly); virtual ~CordbModule(); virtual void Neuter(); @@ -4354,9 +4348,9 @@ class CordbModule : public CordbBase, const WCHAR * GetNGenImagePath(); - const VMPTR_DomainFile GetRuntimeDomainFile () + const VMPTR_DomainAssembly GetRuntimeDomainAssembly () { - return m_vmDomainFile; + return m_vmDomainAssembly; } const VMPTR_Module GetRuntimeModule() @@ -4391,7 +4385,7 @@ class CordbModule : public CordbBase, // The real handle into the VM for a module. This is appdomain aware. // This is the primary VM counterpart for the CordbModule. - VMPTR_DomainFile m_vmDomainFile; + VMPTR_DomainAssembly m_vmDomainAssembly; VMPTR_Module m_vmModule; @@ -4806,7 +4800,7 @@ class CordbType : public CordbBase, public ICorDebugType, public ICorDebugType2 void DestNaryType(Instantiation *pInst); CorElementType GetElementType() { return m_elementType; } - VMPTR_DomainFile GetDomainFile(); + VMPTR_DomainAssembly GetDomainAssembly(); VMPTR_Module GetModule(); // If this is a ptr type, get the CordbType that it points to. @@ -6266,10 +6260,6 @@ class CordbThread : public CordbBase, public ICorDebugThread, BOOL ConvertFrameForILMethodWithoutMetadata(ICorDebugFrame * pFrame, ICorDebugInternalFrame2 ** ppInternalFrame2); - // Gets/sets m_fCreationEventQueued - bool CreateEventWasQueued(); - void SetCreateEventQueued(); - //----------------------------------------------------------- // Data members //----------------------------------------------------------- @@ -6327,11 +6317,6 @@ class CordbThread : public CordbBase, public ICorDebugThread, // Both events will set this bit high. Be careful not to reset this bit inbetween them. bool m_fException; - // True if a creation event has been queued for this thread - // The event may or may not have been dispatched yet - // Bugfix DevDiv2\DevDiv 77523 - this is only being set from ShimProcess::QueueFakeThreadAttachEventsNativeOrder - bool m_fCreationEventQueued; - // Object handle for Exception object in debuggee. VMPTR_OBJECTHANDLE m_vmExcepObjHandle; diff --git a/src/coreclr/debug/di/rsstackwalk.cpp b/src/coreclr/debug/di/rsstackwalk.cpp index 42732435db409e..b115349593fc25 100644 --- a/src/coreclr/debug/di/rsstackwalk.cpp +++ b/src/coreclr/debug/di/rsstackwalk.cpp @@ -634,7 +634,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) _ASSERTE(pCurrentAppDomain != NULL); // Lookup the module - CordbModule* pModule = pCurrentAppDomain->LookupOrCreateModule(pFuncData->vmDomainFile); + CordbModule* pModule = pCurrentAppDomain->LookupOrCreateModule(pFuncData->vmDomainAssembly); PREFIX_ASSUME(pModule != NULL); // Create or look up a CordbNativeCode. There is one for each jitted instance of a method, diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 577574b796019c..38a498752771a6 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -81,7 +81,6 @@ CordbThread::CordbThread(CordbProcess * pProcess, VMPTR_Thread vmThread) : m_fFloatStateValid(false), m_floatStackTop(0), m_fException(false), - m_fCreationEventQueued(false), m_EnCRemapFunctionIP(NULL), m_userState(kInvalidUserState), m_hCachedThread(INVALID_HANDLE_VALUE), @@ -1630,8 +1629,8 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); - VMPTR_DomainFile vmDomainFile = pNativeCode->GetModule()->m_vmDomainFile; - _ASSERTE(!vmDomainFile.IsNull()); + VMPTR_DomainAssembly vmDomainAssembly = pNativeCode->GetModule()->m_vmDomainAssembly; + _ASSERTE(!vmDomainAssembly.IsNull()); // If this thread is stopped due to an exception, never allow SetIP if (HasException()) @@ -1643,7 +1642,7 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, GetProcess()->InitIPCEvent(&event, DB_IPCE_SET_IP, true, GetAppDomain()->GetADToken()); event.SetIP.fCanSetIPOnly = fCanSetIPOnly; event.SetIP.vmThreadToken = m_vmThreadToken; - event.SetIP.vmDomainFile = vmDomainFile; + event.SetIP.vmDomainAssembly = vmDomainAssembly; event.SetIP.mdMethod = pNativeCode->GetMetadataToken(); event.SetIP.vmMethodDesc = pNativeCode->GetVMNativeCodeMethodDescToken(); event.SetIP.startAddress = pNativeCode->GetAddress(); @@ -1655,7 +1654,7 @@ HRESULT CordbThread::SetIP(bool fCanSetIPOnly, "mod:0x%x MethodDef:0x%x offset:0x%x il?:0x%x\n", GetCurrentThreadId(), VmPtrToCookie(m_vmThreadToken), - VmPtrToCookie(vmDomainFile), + VmPtrToCookie(vmDomainAssembly), pNativeCode->GetMetadataToken(), offset, fIsIL)); @@ -2790,21 +2789,6 @@ HRESULT CordbThread::GetBlockingObjects(ICorDebugBlockingObjectEnum **ppBlocking return hr; } -// ---------------------------------------------------------------------------- -// CordbThread::SetCreateEventQueued -void CordbThread::SetCreateEventQueued() -{ - m_fCreationEventQueued = true; -} - -// ---------------------------------------------------------------------------- -// CordbThread::CreateEventWasQueued -bool CordbThread::CreateEventWasQueued() -{ - return m_fCreationEventQueued; -} - - #ifdef FEATURE_INTEROP_DEBUGGING /* ------------------------------------------------------------------------- * * Unmanaged Thread classes @@ -5265,7 +5249,7 @@ CordbInternalFrame::CordbInternalFrame(CordbThread * pThread, // Find the module of the function. Note that this module isn't necessarily in the same domain as our frame. // FuncEval frames can point to methods they are going to invoke in another domain. CordbModule * pModule = NULL; - pModule = GetProcess()->LookupOrCreateModule(pData->stubFrame.vmDomainFile); + pModule = GetProcess()->LookupOrCreateModule(pData->stubFrame.vmDomainAssembly); _ASSERTE(pModule != NULL); // @@ -9661,7 +9645,7 @@ HRESULT CordbEval::CallParameterizedFunction(ICorDebugFunction *pFunction, event.FuncEval.vmThreadToken = m_thread->m_vmThreadToken; event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = m_function->GetMetadataToken(); - event.FuncEval.vmDomainFile = m_function->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_function->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = nArgs; event.FuncEval.genericArgsCount = nTypeArgs; @@ -9844,7 +9828,7 @@ HRESULT CordbEval::NewParameterizedObject(ICorDebugFunction * pConstructor, event.FuncEval.vmThreadToken = m_thread->m_vmThreadToken; event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = m_function->GetMetadataToken(); - event.FuncEval.vmDomainFile = m_function->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_function->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = nArgs; event.FuncEval.genericArgsCount = nTypeArgs; @@ -9945,7 +9929,7 @@ HRESULT CordbEval::NewParameterizedObjectNoConstructor(ICorDebugClass * pClass, event.FuncEval.funcEvalType = m_evalType; event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = (mdTypeDef)m_class->m_id; - event.FuncEval.vmDomainFile = m_class->GetModule()->GetRuntimeDomainFile(); + event.FuncEval.vmDomainAssembly = m_class->GetModule()->GetRuntimeDomainAssembly(); event.FuncEval.funcEvalKey = hFuncEval.Ptr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = nTypeArgs; @@ -10040,7 +10024,7 @@ HRESULT CordbEval::NewStringWithLength(LPCWSTR wszString, UINT iLength) // Note: no function or module here... event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = mdTypeDefNil; - event.FuncEval.vmDomainFile = VMPTR_DomainFile::NullPtr(); + event.FuncEval.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = 0; event.FuncEval.genericArgsNodeCount = 0; @@ -10157,7 +10141,7 @@ HRESULT CordbEval::NewParameterizedArray(ICorDebugType * pElementType, // Note: no function or module here... event.FuncEval.funcMetadataToken = mdMethodDefNil; event.FuncEval.funcClassMetadataToken = mdTypeDefNil; - event.FuncEval.vmDomainFile = VMPTR_DomainFile::NullPtr(); + event.FuncEval.vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); event.FuncEval.argCount = 0; event.FuncEval.genericArgsCount = 1; diff --git a/src/coreclr/debug/di/rstype.cpp b/src/coreclr/debug/di/rstype.cpp index 3d807bb2434f53..af6a8f5e14a58e 100644 --- a/src/coreclr/debug/di/rstype.cpp +++ b/src/coreclr/debug/di/rstype.cpp @@ -1191,7 +1191,7 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Basic DebuggerIPCE_ExpandedTypeData e; e.elementType = et; e.ClassTypeData.metadataToken = data->metadataToken; - e.ClassTypeData.vmDomainFile = data->vmDomainFile; + e.ClassTypeData.vmDomainAssembly = data->vmDomainAssembly; e.ClassTypeData.vmModule = data->vmModule; e.ClassTypeData.typeHandle = data->vmTypeHandle; return CordbType::TypeDataToType(pAppDomain, &e, pRes); @@ -1254,7 +1254,7 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Expan CordbModule * pClassModule = NULL; EX_TRY { - pClassModule = pAppDomain->LookupOrCreateModule(data->ClassTypeData.vmModule, data->ClassTypeData.vmDomainFile); + pClassModule = pAppDomain->LookupOrCreateModule(data->ClassTypeData.vmModule, data->ClassTypeData.vmDomainAssembly); } EX_CATCH_HRESULT(hr); if( pClassModule == NULL ) @@ -1611,7 +1611,7 @@ HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit) // CordbProcess *pProcess = GetProcess(); mdTypeDef metadataToken; - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); VMPTR_Module vmModule = VMPTR_Module::NullPtr(); { @@ -1620,13 +1620,13 @@ HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit) m_elementType, &metadataToken, &vmModule, - &vmDomainFile); + &vmDomainAssembly); } // // Step 2) Lookup CordbClass based off token + Module. // - CordbModule * pTypeModule = m_appdomain->LookupOrCreateModule(vmModule, vmDomainFile); + CordbModule * pTypeModule = m_appdomain->LookupOrCreateModule(vmModule, vmDomainAssembly); _ASSERTE(pTypeModule != NULL); IfFailThrow(pTypeModule->LookupOrCreateClass(metadataToken, &m_pClass)); @@ -1704,7 +1704,7 @@ HRESULT CordbType::InitInstantiationFieldInfo(BOOL fForceInit) // this may be called multiple times. Each call will discard previous values in m_fieldList and reinitialize // the list with updated information RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainFile(), + pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainAssembly(), m_typeHandleExact, typeHandleApprox, &m_fieldList, @@ -1876,23 +1876,23 @@ CordbType::GetUnboxedObjectSize(ULONG32 *pObjectSize) } } -VMPTR_DomainFile CordbType::GetDomainFile() +VMPTR_DomainAssembly CordbType::GetDomainAssembly() { if (m_pClass != NULL) { CordbModule * pModule = m_pClass->GetModule(); if (pModule) { - return pModule->m_vmDomainFile; + return pModule->m_vmDomainAssembly; } else { - return VMPTR_DomainFile::NullPtr(); + return VMPTR_DomainAssembly::NullPtr(); } } else { - return VMPTR_DomainFile::NullPtr(); + return VMPTR_DomainAssembly::NullPtr(); } } @@ -1937,7 +1937,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) case ELEMENT_TYPE_PTR: data->elementType = m_elementType; data->metadataToken = mdTokenNil; - data->vmDomainFile = VMPTR_DomainFile::NullPtr(); + data->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); data->vmTypeHandle = m_typeHandleExact; if (data->vmTypeHandle.IsNull()) { @@ -1950,7 +1950,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) _ASSERTE(m_pClass != NULL); data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS; data->metadataToken = m_pClass->MDToken(); - data->vmDomainFile = GetDomainFile(); + data->vmDomainAssembly = GetDomainAssembly(); data->vmTypeHandle = m_typeHandleExact; if (m_pClass->HasTypeParams() && data->vmTypeHandle.IsNull()) { @@ -1961,7 +1961,7 @@ HRESULT CordbType::TypeToBasicTypeData(DebuggerIPCE_BasicTypeData *data) // This includes all the "primitive" types, in which CorElementType is a sufficient description. data->elementType = m_elementType; data->metadataToken = mdTokenNil; - data->vmDomainFile = VMPTR_DomainFile::NullPtr(); + data->vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); data->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); break; } @@ -2001,7 +2001,7 @@ void CordbType::TypeToExpandedTypeData(DebuggerIPCE_ExpandedTypeData *data) { data->elementType = m_pClass->IsValueClassNoInit() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS; data->ClassTypeData.metadataToken = m_pClass->GetToken(); - data->ClassTypeData.vmDomainFile = GetDomainFile(); + data->ClassTypeData.vmDomainAssembly = GetDomainAssembly(); data->ClassTypeData.vmModule = GetModule(); data->ClassTypeData.typeHandle = VMPTR_TypeHandle::NullPtr(); @@ -2339,14 +2339,14 @@ HRESULT CordbType::GetTypeID(COR_TYPEID *pId) { mdTypeDef mdToken; VMPTR_Module vmModule = VMPTR_Module::NullPtr(); - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); // get module and token of the simple type GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), et, &mdToken, &vmModule, - &vmDomainFile); + &vmDomainAssembly); vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); } diff --git a/src/coreclr/debug/di/shimpriv.h b/src/coreclr/debug/di/shimpriv.h index 26a939ee8a3a8e..15efec56473493 100644 --- a/src/coreclr/debug/di/shimpriv.h +++ b/src/coreclr/debug/di/shimpriv.h @@ -426,9 +426,6 @@ class ShimProcess // Helper to queue fake assembly and mdule events void QueueFakeAssemblyAndModuleEvent(ICorDebugAssembly * pAssembly); - // Queue fake thread-create events on attach. Order via native threads. - HRESULT QueueFakeThreadAttachEventsNativeOrder(); - // Queue fake thread-create events on attach. No ordering. HRESULT QueueFakeThreadAttachEventsNoOrder(); @@ -491,9 +488,6 @@ class ShimProcess // dispatching an event. void PreDispatchEvent(bool fRealCreateProcessEvent = false); - // Look for a CLR in the process and if found, return it's instance ID - HRESULT FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId); - // Retrieve the IP address and the port number of the debugger proxy. MachineInfo GetMachineInfo(); @@ -526,9 +520,6 @@ class ShimProcess HANDLE m_markAttachPendingEvent; HANDLE m_terminatingEvent; - // Finds the base address of [core]clr.dll - CORDB_ADDRESS GetCLRInstanceBaseAddress(); - // // Event Queues // diff --git a/src/coreclr/debug/di/shimprocess.cpp b/src/coreclr/debug/di/shimprocess.cpp index 72da6068e8235b..8d60f954b4a714 100644 --- a/src/coreclr/debug/di/shimprocess.cpp +++ b/src/coreclr/debug/di/shimprocess.cpp @@ -17,10 +17,6 @@ #include #include "shimpriv.h" -#if !defined(FEATURE_CORESYSTEM) -#include -#endif - //--------------------------------------------------------------------------------------- // // Ctor for a ShimProcess @@ -871,8 +867,6 @@ HRESULT ShimProcess::HandleWin32DebugEvent(const DEBUG_EVENT * pEvent) if (!fSkipResume) { ::Sleep(500); - hrIgnore = GetNativePipeline()->EnsureThreadsRunning(); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hrIgnore); } } } @@ -1020,9 +1014,6 @@ void ShimProcess::QueueFakeAttachEventsIfNeeded(bool fRealCreateProcessEvent) // same order that V2 used. So without using platform-specific thread-enumeration, // we can't get the V2 ordering. // -// Compare to code:ShimProcess::QueueFakeThreadAttachEventsNativeOrder, -// which sends threads in the OS native thread create order. -// HRESULT ShimProcess::QueueFakeThreadAttachEventsNoOrder() { ICorDebugProcess * pProcess = GetProcess(); @@ -1061,136 +1052,6 @@ HRESULT ShimProcess::QueueFakeThreadAttachEventsNoOrder() return S_OK; } -//--------------------------------------------------------------------------------------- -// Send fake Thread-create events for attach, using the order of the OS native -// thread list. -// -// Returns: -// S_OK on success, else error. -// -// Notes: -// This sends fake thread-create events, ala V2 attach. -// See code:ShimProcess::QueueFakeAttachEvents for details -// The order of the thread creates matches the OS's native thread list. -// This is important because the debugger can use the order of thread-create -// callbacks to associate logical thread-ids (0,1,2...) with threads. Users -// may rely on thread 0 always being the main thread. -// In contrast, the order from ICorDebugProcess::EnumerateThreads is random. -// -// Compare to code:ShimProcess::QueueFakeThreadAttachEventsNoOrder, which -// sends the threads in an arbitrary order. -HRESULT ShimProcess::QueueFakeThreadAttachEventsNativeOrder() -{ -#ifdef FEATURE_CORESYSTEM - _ASSERTE("NYI"); - return E_FAIL; -#else - ICorDebugProcess * pProcess = GetProcess(); - - DWORD dwProcessId; - HRESULT hr = pProcess->GetID(&dwProcessId); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - if (FAILED(hr)) - { - return hr; - } - - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - { - hr = HRESULT_FROM_GetLastError(); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - return hr; - } - // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. - HandleHolder hSnapshotHolder(hThreadSnap); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - { - hr = HRESULT_FROM_GetLastError(); - return hr; - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwProcessId) - { - RSExtSmartPtr pThread; - pProcess->GetThread(te32.th32ThreadID, &pThread); - if (pThread != NULL) - { - // If we fail to get the appdomain for some reason, then then - // we can't dispatch this thread callback. But we can still - // finish enumerating. - RSExtSmartPtr pAppDomain; - HRESULT hrGetAppDomain = pThread->GetAppDomain(&pAppDomain); - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hrGetAppDomain); - if (pAppDomain != NULL) - { - GetShimCallback()->CreateThread(pAppDomain, pThread); - AddDuplicateCreationEvent(pThread); - - //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications - // mark that this thread has queued a create event - CordbThread* pThreadInternal = static_cast(pThread.GetValue()); - pThreadInternal->SetCreateEventQueued(); - } - } - } - } while(Thread32Next(hThreadSnap, &te32)); - - - //fix for issue DevDiv2\DevDiv 77523 - threads are switched out in SQL don't get thread create notifications - // - - - // Threads which were switched out won't be present in the native thread order enumeration above. - // In order to not miss them we will enumerate all the managed thread objects and for any that we haven't - // already queued a notification for, we will queue a notification now. - RSExtSmartPtr pThreadEnum; - RSExtSmartPtr pThread; - hr = pProcess->EnumerateThreads(&pThreadEnum); - if (FAILED(hr)) - { - return hr; - } - - ULONG cDummy; - - while(SUCCEEDED(pThreadEnum->Next(1, &pThread, &cDummy)) && (pThread != NULL)) - { - RSExtSmartPtr pAppDomain; - hr = pThread->GetAppDomain(&pAppDomain); - CordbThread* pThreadInternal = static_cast(pThread.GetValue()); - - // Getting the appdomain shouldn't fail. If it does, we can't dispatch - // this callback, but we can still dispatch the other thread creates. - SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); - if (pAppDomain != NULL && !pThreadInternal->CreateEventWasQueued()) - { - GetShimCallback()->CreateThread(pAppDomain, pThread); - AddDuplicateCreationEvent(pThread); - pThreadInternal->SetCreateEventQueued(); - } - pThread.Clear(); - } - - - return S_OK; -#endif -} - //--------------------------------------------------------------------------------------- // Queues the fake Assembly and Module load events // @@ -1476,15 +1337,9 @@ void ShimProcess::QueueFakeAttachEvents() // // Third, Queue all Threads // -#if !defined(FEATURE_DBGIPC_TRANSPORT_DI) && !defined(FEATURE_CORESYSTEM) - // Use OS thread enumeration facilities to ensure that the managed thread - // thread order is the same as the corresponding native thread order. - QueueFakeThreadAttachEventsNativeOrder(); -#else // Use ICorDebug to enumerate threads. The order of managed threads may // not match the order the threads were created in. QueueFakeThreadAttachEventsNoOrder(); -#endif // Forth, Queue all Connections. // Enumerate connections is not exposed through ICorDebug, so we need to go use a private hook on CordbProcess. @@ -1730,86 +1585,6 @@ void ShimProcess::PreDispatchEvent(bool fRealCreateProcessEvent /*= false*/) } -// ---------------------------------------------------------------------------- -// ShimProcess::GetCLRInstanceBaseAddress -// Finds the base address of [core]clr.dll -// Arguments: none -// Return value: returns the base address of [core]clr.dll if possible or NULL otherwise -// -CORDB_ADDRESS ShimProcess::GetCLRInstanceBaseAddress() -{ - CORDB_ADDRESS baseAddress = CORDB_ADDRESS(NULL); - DWORD dwPid = m_pLiveDataTarget->GetPid(); - -#if defined(FEATURE_CORESYSTEM) - // Debugger attaching to CoreCLR via CoreCLRCreateCordbObject should have already specified CLR module address. - // Code that help to find it now lives in dbgshim. -#else - // get a "snapshot" of all modules in the target - HandleHolder hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid); - MODULEENTRY32 moduleEntry = { 0 }; - - if (hSnapshot == INVALID_HANDLE_VALUE) - { - // we haven't got a loaded CLR yet - baseAddress = CORDB_ADDRESS(NULL); - } - else - { - // we need to loop through the modules until we find mscorwks.dll - moduleEntry.dwSize = sizeof(MODULEENTRY32); - - if (!Module32First(hSnapshot, &moduleEntry)) - { - baseAddress = CORDB_ADDRESS(NULL); - } - else - { - - do - { - if (!_wcsicmp(moduleEntry.szModule, MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W))) - { - // we found it, so save the base address - baseAddress = PTR_TO_CORDB_ADDRESS(moduleEntry.modBaseAddr); - } - } while (Module32Next(hSnapshot, &moduleEntry)); - } - } -#endif - return baseAddress; -} // ShimProcess::GetCLRInstanceBaseAddress - -// ---------------------------------------------------------------------------- -// ShimProcess::FindLoadedCLR -// -// Description: -// Look for any CLR loaded into the process. If found, return the instance ID for it. -// -// Arguments: -// * pClrInstanceId - out parameter for the instance ID of the CLR -// -// Return Value: -// Returns S_OK if a CLR was found, and stores its instance ID in pClrInstanceId. -// Otherwise returns an error code. -// -// Notes: -// If there are multiple CLRs loaded in the process, the one chosen for the returned -// instance ID is unspecified. -// -HRESULT ShimProcess::FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId) -{ - *pClrInstanceId = GetCLRInstanceBaseAddress(); - - if (*pClrInstanceId == 0) - { - return E_UNEXPECTED; - } - - return S_OK; -} - - //--------------------------------------------------------------------------------------- // // Locates DAC by finding mscordac{wks|core} next to DBI diff --git a/src/coreclr/debug/di/windowspipeline.cpp b/src/coreclr/debug/di/windowspipeline.cpp index cea89e73874001..68ac4a216c6605 100644 --- a/src/coreclr/debug/di/windowspipeline.cpp +++ b/src/coreclr/debug/di/windowspipeline.cpp @@ -92,14 +92,7 @@ class WindowsNativePipeline : // Terminate the debuggee process. virtual BOOL TerminateProcess(UINT32 exitCode); - // Resume any suspended threads - virtual HRESULT EnsureThreadsRunning(); - protected: - void UpdateDebugSetProcessKillOnExit(); - - HRESULT IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent); - // Cached value from DebugSetProcessKillOnExit. // This is thread-local, and impacts all debuggees on the thread. bool m_fKillOnExit; @@ -125,46 +118,10 @@ BOOL WindowsNativePipeline::DebugSetProcessKillOnExit(bool fKillOnExit) { // Can't call kernel32!DebugSetProcessKillOnExit until after the event thread // has spawned a debuggee. So cache the value now and call it later. - // This bit is enforced in code:WindowsNativePipeline::UpdateDebugSetProcessKillOnExit m_fKillOnExit = fKillOnExit; return TRUE; } -// Enforces the bit set in code:WindowsNativePipeline::DebugSetProcessKillOnExit -void WindowsNativePipeline::UpdateDebugSetProcessKillOnExit() -{ -#if !defined(FEATURE_CORESYSTEM) - // Late bind to DebugSetProcessKillOnExit - WinXP and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - SIMPLIFYING_ASSUMPTION(hKernel32 != NULL); - if (hKernel32 == NULL) - return; - - typedef BOOL (*DebugSetProcessKillOnExitSig) (BOOL); - DebugSetProcessKillOnExitSig pDebugSetProcessKillOnExit = - reinterpret_cast(GetProcAddress(hKernel32, "DebugSetProcessKillOnExit")); - - // If the API doesn't exist (eg. Win2k) - there isn't anything we can do, just - // silently ignore the request. - if (pDebugSetProcessKillOnExit == NULL) - return; - - BOOL ret = pDebugSetProcessKillOnExit(m_fKillOnExit); - - // Not a good failure path here. - // 1) This shouldn't fail. - // 2) Even if it does, this is likely called after the debuggee - // has already been created, and if this API fails, most scenarios will - // be unaffected, so we don't want to fail the overall debugging session. - SIMPLIFYING_ASSUMPTION(ret); - -#else - // The API doesn't exit on CoreSystem, just return - return; -#endif -} - // Create an process under the debugger. HRESULT WindowsNativePipeline::CreateProcessUnderDebugger( MachineInfo machineInfo, @@ -199,7 +156,6 @@ HRESULT WindowsNativePipeline::CreateProcessUnderDebugger( } m_dwProcessId = lpProcessInformation->dwProcessId; - UpdateDebugSetProcessKillOnExit(); return S_OK; } @@ -213,104 +169,23 @@ HRESULT WindowsNativePipeline::DebugActiveProcess(MachineInfo machineInfo, const { hr = S_OK; m_dwProcessId = processDescriptor.m_Pid; - UpdateDebugSetProcessKillOnExit(); } else { hr = HRESULT_FROM_GetLastError(); - - // There are at least two scenarios in which DebugActiveProcess() returns E_INVALIDARG: - // 1) if the specified process doesn't exist, or - // 2) if the specified process already has a debugger atttached - // We need to distinguish these two cases in order to return the correct HR. - if (hr == E_INVALIDARG) - { - // Check whether a debugger is known to be already attached. - // Note that this API won't work on some OSes, in which case we err on the side of returning E_INVALIDARG - // even though a debugger may be attached. Another approach could be to assume that if - // OpenProcess succeeded, then DebugActiveProcess must only have failed because a debugger is - // attached. But I think it's better to only return the specific error code if we know for sure - // the case is true. - BOOL fIsDebuggerPresent = FALSE; - if (SUCCEEDED(IsRemoteDebuggerPresent(processDescriptor.m_Pid, &fIsDebuggerPresent))) - { - if (fIsDebuggerPresent) - { - hr = CORDBG_E_DEBUGGER_ALREADY_ATTACHED; - } - } - } } return hr; } -// Determine (if possible) whether a debugger is attached to the target process -HRESULT WindowsNativePipeline::IsRemoteDebuggerPresent(DWORD processId, BOOL* pfDebuggerPresent) -{ -#if !defined(FEATURE_CORESYSTEM) - - // Get a process handle for the process ID. - HandleHolder hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId); - if (hProc == NULL) - return HRESULT_FROM_GetLastError(); - - // Delay-bind to CheckRemoteDebuggerPresent - WinXP SP1 and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - - typedef BOOL (*CheckRemoteDebuggerPresentSig) (HANDLE, PBOOL); - CheckRemoteDebuggerPresentSig pCheckRemoteDebuggerPresent = - reinterpret_cast(GetProcAddress(hKernel32, "CheckRemoteDebuggerPresent")); - if (pCheckRemoteDebuggerPresent == NULL) - return HRESULT_FROM_GetLastError(); - - // API exists - call it - if (!pCheckRemoteDebuggerPresent(hProc, pfDebuggerPresent)) - return HRESULT_FROM_GetLastError(); - - return S_OK; -#else - - //CoreSystem doesn't have this API - return E_FAIL; -#endif -} - // Detach HRESULT WindowsNativePipeline::DebugActiveProcessStop(DWORD processId) { -#if !defined(FEATURE_CORESYSTEM) - // Late-bind to DebugActiveProcessStop since it's WinXP and above only - HModuleHolder hKernel32; - hKernel32 = WszLoadLibrary(W("kernel32")); - if (hKernel32 == NULL) - return HRESULT_FROM_GetLastError(); - - typedef BOOL (*DebugActiveProcessStopSig) (DWORD); - DebugActiveProcessStopSig pDebugActiveProcessStop = - reinterpret_cast(GetProcAddress(hKernel32, "DebugActiveProcessStop")); - - // Win2K will fail here - can't find DebugActiveProcessStop - if (pDebugActiveProcessStop == NULL) - return HRESULT_FROM_GetLastError(); - - // Ok, the API exists, call it - if (!pDebugActiveProcessStop(processId)) - { - // Detach itself failed - return HRESULT_FROM_GetLastError(); - } -#else - // The API exists, call it if (!::DebugActiveProcessStop(processId)) { // Detach itself failed return HRESULT_FROM_GetLastError(); } -#endif return S_OK; } @@ -359,60 +234,3 @@ BOOL WindowsNativePipeline::TerminateProcess(UINT32 exitCode) return ::TerminateProcess(hProc, exitCode); } - -// Resume any suspended threads (but just once) -HRESULT WindowsNativePipeline::EnsureThreadsRunning() -{ -#ifdef FEATURE_CORESYSTEM - _ASSERTE("NYI"); - return E_FAIL; -#else - _ASSERTE(m_dwProcessId != 0); - - // Take a snapshot of all running threads (similar to ShimProcess::QueueFakeThreadAttachEventsNativeOrder) - // Alternately we could return thread creation/exit in WaitForDebugEvent. But we expect this to be used - // very rarely, so no need to complicate more common codepaths. - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return HRESULT_FROM_GetLastError(); - - // HandleHolder doesn't deal with INVALID_HANDLE_VALUE, so we only assign if we have a legal value. - HandleHolder hSnapshotHolder(hThreadSnap); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - return HRESULT_FROM_GetLastError(); - - // Now walk the thread list of the system and attempt to resume any that are part of this process - // Ignore errors - this is a best effort (but ASSERT in CHK builds since we don't expect errors - // in practice - we expect the process to be frozen at a debug event, so no races etc.) - - HRESULT hr = S_FALSE; // no thread was resumed - do - { - if (te32.th32OwnerProcessID == m_dwProcessId) - { - HandleHolder hThread = ::OpenThread(THREAD_SUSPEND_RESUME, FALSE, te32.th32ThreadID); - _ASSERTE(hThread != NULL); - if (hThread != NULL) - { - // Resume each thread exactly once (if they were suspended multiple times, - // then EnsureThreadsRunning would need to be called multiple times until it - // returned S_FALSE. - DWORD prevCount = ::ResumeThread(hThread); - _ASSERTE(prevCount >= 0); - if (prevCount >= 1) - hr = S_OK; // some thread was resumed - } - } - } while(Thread32Next(hThreadSnap, &te32)); - - return hr; -#endif -} diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 1e326e724250b6..bd96c50fc59d31 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -1347,7 +1347,7 @@ DebuggerEval::DebuggerEval(CONTEXT * pContext, DebuggerIPCE_FuncEvalInfo * pEval // could get unloaded between now and when the funceval actually starts. So we stash an // AppDomain ID which is safe to use after the AD is unloaded. It's only safe to // use the DebuggerModule* after we've verified the ADID is still valid (i.e. by entering that domain). - m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainFile); + m_debuggerModule = g_pDebugger->LookupOrCreateModule(pEvalInfo->vmDomainAssembly); m_funcEvalKey = pEvalInfo->funcEvalKey; m_argCount = pEvalInfo->argCount; m_targetCodeAddr = NULL; @@ -5187,10 +5187,10 @@ void Debugger::SendSyncCompleteIPCEvent(bool isEESuspendedForGC) } // -// Lookup or create a DebuggerModule for the given pDomainFile. +// Lookup or create a DebuggerModule for the given pDomainAssembly. // // Arguments: -// pDomainFile - non-null domain file. +// pDomainAssembly - non-null domain file. // // Returns: // DebuggerModule instance for the given domain file. May be lazily created. @@ -5199,36 +5199,36 @@ void Debugger::SendSyncCompleteIPCEvent(bool isEESuspendedForGC) // @dbgtodo JMC - this should go away when we get rid of DebuggerModule. // -DebuggerModule * Debugger::LookupOrCreateModule(DomainFile * pDomainFile) +DebuggerModule * Debugger::LookupOrCreateModule(DomainAssembly * pDomainAssembly) { - _ASSERTE(pDomainFile != NULL); - LOG((LF_CORDB, LL_INFO1000, "D::LOCM df=0x%x\n", pDomainFile)); - DebuggerModule * pDModule = LookupOrCreateModule(pDomainFile->GetModule(), pDomainFile->GetAppDomain()); - LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pDomainFile->GetModule(), pDomainFile->GetAppDomain(), pDModule)); + _ASSERTE(pDomainAssembly != NULL); + LOG((LF_CORDB, LL_INFO1000, "D::LOCM df=0x%x\n", pDomainAssembly)); + DebuggerModule * pDModule = LookupOrCreateModule(pDomainAssembly->GetModule(), pDomainAssembly->GetAppDomain()); + LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x\n", pDomainAssembly->GetModule(), pDomainAssembly->GetAppDomain(), pDModule)); _ASSERTE(pDModule != NULL); - _ASSERTE(pDModule->GetDomainFile() == pDomainFile); + _ASSERTE(pDModule->GetDomainAssembly() == pDomainAssembly); return pDModule; } -// Overloaded Wrapper around for VMPTR_DomainFile-->DomainFile* +// Overloaded Wrapper around for VMPTR_DomainAssembly-->DomainAssembly* // // Arguments: -// vmDomainFile - VMPTR cookie for a domain file. This can be NullPtr(). +// vmDomainAssembly - VMPTR cookie for a domain file. This can be NullPtr(). // // Returns: // Debugger Module instance for the given domain file. May be lazily created. // // Notes: // VMPTR comes from IPC events -DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainFile vmDomainFile) +DebuggerModule * Debugger::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly) { - DomainFile * pDomainFile = vmDomainFile.GetRawPtr(); - if (pDomainFile == NULL) + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetRawPtr(); + if (pDomainAssembly == NULL) { return NULL; } - return LookupOrCreateModule(pDomainFile); + return LookupOrCreateModule(pDomainAssembly); } // Lookup or create a DebuggerModule for the given (Module, AppDomain) pair. @@ -5281,9 +5281,9 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD HRESULT hr = S_OK; EX_TRY { - DomainFile * pDomainFile = pModule->GetDomainFile(); - SIMPLIFYING_ASSUMPTION(pDomainFile != NULL); - dmod = AddDebuggerModule(pDomainFile); // throws + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); + SIMPLIFYING_ASSUMPTION(pDomainAssembly != NULL); + dmod = AddDebuggerModule(pDomainAssembly); // throws } EX_CATCH_HRESULT(hr); SIMPLIFYING_ASSUMPTION(dmod != NULL); // may not be true in OOM cases; but LS doesn't handle OOM. @@ -5293,19 +5293,19 @@ DebuggerModule* Debugger::LookupOrCreateModule(Module* pModule, AppDomain *pAppD _ASSERTE( (dmod == NULL) || (dmod->GetAppDomain() == pAppDomain) ); LOG((LF_CORDB, LL_INFO1000, "D::LOCM m=0x%x ad=0x%x -> dm=0x%x(Mod=0x%x, DomFile=0x%x, AD=0x%x)\n", - pModule, pAppDomain, dmod, dmod->GetRuntimeModule(), dmod->GetDomainFile(), dmod->GetAppDomain())); + pModule, pAppDomain, dmod, dmod->GetRuntimeModule(), dmod->GetDomainAssembly(), dmod->GetAppDomain())); return dmod; } // Create a new DebuggerModule object // // Arguments: -// pDomainFile- runtime domain file to create debugger module object around +// pDomainAssembly- runtime domain file to create debugger module object around // // Returns: // New instnace of a DebuggerModule. Throws on failure. // -DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) +DebuggerModule* Debugger::AddDebuggerModule(DomainAssembly * pDomainAssembly) { CONTRACTL { @@ -5314,16 +5314,16 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) } CONTRACTL_END; - LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainFile)); + LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x\n", pDomainAssembly)); DebuggerDataLockHolder chInfo(this); - Module * pRuntimeModule = pDomainFile->GetCurrentModule(); - AppDomain * pAppDomain = pDomainFile->GetAppDomain(); + Module * pRuntimeModule = pDomainAssembly->GetModule(); + AppDomain * pAppDomain = pDomainAssembly->GetAppDomain(); HRESULT hr = CheckInitModuleTable(); IfFailThrow(hr); - DebuggerModule* pModule = new (interopsafe) DebuggerModule(pRuntimeModule, pDomainFile, pAppDomain); + DebuggerModule* pModule = new (interopsafe) DebuggerModule(pRuntimeModule, pDomainAssembly, pAppDomain); _ASSERTE(pModule != NULL); // throws on oom TRACE_ALLOC(pModule); @@ -5332,7 +5332,7 @@ DebuggerModule* Debugger::AddDebuggerModule(DomainFile * pDomainFile) // @dbgtodo inspection/exceptions - this may leak module in OOM case. LS is not OOM resilient; and we // expect to get rid of DebuggerModule anyways. - LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x -> dm=0x%x\n", pDomainFile, pModule)); + LOG((LF_CORDB, LL_INFO1000, "D::ADM df=0x%x -> dm=0x%x\n", pDomainAssembly, pModule)); return pModule; } @@ -6246,7 +6246,7 @@ void Debugger::LockAndSendEnCRemapEvent(DebuggerJitInfo * dji, SIZE_T currentIP, Module *pRuntimeModule = pFD->GetModule(); DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); - ipce->EnCRemap.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + ipce->EnCRemap.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRE: %s::%s " "dmod:0x%x, methodDef:0x%x \n", @@ -6315,7 +6315,7 @@ void Debugger::LockAndSendEnCRemapCompleteEvent(MethodDesc *pFD) Module *pRuntimeModule = pFD->GetModule(); DebuggerModule * pDModule = LookupOrCreateModule(pRuntimeModule, thread->GetDomain()); - ipce->EnCRemapComplete.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + ipce->EnCRemapComplete.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); LOG((LF_CORDB, LL_INFO10000, "D::LASEnCRC: %s::%s " @@ -6381,7 +6381,7 @@ void Debugger::SendEnCUpdateEvent(DebuggerIPCEventType eventType, _ASSERTE(pModule->GetDomain()->IsAppDomain()); DebuggerModule * pDModule = LookupOrCreateModule(pModule, pModule->GetDomain()->AsAppDomain()); - event->EnCUpdate.vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + event->EnCUpdate.vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); m_pRCThread->SendIPCEvent(); @@ -9426,7 +9426,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, DWORD dwModuleName, // length of pszModuleName in chars, not including null. Assembly *pAssembly, AppDomain *pAppDomain, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching) { @@ -9461,13 +9461,13 @@ void Debugger::LoadModule(Module* pRuntimeModule, { // The loader lookups may throw or togggle GC mode, so do them inside a TRY/Catch and // outside any debugger locks. - Module * pManifestModule = pRuntimeModule->GetAssembly()->GetManifestModule(); + Module * pManifestModule = pRuntimeModule->GetAssembly()->GetModule(); _ASSERTE(pManifestModule != pRuntimeModule); _ASSERTE(pManifestModule->IsManifest()); _ASSERTE(pManifestModule->GetAssembly() == pRuntimeModule->GetAssembly()); - DomainFile * pManifestDomainFile = pManifestModule->GetDomainFile(); + DomainAssembly * pManifestDomainAssembly = pManifestModule->GetDomainAssembly(); DebuggerLockHolder dbgLockHolder(this); @@ -9477,7 +9477,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, DebuggerIPCEvent eventMetadataUpdate; InitIPCEvent(&eventMetadataUpdate, DB_IPCE_METADATA_UPDATE, NULL, pAppDomain); - eventMetadataUpdate.MetadataUpdateData.vmDomainFile.SetRawPtr(pManifestDomainFile); + eventMetadataUpdate.MetadataUpdateData.vmDomainAssembly.SetRawPtr(pManifestDomainAssembly); SendRawEvent(&eventMetadataUpdate); } @@ -9499,7 +9499,7 @@ void Debugger::LoadModule(Module* pRuntimeModule, // The RS has logic to ignore duplicate ModuleLoad events. We have to send what could possibly be a dup, though, // due to some really nasty issues with getting proper assembly and module load events from the loader when dealing // with shared assemblies. - module = LookupOrCreateModule(pDomainFile); + module = LookupOrCreateModule(pDomainAssembly); _ASSERTE(module != NULL); @@ -9509,18 +9509,18 @@ void Debugger::LoadModule(Module* pRuntimeModule, module->SetCanChangeJitFlags(true); - // @dbgtodo inspection - Check whether the DomainFile we get is consistent with the Module and AppDomain we get. + // @dbgtodo inspection - Check whether the DomainAssembly we get is consistent with the Module and AppDomain we get. // We should simply things when we actually get rid of DebuggerModule, possibly by just passing the - // DomainFile around. - _ASSERTE(module->GetDomainFile() == pDomainFile); - _ASSERTE(module->GetAppDomain() == pDomainFile->GetAppDomain()); - _ASSERTE(module->GetRuntimeModule() == pDomainFile->GetModule()); + // DomainAssembly around. + _ASSERTE(module->GetDomainAssembly() == pDomainAssembly); + _ASSERTE(module->GetAppDomain() == pDomainAssembly->GetAppDomain()); + _ASSERTE(module->GetRuntimeModule() == pDomainAssembly->GetModule()); // Send a load module event to the Right Side. ipce = m_pRCThread->GetIPCEventSendBuffer(); InitIPCEvent(ipce,DB_IPCE_LOAD_MODULE, pThread, pAppDomain); - ipce->LoadModuleData.vmDomainFile.SetRawPtr(pDomainFile); + ipce->LoadModuleData.vmDomainAssembly.SetRawPtr(pDomainAssembly); m_pRCThread->SendIPCEvent(); @@ -9588,7 +9588,7 @@ void Debugger::SendRawUpdateModuleSymsEvent(Module *pRuntimeModule, AppDomain *p g_pEEInterface->GetThread(), pAppDomain); - ipce->UpdateModuleSymsData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL)); + ipce->UpdateModuleSymsData.vmDomainAssembly.SetRawPtr((module ? module->GetDomainAssembly() : NULL)); m_pRCThread->SendIPCEvent(); } @@ -9695,8 +9695,8 @@ 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(), false, - module, module->GetRuntimeModule(), module->GetDomainFile()); + pRuntimeModule, pRuntimeModule->GetDomainAssembly(), false, + module, module->GetRuntimeModule(), module->GetDomainAssembly()); // Note: the appdomain the module was loaded in must match the appdomain we're unloading it from. If it doesn't, // then we've either found the wrong DebuggerModule in LookupModule or we were passed bad data. @@ -9705,7 +9705,7 @@ void Debugger::UnloadModule(Module* pRuntimeModule, // Send the unload module event to the Right Side. DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer(); InitIPCEvent(ipce, DB_IPCE_UNLOAD_MODULE, thread, pAppDomain); - ipce->UnloadModuleData.vmDomainFile.SetRawPtr((module ? module->GetDomainFile() : NULL)); + ipce->UnloadModuleData.vmDomainAssembly.SetRawPtr((module ? module->GetDomainAssembly() : NULL)); ipce->UnloadModuleData.debuggerAssemblyToken.Set(pRuntimeModule->GetClassLoader()->GetAssembly()); m_pRCThread->SendIPCEvent(); @@ -9877,7 +9877,7 @@ void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken, InitIPCEvent(pEvent, DB_IPCE_LOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain); pEvent->LoadClass.classMetadataToken = classMetadataToken; - pEvent->LoadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL)); + pEvent->LoadClass.vmDomainAssembly.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainAssembly() : NULL)); pEvent->LoadClass.classDebuggerAssemblyToken.Set(pAssembly); @@ -9889,7 +9889,7 @@ void Debugger::SendClassLoadUnloadEvent (mdTypeDef classMetadataToken, InitIPCEvent(pEvent, DB_IPCE_UNLOAD_CLASS, g_pEEInterface->GetThread(), pAppDomain); pEvent->UnloadClass.classMetadataToken = classMetadataToken; - pEvent->UnloadClass.vmDomainFile.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainFile() : NULL)); + pEvent->UnloadClass.vmDomainAssembly.SetRawPtr((pClassDebuggerModule ? pClassDebuggerModule->GetDomainAssembly() : NULL)); pEvent->UnloadClass.classDebuggerAssemblyToken.Set(pAssembly); } @@ -9940,10 +9940,10 @@ BOOL Debugger::SendSystemClassLoadUnloadEvent(mdTypeDef classMetadataToken, // Only notify for app domains where the module has been fully loaded already // We used to make a different check here domain->ContainsAssembly() but that - // triggers too early in the loading process. FindDomainFile will not become + // triggers too early in the loading process. FindDomainAssembly will not become // non-NULL until the module is fully loaded into the domain which is what we // want. - if (classModule->GetDomainFile() != NULL ) + if (classModule->GetDomainAssembly() != NULL ) { // Find the Left Side module that this class belongs in. DebuggerModule* pModule = LookupOrCreateModule(classModule, pAppDomain); @@ -10528,7 +10528,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) _ASSERTE(hr == S_OK); DebuggerBreakpoint * pDebuggerBP = NULL; - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->BreakpointData.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->BreakpointData.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->BreakpointData.funcMetadataToken); MethodDesc * pMethodDesc = pEvent->BreakpointData.nativeCodeMethodDescToken.UnWrap(); @@ -10847,7 +10847,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) { LOG((LF_ENC, LL_INFO100, "D::HIPCE: DB_IPCE_APPLY_CHANGES 1\n")); - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->ApplyChanges.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->ApplyChanges.vmDomainAssembly); // // @todo handle error. // @@ -10864,7 +10864,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_CLASS_LOAD_FLAG: { - DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainFile); + DebuggerModule *pDebuggerModule = LookupOrCreateModule(pEvent->SetClassLoad.vmDomainAssembly); _ASSERTE(pDebuggerModule != NULL); @@ -10914,7 +10914,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) // unexpected in an OOM situation. Quickly just sanity check them. // Thread * pThread = pEvent->SetIP.vmThreadToken.GetRawPtr(); - Module * pModule = pEvent->SetIP.vmDomainFile.GetRawPtr()->GetModule(); + Module * pModule = pEvent->SetIP.vmDomainAssembly.GetRawPtr()->GetModule(); // Get the DJI for this function DebuggerMethodInfo * pDMI = GetOrCreateMethodInfo(pModule, pEvent->SetIP.mdMethod); @@ -11244,7 +11244,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_METHOD_JMC_STATUS: { // Get the info out of the event - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0); @@ -11292,7 +11292,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_GET_METHOD_JMC_STATUS: { // Get the method - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); Module * pModule = pDebuggerModule->GetRuntimeModule(); @@ -11326,7 +11326,7 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent) case DB_IPCE_SET_MODULE_JMC_STATUS: { // Get data out of event - DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainFile); + DebuggerModule * pDebuggerModule = LookupOrCreateModule(pEvent->SetJMCFunctionStatus.vmDomainAssembly); bool fStatus = (pEvent->SetJMCFunctionStatus.dwStatus != 0); @@ -11818,7 +11818,7 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D case ELEMENT_TYPE_BYREF: res->vmTypeHandle = WrapTypeHandle(th); res->metadataToken = mdTokenNil; - res->vmDomainFile.SetRawPtr(NULL); + res->vmDomainAssembly.SetRawPtr(NULL); break; case ELEMENT_TYPE_CLASS: @@ -11828,14 +11828,14 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D // only set if instantiated res->metadataToken = th.GetCl(); DebuggerModule * pDModule = LookupOrCreateModule(th.GetModule(), pAppDomain); - res->vmDomainFile.SetRawPtr((pDModule ? pDModule->GetDomainFile() : NULL)); + res->vmDomainAssembly.SetRawPtr((pDModule ? pDModule->GetDomainAssembly() : NULL)); break; } default: res->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); res->metadataToken = mdTokenNil; - res->vmDomainFile.SetRawPtr(NULL); + res->vmDomainAssembly.SetRawPtr(NULL); break; } return; @@ -11907,8 +11907,8 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, res->ClassTypeData.typeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); // only set if instantiated res->ClassTypeData.metadataToken = th.GetCl(); DebuggerModule * pModule = LookupOrCreateModule(th.GetModule(), pAppDomain); - res->ClassTypeData.vmDomainFile.SetRawPtr((pModule ? pModule->GetDomainFile() : NULL)); - _ASSERTE(!res->ClassTypeData.vmDomainFile.IsNull()); + res->ClassTypeData.vmDomainAssembly.SetRawPtr((pModule ? pModule->GetDomainAssembly() : NULL)); + _ASSERTE(!res->ClassTypeData.vmDomainAssembly.IsNull()); break; } @@ -11968,7 +11968,7 @@ HRESULT Debugger::BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData *data, Ty } else { - DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->vmDomainFile); + DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->vmDomainAssembly); th = g_pEEInterface->FindLoadedClass(pDebuggerModule->GetRuntimeModule(), data->metadataToken); if (th.IsNull()) @@ -12070,7 +12070,7 @@ TypeHandle Debugger::TypeDataWalk::ReadTypeHandle() case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_VALUETYPE: { - DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->data.ClassTypeData.vmDomainFile); + DebuggerModule *pDebuggerModule = g_pDebugger->LookupOrCreateModule(data->data.ClassTypeData.vmDomainAssembly); th = ReadInstantiation(pDebuggerModule->GetRuntimeModule(), data->data.ClassTypeData.metadataToken, data->numTypeArgs); break; } @@ -14403,7 +14403,7 @@ void Debugger::SendLogSwitchSetting(int iLevel, // pDomain - domain file for the domain in which the notification occurred // classToken - metadata token for the type of the notification object void Debugger::SendCustomDebuggerNotification(Thread * pThread, - DomainFile * pDomain, + DomainAssembly * pDomain, mdTypeDef classToken) { CONTRACTL @@ -14434,10 +14434,10 @@ void Debugger::SendCustomDebuggerNotification(Thread * pThread, curThread, curThread->GetDomain()); - VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::MakePtr(pDomain); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::MakePtr(pDomain); ipce->CustomNotification.classToken = classToken; - ipce->CustomNotification.vmDomainFile = vmDomainFile; + ipce->CustomNotification.vmDomainAssembly = vmDomainAssembly; m_pRCThread->SendIPCEvent(); @@ -14725,16 +14725,6 @@ HRESULT Debugger::IterateAppDomainsForPdbs() if (!pDomainAssembly->IsVisibleToDebugger()) continue; - DomainAssembly::ModuleIterator j = pDomainAssembly->IterateModules(kModIterIncludeLoading); - while (j.Next()) - { - DomainFile * pDomainFile = j.GetDomainFile(); - if (!pDomainFile->ShouldNotifyDebugger()) - continue; - - Module* pRuntimeModule = pDomainFile->GetModule(); - CopyModulePdb(pRuntimeModule); - } if (pDomainAssembly->ShouldNotifyDebugger()) { CopyModulePdb(pDomainAssembly->GetModule()); diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 084f1da6a5c93f..9703354ec4235a 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -472,7 +472,7 @@ typedef DPTR(class DebuggerModule) PTR_DebuggerModule; class DebuggerModule { public: - DebuggerModule(Module * pRuntimeModule, DomainFile * pDomainFile, AppDomain * pAppDomain); + DebuggerModule(Module * pRuntimeModule, DomainAssembly * pDomainAssembly, AppDomain * pAppDomain); // Do we have any optimized code in the module? // JMC-probes aren't emitted in optimized code, @@ -504,16 +504,16 @@ class DebuggerModule // If the Runtime module is shared, then this gives a common DM. // If the runtime module is not shared, then this is an identity function. // - // The runtime has the notion of "DomainFile", which is 1:1 with DebuggerModule + // The runtime has the notion of "DomainAssembly", which is 1:1 with DebuggerModule // and thus 1:1 with CordbModule. The CordbModule hash table on the RS now uses - // the DomainFile as the key instead of DebuggerModule. This is a temporary + // the DomainAssembly as the key instead of DebuggerModule. This is a temporary // workaround to facilitate the removal of DebuggerModule. // DebuggerModule * GetPrimaryModule(); - DomainFile * GetDomainFile() + DomainAssembly * GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return m_pRuntimeDomainFile; + return m_pRuntimeDomainAssembly; } // Called by DebuggerModuleTable to set our primary module @@ -528,7 +528,7 @@ class DebuggerModule DebuggerModule* m_pPrimaryModule; PTR_Module m_pRuntimeModule; - PTR_DomainFile m_pRuntimeDomainFile; + PTR_DomainAssembly m_pRuntimeDomainAssembly; AppDomain* m_pAppDomain; @@ -1893,9 +1893,9 @@ class Debugger : public DebugInterface DWORD dwModuleName, Assembly *pAssembly, AppDomain *pAppDomain, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching); - DebuggerModule * AddDebuggerModule(DomainFile * pDomainFile); + DebuggerModule * AddDebuggerModule(DomainAssembly * pDomainAssembly); void UnloadModule(Module* pRuntimeModule, @@ -2068,8 +2068,8 @@ class Debugger : public DebugInterface bool HandleIPCEvent(DebuggerIPCEvent* event); - DebuggerModule * LookupOrCreateModule(VMPTR_DomainFile vmDomainFile); - DebuggerModule * LookupOrCreateModule(DomainFile * pDomainFile); + DebuggerModule * LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAssembly); + DebuggerModule * LookupOrCreateModule(DomainAssembly * pDomainAssembly); DebuggerModule * LookupOrCreateModule(Module * pModule, AppDomain * pAppDomain); HRESULT GetAndSendInterceptCommand(DebuggerIPCEvent *event); @@ -2437,7 +2437,7 @@ class Debugger : public DebugInterface } // send a custom debugger notification to the RS - void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomain, mdTypeDef classToken); + void SendCustomDebuggerNotification(Thread * pThread, DomainAssembly * pDomain, mdTypeDef classToken); // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side. void SendMDANotification( diff --git a/src/coreclr/debug/ee/debugger.inl b/src/coreclr/debug/ee/debugger.inl index 0eba7edccf87d5..be4e3f67c4dafa 100644 --- a/src/coreclr/debug/ee/debugger.inl +++ b/src/coreclr/debug/ee/debugger.inl @@ -52,16 +52,16 @@ inline DebuggerModuleTable * Debugger::GetModuleTable() // @dbgtodo inspection - get rid of this entire class as we move things out-of-proc. //----------------------------------------------------------------------------- inline DebuggerModule::DebuggerModule(Module * pRuntimeModule, - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, AppDomain * pAppDomain) : m_enableClassLoadCallbacks(FALSE), m_pPrimaryModule(NULL), m_pRuntimeModule(pRuntimeModule), - m_pRuntimeDomainFile(pDomainFile), + m_pRuntimeDomainAssembly(pDomainAssembly), m_pAppDomain(pAppDomain) { LOG((LF_CORDB,LL_INFO10000, "DM::DM this:0x%x Module:0x%x DF:0x%x AD:0x%x\n", - this, pRuntimeModule, pDomainFile, pAppDomain)); + this, pRuntimeModule, pDomainAssembly, pAppDomain)); // Pick a primary module. // Arguably, this could be in DebuggerModuleTable::AddModule diff --git a/src/coreclr/debug/ee/debuggermodule.cpp b/src/coreclr/debug/ee/debuggermodule.cpp index fb6fa53652fbee..633567f0dd85f5 100644 --- a/src/coreclr/debug/ee/debuggermodule.cpp +++ b/src/coreclr/debug/ee/debuggermodule.cpp @@ -253,7 +253,7 @@ void DebuggerModuleTable::RemoveModule(Module* pModule, AppDomain *pAppDomain) if ((pRuntimeModule == pModule) && (pDM->GetAppDomain() == pAppDomain)) { LOG((LF_CORDB, LL_INFO1000, "DMT::RM Removing DebuggerMod:0x%x - Module:0x%x DF:0x%x AD:0x%x\n", - pDM, pModule, pDM->GetDomainFile(), pAppDomain)); + pDM, pModule, pDM->GetDomainAssembly(), pAppDomain)); TRACE_FREE(pDM); DeleteInteropSafe(pDM); Delete(HASH(pRuntimeModule), (HASHENTRY *) pDME); diff --git a/src/coreclr/debug/ee/rcthread.cpp b/src/coreclr/debug/ee/rcthread.cpp index 0f48eb2c95e188..961b06c879f952 100644 --- a/src/coreclr/debug/ee/rcthread.cpp +++ b/src/coreclr/debug/ee/rcthread.cpp @@ -513,19 +513,6 @@ HRESULT DebuggerRCThread::SetupRuntimeOffsets(DebuggerIPCControlBlock * pDebugge pDebuggerRuntimeOffsets->m_excepNotForRuntimeBPAddr = (void*) ExceptionNotForRuntimeFlare; pDebuggerRuntimeOffsets->m_notifyRSOfSyncCompleteBPAddr = (void*) NotifyRightSideOfSyncCompleteFlare; pDebuggerRuntimeOffsets->m_debuggerWordTLSIndex = g_debuggerWordTLSIndex; - -#if !defined(FEATURE_CORESYSTEM) - // Grab the address of RaiseException in kernel32 because we have to play some games with exceptions - // that are generated there (just another reason why mixed mode debugging is shady). See bug 476768. - HMODULE hModule = WszGetModuleHandle(W("kernel32.dll")); - _ASSERTE(hModule != NULL); - PREFAST_ASSUME(hModule != NULL); - pDebuggerRuntimeOffsets->m_raiseExceptionAddr = GetProcAddress(hModule, "RaiseException"); - _ASSERTE(pDebuggerRuntimeOffsets->m_raiseExceptionAddr != NULL); - hModule = NULL; -#else - pDebuggerRuntimeOffsets->m_raiseExceptionAddr = NULL; -#endif #endif // FEATURE_INTEROP_DEBUGGING pDebuggerRuntimeOffsets->m_pPatches = DebuggerController::GetPatchTable(); @@ -575,14 +562,14 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE; -#if defined(_DEBUG) || !defined(FEATURE_CORESYSTEM) +#if defined(_DEBUG) DebuggerIPCEvent *event = ((DebugFilterParam *)pv)->event; DWORD pid = GetCurrentProcessId(); DWORD tid = GetCurrentThreadId(); DebuggerIPCEventType type = (DebuggerIPCEventType) (event->type & DB_IPCE_TYPE_MASK); -#endif // _DEBUG || !FEATURE_CORESYSTEM +#endif // _DEBUG // We should never AV here. In a debug build, throw up an assert w/ lots of useful (private) info. #ifdef _DEBUG @@ -613,18 +600,6 @@ static LONG _debugFilter(LPEXCEPTION_POINTERS ep, PVOID pv) } #endif -// this message box doesn't work well on coresystem... we actually get in a recursive exception handling loop -#ifndef FEATURE_CORESYSTEM - // We took an AV on the helper thread. This is a catastrophic situation so we can - // simply call the EE's catastrophic message box to display the error. - EEMessageBoxCatastrophic( - IDS_DEBUG_UNHANDLEDEXCEPTION_IPC, IDS_DEBUG_SERVICE_CAPTION, - type, - ep->ExceptionRecord->ExceptionCode, - GetIP(ep->ContextRecord), - pid, pid, tid, tid); -#endif - // For debugging, we can change the behavior by manually setting eax. // EXCEPTION_EXECUTE_HANDLER=1, EXCEPTION_CONTINUE_SEARCH=0, EXCEPTION_CONTINUE_EXECUTION=-1 return EXCEPTION_CONTINUE_SEARCH; diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 0bda865bd0f59b..82d5c4d1e465aa 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -588,27 +588,27 @@ class IDacDbiInterface // pData - required out parameter which will be filled out with module properties // // Notes: - // See definition of DomainFileInfo for more details about what properties + // See definition of DomainAssemblyInfo for more details about what properties // this gives back. virtual void GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData) = 0; // - // Get properties for a DomainFile + // Get properties for a DomainAssembly // // Arguments: - // vmDomainFile - vm handle to a DomainFile + // vmDomainAssembly - vm handle to a DomainAssembly // pData - required out parameter which will be filled out with module properties // // Notes: - // See definition of DomainFileInfo for more details about what properties + // See definition of DomainAssemblyInfo for more details about what properties // this gives back. virtual - void GetDomainFileData(VMPTR_DomainFile vmDomainFile, OUT DomainFileInfo * pData) = 0; + void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData) = 0; virtual - void GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule) = 0; + void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) = 0; //......................................................................... // These methods were the methods that DBI was calling from IXClrData in V2. @@ -672,7 +672,7 @@ class IDacDbiInterface // Get the values of the JIT Optimization and EnC flags. // // Arguments: - // vmDomainFile - (input) VM DomainFile (module) for which we are retrieving flags + // vmDomainAssembly - (input) VM DomainAssembly (module) for which we are retrieving flags // pfAllowJITOpts - (mandatory output) true iff this is not compiled for debug, // i.e., without optimization // pfEnableEnc - (mandatory output) true iff this module has EnC enabled @@ -687,7 +687,7 @@ class IDacDbiInterface virtual void GetCompilerFlags( - VMPTR_DomainFile vmDomainFile, + VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pfAllowJITOpts, OUT BOOL * pfEnableEnC) = 0; @@ -695,7 +695,7 @@ class IDacDbiInterface // Set the values of the JIT optimization and EnC flags. // // Arguments: - // vmDomainFile - (input) VM DomainFile (module) for which we are retrieving flags + // vmDomainAssembly - (input) VM DomainAssembly (module) for which we are retrieving flags // pfAllowJITOpts - (input) true iff this should not be compiled for debug, // i.e., without optimization // pfEnableEnc - (input) true iff this module should have EnC enabled. If this is @@ -717,7 +717,7 @@ class IDacDbiInterface //......................................................................... virtual - HRESULT SetCompilerFlags(VMPTR_DomainFile vmDomainFile, + HRESULT SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, BOOL fAllowJitOpts, BOOL fEnableEnC) = 0; @@ -784,7 +784,7 @@ class IDacDbiInterface // Arguments: // vmModule - new module from the enumeration // pUserData - user data passed to EnumerateModulesInAssembly - typedef void (*FP_MODULE_ENUMERATION_CALLBACK)(VMPTR_DomainFile vmModule, CALLBACK_DATA pUserData); + typedef void (*FP_MODULE_ENUMERATION_CALLBACK)(VMPTR_DomainAssembly vmModule, CALLBACK_DATA pUserData); // // Enumerates all the code Modules in an assembly. @@ -1277,7 +1277,7 @@ class IDacDbiInterface // The debugger can't duplicate this policy with 100% accuracy, and // so we need DAC to lookup the assembly that was actually loaded. virtual - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainFile vmScope, mdToken tkAssemblyRef) = 0; + VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef) = 0; //----------------------------------------------------------------------------- // Interface for initializing the native/IL sequence points and native var info @@ -1707,13 +1707,13 @@ class IDacDbiInterface // // Arguments: // Input: - // vmDomainFile - module containing metadata for the method + // vmDomainAssembly - module containing metadata for the method // functionToken - metadata token for the function // Output (required): // codeInfo - start address and size of the IL // pLocalSigToken - signature token for the method virtual - void GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, + void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT TargetBuffer * pCodeInfo, OUT mdToken * pLocalSigToken) = 0; @@ -1723,7 +1723,7 @@ class IDacDbiInterface // and hot and cold region information. // Arguments: // Input: - // vmDomainFile - module containing metadata for the method + // vmDomainAssembly - module containing metadata for the method // functionToken - token for the function for which we need code info // Output (required): // pCodeInfo - data structure describing the native code regions. @@ -1733,7 +1733,7 @@ class IDacDbiInterface // invalid (i.e., pCodeInfo->IsValid is false). virtual - void GetNativeCodeInfo(VMPTR_DomainFile vmDomainFile, + void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT NativeCodeFunctionData * pCodeInfo) = 0; @@ -1798,7 +1798,7 @@ class IDacDbiInterface // get field information and object size for an instantiated generic // // Arguments: - // input: vmDomainFile - module containing metadata for the type + // input: vmDomainAssembly - module containing metadata for the type // thExact - exact type handle for type (may be NULL) // thApprox - approximate type handle for the type // output: @@ -1807,7 +1807,7 @@ class IDacDbiInterface // pObjectSize - size of the instantiated object // virtual - void GetInstantiationFieldInfo (VMPTR_DomainFile vmDomainFile, + void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, OUT DacDbiArrayList * pFieldList, @@ -1992,12 +1992,12 @@ class IDacDbiInterface // input: vmAppDomain - Appdomain in which simpleType resides // simpleType - CorElementType value corresponding to a simple type // output: pMetadataToken - the metadata token corresponding to simpleType, - // in the scope of vmDomainFile. - // vmDomainFile - the domainFile for simpleType + // in the scope of vmDomainAssembly. + // vmDomainAssembly - the domainAssembly for simpleType // Notes: // This is inspection-only. If the type is not yet loaded, it will throw CORDBG_E_CLASS_NOT_LOADED. // It will not try to load a type. - // If the type has been loaded, vmDomainFile will be non-null unless the target is somehow corrupted. + // If the type has been loaded, vmDomainAssembly will be non-null unless the target is somehow corrupted. // In that case, we will throw CORDBG_E_TARGET_INCONSISTENT. virtual @@ -2005,7 +2005,7 @@ class IDacDbiInterface CorElementType simpleType, OUT mdTypeDef * pMetadataToken, OUT VMPTR_Module * pVmModule, - OUT VMPTR_DomainFile * pVmDomainFile) = 0; + OUT VMPTR_DomainAssembly * pVmDomainAssembly) = 0; // for the specified object returns TRUE if the object derives from System.Exception virtual @@ -2459,7 +2459,7 @@ class IDacDbiInterface virtual bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module * pModule, - OUT VMPTR_DomainFile * pDomainFile) = 0; + OUT VMPTR_DomainAssembly * pDomainAssembly) = 0; // Reference Walking. @@ -2731,7 +2731,7 @@ class IDacDbiInterface HRESULT GetDelegateFunctionData( DelegateType delegateType, VMPTR_Object delegateObject, - OUT VMPTR_DomainFile *ppFunctionDomainFile, + OUT VMPTR_DomainAssembly *ppFunctionDomainAssembly, OUT mdMethodDef *pMethodDef) = 0; virtual diff --git a/src/coreclr/debug/inc/dacdbistructures.h b/src/coreclr/debug/inc/dacdbistructures.h index 5e02a68a792c91..aca5c668de42be 100644 --- a/src/coreclr/debug/inc/dacdbistructures.h +++ b/src/coreclr/debug/inc/dacdbistructures.h @@ -162,15 +162,15 @@ struct MSLAYOUT TargetBuffer //=================================================================================== // Module properties, retrieved by DAC. -// Describes a VMPTR_DomainFile representing a module. +// Describes a VMPTR_DomainAssembly representing a module. // In the VM, a raw Module may be domain neutral and shared by many appdomains. -// Whereas a DomainFile is like a { AppDomain, Module} pair. DomainFile corresponds +// Whereas a DomainAssembly is like a { AppDomain, Module} pair. DomainAssembly corresponds // much more to ICorDebugModule (which also has appdomain affinity). //=================================================================================== -struct MSLAYOUT DomainFileInfo +struct MSLAYOUT DomainAssemblyInfo { - // The appdomain that the DomainFile is associated with. - // Although VMPTR_Module may be shared across multiple domains, a DomainFile has appdomain affinity. + // The appdomain that the DomainAssembly is associated with. + // Although VMPTR_Module may be shared across multiple domains, a DomainAssembly has appdomain affinity. VMPTR_AppDomain vmAppDomain; // The assembly this module belongs to. All modules live in an assembly. @@ -624,7 +624,7 @@ class MSLAYOUT EnCHangingFieldInfo mdFieldDef fieldToken, CorElementType elementType, mdTypeDef metadataToken, - VMPTR_DomainFile vmDomainFile); + VMPTR_DomainAssembly vmDomainAssembly); DebuggerIPCE_BasicTypeData GetObjectTypeData() const { return m_objectTypeData; }; mdFieldDef GetFieldToken() const { return m_fldToken; }; @@ -660,7 +660,7 @@ enum AreValueTypesBoxed { NoValueTypeBoxing, OnlyPrimitivesUnboxed, AllBoxed }; typedef struct MSLAYOUT { // domain file for the type - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; // metadata token for the type. This may be a typeRef (for requests) or a typeDef (for responses). mdToken typeToken; } TypeRefData; @@ -746,7 +746,7 @@ struct MSLAYOUT DacGcReference struct MSLAYOUT DacExceptionCallStackData { VMPTR_AppDomain vmAppDomain; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; CORDB_ADDRESS ip; mdMethodDef methodDef; BOOL isLastForeignExceptionFrame; diff --git a/src/coreclr/debug/inc/dacdbistructures.inl b/src/coreclr/debug/inc/dacdbistructures.inl index f9c0404b659c47..84dd2343198633 100644 --- a/src/coreclr/debug/inc/dacdbistructures.inl +++ b/src/coreclr/debug/inc/dacdbistructures.inl @@ -712,14 +712,14 @@ void EnCHangingFieldInfo::Init(VMPTR_Object pObject, mdFieldDef fieldToken, CorElementType elementType, mdTypeDef metadataToken, - VMPTR_DomainFile vmDomainFile) + VMPTR_DomainAssembly vmDomainAssembly) { m_vmObject = pObject; m_offsetToVars = offset; m_fldToken = fieldToken; m_objectTypeData.elementType = elementType; m_objectTypeData.metadataToken = metadataToken; - m_objectTypeData.vmDomainFile = vmDomainFile; + m_objectTypeData.vmDomainAssembly = vmDomainAssembly; } diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index ddef09554cf80d..e433532c29a16f 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -126,7 +126,6 @@ struct MSLAYOUT DebuggerIPCRuntimeOffsets void *m_signalHijackCompleteBPAddr; void *m_excepNotForRuntimeBPAddr; void *m_notifyRSOfSyncCompleteBPAddr; - void *m_raiseExceptionAddr; // The address of kernel32!RaiseException in the debuggee DWORD m_debuggerWordTLSIndex; // The TLS slot for the debugger word used in the debugger hijack functions #endif // FEATURE_INTEROP_DEBUGGING SIZE_T m_TLSIndex; // The TLS index of the thread-local storage for coreclr.dll @@ -364,30 +363,6 @@ struct MSLAYOUT DebuggerIPCControlBlockTransport #include "dbgtransportsession.h" #endif // defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI) -#if defined(TARGET_X86) && !defined(FEATURE_CORESYSTEM) -// We have an versioning requirement. -// Certain portions of the v1.0 and v1.1 IPC block are shared. This is b/c a v1.1 debugger needs to be able -// to look at a v2.0 app enough to recognize the version mismatch. -// This check is only necessary for platforms that ran on v1.1 (Win32-x86) - -// Just to catch any potential illegal change in the IPC block, we assert the offsets against the offsets from v1.1. -// The constants here are pulled from v1.1. -// The RS will look at these versioning fields, so they absolutely must line up. -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolCurrent) == 0x10); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_leftSideProtocolMinSupported) == 0x14); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolCurrent) == 0x18); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProtocolMinSupported) == 0x1c); - -// Unfortunately, on detecting such failure, v1.1 will also null out LSEA, LSER and RSPH. -// If these get adjusted, a version-mismatch attach will effectively null out random fields. -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSEA) == 0x30); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_paddingObsoleteLSER) == 0x34); -static_assert_no_msg(offsetof(DebuggerIPCControlBlock, m_rightSideProcessHandle) == 0x38); - - - -#endif - #define INITIAL_APP_DOMAIN_INFO_LIST_SIZE 16 @@ -847,15 +822,13 @@ typedef VMPTR_Base VMPTR_CONTEXT; typedef VMPTR_Base VMPTR_CONTEXT; #endif -// DomainFile is a base-class for a CLR module, with app-domain affinity. -// For domain-neutral modules (like CoreLib), there is a DomainFile instance +// DomainAssembly is a base-class for a CLR module, with app-domain affinity. +// For domain-neutral modules (like CoreLib), there is a DomainAssembly instance // for each appdomain the module lives in. // This is the canonical handle ICorDebug uses to a CLR module. -DEFINE_VMPTR(class DomainFile, PTR_DomainFile, VMPTR_DomainFile); +DEFINE_VMPTR(class DomainAssembly, PTR_DomainAssembly, VMPTR_DomainAssembly); DEFINE_VMPTR(class Module, PTR_Module, VMPTR_Module); -// DomainAssembly derives from DomainFile and represents a manifest module. -DEFINE_VMPTR(class DomainAssembly, PTR_DomainAssembly, VMPTR_DomainAssembly); DEFINE_VMPTR(class Assembly, PTR_Assembly, VMPTR_Assembly); DEFINE_VMPTR(class PEAssembly, PTR_PEAssembly, VMPTR_PEAssembly); @@ -1285,7 +1258,7 @@ inline bool IsEqualOrCloserToRoot(FramePointer fp1, FramePointer fp2) struct MSLAYOUT DebuggerIPCE_FuncData { mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdTypeDef classMetadataToken; @@ -1425,7 +1398,7 @@ struct MSLAYOUT DebuggerIPCE_STRData struct MSLAYOUT { mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_MethodDesc vmMethodDesc; CorDebugInternalFrameType frameType; } stubFrame; @@ -1469,7 +1442,7 @@ struct MSLAYOUT DebuggerIPCE_BasicTypeData CorElementType elementType; mdTypeDef metadataToken; VMPTR_Module vmModule; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_TypeHandle vmTypeHandle; }; @@ -1505,7 +1478,7 @@ struct MSLAYOUT DebuggerIPCE_ExpandedTypeData { mdTypeDef metadataToken; VMPTR_Module vmModule; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; VMPTR_TypeHandle typeHandle; // if non-null then further fetches will be needed to get type arguments } ClassTypeData; @@ -1679,7 +1652,7 @@ struct MSLAYOUT DebuggerIPCE_FuncEvalInfo DebuggerIPCE_FuncEvalType funcEvalType; mdMethodDef funcMetadataToken; mdTypeDef funcClassMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; RSPTR_CORDBEVAL funcEvalKey; bool evalDuringException; @@ -1917,7 +1890,7 @@ struct MSLAYOUT DebuggerIPCEvent { // Module whos metadata is being updated // This tells the RS that the metadata for that module has become invalid. - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; } MetadataUpdateData; @@ -1960,13 +1933,13 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { // Module that was just loaded. - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; }LoadModuleData; struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY debuggerAssemblyToken; } UnloadModuleData; @@ -1975,7 +1948,7 @@ struct MSLAYOUT DebuggerIPCEvent // Queury PDB from OOP struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; } UpdateModuleSymsData; DebuggerMDANotification MDANotification; @@ -1984,7 +1957,7 @@ struct MSLAYOUT DebuggerIPCEvent { LSPTR_BREAKPOINT breakpointToken; mdMethodDef funcMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; bool isIL; SIZE_T offset; SIZE_T encVersion; @@ -2064,7 +2037,7 @@ struct MSLAYOUT DebuggerIPCEvent // Apply an EnC edit struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; // Module to edit + VMPTR_DomainAssembly vmDomainAssembly; // Module to edit DWORD cbDeltaMetadata; // size of blob pointed to by pDeltaMetadata CORDB_ADDRESS pDeltaMetadata; // pointer to delta metadata in debuggee // it's the RS's responsibility to allocate and free @@ -2081,20 +2054,20 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY classDebuggerAssemblyToken; } LoadClass; struct MSLAYOUT { mdTypeDef classMetadataToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; LSPTR_ASSEMBLY classDebuggerAssemblyToken; } UnloadClass; struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; bool flag; } SetClassLoad; @@ -2125,7 +2098,7 @@ struct MSLAYOUT DebuggerIPCEvent CORDB_ADDRESS startAddress; bool fCanSetIPOnly; VMPTR_Thread vmThreadToken; - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef mdMethod; VMPTR_MethodDesc vmMethodDesc; SIZE_T offset; @@ -2154,7 +2127,7 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { // Domain file for the domain in which the notification occurred - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; // metadata token for the type of the CustomNotification object's type mdTypeDef classToken; @@ -2219,7 +2192,7 @@ struct MSLAYOUT DebuggerIPCEvent struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; BOOL fAllowJitOpts; BOOL fEnableEnC; } JitDebugInfo; @@ -2227,7 +2200,7 @@ struct MSLAYOUT DebuggerIPCEvent // EnC Remap opportunity struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken ; // methodDef of function with remap opportunity SIZE_T currentVersionNumber; // version currently executing SIZE_T resumeVersionNumber; // latest version @@ -2239,7 +2212,7 @@ struct MSLAYOUT DebuggerIPCEvent // EnC Remap has taken place struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken; // methodDef of function that was remapped } EnCRemapComplete; @@ -2247,7 +2220,7 @@ struct MSLAYOUT DebuggerIPCEvent // specific edit made by EnC (function add/update or field add). struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdToken memberMetadataToken; // Either a methodDef token indicating the function that // was updated/added, or a fieldDef token indicating the // field which was added. @@ -2268,7 +2241,7 @@ struct MSLAYOUT DebuggerIPCEvent // @todo - Perhaps we can bundle these up so we can set multiple funcs w/ 1 event? struct MSLAYOUT { - VMPTR_DomainFile vmDomainFile; + VMPTR_DomainAssembly vmDomainAssembly; mdMethodDef funcMetadataToken; DWORD dwStatus; } SetJMCFunctionStatus; diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp index 6d3ed5b345cf7c..3ff580717e72a8 100644 --- a/src/coreclr/debug/shared/dbgtransportsession.cpp +++ b/src/coreclr/debug/shared/dbgtransportsession.cpp @@ -2696,11 +2696,6 @@ bool DbgTransportSession::DbgTransportShouldInjectFault(DbgTransportFaultOp eOp, if (dwChance < (s_dwFaultInjection & DBG_TRANSPORT_FAULT_RATE_MASK)) { DbgTransportLog(LC_FaultInject, "Injected fault for %s operation", szOpName); -#if defined(FEATURE_CORESYSTEM) - // not supported -#else - WSASetLastError(WSAEFAULT); -#endif // defined(FEATURE_CORESYSTEM) return true; } } diff --git a/src/coreclr/dlls/dbgshim/dbgshim.cpp b/src/coreclr/dlls/dbgshim/dbgshim.cpp index 40e4d7dea4bf26..c82625487cfe85 100644 --- a/src/coreclr/dlls/dbgshim/dbgshim.cpp +++ b/src/coreclr/dlls/dbgshim/dbgshim.cpp @@ -1956,9 +1956,7 @@ GetContinueStartupEvent( #endif // !TARGET_UNIX -#if defined(FEATURE_CORESYSTEM) #include "debugshim.h" -#endif //----------------------------------------------------------------------------- // Public API. @@ -1980,26 +1978,17 @@ CLRCreateInstance( { PUBLIC_CONTRACT; -#if defined(FEATURE_CORESYSTEM) - if (ppInterface == NULL) return E_POINTER; if (clsid != CLSID_CLRDebugging || riid != IID_ICLRDebugging) return E_NOINTERFACE; -#if defined(FEATURE_CORESYSTEM) GUID skuId = CLR_ID_ONECORE_CLR; -#else - GUID skuId = CLR_ID_CORECLR; -#endif CLRDebuggingImpl *pDebuggingImpl = new (nothrow) CLRDebuggingImpl(skuId); if (NULL == pDebuggingImpl) return E_OUTOFMEMORY; return pDebuggingImpl->QueryInterface(riid, ppInterface); -#else - return E_NOTIMPL; -#endif } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e270bcdc91ee47..c15f926fa756b1 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2444,8 +2444,6 @@ heap_segment* gc_heap::reserved_free_regions_sip[max_generation]; int gc_heap::num_sip_regions = 0; -size_t gc_heap::committed_in_free = 0; - size_t gc_heap::end_gen0_region_space = 0; size_t gc_heap::gen0_pinned_free_space = 0; @@ -11139,9 +11137,6 @@ heap_segment* gc_heap::get_free_region (int gen_number, size_t size) { heap_segment* region = 0; - // TODO: the update to committed_in_free is incorrect - we'd need synchorization 'cause a thread - // could be getting a small and another one could be getting a large region at the same time. - // This is only used for recording. if (gen_number <= max_generation) { assert (size == 0); @@ -11543,6 +11538,8 @@ void gc_heap::decommit_heap_segment_pages (heap_segment* seg, if (use_large_pages_p) return; uint8_t* page_start = align_on_page (heap_segment_allocated(seg)); + assert (heap_segment_committed (seg) >= page_start); + size_t size = heap_segment_committed (seg) - page_start; extra_space = align_on_page (extra_space); if (size >= max ((extra_space + 2*OS_PAGE_SIZE), MIN_DECOMMIT_SIZE)) @@ -11563,10 +11560,10 @@ size_t gc_heap::decommit_heap_segment_pages_worker (heap_segment* seg, #endif assert (!use_large_pages_p); uint8_t* page_start = align_on_page (new_committed); - size_t size = heap_segment_committed (seg) - page_start; + ptrdiff_t size = heap_segment_committed (seg) - page_start; if (size > 0) { - bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); + bool decommit_succeeded_p = virtual_decommit (page_start, (size_t)size, heap_segment_oh (seg), heap_number); if (decommit_succeeded_p) { dprintf (3, ("Decommitting heap segment [%Ix, %Ix[(%d)", @@ -11601,10 +11598,11 @@ void gc_heap::decommit_heap_segment (heap_segment* seg) dprintf (3, ("Decommitting heap segment %Ix(%Ix)", (size_t)seg, heap_segment_mem (seg))); -#ifdef BACKGROUND_GC +#if defined(BACKGROUND_GC) && !defined(USE_REGIONS) page_start += OS_PAGE_SIZE; -#endif //BACKGROUND_GC +#endif //BACKGROUND_GC && !USE_REGIONS + assert (heap_segment_committed (seg) >= page_start); size_t size = heap_segment_committed (seg) - page_start; bool decommit_succeeded_p = virtual_decommit (page_start, size, heap_segment_oh (seg), heap_number); @@ -13563,7 +13561,6 @@ gc_heap::init_gc_heap (int h_number) sip_seg_maxgen_interval = 3; num_condemned_regions = 0; #endif //STRESS_REGIONS - committed_in_free = 0; end_gen0_region_space = 0; gen0_pinned_free_space = 0; gen0_large_chunk_found = false; @@ -20423,23 +20420,33 @@ void gc_heap::gc1() if (n < max_generation) { - compute_promoted_allocation (1 + n); + int highest_gen_number = +#ifdef USE_REGIONS + max_generation; +#else //USE_REGIONS + 1 + n; +#endif //USE_REGIONS + + for (int older_gen_idx = (1 + n); older_gen_idx <= highest_gen_number; older_gen_idx++) + { + compute_promoted_allocation (older_gen_idx); - dynamic_data* dd = dynamic_data_of (1 + n); - size_t new_fragmentation = generation_free_list_space (generation_of (1 + n)) + - generation_free_obj_space (generation_of (1 + n)); + dynamic_data* dd = dynamic_data_of (older_gen_idx); + size_t new_fragmentation = generation_free_list_space (generation_of (older_gen_idx)) + + generation_free_obj_space (generation_of (older_gen_idx)); #ifdef BACKGROUND_GC - if (current_c_gc_state != c_gc_state_planning) + if (current_c_gc_state != c_gc_state_planning) #endif //BACKGROUND_GC - { - if (settings.promotion) { - dd_fragmentation (dd) = new_fragmentation; - } - else - { - //assert (dd_fragmentation (dd) == new_fragmentation); + if (settings.promotion) + { + dd_fragmentation (dd) = new_fragmentation; + } + else + { + //assert (dd_fragmentation (dd) == new_fragmentation); + } } } } @@ -24359,8 +24366,17 @@ size_t gc_heap::committed_size() } #ifdef USE_REGIONS + size_t committed_in_free = 0; + + for (int kind = basic_free_region; kind < count_free_region_kinds; kind++) + { + committed_in_free += free_regions[kind].get_size_committed_in_free(); + } + + dprintf (3, ("h%d committed in free %Id", heap_number, committed_in_free)); + total_committed += committed_in_free; -#endif //USE_REGIO +#endif //USE_REGIONS return total_committed; } @@ -27448,7 +27464,7 @@ void gc_heap::plan_phase (int condemned_gen_number) _sort (&mark_list[0], mark_list_index - 1, 0); #endif //USE_VXSORT - dprintf (3, ("using mark list at GC #%d", settings.gc_index)); + dprintf (3, ("using mark list at GC #%Id", (size_t)settings.gc_index)); //verify_qsort_array (&mark_list[0], mark_list_index-1); #endif //!MULTIPLE_HEAPS use_mark_list = TRUE; @@ -30125,6 +30141,11 @@ void gc_heap::sweep_region_in_plan (heap_segment* region, heap_segment_saved_allocated (region) = heap_segment_allocated (region); heap_segment_allocated (region) = last_marked_obj_end; heap_segment_plan_allocated (region) = heap_segment_allocated (region); + + int plan_gen_num = heap_segment_plan_gen_num (region); + generation_allocation_size (generation_of (plan_gen_num)) += heap_segment_survived (region); + dprintf (REGIONS_LOG, ("sip: g%d alloc size is now %Id", plan_gen_num, + generation_allocation_size (generation_of (plan_gen_num)))); } inline @@ -36650,7 +36671,7 @@ void gc_heap::mark_through_cards_for_segments (card_fn fn, BOOL relocating CARD_ hpt->heap_number, heap_number, n_eph, n_gen, n_card_set, total_cards_cleared, (n_eph ? (int)(((float)n_gen / (float)n_eph) * 100) : 0))); dprintf (3, ("h%d marking h%d Msoh: total cross %Id, useful: %Id, running ratio: %d", - hpt->heap_number, heap_number, n_eph_soh, n_gen_soh, + hpt->heap_number, heap_number, (size_t)n_eph_soh, (size_t)n_gen_soh, (n_eph_soh ? (int)(((float)n_gen_soh / (float)n_eph_soh) * 100) : 0))); #else generation_skip_ratio = ((n_eph > MIN_SOH_CROSS_GEN_REFS) ? (int)(((float)n_gen / (float)n_eph) * 100) : 100); @@ -41398,7 +41419,7 @@ void gc_heap::mark_through_cards_for_uoh_objects (card_fn fn, hpt->heap_number, heap_number, n_eph, n_gen, n_card_set, total_cards_cleared, (n_eph ? (int)(((float)n_gen / (float)n_eph) * 100) : 0))); dprintf (3, ("h%d marking h%d Mloh: total cross %Id, useful: %Id, running ratio: %d", - hpt->heap_number, heap_number, n_eph_loh, n_gen_loh, + hpt->heap_number, heap_number, (size_t)n_eph_loh, (size_t)n_gen_loh, (n_eph_loh ? (int)(((float)n_gen_loh / (float)n_eph_loh) * 100) : 0))); #else generation_skip_ratio = min (((n_eph > MIN_LOH_CROSS_GEN_REFS) ? @@ -44081,12 +44102,8 @@ GCHeap::Alloc(gc_alloc_context* context, size_t size, uint32_t flags REQD_ALIGN_ } CHECK_ALLOC_AND_POSSIBLY_REGISTER_FOR_FINALIZATION(newAlloc, size, flags & GC_ALLOC_FINALIZE); - #ifdef USE_REGIONS - if (!IsHeapPointer (newAlloc)) - { - GCToOSInterface::DebugBreak(); - } + assert (IsHeapPointer (newAlloc)); #endif //USE_REGIONS return newAlloc; diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 886ea17743880d..d727a4685c527e 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -87,8 +87,8 @@ class GCConfigStringHolder INT_CONFIG (SegmentSize, "GCSegmentSize", NULL, 0, "Specifies the managed heap segment size") \ INT_CONFIG (LatencyMode, "GCLatencyMode", NULL, -1, "Specifies the GC latency mode - batch, interactive or low latency (note that the same " \ "thing can be specified via API which is the supported way") \ - INT_CONFIG (LatencyLevel, "GCLatencyLevel", NULL, 1, "Specifies the GC latency level that you want to optimize for. Must be a number from 0" \ - "3. See documentation for more details on each level.") \ + INT_CONFIG (LatencyLevel, "GCLatencyLevel", NULL, 1, "Specifies the GC latency level that you want to optimize for. Must be a number from 0 " \ + "to 3. See documentation for more details on each level.") \ INT_CONFIG (LogFileSize, "GCLogFileSize", NULL, 0, "Specifies the GC log file size") \ INT_CONFIG (CompactRatio, "GCCompactRatio", NULL, 0, "Specifies the ratio compacting GCs vs sweeping") \ INT_CONFIG (GCHeapAffinitizeMask, "GCHeapAffinitizeMask", "System.GC.HeapAffinitizeMask", 0, "Specifies processor mask for Server GC threads") \ @@ -117,7 +117,7 @@ class GCConfigStringHolder INT_CONFIG (BGCFLkd, "BGCFLkd", NULL, 11, "Specifies kd for above goal tuning") \ INT_CONFIG (BGCFLff, "BGCFLff", NULL, 100, "Specifies ff ratio") \ INT_CONFIG (BGCFLSmoothFactor, "BGCFLSmoothFactor", NULL, 150, "Smoothing over these") \ - INT_CONFIG (BGCFLGradualD, "BGCFLGradualD", NULL, 0, "Enable gradual D instead of cutting of at the value") \ + INT_CONFIG (BGCFLGradualD, "BGCFLGradualD", NULL, 0, "Enable gradual D instead of cutting off at the value") \ INT_CONFIG (BGCMLkp, "BGCMLkp", NULL, 1000, "Specifies kp for ML tuning") \ INT_CONFIG (BGCMLki, "BGCMLki", NULL, 16, "Specifies ki for ML tuning") \ INT_CONFIG (BGCFLEnableKi, "BGCFLEnableKi", NULL, 1, "Enables ki for above goal tuning") \ diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index baa0272db1368d..567e7c1bd69caf 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -1175,6 +1175,7 @@ class region_free_list heap_segment* unlink_region_front(); heap_segment* unlink_smallest_region (size_t size); size_t get_num_free_regions(); + size_t get_size_committed_in_free() { return size_committed_in_free_regions; } size_t get_size_free_regions() { return size_free_regions; } heap_segment* get_first_free_region() { return head_free_region; } static void unlink_region (heap_segment* region); @@ -3594,9 +3595,6 @@ class gc_heap PER_HEAP int num_sip_regions; - PER_HEAP - size_t committed_in_free; - PER_HEAP // After plan we calculate this as the planned end gen0 space; // but if we end up sweeping, we recalculate it at the end of diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 345a18ef6bc624..67a43e28b20d15 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -291,9 +291,9 @@ static int run(const configuration& config) } // Construct CoreCLR properties. - pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(std::move(tpa_list)); - pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(std::move(app_path)); - pal::string_utf8_t native_search_dirs_utf8 = pal::convert_to_utf8(native_search_dirs.str()); + pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(tpa_list.c_str()); + pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(app_path.c_str()); + pal::string_utf8_t native_search_dirs_utf8 = pal::convert_to_utf8(native_search_dirs.str().c_str()); std::vector user_defined_keys_utf8; std::vector user_defined_values_utf8; @@ -334,7 +334,7 @@ static int run(const configuration& config) int propertyCount = (int)propertyKeys.size(); // Construct arguments - pal::string_utf8_t exe_path_utf8 = pal::convert_to_utf8(std::move(exe_path)); + pal::string_utf8_t exe_path_utf8 = pal::convert_to_utf8(exe_path.c_str()); std::vector argv_lifetime; pal::malloc_ptr argv_utf8{ pal::convert_argv_to_utf8(config.entry_assembly_argc, config.entry_assembly_argv, argv_lifetime) }; pal::string_utf8_t entry_assembly_utf8 = pal::convert_to_utf8(config.entry_assembly_fullpath.c_str()); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 9781299c8049ef..14cb9ec6580e16 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -88,11 +88,28 @@ namespace pal assert(wrote < needed); return { buffer.get() }; } + inline string_utf8_t getenvA(const char* var) + { + DWORD needed = ::GetEnvironmentVariableA(var, nullptr, 0); + if (needed == 0) + return {}; + + malloc_ptr buffer{ (char*)::malloc(needed * sizeof(char)) }; + assert(buffer != nullptr); + DWORD wrote = ::GetEnvironmentVariableA(var, buffer.get(), needed); + assert(wrote < needed); + return { buffer.get() }; + } inline void setenv(const char_t* var, string_t value) { BOOL success = ::SetEnvironmentVariableW(var, value.c_str()); assert(success); } + inline void setenvA(const char* var, string_utf8_t value) + { + BOOL success = ::SetEnvironmentVariableA(var, value.c_str()); + assert(success); + } inline string_t get_exe_path() { char_t file_name[1024]; @@ -177,31 +194,17 @@ namespace pal inline string_utf8_t convert_to_utf8(const char_t* str) { - // Compute the needed buffer - int bytes_req = ::WideCharToMultiByte( - CP_UTF8, 0, // Conversion args - str, -1, // Input string - nullptr, 0, // Null to request side - nullptr, nullptr); + int bytes_req = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr); malloc_ptr buffer{ (char*)::malloc(bytes_req) }; assert(buffer != nullptr); - int written = ::WideCharToMultiByte( - CP_UTF8, 0, // Conversion args - str, -1, // Input string - buffer.get(), bytes_req, // Output buffer - nullptr, nullptr); + int written = ::WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.get(), bytes_req, nullptr, nullptr); assert(bytes_req == written); return { buffer.get() }; } - inline string_utf8_t convert_to_utf8(string_t&& str) - { - return convert_to_utf8(str.c_str()); - } - inline bool try_load_hostpolicy(pal::string_t mock_hostpolicy_value) { const char_t* hostpolicyName = W("hostpolicy.dll"); @@ -360,11 +363,19 @@ namespace pal return {}; return { val }; } + inline string_utf8_t getenvA(const char* var) + { + return getenv(var); + } inline void setenv(const char_t* var, string_t value) { int error = ::setenv(var, value.c_str(), /* overwrite */ 1); assert(error == 0); } + inline void setenvA(const char* var, string_utf8_t value) + { + setenv(var, value.c_str()); + } inline string_t get_exe_path() { return minipal_getexepath(); } @@ -567,11 +578,6 @@ namespace pal return { str }; } - inline string_utf8_t convert_to_utf8(string_t&& str) - { - return std::move(str); - } - inline bool try_load_hostpolicy(pal::string_t mock_hostpolicy_value) { if (!string_ends_with(mock_hostpolicy_value, pal::nativelib_ext)) diff --git a/src/coreclr/hosts/corerun/dotenv.cpp b/src/coreclr/hosts/corerun/dotenv.cpp index 0e0e37c7919b0a..8792d63151f56a 100644 --- a/src/coreclr/hosts/corerun/dotenv.cpp +++ b/src/coreclr/hosts/corerun/dotenv.cpp @@ -7,22 +7,8 @@ #include #include -#ifdef TARGET_WINDOWS -#include -#endif - namespace { - pal::string_t convert_to_string_t(std::string str) - { -#ifdef TARGET_WINDOWS - std::wstring_convert> converter; - return converter.from_bytes(str); -#else - return str; -#endif - } - bool read_var_name(std::istream& file, std::string& var_name_out) { std::string var_name; @@ -326,8 +312,7 @@ dotenv::dotenv(pal::string_t dotEnvFilePath, std::istream& contents) { return dot_env_entry->second; } - pal::string_t env_var_name = convert_to_string_t(name); - return pal::convert_to_utf8(pal::getenv(env_var_name.c_str())); + return pal::getenvA(name.c_str()); }, temp_value)) { _environmentVariables = {}; @@ -341,9 +326,9 @@ void dotenv::load_into_current_process() const { for (std::pair env_vars : _environmentVariables) { - pal::string_t name_string = convert_to_string_t(env_vars.first); - pal::string_t value_string = convert_to_string_t(env_vars.second); - pal::setenv(name_string.c_str(), std::move(value_string)); + pal::string_utf8_t name_string = env_vars.first; + pal::string_utf8_t value_string = env_vars.second; + pal::setenvA(name_string.c_str(), std::move(value_string)); } } diff --git a/src/coreclr/inc/bbsweep.h b/src/coreclr/inc/bbsweep.h index 4e3636681e4e4b..64855ed939ddd7 100644 --- a/src/coreclr/inc/bbsweep.h +++ b/src/coreclr/inc/bbsweep.h @@ -182,97 +182,6 @@ class BBSweep if (!bInitialized) { SECURITY_ATTRIBUTES * pSecurityAttributes = NULL; - -#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO - PSECURITY_DESCRIPTOR pSD = NULL; - PSID pAdminSid = NULL; - HANDLE hToken = NULL; - PACL pACL = NULL; - LPVOID buffer = NULL; - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) - goto cleanup; - - // don't set pSecurityAttributes for AppContainer processes - if(!IsAppContainerProcess(hToken)) - { - SECURITY_ATTRIBUTES securityAttributes; - PSID pUserSid = NULL; - SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; - DWORD retLength; - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:6211) // PREfast warning: Leaking memory 'pSD' due to an exception. -#endif /*_PREFAST_ */ - pSD = (PSECURITY_DESCRIPTOR) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]; - if (!pSD) - goto cleanup; - - if (GetTokenInformation(hToken, TokenOwner, NULL, 0, &retLength)) - goto cleanup; - - buffer = (LPVOID) new char[retLength]; - if (!buffer) - goto cleanup; -#ifdef _PREFAST_ -#pragma warning(pop) -#endif /*_PREFAST_*/ - - // Get the SID for the current user - if (!GetTokenInformation(hToken, TokenOwner, (LPVOID) buffer, retLength, &retLength)) - goto cleanup; - - pUserSid = ((TOKEN_OWNER *) buffer)->Owner; - - // Get the SID for the admin group - // Create a SID for the BUILTIN\Administrators group. - if(! AllocateAndInitializeSid(&SIDAuthNT, 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &pAdminSid)) - goto cleanup; - - EXPLICIT_ACCESS ea[2]; - ZeroMemory(ea, 2 * sizeof(EXPLICIT_ACCESS)); - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow the current user full access - ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; // KEY_ALL_ACCESS; - ea[0].grfAccessMode = SET_ACCESS; - ea[0].grfInheritance= NO_INHERITANCE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; - ea[0].Trustee.ptstrName = (LPTSTR) pUserSid; - - // Initialize an EXPLICIT_ACCESS structure for an ACE. - // The ACE will allow admins full access - ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; //KEY_ALL_ACCESS; - ea[1].grfAccessMode = SET_ACCESS; - ea[1].grfInheritance= NO_INHERITANCE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea[1].Trustee.ptstrName = (LPTSTR) pAdminSid; - - if (SetEntriesInAcl(2, ea, NULL, &pACL) != ERROR_SUCCESS) - goto cleanup; - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) - goto cleanup; - - if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) - goto cleanup; - - memset((void *) &securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); - securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - securityAttributes.lpSecurityDescriptor = pSD; - securityAttributes.bInheritHandle = FALSE; - - pSecurityAttributes = &securityAttributes; - } -#endif // !FEATURE_CORESYSTEM - WCHAR objectName[MAX_LONGPATH] = {0}; WCHAR objectNamePrefix[MAX_LONGPATH] = {0}; GetObjectNamePrefix(processID, fromRuntime, objectNamePrefix); @@ -291,14 +200,6 @@ class BBSweep hTerminationEvent = ::WszCreateEvent(pSecurityAttributes, true, false, NULL); swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hProfWriterSemaphore"), objectNamePrefix); hProfWriterSemaphore = ::WszCreateSemaphore(pSecurityAttributes, MAX_COUNT, MAX_COUNT, objectName); - -#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO -cleanup: - if (pSD) delete [] ((char *) pSD); - if (pAdminSid) FreeSid(pAdminSid); - if (hToken) CloseHandle(hToken); - if (buffer) delete [] ((char *) buffer); -#endif } bInitialized = hSweepMutex && @@ -378,7 +279,7 @@ class BBSweep } else { -#if defined (FEATURE_CORESYSTEM) && !defined(DACCESS_COMPILE) +#if !defined(DACCESS_COMPILE) #define MODULE_NAME W("api-ms-win-security-appcontainer-l1-1-0.dll") #else #define MODULE_NAME W("kernel32.dll") diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 28b1010666369f..e544430fa587ba 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -176,7 +176,6 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls" CONFIG_DWORD_INFO(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "") CONFIG_DWORD_INFO(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgEnableMixedModeDebugging, W("DbgEnableMixedModeDebuggingInternalOnly"), 0, "") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing") @@ -562,21 +561,36 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, /// Tiered Compilation /// #ifdef FEATURE_TIERED_COMPILATION +#ifdef _DEBUG +// Use lower values to exercise more paths sooner +#define TC_BackgroundWorkerTimeoutMs (100) +#define TC_CallCountThreshold (2) +#define TC_CallCountingDelayMs (1) +#define TC_DelaySingleProcMultiplier (2) +#define TC_DeleteCallCountingStubsAfter (1) +#else // !_DEBUG +#define TC_BackgroundWorkerTimeoutMs (4000) +#define TC_CallCountThreshold (30) +#define TC_CallCountingDelayMs (100) +#define TC_DelaySingleProcMultiplier (10) +#define TC_DeleteCallCountingStubsAfter (4096) +#endif // _DEBUG RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), 4000, "How long in milliseconds the background worker thread may remain idle before exiting.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), 30, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), 10, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), TC_BackgroundWorkerTimeoutMs, "How long in milliseconds the background worker thread may remain idle before exiting.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), TC_CallCountingDelayMs, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), TC_DelaySingleProcMultiplier, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_UseCallCountingStubs, W("TC_UseCallCountingStubs"), 1, "Uses call counting stubs for faster call counting.") -#ifdef _DEBUG -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 1, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") -#else -RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 4096, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") -#endif +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), TC_DeleteCallCountingStubsAfter, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") +#undef TC_BackgroundWorkerTimeoutMs +#undef TC_CallCountThreshold +#undef TC_CallCountingDelayMs +#undef TC_DelaySingleProcMultiplier +#undef TC_DeleteCallCountingStubsAfter #endif // FEATURE_TIERED_COMPILATION /// diff --git a/src/coreclr/inc/clrtypes.h b/src/coreclr/inc/clrtypes.h index 6050936814e6fa..5e83573e7aa943 100644 --- a/src/coreclr/inc/clrtypes.h +++ b/src/coreclr/inc/clrtypes.h @@ -11,7 +11,7 @@ #ifndef CLRTYPES_H_ #define CLRTYPES_H_ -#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) && defined(FEATURE_CORESYSTEM) +#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) // Prefer intsafe.h when available, which defines many of the MAX/MIN // values below (which is why they are in #ifndef blocks). #include diff --git a/src/coreclr/inc/ostype.h b/src/coreclr/inc/ostype.h index ddb0ec5d01b8ef..78494c71c2b66e 100644 --- a/src/coreclr/inc/ostype.h +++ b/src/coreclr/inc/ostype.h @@ -31,20 +31,6 @@ extern RunningOnStatusEnum gRunningOnStatus; void InitRunningOnVersionStatus(); -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -typedef enum -{ - WINRT_STATUS_UNINITED = 0, - WINRT_STATUS_UNSUPPORTED, - WINRT_STATUS_SUPPORTED -} -WinRTStatusEnum; - -extern WinRTStatusEnum gWinRTStatus; - -void InitWinRTStatus(); -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM - //***************************************************************************** // Returns true if you are running on Windows 8 or newer. //***************************************************************************** @@ -65,28 +51,10 @@ inline BOOL RunningOnWin8() #ifdef FEATURE_COMINTEROP -#ifdef FEATURE_CORESYSTEM - inline BOOL WinRTSupported() { return RunningOnWin8(); } -#else -inline BOOL WinRTSupported() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - - if (gWinRTStatus == WINRT_STATUS_UNINITED) - { - InitWinRTStatus(); - } - - return gWinRTStatus == WINRT_STATUS_SUPPORTED; -} -#endif // FEATURE_CORESYSTEM #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 65cda94ed9900b..081299e7bfdbc4 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -165,9 +165,7 @@ #define FEATURE_DOUBLE_ALIGNMENT_HINT #endif -#if defined(FEATURE_CORESYSTEM) #define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS -#endif // defined(FEATURE_CORESYSTEM) // If defined, support interpretation. diff --git a/src/coreclr/inc/volatile.h b/src/coreclr/inc/volatile.h index 610a408f39fb6e..e127fe25f99b1f 100644 --- a/src/coreclr/inc/volatile.h +++ b/src/coreclr/inc/volatile.h @@ -73,7 +73,10 @@ #endif #if defined(__GNUC__) -#if defined(HOST_ARM) || defined(HOST_ARM64) +#if defined(HOST_ARMV6) +// DMB ISH not valid on ARMv6 +#define VOLATILE_MEMORY_BARRIER() asm volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory") +#elif defined(HOST_ARM) || defined(HOST_ARM64) // This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows. #define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb ish" : : : "memory") #else diff --git a/src/coreclr/inc/vptr_list.h b/src/coreclr/inc/vptr_list.h index ad17ef35a3b609..d8e6cd42bd7c34 100644 --- a/src/coreclr/inc/vptr_list.h +++ b/src/coreclr/inc/vptr_list.h @@ -23,7 +23,6 @@ VPTR_CLASS(ReflectionModule) VPTR_CLASS(AppDomain) VPTR_CLASS(SystemDomain) -VPTR_CLASS(DomainAssembly) VPTR_CLASS(PrecodeStubManager) VPTR_CLASS(StubLinkStubManager) VPTR_CLASS(ThePreStubManager) @@ -39,7 +38,6 @@ VPTR_CLASS(DelegateInvokeStubManager) VPTR_CLASS(TailCallStubManager) #endif VPTR_CLASS(CallCountingStubManager) -VPTR_CLASS(PEAssembly) VPTR_CLASS(PEImageLayout) VPTR_CLASS(ConvertedImageLayout) diff --git a/src/coreclr/inc/winwrap.h b/src/coreclr/inc/winwrap.h index 3bf11baea318b3..0c1b7c22459ceb 100644 --- a/src/coreclr/inc/winwrap.h +++ b/src/coreclr/inc/winwrap.h @@ -188,16 +188,11 @@ #define WszWideCharToMultiByte WideCharToMultiByte #define WszCreateSemaphore(_secattr, _count, _maxcount, _name) CreateSemaphoreExW((_secattr), (_count), (_maxcount), (_name), 0, MAXIMUM_ALLOWED | SYNCHRONIZE | SEMAPHORE_MODIFY_STATE) -#ifdef FEATURE_CORESYSTEM - -// CoreSystem has GetFileVersionInfo{Size}Ex but not GetFileVersionInfoSize{Size} #undef GetFileVersionInfo #define GetFileVersionInfo(_filename, _handle, _len, _data) GetFileVersionInfoEx(0, (_filename), (_handle), (_len), (_data)) #undef GetFileVersionInfoSize #define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle)) -#endif // FEATURE_CORESYSTEM - #ifndef _T #define _T(str) W(str) #endif @@ -259,12 +254,6 @@ inline DWORD GetMaxDBCSCharByteSize() #endif // HOST_UNIX } -#ifndef HOST_UNIX -BOOL RunningInteractive(); -#else // !HOST_UNIX -#define RunningInteractive() FALSE -#endif // !HOST_UNIX - #ifndef Wsz_mbstowcs #define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize) #endif @@ -481,11 +470,7 @@ inline int LateboundMessageBoxA(HWND hWnd, return LateboundMessageBoxW(hWnd, wszText, wszCaption, uType); } -#if defined(FEATURE_CORESYSTEM) - #define MessageBoxW LateboundMessageBoxW #define MessageBoxA LateboundMessageBoxA -#endif // FEATURE_CORESYSTEM - #endif // __WIN_WRAP_H__ diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index c46cdd18a164ee..ebca7e65daaac7 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -32,6 +32,9 @@ function(create_standalone_jit) elseif((TARGETDETAILS_ARCH STREQUAL "arm") OR (TARGETDETAILS_ARCH STREQUAL "armel")) set(JIT_ARCH_SOURCES ${JIT_ARM_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_ARM_HEADERS}) + elseif((TARGETDETAILS_ARCH STREQUAL "armv6") OR (TARGETDETAILS_ARCH STREQUAL "armv6l")) + set(JIT_ARCH_SOURCES ${JIT_ARMV6_SOURCES}) + set(JIT_ARCH_HEADERS ${JIT_ARMV6_HEADERS}) elseif(TARGETDETAILS_ARCH STREQUAL "x86") set(JIT_ARCH_SOURCES ${JIT_I386_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_I386_HEADERS}) @@ -220,6 +223,10 @@ set( JIT_ARM64_SOURCES hwintrinsiccodegenarm64.cpp ) +set( JIT_ARMV6_SOURCES + # Not supported as JIT target +) + set( JIT_S390X_SOURCES # Not supported as JIT target ) @@ -362,6 +369,10 @@ set( JIT_ARM_HEADERS registerarm.h ) +set ( JIT_ARMV6_HEADERS + # Not supported as JIT target +) + set ( JIT_S390X_HEADERS # Not supported as JIT target ) @@ -380,6 +391,8 @@ convert_to_absolute_path(JIT_I386_SOURCES ${JIT_I386_SOURCES}) convert_to_absolute_path(JIT_I386_HEADERS ${JIT_I386_HEADERS}) convert_to_absolute_path(JIT_ARM64_SOURCES ${JIT_ARM64_SOURCES}) convert_to_absolute_path(JIT_ARM64_HEADERS ${JIT_ARM64_HEADERS}) +convert_to_absolute_path(JIT_ARMV6_SOURCES ${JIT_ARMV6_SOURCES}) +convert_to_absolute_path(JIT_ARMV6_HEADERS ${JIT_ARMV6_HEADERS}) convert_to_absolute_path(JIT_S390X_SOURCES ${JIT_S390X_SOURCES}) convert_to_absolute_path(JIT_S390X_HEADERS ${JIT_S390X_HEADERS}) @@ -389,6 +402,9 @@ if(CLR_CMAKE_TARGET_ARCH_AMD64) elseif(CLR_CMAKE_TARGET_ARCH_ARM) set(JIT_ARCH_SOURCES ${JIT_ARM_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_ARM_HEADERS}) +elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + set(JIT_ARCH_SOURCES ${JIT_ARMV6_SOURCES}) + set(JIT_ARCH_HEADERS ${JIT_ARMV6_HEADERS}) elseif(CLR_CMAKE_TARGET_ARCH_I386) set(JIT_ARCH_SOURCES ${JIT_I386_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_I386_HEADERS}) @@ -550,13 +566,13 @@ if (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) endif (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) if (CLR_CMAKE_TARGET_UNIX) - if (NOT ARCH_TARGET_NAME STREQUAL s390x) + if (NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6) if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) install_clr(TARGETS clrjit_universal_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME} DESTINATIONS . COMPONENT jit) else() install_clr(TARGETS clrjit_unix_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME} DESTINATIONS . COMPONENT jit) endif() - endif(NOT ARCH_TARGET_NAME STREQUAL s390x) + endif(NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6) endif() if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_PGO_INSTRUMENT) diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 9dd13cdc125332..18cb59068bab39 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -82,7 +82,7 @@ bool CodeGen::genInstrWithConstant( // generate two or more instructions // first we load the immediate into tmpReg - instGen_Set_Reg_To_Imm(attr, tmpReg, imm); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, imm); // generate the instruction using a three register encoding with the immediate in tmpReg GetEmitter()->emitIns_R_R_R(ins, attr, reg1, reg2, tmpReg); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index abcd70d040f0b9..595e2a232e5415 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -120,7 +120,7 @@ bool CodeGen::genInstrWithConstant(instruction ins, // generate two or more instructions // first we load the immediate into tmpReg - instGen_Set_Reg_To_Imm(size, tmpReg, imm); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, imm); regSet.verifyRegUsed(tmpReg); // when we are in an unwind code region diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 66ecbac761cb5e..24c57d110b7bab 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -2416,7 +2416,7 @@ class CopyBlockUnrollHelper const int dstOffsetAligned = AlignUp((UINT)dstOffset, storePairRegsAlignment); - if (endDstOffset - dstOffsetAligned >= storePairRegsWritesBytes) + if (byteCount >= (unsigned)storePairRegsWritesBytes) { const int dstBytesToAlign = dstOffsetAligned - dstOffset; diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 1c9eda6f63afc1..fe8b2d82dcaec9 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -6385,16 +6385,31 @@ void CodeGen::genEnregisterOSRArgsAndLocals() void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed) { - // For OSR the original method has set this up for us. + assert(compiler->compGeneratingProlog); + + const bool reportArg = compiler->lvaReportParamTypeArg(); + if (compiler->opts.IsOSR()) { + PatchpointInfo* const ppInfo = compiler->info.compPatchpointInfo; + if (reportArg) + { + // OSR method will use Tier0 slot to report context arg. + // + assert(ppInfo->HasGenericContextArgOffset()); + JITDUMP("OSR method will use Tier0 frame slot for generics context arg.\n"); + } + else if (compiler->lvaKeepAliveAndReportThis()) + { + // OSR method will use Tier0 slot to report `this` as context. + // + assert(ppInfo->HasKeptAliveThis()); + JITDUMP("OSR method will use Tier0 frame slot for generics context `this`.\n"); + } + return; } - assert(compiler->compGeneratingProlog); - - bool reportArg = compiler->lvaReportParamTypeArg(); - // We should report either generic context arg or "this" when used so. if (!reportArg) { diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 7da0bd72856251..cfc97dc6b1370c 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1972,6 +1972,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) inst_Mov(TYP_FLOAT, tempXmm, reg1, /* canSkip */ false); GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm); } + genProduceReg(lclNode); } #elif defined(TARGET_AMD64) assert(!TargetOS::IsWindows || !"Multireg store to SIMD reg not supported on Windows x64"); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index be0c4393cab8bd..cf87223f71760b 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -4636,7 +4636,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Run an early flow graph simplification pass // auto earlyUpdateFlowGraphPhase = [this]() { - const bool doTailDup = false; + constexpr bool doTailDup = false; fgUpdateFlowGraph(doTailDup); }; DoPhase(this, PHASE_EARLY_UPDATE_FLOW_GRAPH, earlyUpdateFlowGraphPhase); @@ -4776,6 +4776,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Unroll loops // DoPhase(this, PHASE_UNROLL_LOOPS, &Compiler::optUnrollLoops); + + // Clear loop table info that is not used after this point, and might become invalid. + // + DoPhase(this, PHASE_CLEAR_LOOP_INFO, &Compiler::optClearLoopIterInfo); } #ifdef DEBUG @@ -4909,7 +4913,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // update the flowgraph if we modified it during the optimization phase // auto optUpdateFlowGraphPhase = [this]() { - const bool doTailDup = false; + constexpr bool doTailDup = false; fgUpdateFlowGraph(doTailDup); }; DoPhase(this, PHASE_OPT_UPDATE_FLOW_GRAPH, optUpdateFlowGraphPhase); @@ -4966,11 +4970,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // DoPhase(this, PHASE_SIMPLE_LOWERING, &Compiler::fgSimpleLowering); -#ifdef DEBUG - fgDebugCheckBBlist(); - fgDebugCheckLinks(); -#endif - // Enable this to gather statistical data such as // call and register argument info, flowgraph and loop info, etc. compJitStats(); @@ -5021,10 +5020,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl // Copied from rpPredictRegUse() SetFullPtrRegMapRequired(codeGen->GetInterruptible() || !codeGen->isFramePointerUsed()); -#ifdef DEBUG - fgDebugCheckLinks(); -#endif - #if FEATURE_LOOP_ALIGN // Place loop alignment instructions DoPhase(this, PHASE_ALIGN_LOOPS, &Compiler::placeLoopAlignInstructions); @@ -5630,11 +5625,8 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr, // Set this before the first 'BADCODE' // Skip verification where possible - //.tiVerificationNeeded = !compileFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION); assert(compileFlags->IsSet(JitFlags::JIT_FLAG_SKIP_VERIFICATION)); - assert(!compIsForInlining() || !tiVerificationNeeded); // Inlinees must have been verified. - /* Setup an error trap */ struct Param @@ -6161,17 +6153,9 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, eeGetMethodFullName(info.compMethodHnd), dspPtr(impTokenLookupContextHandle))); } - if (tiVerificationNeeded) - { - JITLOG((LL_INFO10000, "tiVerificationNeeded initially set to true for %s\n", info.compFullName)); - } #endif // DEBUG - /* Since tiVerificationNeeded can be turned off in the middle of - compiling a method, and it might have caused blocks to be queued up - for reimporting, impCanReimport can be used to check for reimporting. */ - - impCanReimport = (tiVerificationNeeded || compStressCompile(STRESS_CHK_REIMPORT, 15)); + impCanReimport = compStressCompile(STRESS_CHK_REIMPORT, 15); /* Initialize set a bunch of global values */ @@ -6401,9 +6385,10 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, // Honor the config setting that tells the jit to // always optimize methods with loops. // - // If that's not set, and OSR is enabled, the jit may still + // If neither of those apply, and OSR is enabled, the jit may still // decide to optimize, if there's something in the method that - // OSR currently cannot handle. + // OSR currently cannot handle, or we're optionally suppressing + // OSR by method hash. // const char* reason = nullptr; @@ -6411,35 +6396,42 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, { reason = "tail.call and not BBINSTR"; } - else if ((info.compFlags & CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS) != 0) + else if (compHasBackwardJump && ((info.compFlags & CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS) != 0)) { - if (compHasBackwardJump) - { - reason = "loop"; - } + reason = "loop"; } - else if (JitConfig.TC_OnStackReplacement() > 0) + + if (compHasBackwardJump && (reason == nullptr) && (JitConfig.TC_OnStackReplacement() > 0)) { - const bool patchpointsOK = compCanHavePatchpoints(&reason); - assert(patchpointsOK || (reason != nullptr)); + const char* noPatchpointReason = nullptr; + bool canEscapeViaOSR = compCanHavePatchpoints(&reason); #ifdef DEBUG - // Optionally disable OSR by method hash. - // - if (patchpointsOK && compHasBackwardJump) + if (canEscapeViaOSR) { + // Optionally disable OSR by method hash. This will force any + // method that might otherwise get trapped in Tier0 to be optimized. + // static ConfigMethodRange JitEnableOsrRange; JitEnableOsrRange.EnsureInit(JitConfig.JitEnableOsrRange()); const unsigned hash = impInlineRoot()->info.compMethodHash(); if (!JitEnableOsrRange.Contains(hash)) { - JITDUMP("Disabling OSR -- Method hash 0x%08x not within range ", hash); - JITDUMPEXEC(JitEnableOsrRange.Dump()); - JITDUMP("\n"); - reason = "OSR disabled by JitEnableOsrRange"; + canEscapeViaOSR = false; + reason = "OSR disabled by JitEnableOsrRange"; } } #endif + + if (canEscapeViaOSR) + { + JITDUMP("\nOSR enabled for this method\n"); + } + else + { + JITDUMP("\nOSR disabled for this method: %s\n", noPatchpointReason); + assert(reason != nullptr); + } } if (reason != nullptr) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 0d4a9398481fde..967d27eac4703b 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4844,7 +4844,7 @@ class Compiler static LONG jitNestingLevel; #endif // DEBUG - static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut); + static bool impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut = nullptr); void impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, InlineResult* inlineResult); @@ -5945,7 +5945,7 @@ class Compiler bool fgReorderBlocks(); - void fgDetermineFirstColdBlock(); + PhaseStatus fgDetermineFirstColdBlock(); bool fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc = nullptr); @@ -6931,7 +6931,7 @@ class Compiler } #ifdef DEBUG - void lpValidatePreHeader() + void lpValidatePreHeader() const { // If this is called, we expect there to be a pre-header. assert(lpFlags & LPFLG_HAS_PREHEAD); @@ -6992,6 +6992,8 @@ class Compiler BasicBlock* exit, unsigned char exitCnt); + void optClearLoopIterInfo(); + #ifdef DEBUG void optPrintLoopInfo(unsigned lnum, bool printVerbose = false); void optPrintLoopInfo(const LoopDsc* loop, bool printVerbose = false); @@ -7120,12 +7122,6 @@ class Compiler bool optNarrowTree(GenTree* tree, var_types srct, var_types dstt, ValueNumPair vnpNarrow, bool doit); - /************************************************************************** - * Optimization conditions - *************************************************************************/ - - bool optAvoidIntMult(void); - protected: // The following is the upper limit on how many expressions we'll keep track // of for the CSE analysis. @@ -8082,7 +8078,6 @@ class Compiler CORINFO_RESOLVED_TOKEN* pConstrainedToken, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult); - inline CORINFO_CALLINFO_FLAGS addVerifyFlag(CORINFO_CALLINFO_FLAGS flags); void eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS flags, @@ -10713,12 +10708,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ public: - // Set to true if verification cannot be skipped for this method - // CoreCLR does not ever run IL verification. Compile out the verifier from the JIT by making this a constant. - // TODO: Delete the verifier from the JIT? (https://github.com/dotnet/runtime/issues/32648) - // bool tiVerificationNeeded; - static const bool tiVerificationNeeded = false; - // Returns true if child is equal to or a subtype of parent for merge purposes // This support is necessary to suport attributes that are not described in // for example, signatures. For example, the permanent home byref (byref that diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 5a7b17f776f2c6..f03ecd43f77025 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1986,13 +1986,18 @@ inline bool Compiler::lvaKeepAliveAndReportThis() // the VM requires us to keep the generics context alive or it is used in a look-up. // We keep it alive in the lookup scenario, even when the VM didn't ask us to, // because collectible types need the generics context when gc-ing. + // + // Methoods that can inspire OSR methods must always report context as live + // if (genericsContextIsThis) { - const bool mustKeep = (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_KEEP_ALIVE) != 0; + const bool mustKeep = (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_KEEP_ALIVE) != 0; + const bool hasPatchpoint = doesMethodHavePatchpoints() || doesMethodHavePartialCompilationPatchpoints(); - if (lvaGenericsContextInUse || mustKeep) + if (lvaGenericsContextInUse || mustKeep || hasPatchpoint) { - JITDUMP("Reporting this as generic context: %s\n", mustKeep ? "must keep" : "referenced"); + JITDUMP("Reporting this as generic context: %s\n", + mustKeep ? "must keep" : (hasPatchpoint ? "patchpoints" : "referenced")); return true; } } @@ -2024,6 +2029,13 @@ inline bool Compiler::lvaReportParamTypeArg() { return true; } + + // Methoods that have patchpoints always report context as live + // + if (doesMethodHavePatchpoints() || doesMethodHavePartialCompilationPatchpoints()) + { + return true; + } } // Otherwise, we don't need to report it -- the generics context parameter is unused. @@ -2343,29 +2355,29 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX inline unsigned Compiler::compMapILargNum(unsigned ILargNum) { - assert(ILargNum < info.compILargsCount || tiVerificationNeeded); + assert(ILargNum < info.compILargsCount); // Note that this works because if compRetBuffArg/compTypeCtxtArg/lvVarargsHandleArg are not present // they will be BAD_VAR_NUM (MAX_UINT), which is larger than any variable number. if (ILargNum >= info.compRetBuffArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } if (ILargNum >= (unsigned)info.compTypeCtxtArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } if (ILargNum >= (unsigned)lvaVarargsHandleArg) { ILargNum++; - assert(ILargNum < info.compLocalsCount || tiVerificationNeeded); // compLocals count already adjusted. + assert(ILargNum < info.compLocalsCount); // compLocals count already adjusted. } - assert(ILargNum < info.compArgsCount || tiVerificationNeeded); + assert(ILargNum < info.compArgsCount); return (ILargNum); } @@ -3566,22 +3578,6 @@ inline bool Compiler::LoopDsc::lpArrLenLimit(Compiler* comp, ArrIndex* index) co return false; } -/* -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XX XX -XX Optimization activation rules XX -XX XX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -*/ - -// should we try to replace integer multiplication with lea/add/shift sequences? -inline bool Compiler::optAvoidIntMult(void) -{ - return (compCodeOpt() != SMALL_CODE); -} - /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h index e5c15c1d438a6c..8f72dcce2360cd 100644 --- a/src/coreclr/jit/compphases.h +++ b/src/coreclr/jit/compphases.h @@ -5,7 +5,7 @@ // // -// Names of x86 JIT phases, in order. Assumes that the caller defines CompPhaseNameMacro +// Names of JIT phases, in order. Assumes that the caller defines CompPhaseNameMacro // in a useful way before including this file, e.g., to define the phase enumeration and the // corresponding array of string names of those phases. This include file undefines CompPhaseNameMacro // after the last use. @@ -61,6 +61,7 @@ CompPhaseNameMacro(PHASE_ZERO_INITS, "Redundant zero Inits", CompPhaseNameMacro(PHASE_FIND_LOOPS, "Find loops", "LOOP-FND", false, -1, false) CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false) CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1, false) +CompPhaseNameMacro(PHASE_CLEAR_LOOP_INFO, "Clear loop info", "LP-CLEAR", false, -1, false) CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1, false) CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1, false) CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1, false) @@ -86,7 +87,6 @@ CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true) CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false) CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1, false) -CompPhaseNameMacro(PHASE_ALIGN_LOOPS, "Place 'align' instructions", "LOOP-ALIGN", false, -1, false) CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1, false) CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS, false) @@ -100,6 +100,7 @@ CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN, false) CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN, false) CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN, false) +CompPhaseNameMacro(PHASE_ALIGN_LOOPS, "Place 'align' instructions", "LOOP-ALIGN", false, -1, false) CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1, false) CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1, false) CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1, false) diff --git a/src/coreclr/jit/earlyprop.cpp b/src/coreclr/jit/earlyprop.cpp index f00b3f6e3ad6e6..283c9c8901ae7c 100644 --- a/src/coreclr/jit/earlyprop.cpp +++ b/src/coreclr/jit/earlyprop.cpp @@ -110,7 +110,7 @@ void Compiler::optCheckFlagsAreSet(unsigned methodFlag, if ((basicBlock->bbFlags & bbFlag) == 0) { printf("%s is not set on " FMT_BB " but is required because of the following tree \n", bbFlagStr, - compCurBB->bbNum); + basicBlock->bbNum); gtDispTree(tree); assert(false); } diff --git a/src/coreclr/jit/ee_il_dll.hpp b/src/coreclr/jit/ee_il_dll.hpp index 33d5fab12ac5bf..337ca8f1479775 100644 --- a/src/coreclr/jit/ee_il_dll.hpp +++ b/src/coreclr/jit/ee_il_dll.hpp @@ -294,11 +294,3 @@ inline CORINFO_CALLINFO_FLAGS combine(CORINFO_CALLINFO_FLAGS flag1, CORINFO_CALL { return (CORINFO_CALLINFO_FLAGS)(flag1 | flag2); } -inline CORINFO_CALLINFO_FLAGS Compiler::addVerifyFlag(CORINFO_CALLINFO_FLAGS flags) -{ - if (tiVerificationNeeded) - { - flags = combine(flags, CORINFO_CALLINFO_VERIFICATION); - } - return flags; -} diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index d6ed324deb242a..5cef7d5aa12f25 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -193,7 +193,7 @@ bool IsDstDstSrcAVXInstruction(instruction ins); bool IsDstSrcSrcAVXInstruction(instruction ins); bool HasRegularWideForm(instruction ins); bool HasRegularWideImmediateForm(instruction ins); -bool DoesWriteZeroFlag(instruction ins); +static bool DoesWriteZeroFlag(instruction ins); bool DoesWriteSignFlag(instruction ins); bool DoesResetOverflowAndCarryFlags(instruction ins); bool IsFlagsAlwaysModified(instrDesc* id); diff --git a/src/coreclr/jit/error.cpp b/src/coreclr/jit/error.cpp index 1845af97b5731f..dfb5a859b43008 100644 --- a/src/coreclr/jit/error.cpp +++ b/src/coreclr/jit/error.cpp @@ -258,11 +258,7 @@ void debugError(const char* msg, const char* file, unsigned line) // If ComPlus_JitRequired is 0 or is not set, we will not assert. if (JitConfig.JitRequired() == 1 || getBreakOnBadCode()) { - // Don't assert if verification is done. - if (!env->compiler->tiVerificationNeeded || getBreakOnBadCode()) - { - assertAbort(msg, file, line); - } + assertAbort(msg, file, line); } BreakIfDebuggerPresent(); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 6b41c055422b0b..7f8bd7b01c6d03 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -2229,7 +2229,7 @@ void Compiler::fgAdjustForAddressExposedOrWrittenThis() LclVarDsc* thisVarDsc = lvaGetDesc(info.compThisArg); // Optionally enable adjustment during stress. - if (!tiVerificationNeeded && compStressCompile(STRESS_GENERIC_VARN, 15)) + if (compStressCompile(STRESS_GENERIC_VARN, 15)) { thisVarDsc->lvHasILStoreOp = true; } @@ -3516,9 +3516,6 @@ void Compiler::fgFindBasicBlocks() #endif // !FEATURE_EH_FUNCLETS -#ifndef DEBUG - if (tiVerificationNeeded) -#endif { // always run these checks for a debug build verCheckNestingLevel(initRoot); @@ -3527,7 +3524,7 @@ void Compiler::fgFindBasicBlocks() #ifndef DEBUG // fgNormalizeEH assumes that this test has been passed. And Ssa assumes that fgNormalizeEHTable // has been run. So do this unless we're in minOpts mode (and always in debug). - if (tiVerificationNeeded || !opts.MinOpts()) + if (!opts.MinOpts()) #endif { fgCheckBasicBlockControlFlow(); @@ -4552,7 +4549,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) BasicBlock* bPrev = block->bbPrev; - JITDUMP("fgRemoveBlock " FMT_BB "\n", block->bbNum); + JITDUMP("fgRemoveBlock " FMT_BB ", unreachable=%s\n", block->bbNum, dspBool(unreachable)); // If we've cached any mappings from switch blocks to SwitchDesc's (which contain only the // *unique* successors of the switch block), invalidate that cache, since an entry in one of @@ -4576,12 +4573,6 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) fgUnreachableBlock(block); - /* If this is the last basic block update fgLastBB */ - if (block == fgLastBB) - { - fgLastBB = bPrev; - } - #if defined(FEATURE_EH_FUNCLETS) // If block was the fgFirstFuncletBB then set fgFirstFuncletBB to block->bbNext if (block == fgFirstFuncletBB) @@ -4634,7 +4625,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable) leaveBlk->bbRefs = 0; leaveBlk->bbPreds = nullptr; - fgRemoveBlock(leaveBlk, true); + fgRemoveBlock(leaveBlk, /* unreachable */ true); #if defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM) fgClearFinallyTargetBit(leaveBlk->bbJumpDest); diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp index 0bc461ebbb9495..2df6d000419b9e 100644 --- a/src/coreclr/jit/fgdiagnostic.cpp +++ b/src/coreclr/jit/fgdiagnostic.cpp @@ -3534,12 +3534,22 @@ void Compiler::fgDebugCheckNodesUniqueness() // - If the method has natural loops, the loop table is not null // - Loop `top` must come before `bottom`. // - Loop `entry` must be between `top` and `bottom`. +// - Children loops of a loop are disjoint. // - All basic blocks with loop numbers set have a corresponding loop in the table // - All basic blocks without a loop number are not in a loop // - All parents of the loop with the block contain that block +// - If the loop has a pre-header, it is valid +// - The loop flags are valid // void Compiler::fgDebugCheckLoopTable() { +#ifdef DEBUG + if (verbose) + { + printf("*************** In fgDebugCheckLoopTable\n"); + } +#endif // DEBUG + if (optLoopCount > 0) { assert(optLoopTable != nullptr); @@ -3655,8 +3665,38 @@ void Compiler::fgDebugCheckLoopTable() assert(loop.lpExit == nullptr); } - if (loop.lpParent != BasicBlock::NOT_IN_LOOP) + if (loop.lpParent == BasicBlock::NOT_IN_LOOP) { + // This is a top-level loop. + + // Verify all top-level loops are disjoint. We don't have a list of just these (such as a + // top-level pseudo-loop entry with a list of all top-level lists), so we have to iterate + // over the entire loop table. + for (unsigned j = 0; j < optLoopCount; j++) + { + if (i == j) + { + // Don't compare against ourselves. + continue; + } + const LoopDsc& otherLoop = optLoopTable[j]; + if (otherLoop.lpFlags & LPFLG_REMOVED) + { + continue; + } + if (otherLoop.lpParent != BasicBlock::NOT_IN_LOOP) + { + // Only consider top-level loops + continue; + } + assert(MappedChecks::lpDisjoint(blockNumMap, &loop, otherLoop)); + } + } + else + { + // This is not a top-level loop + + assert(loop.lpParent != BasicBlock::NOT_IN_LOOP); assert(loop.lpParent < optLoopCount); assert(loop.lpParent < i); // outer loops come before inner loops in the table const LoopDsc& parentLoop = optLoopTable[loop.lpParent]; @@ -3674,10 +3714,12 @@ void Compiler::fgDebugCheckLoopTable() assert(child < optLoopCount); assert(i < child); // outer loops come before inner loops in the table const LoopDsc& childLoop = optLoopTable[child]; - if ((childLoop.lpFlags & LPFLG_REMOVED) == 0) // removed child loop might still be in table + if (childLoop.lpFlags & LPFLG_REMOVED) // removed child loop might still be in table { - assert(MappedChecks::lpContains(blockNumMap, &loop, childLoop)); + continue; } + assert(MappedChecks::lpContains(blockNumMap, &loop, childLoop)); + assert(childLoop.lpParent == i); } // Verify all child loops are disjoint. @@ -3734,6 +3776,43 @@ void Compiler::fgDebugCheckLoopTable() assert(MappedChecks::lpContains(blockNumMap, &loop, predBlock)); } } + + loop.lpValidatePreHeader(); + } + + // Check the flags. + // Note that the various init/limit flags are only used when LPFLG_ITER is set, but they are set first, + // separately, and only if everything works out is LPFLG_ITER set. If LPFLG_ITER is NOT set, the + // individual flags are not un-set (arguably, they should be). + + // Only one of the `init` flags can be set. + assert(genCountBits((unsigned)(loop.lpFlags & (LPFLG_VAR_INIT | LPFLG_CONST_INIT))) <= 1); + + // Only one of the `limit` flags can be set. (Note that LPFLG_SIMD_LIMIT is a "sub-flag" that can be + // set when LPFLG_CONST_LIMIT is set.) + assert(genCountBits((unsigned)(loop.lpFlags & (LPFLG_VAR_LIMIT | LPFLG_CONST_LIMIT | LPFLG_ARRLEN_LIMIT))) <= + 1); + + // LPFLG_SIMD_LIMIT can only be set if LPFLG_CONST_LIMIT is set. + if (loop.lpFlags & LPFLG_SIMD_LIMIT) + { + assert(loop.lpFlags & LPFLG_CONST_LIMIT); + } + + if (loop.lpFlags & (LPFLG_CONST_INIT | LPFLG_VAR_INIT)) + { + assert(loop.lpInitBlock != nullptr); + + if (loop.lpFlags & LPFLG_VAR_INIT) + { + assert(loop.lpVarInit < lvaCount); + } + } + + if (loop.lpFlags & LPFLG_ITER) + { + loop.VERIFY_lpIterTree(); + loop.VERIFY_lpTestTree(); } } diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 4fa511f63dbddb..514b6879a9f6b3 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -175,7 +175,7 @@ PhaseStatus Compiler::fgRemoveEmptyFinally() nextBlock = leaveBlock->bbNext; leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS; - fgRemoveBlock(leaveBlock, true); + fgRemoveBlock(leaveBlock, /* unreachable */ true); // Cleanup the postTryFinallyBlock fgCleanupContinuation(postTryFinallyBlock); @@ -194,8 +194,8 @@ PhaseStatus Compiler::fgRemoveEmptyFinally() firstBlock->bbRefs = 0; // Remove the handler block. - const bool unreachable = true; firstBlock->bbFlags &= ~BBF_DONT_REMOVE; + constexpr bool unreachable = true; fgRemoveBlock(firstBlock, unreachable); // Find enclosing try region for the try, if any, and update @@ -1181,7 +1181,7 @@ PhaseStatus Compiler::fgCloneFinally() nextBlock = leaveBlock->bbNext; leaveBlock->bbFlags &= ~BBF_KEEP_BBJ_ALWAYS; - fgRemoveBlock(leaveBlock, true); + fgRemoveBlock(leaveBlock, /* unreachable */ true); // Make sure iteration isn't going off the deep end. assert(leaveBlock != endCallFinallyRangeBlock); diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 4e446837bcb189..eebe8a8e8eff5c 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -445,8 +445,7 @@ bool Compiler::fgRemoveUnreachableBlocks() else if (block == genReturnBB) { // Don't remove statements for the genReturnBB block, as we might have special hookups there. - // For example, in VSW 364383, - // the profiler hookup needs to have the "void GT_RETURN" statement + // For example, the profiler hookup needs to have the "void GT_RETURN" statement // to properly set the info.compProfilerCallback flag. continue; } @@ -478,10 +477,9 @@ bool Compiler::fgRemoveUnreachableBlocks() if (block->bbFlags & BBF_DONT_REMOVE) { - bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair(); + const bool bIsBBCallAlwaysPair = block->isBBCallAlwaysPair(); - /* Unmark the block as removed, */ - /* clear BBF_INTERNAL as well and set BBJ_IMPORTED */ + // Unmark the block as removed, clear BBF_INTERNAL, and set BBJ_IMPORTED // The successors may be unreachable after this change. changed |= block->NumSucc() > 0; @@ -518,7 +516,7 @@ bool Compiler::fgRemoveUnreachableBlocks() if (block->bbFlags & BBF_REMOVED) { - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); // TODO: couldn't we have fgRemoveBlock() return the block after the (last)one removed // so we don't need the code below? @@ -2285,8 +2283,7 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) { // genReturnBB should never be removed, as we might have special hookups there. // Therefore, we should never come here to remove the statements in the genReturnBB block. - // For example, in VSW 364383, - // the profiler hookup needs to have the "void GT_RETURN" statement + // For example, the profiler hookup needs to have the "void GT_RETURN" statement // to properly set the info.compProfilerCallback flag. noway_assert(block != genReturnBB); @@ -2308,10 +2305,7 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) assert(!block->isBBCallAlwaysPairTail()); // can't remove the BBJ_ALWAYS of a BBJ_CALLFINALLY / BBJ_ALWAYS pair #endif - /* First walk the statement trees in this basic block and delete each stmt */ - - /* Make the block publicly available */ - compCurBB = block; + // First, delete all the code in the block. if (block->IsLIR()) { @@ -2343,13 +2337,13 @@ void Compiler::fgUnreachableBlock(BasicBlock* block) noway_assert(block->bbStmtList == nullptr); } - /* Next update the loop table and bbWeights */ + // Next update the loop table and bbWeights optUpdateLoopsBeforeRemoveBlock(block); - /* Mark the block as removed */ + // Mark the block as removed block->bbFlags |= BBF_REMOVED; - /* update bbRefs and bbPreds for the blocks reached by this block */ + // Update bbRefs and bbPreds for the blocks reached by this block fgRemoveBlockAsPred(block); } @@ -2825,7 +2819,7 @@ bool Compiler::fgOptimizeEmptyBlock(BasicBlock* block) /* Remove the block */ compCurBB = block; - fgRemoveBlock(block, false); + fgRemoveBlock(block, /* unreachable */ false); return true; default: @@ -6108,7 +6102,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) /* no references -> unreachable - remove it */ /* For now do not update the bbNum, do it at the end */ - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); change = true; modified = true; @@ -6126,7 +6120,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication) case BBJ_ALWAYS: if (block->bbJumpDest == block) { - fgRemoveBlock(block, true); + fgRemoveBlock(block, /* unreachable */ true); change = true; modified = true; diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 21f0f583340a8f..e2786ce57d820d 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -67,7 +67,6 @@ static bool blockNeedsGCPoll(BasicBlock* block) // Returns: // PhaseStatus indicating what, if anything, was changed. // - PhaseStatus Compiler::fgInsertGCPolls() { PhaseStatus result = PhaseStatus::MODIFIED_NOTHING; @@ -181,13 +180,6 @@ PhaseStatus Compiler::fgInsertGCPolls() constexpr bool computeDoms = false; fgUpdateChangedFlowGraph(computePreds, computeDoms); } -#ifdef DEBUG - if (verbose) - { - printf("*************** After fgInsertGCPolls()\n"); - fgDispBasicBlocks(true); - } -#endif // DEBUG return result; } @@ -3093,6 +3085,9 @@ void Compiler::fgSimpleLowering() fgDispHandlerTab(); printf("\n"); } + + fgDebugCheckBBlist(); + fgDebugCheckLinks(); #endif } @@ -3374,7 +3369,7 @@ void Compiler::fgCreateFunclets() * or are rarely executed. */ -void Compiler::fgDetermineFirstColdBlock() +PhaseStatus Compiler::fgDetermineFirstColdBlock() { #ifdef DEBUG if (verbose) @@ -3388,19 +3383,19 @@ void Compiler::fgDetermineFirstColdBlock() // assert(fgSafeBasicBlockCreation); - fgFirstColdBlock = nullptr; + assert(fgFirstColdBlock == nullptr); if (!opts.compProcedureSplitting) { JITDUMP("No procedure splitting will be done for this method\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #ifdef DEBUG if ((compHndBBtabCount > 0) && !opts.compProcedureSplittingEH) { JITDUMP("No procedure splitting will be done for this method with EH (by request)\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #endif // DEBUG @@ -3411,7 +3406,7 @@ void Compiler::fgDetermineFirstColdBlock() if (compHndBBtabCount > 0) { JITDUMP("No procedure splitting will be done for this method with EH (implementation limitation)\n"); - return; + return PhaseStatus::MODIFIED_NOTHING; } #endif // FEATURE_EH_FUNCLETS @@ -3482,7 +3477,7 @@ void Compiler::fgDetermineFirstColdBlock() if (prevToFirstColdBlock == nullptr) { - return; // To keep Prefast happy + return PhaseStatus::MODIFIED_EVERYTHING; // To keep Prefast happy } // If we only have one cold block @@ -3578,14 +3573,12 @@ EXIT:; { printf("fgFirstColdBlock is NULL.\n"); } - - fgDispBasicBlocks(); } - - fgVerifyHandlerTab(); #endif // DEBUG fgFirstColdBlock = firstColdBlock; + + return PhaseStatus::MODIFIED_EVERYTHING; } /* static */ diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 678a2a60409db7..35b9d2d829ca42 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -4176,6 +4176,7 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) case GT_LCL_VAR: case GT_LCL_FLD: + case GT_CLS_VAR: // We evaluate op2 before op1 bReverseInAssignment = true; @@ -5226,7 +5227,7 @@ bool GenTree::OperRequiresCallFlag(Compiler* comp) // Return Value: // True if the given node contains an implicit indirection // -// Note that for the GT_HWINTRINSIC node we have to examine the +// Note that for the [HW]INTRINSIC nodes we have to examine the // details of the node to determine its result. // @@ -5250,6 +5251,8 @@ bool GenTree::OperIsImplicitIndir() const case GT_ARR_ELEM: case GT_ARR_OFFSET: return true; + case GT_INTRINSIC: + return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType; #ifdef FEATURE_SIMD case GT_SIMD: { @@ -5306,18 +5309,8 @@ bool GenTree::OperMayThrow(Compiler* comp) case GT_INTRINSIC: // If this is an intrinsic that represents the object.GetType(), it can throw an NullReferenceException. - // Report it as may throw. - // Note: Some of the rest of the existing intrinsics could potentially throw an exception (for example - // the array and string element access ones). They are handled differently than the GetType intrinsic - // and are not marked with GTF_EXCEPT. If these are revisited at some point to be marked as - // GTF_EXCEPT, - // the code below might need to be specialized to handle them properly. - if ((this->gtFlags & GTF_EXCEPT) != 0) - { - return true; - } - - break; + // Currently, this is the only intrinsic that can throw an exception. + return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType; case GT_CALL: @@ -19294,20 +19287,22 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; -#if defined(TARGET_XARCH) - if (simdSize == 32) - { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - } -#endif // TARGET_XARCH - switch (op) { #if defined(TARGET_XARCH) case GT_EQ: { - intrinsic = (simdSize == 32) ? NI_Vector256_op_Equality : NI_Vector128_op_Equality; + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Equality; + } + else + { + intrinsic = NI_Vector128_op_Equality; + } break; } @@ -19323,6 +19318,12 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op, if (simdSize == 32) { + // TODO-XArch-CQ: It's a non-trivial amount of work to support these + // for floating-point while only utilizing AVX. It would require, among + // other things, inverting the comparison and potentially support for a + // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + intrinsic = NI_Vector256_op_Equality; getAllBitsSet = NI_Vector256_get_AllBitsSet; } @@ -19433,14 +19434,6 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, NamedIntrinsic intrinsic = NI_Illegal; -#if defined(TARGET_XARCH) - if (simdSize == 32) - { - assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); - assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); - } -#endif // TARGET_XARCH - switch (op) { #if defined(TARGET_XARCH) @@ -19453,7 +19446,20 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, // We want to generate a comparison along the lines of // GT_XX(op1, op2).As() != Vector128.Zero - intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; + if (simdSize == 32) + { + // TODO-XArch-CQ: It's a non-trivial amount of work to support these + // for floating-point while only utilizing AVX. It would require, among + // other things, inverting the comparison and potentially support for a + // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. + assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Inequality; + } + else + { + intrinsic = NI_Vector128_op_Inequality; + } op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false); @@ -19475,7 +19481,17 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op, case GT_NE: { - intrinsic = (simdSize == 32) ? NI_Vector256_op_Inequality : NI_Vector128_op_Inequality; + if (simdSize == 32) + { + assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); + assert(varTypeIsFloating(simdBaseType) || compIsaSupportedDebugOnly(InstructionSet_AVX2)); + + intrinsic = NI_Vector256_op_Inequality; + } + else + { + intrinsic = NI_Vector128_op_Inequality; + } break; } #elif defined(TARGET_ARM64) @@ -22009,8 +22025,7 @@ bool GenTreeLclFld::IsOffsetMisaligned() const bool GenTree::IsInvariant() const { - GenTree* lclVarTree = nullptr; - return OperIsConst() || Compiler::impIsAddressInLocal(this, &lclVarTree); + return OperIsConst() || Compiler::impIsAddressInLocal(this); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 0a5559dfd4122c..fe9729ee7a9f15 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -285,7 +285,26 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, bool isIsaSupported = comp->compSupportsHWIntrinsic(isa); - if ((strcmp(methodName, "get_IsSupported") == 0) || (strcmp(methodName, "get_IsHardwareAccelerated") == 0)) + bool isHardwareAcceleratedProp = (strcmp(methodName, "get_IsHardwareAccelerated") == 0); +#ifdef TARGET_XARCH + if (isHardwareAcceleratedProp) + { + // Special case: Some of Vector128/256 APIs are hardware accelerated with Sse1 and Avx1, + // but we want IsHardwareAccelerated to return true only when all of them are (there are + // still can be cases where e.g. Sse41 might give an additional boost for Vector128, but it's + // not important enough to bump the minimal Sse version here) + if (strcmp(className, "Vector128") == 0) + { + isa = InstructionSet_SSE2; + } + else if (strcmp(className, "Vector256") == 0) + { + isa = InstructionSet_AVX2; + } + } +#endif + + if ((strcmp(methodName, "get_IsSupported") == 0) || isHardwareAcceleratedProp) { return isIsaSupported ? (comp->compExactlyDependsOn(isa) ? NI_IsSupported_True : NI_IsSupported_Dynamic) : NI_IsSupported_False; diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 43bd543c599f1d..4551ed9e4e1ce1 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -577,6 +577,25 @@ struct HWIntrinsicInfo return lookup(id).ins[type - TYP_BYTE]; } + static instruction lookupIns(GenTreeHWIntrinsic* intrinsicNode) + { + assert(intrinsicNode != nullptr); + + NamedIntrinsic intrinsic = intrinsicNode->GetHWIntrinsicId(); + var_types type = TYP_UNKNOWN; + + if (lookupCategory(intrinsic) == HW_Category_Scalar) + { + type = intrinsicNode->TypeGet(); + } + else + { + type = intrinsicNode->GetSimdBaseType(); + } + + return lookupIns(intrinsic, type); + } + static HWIntrinsicCategory lookupCategory(NamedIntrinsic id) { return lookup(id).category; diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index e4b9a1326680c0..6dfe48047c094e 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -206,6 +206,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { const HWIntrinsic intrin(node); + // We need to validate that other phases of the compiler haven't introduced unsupported intrinsics + assert(compiler->compIsaSupportedDebugOnly(HWIntrinsicInfo::lookupIsa(intrin.id))); + regNumber targetReg = node->GetRegNum(); regNumber op1Reg = REG_NA; diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index d6490c59b2e360..10c8dcaedb197a 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -86,6 +86,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); size_t numArgs = node->GetOperandCount(); + // We need to validate that other phases of the compiler haven't introduced unsupported intrinsics + assert(compiler->compIsaSupportedDebugOnly(isa)); + int ival = HWIntrinsicInfo::lookupIval(intrinsicId, compiler->compOpportunisticallyDependsOn(InstructionSet_AVX)); assert(HWIntrinsicInfo::RequiresCodegen(intrinsicId)); diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index f1b84825f21762..aec1be705f3db8 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -1024,7 +1024,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1287,7 +1287,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1305,7 +1305,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1339,7 +1339,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1357,7 +1357,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1391,7 +1391,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1409,7 +1409,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1443,7 +1443,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -1461,7 +1461,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, { assert(sig->numArgs == 2); - if ((simdSize != 32) || varTypeIsFloating(simdBaseType) || compExactlyDependsOn(InstructionSet_AVX2)) + if ((simdSize != 32) || compExactlyDependsOn(InstructionSet_AVX2)) { var_types simdType = getSIMDTypeForSize(simdSize); @@ -2024,7 +2024,12 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, assert(sig->numArgs == 1); var_types simdType = getSIMDTypeForSize(simdSize); - if (varTypeIsFloating(simdBaseType)) + if ((simdSize == 32) && !compOpportunisticallyDependsOn(InstructionSet_AVX2)) + { + // Vector256 for integer types requires AVX2 + break; + } + else if (varTypeIsFloating(simdBaseType)) { if (!compOpportunisticallyDependsOn(InstructionSet_SSE3)) { diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 648b4a8493d2f7..b9cc2ff883d64a 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -91,42 +91,6 @@ void Compiler::impPushOnStack(GenTree* tree, typeInfo ti) CORINFO_CLASS_HANDLE clsHnd = ti.GetClassHandle(); assert(clsHnd != NO_CLASS_HANDLE); } - - if (tiVerificationNeeded && !ti.IsDead()) - { - assert(typeInfo::AreEquivalent(NormaliseForStack(ti), ti)); // types are normalized - - // The ti type is consistent with the tree type. - // - - // On 64-bit systems, nodes whose "proper" type is "native int" get labeled TYP_LONG. - // In the verification type system, we always transform "native int" to "TI_INT". - // Ideally, we would keep track of which nodes labeled "TYP_LONG" are really "native int", but - // attempts to do that have proved too difficult. Instead, we'll assume that in checks like this, - // when there's a mismatch, it's because of this reason -- the typeInfo::AreEquivalentModuloNativeInt - // method used in the last disjunct allows exactly this mismatch. - assert(ti.IsDead() || (ti.IsByRef() && ((tree->TypeGet() == TYP_I_IMPL) || (tree->TypeGet() == TYP_BYREF))) || - (ti.IsUnboxedGenericTypeVar() && tree->TypeGet() == TYP_REF) || - (ti.IsObjRef() && tree->TypeGet() == TYP_REF) || (ti.IsMethod() && tree->TypeGet() == TYP_I_IMPL) || - (ti.IsType(TI_STRUCT) && tree->TypeGet() != TYP_REF) || - typeInfo::AreEquivalentModuloNativeInt(NormaliseForStack(ti), - NormaliseForStack(typeInfo(tree->TypeGet())))); - - // If it is a struct type, make certain we normalized the primitive types - assert(!ti.IsType(TI_STRUCT) || - info.compCompHnd->getTypeForPrimitiveValueClass(ti.GetClassHandle()) == CORINFO_TYPE_UNDEF); - } - -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("About to push to stack: "); - ti.Dump(); - } -#endif // VERBOSE_VERIFY - #endif // DEBUG verCurrentState.esStack[verCurrentState.esStackDepth].seTypeInfo = ti; @@ -257,14 +221,7 @@ void Compiler::impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolv pResolvedToken->token = getU4LittleEndian(addr); pResolvedToken->tokenType = kind; - if (!tiVerificationNeeded) - { - info.compCompHnd->resolveToken(pResolvedToken); - } - else - { - Verify(eeTryResolveToken(pResolvedToken), "Token resolution failed"); - } + info.compCompHnd->resolveToken(pResolvedToken); } /***************************************************************************** @@ -279,19 +236,6 @@ StackEntry Compiler::impPopStack() BADCODE("stack underflow"); } -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - JITDUMP("\n"); - printf(TI_DUMP_PADDING); - printf("About to pop from the stack: "); - const typeInfo& ti = verCurrentState.esStack[verCurrentState.esStackDepth - 1].seTypeInfo; - ti.Dump(); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - return verCurrentState.esStack[--verCurrentState.esStackDepth]; } @@ -824,7 +768,7 @@ void Compiler::impAssignTempGen(unsigned tmpNum, // so at least ignore it in the case when verification is turned on // since any block that tries to use the temp would have failed verification. var_types varType = lvaTable[tmpNum].lvType; - assert(tiVerificationNeeded || varType == TYP_UNDEF || varTypeIsStruct(varType)); + assert(varType == TYP_UNDEF || varTypeIsStruct(varType)); lvaSetStruct(tmpNum, structType, false); varType = lvaTable[tmpNum].lvType; @@ -2487,21 +2431,9 @@ bool Compiler::impSpillStackEntry(unsigned level, /* Allocate a temp if we haven't been asked to use a particular one */ - if (tiVerificationNeeded) + if (tnum != BAD_VAR_NUM && (tnum >= lvaCount)) { - // Ignore bad temp requests (they will happen with bad code and will be - // catched when importing the destblock) - if (tnum != BAD_VAR_NUM && tnum >= lvaCount) - { - return false; - } - } - else - { - if (tnum != BAD_VAR_NUM && (tnum >= lvaCount)) - { - return false; - } + return false; } bool isNewTemp = false; @@ -2511,27 +2443,6 @@ bool Compiler::impSpillStackEntry(unsigned level, tnum = lvaGrabTemp(true DEBUGARG(reason)); isNewTemp = true; } - else if (tiVerificationNeeded && lvaTable[tnum].TypeGet() != TYP_UNDEF) - { - // if verification is needed and tnum's type is incompatible with - // type on that stack, we grab a new temp. This is safe since - // we will throw a verification exception in the dest block. - - var_types valTyp = tree->TypeGet(); - var_types dstTyp = lvaTable[tnum].TypeGet(); - - // if the two types are different, we return. This will only happen with bad code and will - // be catched when importing the destblock. We still allow int/byrefs and float/double differences. - if ((genActualType(valTyp) != genActualType(dstTyp)) && - !( -#ifndef TARGET_64BIT - (valTyp == TYP_I_IMPL && dstTyp == TYP_BYREF) || (valTyp == TYP_BYREF && dstTyp == TYP_I_IMPL) || -#endif // !TARGET_64BIT - (varTypeIsFloating(dstTyp) && varTypeIsFloating(valTyp)))) - { - return false; - } - } /* Assign the spilled entry to the temp */ impAssignTempGen(tnum, tree, verCurrentState.esStack[level].seTypeInfo.GetClassHandle(), level); @@ -2646,11 +2557,9 @@ inline void Compiler::impSpillSideEffects(bool spillGlobEffects, unsigned chkLev { GenTree* tree = verCurrentState.esStack[i].val; - GenTree* lclVarTree; - if ((tree->gtFlags & spillFlags) != 0 || - (spillGlobEffects && // Only consider the following when spillGlobEffects == true - !impIsAddressInLocal(tree, &lclVarTree) && // No need to spill the GT_ADDR node on a local. + (spillGlobEffects && // Only consider the following when spillGlobEffects == true + !impIsAddressInLocal(tree) && // No need to spill the GT_ADDR node on a local. gtHasLocalsWithAddrOp(tree))) // Spill if we still see GT_LCL_VAR that contains lvHasLdAddrOp or // lvAddrTaken flag. { @@ -6360,8 +6269,8 @@ void Compiler::verVerifyCall(OPCODE opcode, info.compCompHnd->resolveToken(&delegateResolvedToken); CORINFO_CALL_INFO delegateCallInfo; - eeGetCallInfo(&delegateResolvedToken, nullptr /* constraint typeRef */, - addVerifyFlag(CORINFO_CALLINFO_SECURITYCHECKS), &delegateCallInfo); + eeGetCallInfo(&delegateResolvedToken, nullptr /* constraint typeRef */, CORINFO_CALLINFO_SECURITYCHECKS, + &delegateCallInfo); bool isOpenDelegate = false; VerifyOrReturn(info.compCompHnd->isCompatibleDelegate(objTypeHandle, delegateResolvedToken.hClass, @@ -9542,6 +9451,10 @@ var_types Compiler::impImportCall(OPCODE opcode, // Take care to pass raw IL offset here as the 'debug info' might be different for // inlinees. rawILOffset); + + // Devirtualization may change which method gets invoked. Update our local cache. + // + methHnd = callInfo->hMethod; } if (impIsThis(obj)) @@ -9613,9 +9526,6 @@ var_types Compiler::impImportCall(OPCODE opcode, { if (newobjThis->gtOper == GT_COMMA) { - // In coreclr the callout can be inserted even if verification is disabled - // so we cannot rely on tiVerificationNeeded alone - // We must have inserted the callout. Get the real newobj. newobjThis = newobjThis->AsOp()->gtOp2; } @@ -9924,14 +9834,6 @@ var_types Compiler::impImportCall(OPCODE opcode, eeGetCallSiteSig(pResolvedToken->token, pResolvedToken->tokenScope, pResolvedToken->tokenContext, sig); } - // Find the return type used for verification by interpreting the method signature. - // NB: we are clobbering the already established sig. - if (tiVerificationNeeded) - { - // Actually, we never get the sig for the original method. - sig = &(callInfo->verSig); - } - typeInfo tiRetVal = verMakeTypeInfo(sig->retType, sig->retTypeClass); tiRetVal.NormaliseForStack(); @@ -9942,17 +9844,6 @@ var_types Compiler::impImportCall(OPCODE opcode, tiRetVal.SetIsReadonlyByRef(); } - if (tiVerificationNeeded) - { - // We assume all calls return permanent home byrefs. If they - // didn't they wouldn't be verifiable. This is also covering - // the Address() helper for multidimensional arrays. - if (tiRetVal.IsByRef()) - { - tiRetVal.SetIsPermanentHomeByRef(); - } - } - if (call->IsCall()) { // Sometimes "call" is not a GT_CALL (if we imported an intrinsic that didn't turn into a call) @@ -11792,22 +11683,27 @@ void Compiler::impImportBlockCode(BasicBlock* block) CORINFO_HELPER_DESC calloutHelper; const BYTE* lastLoadToken = nullptr; - // reject cyclic constraints - if (tiVerificationNeeded) - { - Verify(!info.hasCircularClassConstraints, "Method parent has circular class type parameter constraints."); - Verify(!info.hasCircularMethodConstraints, "Method has circular method type parameter constraints."); - } - /* Get the tree list started */ impBeginTreeList(); #ifdef FEATURE_ON_STACK_REPLACEMENT - // Is OSR enabled? + bool enablePatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0); + +#ifdef DEBUG + + // Optionally suppress patchpoints by method hash // - if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0)) + static ConfigMethodRange JitEnablePatchpointRange; + JitEnablePatchpointRange.EnsureInit(JitConfig.JitEnablePatchpointRange()); + const unsigned hash = impInlineRoot()->info.compMethodHash(); + const bool inRange = JitEnablePatchpointRange.Contains(hash); + enablePatchpoints &= inRange; + +#endif // DEBUG + + if (enablePatchpoints) { // We don't inline at Tier0, if we do, we may need rethink our approach. // Could probably support inlines that don't introduce flow. @@ -11822,13 +11718,13 @@ void Compiler::impImportBlockCode(BasicBlock* block) // if (!compTailPrefixSeen) { - assert(compCanHavePatchpoints()); - // The normaly policy is only to add patchpoints to the targets of lexically // backwards branches. // if (compHasBackwardJump) { + assert(compCanHavePatchpoints()); + // Is the start of this block a suitable patchpoint? // if (((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) != 0) && (verCurrentState.esStackDepth == 0)) @@ -11859,8 +11755,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) const bool tryOffsetOSR = offsetOSR >= 0; const bool tryRandomOSR = randomOSR > 0; - if ((tryOffsetOSR || tryRandomOSR) && (verCurrentState.esStackDepth == 0) && !block->hasHndIndex() && - ((block->bbFlags & BBF_PATCHPOINT) == 0)) + if (compCanHavePatchpoints() && (tryOffsetOSR || tryRandomOSR) && (verCurrentState.esStackDepth == 0) && + !block->hasHndIndex() && ((block->bbFlags & BBF_PATCHPOINT) == 0)) { // Block start can have a patchpoint. See if we should add one. // @@ -12332,11 +12228,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) val = getU4LittleEndian(codeAddr); JITDUMP(" %08X", val); - if (tiVerificationNeeded) - { - Verify(info.compCompHnd->isValidStringRef(info.compScopeHnd, val), "bad string"); - tiRetVal = typeInfo(TI_REF, impGetStringClass()); - } impPushOnStack(gtNewSconNode(val, info.compScopeHnd), tiRetVal); break; @@ -12392,11 +12283,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) STARG: JITDUMP(" %u", lclNum); - if (tiVerificationNeeded) - { - Verify(lclNum < info.compILargsCount, "bad arg num"); - } - if (compIsForInlining()) { op1 = impInlineFetchArg(lclNum, impInlineInfo->inlArgInfo, impInlineInfo->lclVarInfo); @@ -12417,18 +12303,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // We should have seen this arg write in the prescan assert(lvaTable[lclNum].lvHasILStoreOp); - if (tiVerificationNeeded) - { - typeInfo& tiLclVar = lvaTable[lclNum].lvVerTypeInfo; - Verify(tiCompatibleWith(impStackTop().seTypeInfo, NormaliseForStack(tiLclVar), true), - "type mismatch"); - - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiLclVar.IsThisPtr(), "storing to uninit this ptr"); - } - } - goto VAR_ST; case CEE_STLOC: @@ -12452,14 +12326,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert(lclNum >= 0 && lclNum < 4); LOC_ST: - if (tiVerificationNeeded) - { - Verify(lclNum < info.compMethodInfo->locals.numArgs, "bad local num"); - Verify(tiCompatibleWith(impStackTop().seTypeInfo, - NormaliseForStack(lvaTable[lclNum + numArgs].lvVerTypeInfo), true), - "type mismatch"); - } - if (compIsForInlining()) { lclTyp = impInlineInfo->lclVarInfo[lclNum + impInlineInfo->argCnt].lclTypeInfo; @@ -12477,7 +12343,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (lclNum >= info.compLocalsCount && lclNum != lvaArg0Var) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. BADCODE("Bad IL"); } @@ -12519,7 +12384,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Downcast the TYP_I_IMPL into a 32-bit Int for x86 JIT compatiblity if (varTypeIsI(op1->TypeGet()) && (genActualType(lclTyp) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op1 = gtNewCastNode(TYP_INT, op1, false, TYP_INT); } #endif // TARGET_64BIT @@ -12633,11 +12497,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclNum = getU1LittleEndian(codeAddr); LDLOCA: JITDUMP(" %u", lclNum); - if (tiVerificationNeeded) - { - Verify(lclNum < info.compMethodInfo->locals.numArgs, "bad local num"); - Verify(info.compInitMem, "initLocals not set"); - } if (compIsForInlining()) { @@ -12714,23 +12573,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert((op1->gtFlags & GTF_GLOB_REF) == 0); tiRetVal = lvaTable[lclNum].lvVerTypeInfo; - if (tiVerificationNeeded) - { - // Don't allow taking address of uninit this ptr. - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiRetVal.IsThisPtr(), "address of uninit this ptr"); - } - - if (!tiRetVal.IsByRef()) - { - tiRetVal.MakeByRef(); - } - else - { - Verify(false, "byref to byref"); - } - } impPushOnStack(op1, tiRetVal); break; @@ -12742,10 +12584,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("arglist in non-vararg method"); } - if (tiVerificationNeeded) - { - tiRetVal = typeInfo(TI_STRUCT, impGetRuntimeArgumentHandle()); - } assertImp((info.compMethodInfo->args.callConv & CORINFO_CALLCONV_MASK) == CORINFO_CALLCONV_VARARG); /* The ARGLIST cookie is a hidden 'last' parameter, we have already @@ -12797,11 +12635,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("endfilter outside filter"); } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsType(TI_INT), "bad endfilt arg"); - } - op1 = impPopStack().val; assertImp(op1->gtType == TYP_INT); if (!bbInFilterILRange(block)) @@ -12840,11 +12673,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) assert(!compIsForInlining()); - if (tiVerificationNeeded) - { - Verify(false, "Invalid opcode: CEE_JMP"); - } - if ((info.compFlags & CORINFO_FLG_SYNCH) || block->hasTryIndex() || block->hasHndIndex()) { /* CEE_JMP does not make sense in some "protected" regions. */ @@ -12901,30 +12729,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) ldelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - - typeInfo arrayElemType = verMakeTypeInfo(ldelemClsHnd); - Verify(tiArray.IsNullObjRef() || - typeInfo::AreEquivalent(verGetArrayElemType(tiArray), arrayElemType), - "bad array"); - - tiRetVal = arrayElemType; - tiRetVal.MakeByRef(); - if (prefixFlags & PREFIX_READONLY) - { - tiRetVal.SetIsReadonlyByRef(); - } - - // an array interior pointer is always in the heap - tiRetVal.SetIsPermanentHomeByRef(); - } - // If it's a value class array we just do a simple address-of if (eeIsValueClass(ldelemClsHnd)) { @@ -12975,20 +12779,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) ldelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - tiRetVal = verMakeTypeInfo(ldelemClsHnd); - - Verify(tiArray.IsNullObjRef() || tiCompatibleWith(verGetArrayElemType(tiArray), tiRetVal, false), - "type of array incompatible with type operand"); - tiRetVal.NormaliseForStack(); - } - // If it's a reference type or generic variable type // then just generate code as though it's a ldelem.ref instruction if (!eeIsValueClass(ldelemClsHnd)) @@ -13044,47 +12834,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto ARR_LD; ARR_LD: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(1).seTypeInfo; - typeInfo tiIndex = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - if (tiArray.IsNullObjRef()) - { - if (lclTyp == TYP_REF) - { // we will say a deref of a null array yields a null ref - tiRetVal = typeInfo(TI_NULL); - } - else - { - tiRetVal = typeInfo(lclTyp); - } - } - else - { - tiRetVal = verGetArrayElemType(tiArray); - typeInfo arrayElemTi = typeInfo(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_LDELEM_I) - { - arrayElemTi = typeInfo::nativeInt(); - } - - if (lclTyp != TYP_REF && lclTyp != TYP_STRUCT) - { - Verify(typeInfo::AreEquivalent(tiRetVal, arrayElemTi), "bad array"); - } - else -#endif // TARGET_64BIT - { - Verify(tiRetVal.IsType(arrayElemTi.GetType()), "bad array"); - } - } - tiRetVal.NormaliseForStack(); - } ARR_LD_POST_VERIFY: /* Pull the index value and array address */ @@ -13179,22 +12928,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) stelemClsHnd = resolvedToken.hClass; - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - typeInfo arrayElem = verMakeTypeInfo(stelemClsHnd); - - Verify(tiArray.IsNullObjRef() || tiCompatibleWith(arrayElem, verGetArrayElemType(tiArray), false), - "type operand incompatible with array element type"); - arrayElem.NormaliseForStack(); - Verify(tiCompatibleWith(tiValue, arrayElem, true), "value incompatible with type operand"); - } - // If it's a reference type just behave as though it's a stelem.ref instruction if (!eeIsValueClass(stelemClsHnd)) { @@ -13209,21 +12942,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } case CEE_STELEM_REF: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - Verify(tiValue.IsObjRef(), "bad value"); - - // we only check that it is an object referece, The helper does additional checks - Verify(tiArray.IsNullObjRef() || verGetArrayElemType(tiArray).IsType(TI_REF), "bad array"); - } - STELEM_REF_POST_VERIFY: if (opts.OptimizationEnabled()) @@ -13266,29 +12984,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto ARR_ST; ARR_ST: - - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop(2).seTypeInfo; - typeInfo tiIndex = impStackTop(1).seTypeInfo; - typeInfo tiValue = impStackTop().seTypeInfo; - - // As per ECMA 'index' specified can be either int32 or native int. - Verify(tiIndex.IsIntOrNativeIntType(), "bad index"); - typeInfo arrayElem = typeInfo(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_STELEM_I) - { - arrayElem = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - Verify(tiArray.IsNullObjRef() || typeInfo::AreEquivalent(verGetArrayElemType(tiArray), arrayElem), - "bad array"); - - Verify(tiCompatibleWith(NormaliseForStack(tiValue), arrayElem.NormaliseForStack(), true), - "bad value"); - } - ARR_ST_POST_VERIFY: /* The strict order of evaluation is LHS-operands, RHS-operands, range-check, and then assignment. However, codegen currently @@ -13455,33 +13150,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* Pull two values and push back the result */ - if (tiVerificationNeeded) - { - const typeInfo& tiOp1 = impStackTop(1).seTypeInfo; - const typeInfo& tiOp2 = impStackTop().seTypeInfo; - - Verify(tiCompatibleWith(tiOp1, tiOp2, true), "different arg type"); - if (oper == GT_ADD || oper == GT_DIV || oper == GT_SUB || oper == GT_MUL || oper == GT_MOD) - { - Verify(tiOp1.IsNumberType(), "not number"); - } - else - { - Verify(tiOp1.IsIntegerType(), "not integer"); - } - - Verify(!ovfl || tiOp1.IsIntegerType(), "not integer"); - - tiRetVal = tiOp1; - -#ifdef TARGET_64BIT - if (tiOp2.IsNativeIntType()) - { - tiRetVal = tiOp2; - } -#endif // TARGET_64BIT - } - op2 = impPopStack().val; op1 = impPopStack().val; @@ -13586,13 +13254,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto CEE_SH_OP2; CEE_SH_OP2: - if (tiVerificationNeeded) - { - const typeInfo& tiVal = impStackTop(1).seTypeInfo; - const typeInfo& tiShift = impStackTop(0).seTypeInfo; - Verify(tiVal.IsIntegerType() && tiShift.IsType(TI_INT), "Bad shift args"); - tiRetVal = tiVal; - } op2 = impPopStack().val; op1 = impPopStack().val; // operand to be shifted impBashVarAddrsToI(op1, op2); @@ -13604,12 +13265,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_NOT: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsIntegerType(), "bad int value"); - } - op1 = impPopStack().val; impBashVarAddrsToI(op1, nullptr); type = genActualType(op1->TypeGet()); @@ -13617,11 +13272,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_CKFINITE: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsType(TI_DOUBLE), "bad R value"); - } op1 = impPopStack().val; type = op1->TypeGet(); op1 = gtNewOperNode(GT_CKFINITE, type, op1); @@ -13678,12 +13328,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_BRFALSE_S: /* Pop the comparand (now there's a neat term) from the stack */ - if (tiVerificationNeeded) - { - typeInfo& tiVal = impStackTop().seTypeInfo; - Verify(tiVal.IsObjRef() || tiVal.IsByRef() || tiVal.IsIntegerType() || tiVal.IsMethod(), - "bad value"); - } op1 = impPopStack().val; type = op1->TypeGet(); @@ -13806,12 +13450,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto CMP_2_OPs; CMP_2_OPs: - if (tiVerificationNeeded) - { - verVerifyCond(impStackTop(1).seTypeInfo, impStackTop().seTypeInfo, opcode); - tiRetVal = typeInfo(TI_INT); - } - op2 = impPopStack().val; op1 = impPopStack().val; @@ -13914,12 +13552,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) unordered = false; goto CMP_2_OPs_AND_BR_ALL; CMP_2_OPs_AND_BR_ALL: - - if (tiVerificationNeeded) - { - verVerifyCond(impStackTop(1).seTypeInfo, impStackTop().seTypeInfo, opcode); - } - /* Pull two values */ op2 = impPopStack().val; op1 = impPopStack().val; @@ -14007,10 +13639,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto COND_JUMP; case CEE_SWITCH: - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsType(TI_INT), "Bad switch val"); - } /* Pop the switch value off the stack */ op1 = impPopStack().val; assertImp(genActualTypeIsIntOrI(op1->TypeGet())); @@ -14161,40 +13789,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) goto _CONV; _CONV: - // just check that we have a number on the stack - if (tiVerificationNeeded) - { - const typeInfo& tiVal = impStackTop().seTypeInfo; - Verify(tiVal.IsNumberType(), "bad arg"); - -#ifdef TARGET_64BIT - bool isNative = false; - - switch (opcode) - { - case CEE_CONV_OVF_I: - case CEE_CONV_OVF_I_UN: - case CEE_CONV_I: - case CEE_CONV_OVF_U: - case CEE_CONV_OVF_U_UN: - case CEE_CONV_U: - isNative = true; - break; - default: - // leave 'isNative' = false; - break; - } - if (isNative) - { - tiRetVal = typeInfo::nativeInt(); - } - else -#endif // TARGET_64BIT - { - tiRetVal = typeInfo(lclTyp).NormaliseForStack(); - } - } - // only converts from FLOAT or DOUBLE to an integer type // and converts from ULONG (or LONG on ARM) to DOUBLE are morphed to calls @@ -14310,12 +13904,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_NEG: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsNumberType(), "Bad arg"); - } - op1 = impPopStack().val; impBashVarAddrsToI(op1, nullptr); impPushOnStack(gtNewOperNode(GT_NEG, genActualType(op1->gtType), op1), tiRetVal); @@ -14404,22 +13992,40 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_DUP: { - if (tiVerificationNeeded) - { - // Dup could start the beginning of delegate creation sequence, remember that - delegateCreateStart = codeAddr - 1; - impStackTop(0); - } - - // If the expression to dup is simple, just clone it. - // Otherwise spill it to a temp, and reload the temp - // twice. StackEntry se = impPopStack(); GenTree* tree = se.val; tiRetVal = se.seTypeInfo; op1 = tree; - if (!opts.compDbgCode && !op1->IsIntegralConst(0) && !op1->IsFPZero() && !op1->IsLocal()) + // If the expression to dup is simple, just clone it. + // Otherwise spill it to a temp, and reload the temp twice. + bool cloneExpr = false; + + if (!opts.compDbgCode) + { + // Duplicate 0 and +0.0 + if (op1->IsIntegralConst(0) || op1->IsFloatPositiveZero()) + { + cloneExpr = true; + } + // Duplicate locals and addresses of them + else if (op1->IsLocal()) + { + cloneExpr = true; + } + else if (op1->TypeIs(TYP_BYREF) && op1->OperIs(GT_ADDR) && op1->gtGetOp1()->IsLocal() && + (OPCODE)impGetNonPrefixOpcode(codeAddr + sz, codeEndp) != CEE_INITOBJ) + { + cloneExpr = true; + } + } + else + { + // Always clone for debug mode + cloneExpr = true; + } + + if (!cloneExpr) { const unsigned tmpNum = lvaGrabTemp(true DEBUGARG("dup spill")); impAssignTempGen(tmpNum, op1, tiRetVal.GetClassHandle(), (unsigned)CHECK_SPILL_ALL); @@ -14470,22 +14076,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_DOUBLE; goto STIND; STIND: - - if (tiVerificationNeeded) - { - typeInfo instrType(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_STIND_I) - { - instrType = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - verVerifySTIND(impStackTop(1).seTypeInfo, impStackTop(0).seTypeInfo, instrType); - } - else - { - compUnsafeCastUsed = true; // Have to go conservative - } + compUnsafeCastUsed = true; // Have to go conservative STIND_POST_VERIFY: @@ -14511,14 +14102,12 @@ void Compiler::impImportBlockCode(BasicBlock* block) // if (varTypeIsI(op2->gtType) && (genActualType(lclTyp) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op2 = gtNewCastNode(TYP_INT, op2, false, TYP_INT); } // Allow an upcast of op2 from a 32-bit Int into TYP_I_IMPL for x86 JIT compatiblity // if (varTypeIsI(lclTyp) && (genActualType(op2->gtType) == TYP_INT)) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op2 = gtNewCastNode(TYP_I_IMPL, op2, false, TYP_I_IMPL); } } @@ -14613,23 +14202,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_USHORT; goto LDIND; LDIND: - - if (tiVerificationNeeded) - { - typeInfo lclTiType(lclTyp); -#ifdef TARGET_64BIT - if (opcode == CEE_LDIND_I) - { - lclTiType = typeInfo::nativeInt(); - } -#endif // TARGET_64BIT - tiRetVal = verVerifyLDIND(impStackTop().seTypeInfo, lclTiType); - tiRetVal.NormaliseForStack(); - } - else - { - compUnsafeCastUsed = true; // Have to go conservative - } + compUnsafeCastUsed = true; // Have to go conservative LDIND_POST_VERIFY: @@ -14641,7 +14214,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // if (genActualType(op1->gtType) == TYP_INT) { - assert(!tiVerificationNeeded); // We should have thrown the VerificationException before. op1 = gtNewCastNode(TYP_I_IMPL, op1, false, TYP_I_IMPL); } #endif @@ -14711,8 +14283,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); eeGetCallInfo(&resolvedToken, (prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr, - addVerifyFlag(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN)), - &callInfo); + combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), &callInfo); // This check really only applies to intrinsic Array.Address methods if (callInfo.sig.callConv & CORINFO_CALLCONV_PARAMTYPE) @@ -14723,22 +14294,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Do this before DO_LDFTN since CEE_LDVIRTFN does it on its own. impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper); - if (tiVerificationNeeded) - { - // LDFTN could start the beginning of delegate creation sequence, remember that - delegateCreateStart = codeAddr - 2; - - // check any constraints on the callee's class and type parameters - VerifyOrReturn(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "method has unsatisfied class constraints"); - VerifyOrReturn(info.compCompHnd->satisfiesMethodConstraints(resolvedToken.hClass, - resolvedToken.hMethod), - "method has unsatisfied method constraints"); - - mflags = callInfo.verMethodFlags; - Verify(!(mflags & CORINFO_FLG_CONSTRUCTOR), "LDFTN on a constructor"); - } - DO_LDFTN: op1 = impMethodPointer(&resolvedToken, &callInfo); @@ -14766,8 +14321,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); eeGetCallInfo(&resolvedToken, nullptr /* constraint typeRef */, - addVerifyFlag(combine(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), - CORINFO_CALLINFO_CALLVIRT)), + combine(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_LDFTN), + CORINFO_CALLINFO_CALLVIRT), &callInfo); // This check really only applies to intrinsic Array.Address methods @@ -14791,40 +14346,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) CORINFO_SIG_INFO& ftnSig = callInfo.sig; - if (tiVerificationNeeded) - { - - Verify(ftnSig.hasThis(), "ldvirtftn on a static method"); - Verify(!(mflags & CORINFO_FLG_CONSTRUCTOR), "LDVIRTFTN on a constructor"); - - // JIT32 verifier rejects verifiable ldvirtftn pattern - typeInfo declType = - verMakeTypeInfo(resolvedToken.hClass, true); // Change TI_STRUCT to TI_REF when necessary - - typeInfo arg = impStackTop().seTypeInfo; - Verify((arg.IsType(TI_REF) || arg.IsType(TI_NULL)) && tiCompatibleWith(arg, declType, true), - "bad ldvirtftn"); - - CORINFO_CLASS_HANDLE instanceClassHnd = info.compClassHnd; - if (!(arg.IsType(TI_NULL) || (mflags & CORINFO_FLG_STATIC))) - { - instanceClassHnd = arg.GetClassHandleForObjRef(); - } - - // check any constraints on the method's class and type parameters - VerifyOrReturn(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "method has unsatisfied class constraints"); - VerifyOrReturn(info.compCompHnd->satisfiesMethodConstraints(resolvedToken.hClass, - resolvedToken.hMethod), - "method has unsatisfied method constraints"); - - if (mflags & CORINFO_FLG_PROTECTED) - { - Verify(info.compCompHnd->canAccessFamily(info.compMethodHnd, instanceClassHnd), - "Accessing protected method through wrong type."); - } - } - /* Get the object-ref */ op1 = impPopStack().val; assertImp(op1->gtType == TYP_REF); @@ -14937,8 +14458,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) _impResolveToken(CORINFO_TOKENKIND_NewObj); eeGetCallInfo(&resolvedToken, nullptr /* constraint typeRef*/, - addVerifyFlag(combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_ALLOWINSTPARAM)), - &callInfo); + combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_ALLOWINSTPARAM), &callInfo); if (compIsForInlining()) { @@ -14972,19 +14492,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) clsFlags = callInfo.classFlags; if (clsFlags & CORINFO_FLG_ARRAY) { - if (tiVerificationNeeded) - { - CORINFO_CLASS_HANDLE elemTypeHnd; - INDEBUG(CorInfoType corType =) - info.compCompHnd->getChildType(resolvedToken.hClass, &elemTypeHnd); - assert(!(elemTypeHnd == nullptr && corType == CORINFO_TYPE_VALUECLASS)); - Verify(elemTypeHnd == nullptr || - !(info.compCompHnd->getClassAttribs(elemTypeHnd) & CORINFO_FLG_BYREF_LIKE), - "newarr of byref-like objects"); - verVerifyCall(opcode, &resolvedToken, nullptr, ((prefixFlags & PREFIX_TAILCALL_EXPLICIT) != 0), - ((prefixFlags & PREFIX_READONLY) != 0), delegateCreateStart, codeAddr - 1, - &callInfo DEBUGARG(info.compFullName)); - } // Arrays need to call the NEWOBJ helper. assertImp(clsFlags & CORINFO_FLG_VAROBJSIZE); @@ -15176,10 +14683,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) eeGetCallInfo(&resolvedToken, (prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr, // this is how impImportCall invokes getCallInfo - addVerifyFlag( - combine(combine(CORINFO_CALLINFO_ALLOWINSTPARAM, CORINFO_CALLINFO_SECURITYCHECKS), - (opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT - : CORINFO_CALLINFO_NONE)), + combine(combine(CORINFO_CALLINFO_ALLOWINSTPARAM, CORINFO_CALLINFO_SECURITYCHECKS), + (opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT : CORINFO_CALLINFO_NONE), &callInfo); } else @@ -15320,13 +14825,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) impHandleAccessAllowed(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper); } - if (tiVerificationNeeded) - { - verVerifyCall(opcode, &resolvedToken, constraintCall ? &constrainedResolvedToken : nullptr, - explicitTailCall, readonlyCall, delegateCreateStart, codeAddr - 1, - &callInfo DEBUGARG(info.compFullName)); - } - callTyp = impImportCall(opcode, &resolvedToken, constraintCall ? &constrainedResolvedToken : nullptr, newObjThisPtr, prefixFlags, &callInfo, opcodeOffs); if (compDonotInline()) @@ -15446,45 +14944,10 @@ void Compiler::impImportBlockCode(BasicBlock* block) // SkipVerification. impHandleAccessAllowed(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper); - if (tiVerificationNeeded) - { - // You can also pass the unboxed struct to LDFLD - bool bAllowPlainValueTypeAsThis = false; - if (opcode == CEE_LDFLD && impIsValueType(tiObj)) - { - bAllowPlainValueTypeAsThis = true; - } - - verVerifyField(&resolvedToken, fieldInfo, tiObj, isLoadAddress, bAllowPlainValueTypeAsThis); - - // If we're doing this on a heap object or from a 'safe' byref - // then the result is a safe byref too - if (isLoadAddress) // load address - { - if (fieldInfo.fieldFlags & - CORINFO_FLG_FIELD_STATIC) // statics marked as safe will have permanent home - { - if (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN) - { - tiRetVal.SetIsPermanentHomeByRef(); - } - } - else if (tiObj->IsObjRef() || tiObj->IsPermanentHomeByRef()) - { - // ldflda of byref is safe if done on a gc object or on a - // safe byref - tiRetVal.SetIsPermanentHomeByRef(); - } - } - } - else + // Raise InvalidProgramException if static load accesses non-static field + if (isLoadStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) { - // tiVerificationNeeded is false. - // Raise InvalidProgramException if static load accesses non-static field - if (isLoadStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) - { - BADCODE("static access on an instance field"); - } + BADCODE("static access on an instance field"); } // We are using ldfld/a on a static field. We allow it, but need to get side-effect from obj. @@ -15799,20 +15262,10 @@ void Compiler::impImportBlockCode(BasicBlock* block) impHandleAccessAllowed(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper); - if (tiVerificationNeeded) + // Raise InvalidProgramException if static store accesses non-static field + if (isStoreStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) { - verVerifyField(&resolvedToken, fieldInfo, tiObj, true); - typeInfo fieldType = verMakeTypeInfo(ciType, fieldClsHnd); - Verify(tiCompatibleWith(tiVal, fieldType.NormaliseForStack(), true), "type mismatch"); - } - else - { - // tiVerificationNeed is false. - // Raise InvalidProgramException if static store accesses non-static field - if (isStoreStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0)) - { - BADCODE("static access on an instance field"); - } + BADCODE("static access on an instance field"); } // We are using stfld on a static field. @@ -16077,18 +15530,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - // As per ECMA 'numElems' specified can be either int32 or native int. - Verify(impStackTop().seTypeInfo.IsIntOrNativeIntType(), "bad bound"); - - CORINFO_CLASS_HANDLE elemTypeHnd; - info.compCompHnd->getChildType(resolvedToken.hClass, &elemTypeHnd); - Verify(elemTypeHnd == nullptr || - !(info.compCompHnd->getClassAttribs(elemTypeHnd) & CORINFO_FLG_BYREF_LIKE), - "array of byref-like type"); - } - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); accessAllowedResult = @@ -16169,11 +15610,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) break; case CEE_LOCALLOC: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } - // We don't allow locallocs inside handlers if (block->hasHndIndex()) { @@ -16299,12 +15735,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsObjRef(), "obj reference needed"); - // Even if this is a value class, we know it is boxed. - tiRetVal = typeInfo(TI_REF, resolvedToken.hClass); - } accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16376,13 +15806,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; } - if (tiVerificationNeeded) - { - Verify(typeInfo::AreEquivalent(impStackTop().seTypeInfo, verMakeTypeInfo(impGetRefAnyClass())), - "need refany"); - tiRetVal = verMakeTypeInfo(resolvedToken.hClass).MakeByRef(); - } - op1 = impPopStack().val; // make certain it is normalized; op1 = impNormStructVal(op1, impGetRefAnyClass(), (unsigned)CHECK_SPILL_ALL); @@ -16395,12 +15818,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_REFANYTYPE: - if (tiVerificationNeeded) - { - Verify(typeInfo::AreEquivalent(impStackTop().seTypeInfo, verMakeTypeInfo(impGetRefAnyClass())), - "need refany"); - } - op1 = impPopStack().val; // make certain it is normalized; @@ -16524,13 +15941,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (opcode == CEE_UNBOX_ANY && !eeIsValueClass(resolvedToken.hClass)) { - if (tiVerificationNeeded) - { - typeInfo tiUnbox = impStackTop().seTypeInfo; - Verify(tiUnbox.IsObjRef(), "bad unbox.any arg"); - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - tiRetVal.NormaliseForStack(); - } JITDUMP("\n Importing UNBOX.ANY(refClass) as CASTCLASS\n"); op1 = impPopStack().val; goto CASTCLASS; @@ -16541,19 +15951,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) /* (non-byref) type, but here we're making the tiRetVal that is used */ /* for the intermediate pointer which we then transfer onto the OBJ */ /* instruction. OBJ then creates the appropriate tiRetVal. */ - if (tiVerificationNeeded) - { - typeInfo tiUnbox = impStackTop().seTypeInfo; - Verify(tiUnbox.IsObjRef(), "Bad unbox arg"); - - tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - Verify(tiRetVal.IsValueClass(), "not value class"); - tiRetVal.MakeByRef(); - - // We always come from an objref, so this is safe byref - tiRetVal.SetIsPermanentHomeByRef(); - tiRetVal.SetIsReadonlyByRef(); - } op1 = impPopStack().val; assertImp(op1->gtType == TYP_REF); @@ -16722,7 +16119,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } assert(op1->gtType == TYP_BYREF); - assert(!tiVerificationNeeded || tiRetVal.IsByRef()); } else { @@ -16767,7 +16163,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) oper = GT_OBJ; assert(op1->gtType == TYP_BYREF); - assert(!tiVerificationNeeded || tiRetVal.IsByRef()); goto OBJ; } @@ -16796,29 +16191,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiActual = impStackTop().seTypeInfo; - typeInfo tiBox = verMakeTypeInfo(resolvedToken.hClass); - - Verify(verIsBoxable(tiBox), "boxable type expected"); - - // check the class constraints of the boxed type in case we are boxing an uninitialized value - Verify(info.compCompHnd->satisfiesClassConstraints(resolvedToken.hClass), - "boxed type has unsatisfied class constraints"); - - Verify(tiCompatibleWith(tiActual, tiBox.NormaliseForStack(), true), "type mismatch"); - - // Observation: the following code introduces a boxed value class on the stack, but, - // according to the ECMA spec, one would simply expect: tiRetVal = - // typeInfo(TI_REF,impGetObjectClass()); - - // Push the result back on the stack, - // even if clsHnd is a value class we want the TI_REF - // we call back to the EE to get find out what hte type we should push (for nullable we push T) - tiRetVal = typeInfo(TI_REF, info.compCompHnd->getTypeForBox(resolvedToken.hClass)); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16859,11 +16231,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - tiRetVal = typeInfo(TI_INT); - } - op1 = gtNewIconNode(info.compCompHnd->getClassSize(resolvedToken.hClass)); impPushOnStack(op1, tiRetVal); break; @@ -16887,13 +16254,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } } - if (tiVerificationNeeded) - { - Verify(impStackTop().seTypeInfo.IsObjRef(), "object ref expected"); - // box it - tiRetVal = typeInfo(TI_REF, resolvedToken.hClass); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -16960,16 +16320,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_THROW: - if (tiVerificationNeeded) - { - tiRetVal = impStackTop().seTypeInfo; - Verify(tiRetVal.IsObjRef(), "object ref expected"); - if (verTrackObjCtorInitState && (verCurrentState.thisInitialized != TIS_Init)) - { - Verify(!tiRetVal.IsThisPtr(), "throw uninitialized this"); - } - } - // Any block with a throw is rarely executed. block->bbSetRunRarely(); @@ -16997,22 +16347,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) BADCODE("rethrow outside catch"); } - if (tiVerificationNeeded) - { - Verify(block->hasHndIndex(), "rethrow outside catch"); - if (block->hasHndIndex()) - { - EHblkDsc* HBtab = ehGetDsc(block->getHndIndex()); - Verify(!HBtab->HasFinallyOrFaultHandler(), "rethrow in finally or fault"); - if (HBtab->HasFilter()) - { - // we better be in the handler clause part, not the filter part - Verify(jitIsBetween(compCurBB->bbCodeOffs, HBtab->ebdHndBegOffs(), HBtab->ebdHndEndOffs()), - "rethrow in filter"); - } - } - } - /* Create the 'rethrow' helper call */ op1 = gtNewHelperCallNode(CORINFO_HELP_RETHROW, TYP_VOID); @@ -17027,18 +16361,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiTo = impStackTop().seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(tiTo.IsByRef(), "byref expected"); - Verify(!tiTo.IsReadonlyByRef(), "write to readonly byref"); - - Verify(tiCompatibleWith(tiInstr, tiTo.DereferenceByRef(), false), - "type operand incompatible with type of address"); - } - op2 = gtNewIconNode(0); // Value op1 = impPopStack().val; // Dest @@ -17062,11 +16384,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_INITBLK: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } - op3 = impPopStack().val; // Size op2 = impPopStack().val; // Value op1 = impPopStack().val; // Dst addr @@ -17097,10 +16414,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CEE_CPBLK: - if (tiVerificationNeeded) - { - Verify(false, "bad opcode"); - } op3 = impPopStack().val; // Size op2 = impPopStack().val; // Src addr op1 = impPopStack().val; // Dst addr @@ -17141,22 +16454,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) JITDUMP(" %08X", resolvedToken.token); - if (tiVerificationNeeded) - { - typeInfo tiFrom = impStackTop().seTypeInfo; - typeInfo tiTo = impStackTop(1).seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(tiFrom.IsByRef(), "expected byref source"); - Verify(tiTo.IsByRef(), "expected byref destination"); - - Verify(tiCompatibleWith(tiFrom.DereferenceByRef(), tiInstr, false), - "type of source address incompatible with type operand"); - Verify(!tiTo.IsReadonlyByRef(), "write to readonly byref"); - Verify(tiCompatibleWith(tiInstr, tiTo.DereferenceByRef(), false), - "type operand incompatible with type of destination address"); - } - if (!eeIsValueClass(resolvedToken.hClass)) { op1 = impPopStack().val; // address to load from @@ -17196,38 +16493,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) lclTyp = TYP_REF; } - if (tiVerificationNeeded) - { - - typeInfo tiPtr = impStackTop(1).seTypeInfo; - - // Make sure we have a good looking byref - Verify(tiPtr.IsByRef(), "pointer not byref"); - Verify(!tiPtr.IsReadonlyByRef(), "write to readonly byref"); - if (!tiPtr.IsByRef() || tiPtr.IsReadonlyByRef()) - { - compUnsafeCastUsed = true; - } - - typeInfo ptrVal = DereferenceByRef(tiPtr); - typeInfo argVal = verMakeTypeInfo(resolvedToken.hClass); - - if (!tiCompatibleWith(impStackTop(0).seTypeInfo, NormaliseForStack(argVal), true)) - { - Verify(false, "type of value incompatible with type operand"); - compUnsafeCastUsed = true; - } - - if (!tiCompatibleWith(argVal, ptrVal, false)) - { - Verify(false, "type operand incompatible with type of address"); - compUnsafeCastUsed = true; - } - } - else - { - compUnsafeCastUsed = true; - } + compUnsafeCastUsed = true; if (lclTyp == TYP_REF) { @@ -17279,16 +16545,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) return; } - if (tiVerificationNeeded) - { - typeInfo tiPtr = impStackTop().seTypeInfo; - typeInfo tiInstr = verMakeTypeInfo(resolvedToken.hClass); - - Verify(!verIsByRefLike(tiInstr), "mkrefany of byref-like class"); - Verify(!tiPtr.IsReadonlyByRef(), "readonly byref used with mkrefany"); - Verify(typeInfo::AreEquivalent(tiPtr.DereferenceByRef(), tiInstr), "type mismatch"); - } - accessAllowedResult = info.compCompHnd->canAccessClass(&resolvedToken, info.compMethodHnd, &calloutHelper); impHandleAccessAllowed(accessAllowedResult, &calloutHelper); @@ -17318,29 +16574,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) tiRetVal = verMakeTypeInfo(resolvedToken.hClass); - if (tiVerificationNeeded) - { - typeInfo tiPtr = impStackTop().seTypeInfo; - - // Make sure we have a byref - if (!tiPtr.IsByRef()) - { - Verify(false, "pointer not byref"); - compUnsafeCastUsed = true; - } - typeInfo tiPtrVal = DereferenceByRef(tiPtr); - - if (!tiCompatibleWith(tiPtrVal, tiRetVal, false)) - { - Verify(false, "type of address incompatible with type operand"); - compUnsafeCastUsed = true; - } - tiRetVal.NormaliseForStack(); - } - else - { - compUnsafeCastUsed = true; - } + compUnsafeCastUsed = true; if (eeIsValueClass(resolvedToken.hClass)) { @@ -17384,13 +16618,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) } case CEE_LDLEN: - if (tiVerificationNeeded) - { - typeInfo tiArray = impStackTop().seTypeInfo; - Verify(verIsSDArray(tiArray), "bad array"); - tiRetVal = typeInfo(TI_INT); - } - op1 = impPopStack().val; if (opts.OptimizationEnabled()) { @@ -17544,12 +16771,6 @@ void Compiler::impLoadArg(unsigned ilArgNum, IL_OFFSET offset) // It will be mapped to the correct lvaTable index void Compiler::impLoadLoc(unsigned ilLclNum, IL_OFFSET offset) { - if (tiVerificationNeeded) - { - Verify(ilLclNum < info.compMethodInfo->locals.numArgs, "bad loc num"); - Verify(info.compInitMem, "initLocals not set"); - } - if (compIsForInlining()) { if (ilLclNum >= info.compMethodInfo->locals.numArgs) @@ -17672,25 +16893,6 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) { const bool isTailCall = (prefixFlags & PREFIX_TAILCALL) != 0; - if (tiVerificationNeeded) - { - verVerifyThisPtrInitialised(); - - unsigned expectedStack = 0; - if (info.compRetType != TYP_VOID) - { - typeInfo tiVal = impStackTop().seTypeInfo; - typeInfo tiDeclared = - verMakeTypeInfo(info.compMethodInfo->args.retType, info.compMethodInfo->args.retTypeClass); - - Verify(!verIsByRefLike(tiDeclared) || verIsSafeToReturnByRef(tiVal), "byref return"); - - Verify(tiCompatibleWith(tiVal, tiDeclared.NormaliseForStack(), true), "type mismatch"); - expectedStack = 1; - } - Verify(verCurrentState.esStackDepth == expectedStack, "stack non-empty on return"); - } - #ifdef DEBUG // If we are importing an inlinee and have GC ref locals we always // need to have a spill temp for the return value. This temp @@ -18559,27 +17761,6 @@ void Compiler::impImportBlock(BasicBlock* block) #ifdef TARGET_64BIT if (genActualType(tree->gtType) == TYP_I_IMPL && lvaTable[tempNum].lvType == TYP_INT) { - if (tiVerificationNeeded && tgtBlock->bbEntryState != nullptr && - (tgtBlock->bbFlags & BBF_FAILED_VERIFICATION) == 0) - { - // Merge the current state into the entry state of block; - // the call to verMergeEntryStates must have changed - // the entry state of the block by merging the int local var - // and the native-int stack entry. - bool changed = false; - if (verMergeEntryStates(tgtBlock, &changed)) - { - impRetypeEntryStateTemps(tgtBlock); - impReimportBlockPending(tgtBlock); - assert(changed); - } - else - { - tgtBlock->bbFlags |= BBF_FAILED_VERIFICATION; - break; - } - } - // Some other block in the spill clique set this to "int", but now we have "native int". // Change the type and go back to re-import any blocks that used the wrong type. lvaTable[tempNum].lvType = TYP_I_IMPL; @@ -18600,22 +17781,20 @@ void Compiler::impImportBlock(BasicBlock* block) // imported already, we need to change the type of the local and reimport the spill clique. // If the 'byref' side has imported, we insert a cast from int to 'native int' to match // the 'byref' size. - if (!tiVerificationNeeded) + if (genActualType(tree->gtType) == TYP_BYREF && lvaTable[tempNum].lvType == TYP_INT) { - if (genActualType(tree->gtType) == TYP_BYREF && lvaTable[tempNum].lvType == TYP_INT) - { - // Some other block in the spill clique set this to "int", but now we have "byref". - // Change the type and go back to re-import any blocks that used the wrong type. - lvaTable[tempNum].lvType = TYP_BYREF; - reimportSpillClique = true; - } - else if (genActualType(tree->gtType) == TYP_INT && lvaTable[tempNum].lvType == TYP_BYREF) - { - // Spill clique has decided this should be "byref", but this block only pushes an "int". - // Insert a sign-extension to "native int" so we match the clique size. - verCurrentState.esStack[level].val = gtNewCastNode(TYP_I_IMPL, tree, false, TYP_I_IMPL); - } + // Some other block in the spill clique set this to "int", but now we have "byref". + // Change the type and go back to re-import any blocks that used the wrong type. + lvaTable[tempNum].lvType = TYP_BYREF; + reimportSpillClique = true; + } + else if (genActualType(tree->gtType) == TYP_INT && lvaTable[tempNum].lvType == TYP_BYREF) + { + // Spill clique has decided this should be "byref", but this block only pushes an "int". + // Insert a sign-extension to "native int" so we match the clique size. + verCurrentState.esStack[level].val = gtNewCastNode(TYP_I_IMPL, tree, false, TYP_I_IMPL); } + #endif // TARGET_64BIT if (tree->gtType == TYP_DOUBLE && lvaTable[tempNum].lvType == TYP_FLOAT) @@ -18799,25 +17978,6 @@ void Compiler::impImportBlockPending(BasicBlock* block) #endif } - // Additionally, if we need to verify, merge the verification state. - if (tiVerificationNeeded) - { - // Merge the current state into the entry state of block; if this does not change the entry state - // by merging, do not add the block to the pending-list. - bool changed = false; - if (!verMergeEntryStates(block, &changed)) - { - block->bbFlags |= BBF_FAILED_VERIFICATION; - addToPending = true; // We will pop it off, and check the flag set above. - } - else if (changed) - { - addToPending = true; - - JITDUMP("Adding " FMT_BB " to pending set due to new merge result\n", block->bbNum); - } - } - if (!addToPending) { return; @@ -19269,16 +18429,6 @@ void Compiler::verInitCurrentState() verTrackObjCtorInitState = false; verCurrentState.thisInitialized = TIS_Bottom; - if (tiVerificationNeeded) - { - // Track this ptr initialization - if (!info.compIsStatic && (info.compFlags & CORINFO_FLG_CONSTRUCTOR) && lvaTable[0].lvVerTypeInfo.IsObjRef()) - { - verTrackObjCtorInitState = true; - verCurrentState.thisInitialized = TIS_Uninit; - } - } - // initialize stack info verCurrentState.esStackDepth = 0; @@ -19459,22 +18609,8 @@ void Compiler::impImport() if (dsc->pdBB->bbFlags & BBF_FAILED_VERIFICATION) { - -#ifdef TARGET_64BIT - // On AMD64, during verification we have to match JIT64 behavior since the VM is very tighly - // coupled with the JIT64 IL Verification logic. Look inside verHandleVerificationFailure - // method for further explanation on why we raise this exception instead of making the jitted - // code throw the verification exception during execution. - if (tiVerificationNeeded && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_IMPORT_ONLY)) - { - BADCODE("Basic block marked as not verifiable"); - } - else -#endif // TARGET_64BIT - { - verConvertBBToThrowVerificationException(dsc->pdBB DEBUGARG(true)); - impEndTreeList(dsc->pdBB); - } + verConvertBBToThrowVerificationException(dsc->pdBB DEBUGARG(true)); + impEndTreeList(dsc->pdBB); } else { @@ -19484,7 +18620,7 @@ void Compiler::impImport() { return; } - if (compIsForImportOnly() && !tiVerificationNeeded) + if (compIsForImportOnly()) { return; } @@ -19505,8 +18641,6 @@ void Compiler::impImport() block->bbFlags &= ~BBF_VISITED; } #endif - - assert(!compIsForInlining() || !tiVerificationNeeded); } // Checks if a typeinfo (usually stored in the type stack) is a struct. @@ -19555,7 +18689,10 @@ bool Compiler::impIsAddressInLocal(const GenTree* tree, GenTree** lclVarTreeOut) if (op->gtOper == GT_LCL_VAR) { - *lclVarTreeOut = op; + if (lclVarTreeOut != nullptr) + { + *lclVarTreeOut = op; + } return true; } else @@ -22223,7 +21360,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // Look up the new call info. CORINFO_CALL_INFO derivedCallInfo; - eeGetCallInfo(pDerivedResolvedToken, nullptr, addVerifyFlag(CORINFO_CALLINFO_ALLOWINSTPARAM), &derivedCallInfo); + eeGetCallInfo(pDerivedResolvedToken, nullptr, CORINFO_CALLINFO_ALLOWINSTPARAM, &derivedCallInfo); // Update the call. call->gtCallMoreFlags &= ~GTF_CALL_M_VIRTSTUB_REL_INDIRECT; diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index 458f919fe27935..08d4c4a8c8675d 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -595,7 +595,7 @@ INST3(FIRST_BMI_INSTRUCTION, "FIRST_BMI_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE INST3(andn, "andn", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF2), INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND NOT INST3(blsi, "blsi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), INS_Flags_IsDstDstSrcAVXInstruction) // Extract Lowest Set Isolated Bit INST3(blsmsk, "blsmsk", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), INS_Flags_IsDstDstSrcAVXInstruction) // Get Mask Up to Lowest Set Bit -INST3(blsr, "blsr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), INS_Flags_IsDstDstSrcAVXInstruction) // Reset Lowest Set Bit +INST3(blsr, "blsr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Reset Lowest Set Bit INST3(bextr, "bextr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF7), INS_Flags_IsDstDstSrcAVXInstruction) // Bit Field Extract // BMI2 diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 4fc4594c6fb2b9..1346c2069da170 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -471,8 +471,16 @@ CONFIG_INTEGER(JitOffsetOnStackReplacement, W("JitOffsetOnStackReplacement"), -1 #endif // debug #if defined(DEBUG) -CONFIG_STRING(JitEnableOsrRange, W("JitEnableOsrRange")) // Enable osr for only some methods -#endif // debug +// EnableOsrRange allows you to limit the set of methods that will rely on OSR to escape +// from Tier0 code. Methods outside the range that would normally be jitted at Tier0 +// and have patchpoints will instead be switched to optimized. +CONFIG_STRING(JitEnableOsrRange, W("JitEnableOsrRange")) +// EnablePatchpointRange allows you to limit the set of Tier0 methods that +// will have patchpoints, and hence control which methods will create OSR methods. +// Unlike EnableOsrRange, it will not alter the optimization setting for methods +// outside the enabled range. +CONFIG_STRING(JitEnablePatchpointRange, W("JitEnablePatchpointRange")) +#endif // Profile instrumentation options CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index eb76cd663f287b..a1cfc61822216f 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -487,19 +487,7 @@ void Compiler::lvaInitThisPtr(InitVarDscInfo* varDscInfo) lvaSetClass(varDscInfo->varNum, info.compClassHnd); } - if (tiVerificationNeeded) - { - varDsc->lvVerTypeInfo = verMakeTypeInfo(info.compClassHnd); - - if (varDsc->lvVerTypeInfo.IsValueClass()) - { - varDsc->lvVerTypeInfo.MakeByRef(); - } - } - else - { - varDsc->lvVerTypeInfo = typeInfo(); - } + varDsc->lvVerTypeInfo = typeInfo(); // Mark the 'this' pointer for the method varDsc->lvVerTypeInfo.SetIsThisPtr(); @@ -1323,48 +1311,6 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, compFloatingPointUsed = true; } - if (tiVerificationNeeded) - { - varDsc->lvVerTypeInfo = verParseArgSigToTypeInfo(varSig, varList); - } - - if (tiVerificationNeeded) - { - if (varDsc->lvIsParam) - { - // For an incoming ValueType we better be able to have the full type information - // so that we can layout the parameter offsets correctly - - if (varTypeIsStruct(type) && varDsc->lvVerTypeInfo.IsDead()) - { - BADCODE("invalid ValueType parameter"); - } - - // For an incoming reference type we need to verify that the actual type is - // a reference type and not a valuetype. - - if (type == TYP_REF && - !(varDsc->lvVerTypeInfo.IsType(TI_REF) || varDsc->lvVerTypeInfo.IsUnboxedGenericTypeVar())) - { - BADCODE("parameter type mismatch"); - } - } - - // Disallow byrefs to byref like objects (ArgTypeHandle) - // techncally we could get away with just not setting them - if (varDsc->lvVerTypeInfo.IsByRef() && verIsByRefLike(DereferenceByRef(varDsc->lvVerTypeInfo))) - { - varDsc->lvVerTypeInfo = typeInfo(); - } - - // we don't want the EE to assert in lvaSetStruct on bad sigs, so change - // the JIT type to avoid even trying to call back - if (varTypeIsStruct(type) && varDsc->lvVerTypeInfo.IsDead()) - { - type = TYP_VOID; - } - } - if (typeHnd) { unsigned cFlags = info.compCompHnd->getClassAttribs(typeHnd); @@ -1373,11 +1319,8 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, // a primitive. We will need the typeHnd to distinguish them, so we store it here. if ((cFlags & CORINFO_FLG_VALUECLASS) && !varTypeIsStruct(type)) { - if (tiVerificationNeeded == false) - { - // printf("This is a struct that the JIT will treat as a primitive\n"); - varDsc->lvVerTypeInfo = verMakeTypeInfo(typeHnd); - } + // printf("This is a struct that the JIT will treat as a primitive\n"); + varDsc->lvVerTypeInfo = verMakeTypeInfo(typeHnd); } varDsc->lvOverlappingFields = StructHasOverlappingFields(cFlags); @@ -1395,7 +1338,7 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, } if ((varTypeIsStruct(type))) { - lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, !tiVerificationNeeded); + lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, true); if (info.compIsVarArgs) { lvaSetStructUsedAsVarArg(varNum); @@ -4113,8 +4056,8 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, #endif // UNIX_AMD64_ABI /* Variables must be used as the same type throughout the method */ - noway_assert(tiVerificationNeeded || varDsc->lvType == TYP_UNDEF || tree->gtType == TYP_UNKNOWN || - allowStructs || genActualType(varDsc->TypeGet()) == genActualType(tree->gtType) || + noway_assert(varDsc->lvType == TYP_UNDEF || tree->gtType == TYP_UNKNOWN || allowStructs || + genActualType(varDsc->TypeGet()) == genActualType(tree->gtType) || (tree->gtType == TYP_BYREF && varDsc->TypeGet() == TYP_I_IMPL) || (tree->gtType == TYP_I_IMPL && varDsc->TypeGet() == TYP_BYREF) || (tree->gtFlags & GTF_VAR_CAST) || (varTypeIsFloating(varDsc) && varTypeIsFloating(tree)) || diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index f29baa320940d7..b111d73db6a995 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -139,7 +139,7 @@ GenTree* Lowering::LowerNode(GenTree* node) case GT_AND: case GT_OR: case GT_XOR: - return LowerBinaryArithmetic(node->AsOp()); + return LowerBinaryArithmeticCommon(node->AsOp()); case GT_MUL: case GT_MULHI: @@ -2708,10 +2708,16 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp) if (op2->IsIntegralConst(0) && (op1->gtNext == op2) && (op2->gtNext == cmp) && #ifdef TARGET_XARCH - op1->OperIs(GT_AND, GT_OR, GT_XOR, GT_ADD, GT_SUB, GT_NEG)) + (op1->OperIs(GT_AND, GT_OR, GT_XOR, GT_ADD, GT_SUB, GT_NEG) +#ifdef FEATURE_HW_INTRINSICS + || (op1->OperIs(GT_HWINTRINSIC) && + emitter::DoesWriteZeroFlag(HWIntrinsicInfo::lookupIns(op1->AsHWIntrinsic()))) +#endif // FEATURE_HW_INTRINSICS + ) #else // TARGET_ARM64 - op1->OperIs(GT_AND, GT_ADD, GT_SUB)) + op1->OperIs(GT_AND, GT_ADD, GT_SUB) #endif + ) { op1->gtFlags |= GTF_SET_FLAGS; op1->SetUnusedValue(); @@ -4885,20 +4891,29 @@ bool Lowering::AreSourcesPossiblyModifiedLocals(GenTree* addr, GenTree* base, Ge // addressing mode and transform them to a GT_LEA // // Arguments: -// use - the use of the address we want to transform +// addr - the use of the address we want to transform // isContainable - true if this addressing mode can be contained -// targetType - on arm we can use "scale" only for appropriate target type +// parent - the node that consumes the given addr (most likely it's an IND) // // Returns: // true if the address node was changed to a LEA, false otherwise. // -bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType) +bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent) { if (!addr->OperIs(GT_ADD) || addr->gtOverflow()) { return false; } +#ifdef TARGET_ARM64 + if (parent->OperIsIndir() && parent->AsIndir()->IsVolatile() && !varTypeIsGC(addr)) + { + // For Arm64 we avoid using LEA for volatile INDs + // because we won't be able to use ldar/star + return false; + } +#endif + GenTree* base = nullptr; GenTree* index = nullptr; unsigned scale = 0; @@ -4914,6 +4929,8 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, var_types ta &scale, // scaling &offset); // displacement + var_types targetType = parent->OperIsIndir() ? parent->TypeGet() : TYP_UNDEF; + #ifdef TARGET_ARMARCH // Multiplier should be a "natural-scale" power of two number which is equal to target's width. // @@ -5103,7 +5120,7 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) GenTree* parent = use.User(); if (!parent->OperIsIndir() && !parent->OperIs(GT_ADD)) { - TryCreateAddrMode(node, false); + TryCreateAddrMode(node, false, parent); } } #endif // !TARGET_ARMARCH @@ -5117,7 +5134,7 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) } //------------------------------------------------------------------------ -// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// LowerBinaryArithmeticCommon: lowers the given binary arithmetic node. // // Recognizes opportunities for using target-independent "combined" nodes // (currently AND_NOT on ARMArch). Performs containment checks. @@ -5128,41 +5145,39 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node) // Returns: // The next node to lower. // -GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* node) +GenTree* Lowering::LowerBinaryArithmeticCommon(GenTreeOp* binOp) { // TODO-CQ-XArch: support BMI2 "andn" in codegen and condition // this logic on the support for the instruction set on XArch. CLANG_FORMAT_COMMENT_ANCHOR; #ifdef TARGET_ARMARCH - if (comp->opts.OptimizationEnabled() && node->OperIs(GT_AND)) + if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND)) { GenTree* opNode = nullptr; GenTree* notNode = nullptr; - if (node->gtGetOp1()->OperIs(GT_NOT)) + if (binOp->gtGetOp1()->OperIs(GT_NOT)) { - notNode = node->gtGetOp1(); - opNode = node->gtGetOp2(); + notNode = binOp->gtGetOp1(); + opNode = binOp->gtGetOp2(); } - else if (node->gtGetOp2()->OperIs(GT_NOT)) + else if (binOp->gtGetOp2()->OperIs(GT_NOT)) { - notNode = node->gtGetOp2(); - opNode = node->gtGetOp1(); + notNode = binOp->gtGetOp2(); + opNode = binOp->gtGetOp1(); } if (notNode != nullptr) { - node->gtOp1 = opNode; - node->gtOp2 = notNode->AsUnOp()->gtGetOp1(); - node->ChangeOper(GT_AND_NOT); + binOp->gtOp1 = opNode; + binOp->gtOp2 = notNode->AsUnOp()->gtGetOp1(); + binOp->ChangeOper(GT_AND_NOT); BlockRange().Remove(notNode); } } -#endif // TARGET_ARMARCH - - ContainCheckBinary(node); +#endif - return node->gtNext; + return LowerBinaryArithmetic(binOp); } //------------------------------------------------------------------------ @@ -6774,7 +6789,7 @@ void Lowering::ContainCheckBitCast(GenTree* node) void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) { assert(ind->TypeGet() != TYP_STRUCT); - TryCreateAddrMode(ind->Addr(), true, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), true, ind); if (!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)) { if (varTypeIsFloating(ind) && ind->Data()->IsCnsFltOrDbl()) @@ -6842,7 +6857,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind) // TODO-Cleanup: We're passing isContainable = true but ContainCheckIndir rejects // address containment in some cases so we end up creating trivial (reg + offfset) // or (reg + reg) LEAs that are not necessary. - TryCreateAddrMode(ind->Addr(), true, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), true, ind); ContainCheckIndir(ind); if (ind->OperIs(GT_NULLCHECK) || ind->IsUnusedValue()) @@ -6855,7 +6870,7 @@ void Lowering::LowerIndir(GenTreeIndir* ind) // If the `ADDR` node under `STORE_OBJ(dstAddr, IND(struct(ADDR))` // is a complex one it could benefit from an `LEA` that is not contained. const bool isContainable = false; - TryCreateAddrMode(ind->Addr(), isContainable, ind->TypeGet()); + TryCreateAddrMode(ind->Addr(), isContainable, ind); } } diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 92a4ef43f2370a..95843b6bded47e 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -297,7 +297,8 @@ class Lowering final : public Phase void LowerStoreIndir(GenTreeStoreInd* node); GenTree* LowerAdd(GenTreeOp* node); GenTree* LowerMul(GenTreeOp* mul); - GenTree* LowerBinaryArithmetic(GenTreeOp* node); + GenTree* LowerBinaryArithmeticCommon(GenTreeOp* binOp); + GenTree* LowerBinaryArithmetic(GenTreeOp* binOp); bool LowerUnsignedDivOrMod(GenTreeOp* divMod); GenTree* LowerConstIntDivOrMod(GenTree* node); GenTree* LowerSignedDivOrMod(GenTree* node); @@ -306,7 +307,7 @@ class Lowering final : public Phase void ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenTree* addr); void LowerPutArgStk(GenTreePutArgStk* tree); - bool TryCreateAddrMode(GenTree* addr, bool isContainable, var_types targetType = TYP_UNDEF); + bool TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* parent); bool TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode); @@ -343,6 +344,7 @@ class Lowering final : public Phase void LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node); void LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node); void LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node); + GenTree* TryLowerAndOpToResetLowestSetBit(GenTreeOp* binOp); #elif defined(TARGET_ARM64) bool IsValidConstForMovImm(GenTreeHWIntrinsic* node); void LowerHWIntrinsicFusedMultiplyAddScalar(GenTreeHWIntrinsic* node); diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index e1812d7e8df6fa..67e1269dfd429a 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -281,6 +281,22 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) return mul->gtNext; } +//------------------------------------------------------------------------ +// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// +// Arguments: +// node - the arithmetic node to lower +// +// Returns: +// The next node to lower. +// +GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) +{ + ContainCheckBinary(binOp); + + return binOp->gtNext; +} + //------------------------------------------------------------------------ // LowerBlockStore: Lower a block store node // diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 413e4ba74a6a48..37459907558a0b 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -159,6 +159,33 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) return mul->gtNext; } +//------------------------------------------------------------------------ +// LowerBinaryArithmetic: lowers the given binary arithmetic node. +// +// Arguments: +// node - the arithmetic node to lower +// +// Returns: +// The next node to lower. +// +GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) +{ +#ifdef FEATURE_HW_INTRINSICS + if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND) && varTypeIsIntegral(binOp)) + { + GenTree* blsrNode = TryLowerAndOpToResetLowestSetBit(binOp); + if (blsrNode != nullptr) + { + return blsrNode->gtNext; + } + } +#endif + + ContainCheckBinary(binOp); + + return binOp->gtNext; +} + //------------------------------------------------------------------------ // LowerBlockStore: Lower a block store node // @@ -167,7 +194,7 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) // void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { - TryCreateAddrMode(blkNode->Addr(), false); + TryCreateAddrMode(blkNode->Addr(), false, blkNode); GenTree* dstAddr = blkNode->Addr(); GenTree* src = blkNode->Data(); @@ -381,7 +408,7 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT return; } - if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true)) + if (!addr->OperIsAddrMode() && !TryCreateAddrMode(addr, true, blkNode)) { return; } @@ -3429,7 +3456,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) // e6, e7, e4, e5 | e2, e3, e0, e1 // e7, e6, e5, e4 | e3, e2, e1, e0 - shuffleConst = 0x4D; + shuffleConst = 0x4E; break; } @@ -3697,6 +3724,84 @@ void Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node) LowerNode(cast); } } + +//---------------------------------------------------------------------------------------------- +// Lowering::TryLowerAndOpToResetLowestSetBit: Lowers a tree AND(X, ADD(X, -1) to HWIntrinsic::ResetLowestSetBit +// +// Arguments: +// andNode - GT_AND node of integral type +// +// Return Value: +// Returns the replacement node if one is created else nullptr indicating no replacement +// +GenTree* Lowering::TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode) +{ + assert(andNode->OperIs(GT_AND) && varTypeIsIntegral(andNode)); + + GenTree* op1 = andNode->gtGetOp1(); + if (!op1->OperIs(GT_LCL_VAR) || comp->lvaGetDesc(op1->AsLclVar())->IsAddressExposed()) + { + return nullptr; + } + + GenTree* op2 = andNode->gtGetOp2(); + if (!op2->OperIs(GT_ADD)) + { + return nullptr; + } + + GenTree* addOp2 = op2->gtGetOp2(); + if (!addOp2->IsIntegralConst(-1)) + { + return nullptr; + } + + GenTree* addOp1 = op2->gtGetOp1(); + if (!addOp1->OperIs(GT_LCL_VAR) || (addOp1->AsLclVar()->GetLclNum() != op1->AsLclVar()->GetLclNum())) + { + return nullptr; + } + + NamedIntrinsic intrinsic; + if (op1->TypeIs(TYP_LONG) && comp->compOpportunisticallyDependsOn(InstructionSet_BMI1_X64)) + { + intrinsic = NamedIntrinsic::NI_BMI1_X64_ResetLowestSetBit; + } + else if (comp->compOpportunisticallyDependsOn(InstructionSet_BMI1)) + { + intrinsic = NamedIntrinsic::NI_BMI1_ResetLowestSetBit; + } + else + { + return nullptr; + } + + LIR::Use use; + if (!BlockRange().TryGetUse(andNode, &use)) + { + return nullptr; + } + + GenTreeHWIntrinsic* blsrNode = comp->gtNewScalarHWIntrinsicNode(andNode->TypeGet(), op1, intrinsic); + + JITDUMP("Lower: optimize AND(X, ADD(X, -1))\n"); + DISPNODE(andNode); + JITDUMP("to:\n"); + DISPNODE(blsrNode); + + use.ReplaceWith(blsrNode); + + BlockRange().InsertBefore(andNode, blsrNode); + BlockRange().Remove(andNode); + BlockRange().Remove(op2); + BlockRange().Remove(addOp1); + BlockRange().Remove(addOp2); + + ContainCheckHWIntrinsic(blsrNode); + + return blsrNode; +} + #endif // FEATURE_HW_INTRINSICS //---------------------------------------------------------------------------------------------- @@ -5694,7 +5799,7 @@ bool Lowering::TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode void Lowering::ContainCheckHWIntrinsicAddr(GenTreeHWIntrinsic* node, GenTree* addr) { assert((addr->TypeGet() == TYP_I_IMPL) || (addr->TypeGet() == TYP_BYREF)); - TryCreateAddrMode(addr, true); + TryCreateAddrMode(addr, true, node); if ((addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA) || (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp))) && IsSafeToContainMem(node, addr)) diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index f1e97f9692d9ab..88f137ab65764d 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -1299,6 +1299,10 @@ void LinearScan::doLinearScan() DBEXEC(VERBOSE, TupleStyleDump(LSRA_DUMP_POST)); +#ifdef DEBUG + compiler->fgDebugCheckLinks(); +#endif + compiler->compLSRADone = true; } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index e7a3db4e80afd2..f07fe3ca9ed02b 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -13435,28 +13435,6 @@ GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree) std::swap(tree->gtOp1, tree->gtOp2); } - if (!optValnumCSE_phase) - { - GenTree* optimizedTree = nullptr; - if (tree->OperIs(GT_ADD)) - { - optimizedTree = fgOptimizeAddition(tree); - } - else if (tree->OperIs(GT_MUL)) - { - optimizedTree = fgOptimizeMultiply(tree); - } - else if (tree->OperIs(GT_AND)) - { - optimizedTree = fgOptimizeBitwiseAnd(tree); - } - - if (optimizedTree != nullptr) - { - return optimizedTree; - } - } - if (fgOperIsBitwiseRotationRoot(tree->OperGet())) { GenTree* rotationTree = fgRecognizeAndMorphBitwiseRotation(tree); @@ -13477,7 +13455,36 @@ GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree) if (varTypeIsIntegralOrI(tree)) { + genTreeOps oldTreeOper = tree->OperGet(); GenTreeOp* optimizedTree = fgMorphCommutative(tree->AsOp()); + if (optimizedTree != nullptr) + { + if (!optimizedTree->OperIs(oldTreeOper)) + { + // "optimizedTree" could end up being a COMMA. + return optimizedTree; + } + + tree = optimizedTree; + } + } + + if (!optValnumCSE_phase) + { + GenTree* optimizedTree = nullptr; + if (tree->OperIs(GT_ADD)) + { + optimizedTree = fgOptimizeAddition(tree); + } + else if (tree->OperIs(GT_MUL)) + { + optimizedTree = fgOptimizeMultiply(tree); + } + else if (tree->OperIs(GT_AND)) + { + optimizedTree = fgOptimizeBitwiseAnd(tree); + } + if (optimizedTree != nullptr) { return optimizedTree; @@ -13529,8 +13536,7 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) // Fold (x + 0) - given it won't change the tree type to TYP_REF. // TODO-Bug: this code will lose the GC-ness of a tree like "native int + byref(0)". - if (op2->IsCnsIntOrI() && (op2->AsIntCon()->IconValue() == 0) && - ((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF))) + if (op2->IsIntegralConst(0) && ((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF))) { if (op2->IsCnsIntOrI() && (op2->AsIntCon()->gtFieldSeq != nullptr) && (op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField())) @@ -13544,9 +13550,8 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) return op1; } - // TODO-CQ: this transform preserves VNs and can be enabled outside global morph. // Note that these transformations are legal for floating-point ADDs as well. - if (opts.OptimizationEnabled() && fgGlobalMorph) + if (opts.OptimizationEnabled()) { // - a + b = > b - a // ADD((NEG(a), b) => SUB(b, a) @@ -13655,6 +13660,13 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul) return mul; } +#ifdef TARGET_XARCH + // Should we try to replace integer multiplication with lea/add/shift sequences? + bool mulShiftOpt = compCodeOpt() != SMALL_CODE; +#else // !TARGET_XARCH + bool mulShiftOpt = false; +#endif // !TARGET_XARCH + size_t abs_mult = (mult >= 0) ? mult : -mult; size_t lowestBit = genFindLowestBit(abs_mult); bool changeToShift = false; @@ -13697,7 +13709,7 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul) op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult)); changeToShift = true; } - else if ((lowestBit > 1) && jitIsScaleIndexMul(lowestBit) && optAvoidIntMult()) + else if (mulShiftOpt && (lowestBit > 1) && jitIsScaleIndexMul(lowestBit)) { int shift = genLog2(lowestBit); ssize_t factor = abs_mult >> shift; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 7b2108d3edd057..68ea721ae48180 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -4,7 +4,10 @@ #ifndef _NAMEDINTRINSICLIST_H_ #define _NAMEDINTRINSICLIST_H_ -// Named jit intrinsics +// Named jit intrinsics. + +// When adding a new intrinsic that will use the GT_INTRINSIC node and can throw, make sure +// to update the "OperMayThrow" and "fgValueNumberAddExceptionSet" methods to account for that. enum NamedIntrinsic : unsigned short { diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index 805e5b7d2eb3f5..108fde7e984976 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -2599,17 +2599,18 @@ class CSE_Heuristic cse_use_cost *= slotCount; } - // If this CSE is live across a call then we may need to spill an additional caller save register + // If this CSE is live across a call then we may have additional costs // if (candidate->LiveAcrossCall()) { - if (candidate->Expr()->IsCnsFltOrDbl() && (CNT_CALLEE_SAVED_FLOAT == 0) && - (candidate->CseDsc()->csdUseWtCnt <= 4)) + // If we have a floating-point CSE that is both live across a call and there + // are no callee-saved FP registers available, the RA will have to spill at + // the def site and reload at the (first) use site, if the variable is a register + // candidate. Account for that. + if (varTypeIsFloating(candidate->Expr()) && (CNT_CALLEE_SAVED_FLOAT == 0) && !candidate->IsConservative()) { - // Floating point constants are expected to be contained, so unless there are more than 4 uses - // we better not to CSE them, especially on platforms without callee-saved registers - // for values living across calls - return false; + cse_def_cost += 1; + cse_use_cost += 1; } // If we don't have a lot of variables to enregister or we have a floating point type diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index d633a6d84aecd1..dd2f3a8246ede1 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -402,16 +402,14 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar bool removeLoop = false; - /* If an unreachable block was part of a loop entry or bottom then the loop is unreachable */ - /* Special case: the block was the head of a loop - or pointing to a loop entry */ + // If an unreachable block is a loop entry or bottom then the loop is unreachable. + // Special case: the block was the head of a loop - or pointing to a loop entry. for (unsigned loopNum = 0; loopNum < optLoopCount; loopNum++) { LoopDsc& loop = optLoopTable[loopNum]; - /* Some loops may have been already removed by - * loop unrolling or conditional folding */ - + // Some loops may have been already removed by loop unrolling or conditional folding. if (loop.lpFlags & LPFLG_REMOVED) { continue; @@ -454,11 +452,9 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar continue; } - /* If the loop is still in the table - * any block in the loop must be reachable !!! */ + // If the loop is still in the table any block in the loop must be reachable. - noway_assert(loop.lpEntry != block); - noway_assert(loop.lpBottom != block); + noway_assert((loop.lpEntry != block) && (loop.lpBottom != block)); if (loop.lpExit == block) { @@ -468,27 +464,26 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar loop.lpExit = nullptr; } - /* If this points to the actual entry in the loop - * then the whole loop may become unreachable */ + // If `block` flows to the loop entry then the whole loop will become unreachable if it is the + // only non-loop predecessor. switch (block->bbJumpKind) { case BBJ_NONE: - case BBJ_COND: if (block->bbNext == loop.lpEntry) { removeLoop = true; - break; } - if (block->bbJumpKind == BBJ_NONE) + break; + + case BBJ_COND: + if ((block->bbNext == loop.lpEntry) || (block->bbJumpDest == loop.lpEntry)) { - break; + removeLoop = true; } - - FALLTHROUGH; + break; case BBJ_ALWAYS: - noway_assert(block->bbJumpDest); if (block->bbJumpDest == loop.lpEntry) { removeLoop = true; @@ -512,13 +507,12 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar if (removeLoop) { - /* Check if the entry has other predecessors outside the loop - * TODO: Replace this when predecessors are available */ + // Check if the entry has other predecessors outside the loop. + // TODO: Replace this when predecessors are available. for (BasicBlock* const auxBlock : Blocks()) { - /* Ignore blocks in the loop */ - + // Ignore blocks in the loop. if (loop.lpContains(auxBlock)) { continue; @@ -527,21 +521,20 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar switch (auxBlock->bbJumpKind) { case BBJ_NONE: - case BBJ_COND: if (auxBlock->bbNext == loop.lpEntry) { removeLoop = false; - break; } - if (auxBlock->bbJumpKind == BBJ_NONE) + break; + + case BBJ_COND: + if ((auxBlock->bbNext == loop.lpEntry) || (auxBlock->bbJumpDest == loop.lpEntry)) { - break; + removeLoop = false; } - - FALLTHROUGH; + break; case BBJ_ALWAYS: - noway_assert(auxBlock->bbJumpDest); if (auxBlock->bbJumpDest == loop.lpEntry) { removeLoop = false; @@ -592,6 +585,27 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar } } +//------------------------------------------------------------------------ +// optClearLoopIterInfo: Clear the info related to LPFLG_ITER loops in the loop table. +// The various fields related to iterators is known to be valid for loop cloning and unrolling, +// but becomes invalid afterwards. Clear the info that might be used incorrectly afterwards +// in JitDump or by subsequent phases. +// +void Compiler::optClearLoopIterInfo() +{ + for (unsigned lnum = 0; lnum < optLoopCount; lnum++) + { + LoopDsc& loop = optLoopTable[lnum]; + loop.lpFlags &= ~(LPFLG_ITER | LPFLG_VAR_INIT | LPFLG_CONST_INIT | LPFLG_SIMD_LIMIT | LPFLG_VAR_LIMIT | + LPFLG_CONST_LIMIT | LPFLG_ARRLEN_LIMIT); + + loop.lpIterTree = nullptr; + loop.lpInitBlock = nullptr; + loop.lpConstInit = -1; // union with loop.lpVarInit + loop.lpTestTree = nullptr; + } +} + #ifdef DEBUG /***************************************************************************** diff --git a/src/coreclr/jit/phase.cpp b/src/coreclr/jit/phase.cpp index f08134bf11532b..5f2e2172c6f4a5 100644 --- a/src/coreclr/jit/phase.cpp +++ b/src/coreclr/jit/phase.cpp @@ -141,6 +141,8 @@ void Phase::PrePhase() // void Phase::PostPhase(PhaseStatus status) { + comp->EndPhase(m_phase); + #ifdef DEBUG // Don't dump or check post phase unless the phase made changes. @@ -162,16 +164,33 @@ void Phase::PostPhase(PhaseStatus status) // well as the new-style phases that have been updated to return // PhaseStatus from their DoPhase methods. // - static Phases s_allowlist[] = {PHASE_IMPORTATION, PHASE_IBCINSTR, - PHASE_IBCPREP, PHASE_INCPROFILE, - PHASE_INDXCALL, PHASE_MORPH_INLINE, - PHASE_ALLOCATE_OBJECTS, PHASE_EMPTY_TRY, - PHASE_EMPTY_FINALLY, PHASE_MERGE_FINALLY_CHAINS, - PHASE_CLONE_FINALLY, PHASE_MERGE_THROWS, - PHASE_MORPH_GLOBAL, PHASE_INVERT_LOOPS, - PHASE_OPTIMIZE_LAYOUT, PHASE_FIND_LOOPS, - PHASE_BUILD_SSA, PHASE_RATIONALIZE, - PHASE_LOWERING, PHASE_STACK_LEVEL_SETTER}; + // clang-format off + + static Phases s_allowlist[] = { + PHASE_INCPROFILE, + PHASE_IBCPREP, + PHASE_IMPORTATION, + PHASE_PATCHPOINTS, + PHASE_IBCINSTR, + PHASE_INDXCALL, + PHASE_MORPH_INLINE, + PHASE_ALLOCATE_OBJECTS, + PHASE_EMPTY_TRY, + PHASE_EMPTY_FINALLY, + PHASE_MERGE_FINALLY_CHAINS, + PHASE_CLONE_FINALLY, + PHASE_MERGE_THROWS, + PHASE_MORPH_GLOBAL, + PHASE_INVERT_LOOPS, + PHASE_OPTIMIZE_LAYOUT, + PHASE_FIND_LOOPS, + PHASE_BUILD_SSA, + PHASE_INSERT_GC_POLLS, + PHASE_RATIONALIZE, + PHASE_LOWERING, + PHASE_STACK_LEVEL_SETTER}; + + // clang-format on if (madeChanges) { @@ -234,6 +253,4 @@ void Phase::PostPhase(PhaseStatus status) #if DUMP_FLOWGRAPHS comp->fgDumpFlowGraph(m_phase, Compiler::PhasePosition::PostPhase); #endif // DUMP_FLOWGRAPHS - - comp->EndPhase(m_phase); } diff --git a/src/coreclr/jit/typeinfo.cpp b/src/coreclr/jit/typeinfo.cpp index 07809e57268a23..6bc69965d097b0 100644 --- a/src/coreclr/jit/typeinfo.cpp +++ b/src/coreclr/jit/typeinfo.cpp @@ -20,32 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX bool Compiler::tiCompatibleWith(const typeInfo& child, const typeInfo& parent, bool normalisedForStack) const { -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("Verifying compatibility against types: "); - child.Dump(); - printf(" and "); - parent.Dump(); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - bool compatible = typeInfo::tiCompatibleWith(info.compCompHnd, child, parent, normalisedForStack); - -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf(compatible ? " [YES]" : " [NO]"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - return compatible; + return typeInfo::tiCompatibleWith(info.compCompHnd, child, parent, normalisedForStack); } bool Compiler::tiMergeCompatibleWith(const typeInfo& child, const typeInfo& parent, bool normalisedForStack) const @@ -55,41 +30,7 @@ bool Compiler::tiMergeCompatibleWith(const typeInfo& child, const typeInfo& pare bool Compiler::tiMergeToCommonParent(typeInfo* pDest, const typeInfo* pSrc, bool* changed) const { -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf("\n"); - printf(TI_DUMP_PADDING); - printf("Attempting to merge types: "); - pDest->Dump(); - printf(" and "); - pSrc->Dump(); - printf("\n"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - bool mergeable = typeInfo::tiMergeToCommonParent(info.compCompHnd, pDest, pSrc, changed); - -#ifdef DEBUG -#if VERBOSE_VERIFY - if (VERBOSE && tiVerificationNeeded) - { - printf(TI_DUMP_PADDING); - printf(mergeable ? "Merge successful" : "Couldn't merge types"); - if (*changed) - { - assert(mergeable); - printf(", destination type changed to: "); - pDest->Dump(); - } - printf("\n"); - } -#endif // VERBOSE_VERIFY -#endif // DEBUG - - return mergeable; + return typeInfo::tiMergeToCommonParent(info.compCompHnd, pDest, pSrc, changed); } static bool tiCompatibleWithByRef(COMP_HANDLE CompHnd, const typeInfo& child, const typeInfo& parent) diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 356124ab00e5cb..947f774fbdac05 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -8755,38 +8755,42 @@ void Compiler::fgValueNumberTree(GenTree* tree) // Usually the ADDR and IND just cancel out... // except when this GT_ADDR has a valid zero-offset field sequence // + + ValueNumPair addrVNP = ValueNumPair(); FieldSeqNode* zeroOffsetFieldSeq = nullptr; if (GetZeroOffsetFieldMap()->Lookup(tree, &zeroOffsetFieldSeq) && (zeroOffsetFieldSeq != FieldSeqStore::NotAField())) { - ValueNum addrExtended = vnStore->ExtendPtrVN(arg->AsOp()->gtOp1, zeroOffsetFieldSeq); + ValueNum addrExtended = vnStore->ExtendPtrVN(arg->AsIndir()->Addr(), zeroOffsetFieldSeq); if (addrExtended != ValueNumStore::NoVN) { - tree->gtVNPair.SetBoth(addrExtended); // We don't care about lib/cons differences for addresses. + // We don't care about lib/cons differences for addresses. + addrVNP.SetBoth(addrExtended); } else { - // ExtendPtrVN returned a failure result - // So give this address a new unique value - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); + // ExtendPtrVN returned a failure result - give this address a new unique value. + addrVNP.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); } } else { // They just cancel, so fetch the ValueNumber from the op1 of the GT_IND node. // - GenTree* addr = arg->AsIndir()->Addr(); - tree->gtVNPair = addr->gtVNPair; + GenTree* addr = arg->AsIndir()->Addr(); + addrVNP = addr->gtVNPair; // For the CSE phase mark the address as GTF_DONT_CSE // because it will end up with the same value number as tree (the GT_ADDR). addr->gtFlags |= GTF_DONT_CSE; } + + tree->gtVNPair = vnStore->VNPWithExc(addrVNP, vnStore->VNPExceptionSet(arg->gtVNPair)); } else { // May be more cases to do here! But we'll punt for now. - tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_BYREF)); + tree->gtVNPair = vnStore->VNPUniqueWithExc(TYP_BYREF, vnStore->VNPExceptionSet(arg->gtVNPair)); } } else if ((oper == GT_IND) || GenTree::OperIsBlk(oper)) @@ -10992,7 +10996,8 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree) break; case GT_INTRINSIC: - // ToDo: model the exceptions for Intrinsics + assert(tree->AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType); + fgValueNumberAddExceptionSetForIndirection(tree, tree->AsIntrinsic()->gtGetOp1()); break; case GT_IND: diff --git a/src/coreclr/md/enc/metamodelrw.cpp b/src/coreclr/md/enc/metamodelrw.cpp index 34fe8b84e95c88..3fde673faa5c43 100644 --- a/src/coreclr/md/enc/metamodelrw.cpp +++ b/src/coreclr/md/enc/metamodelrw.cpp @@ -309,16 +309,15 @@ ULONG CMiniMdRW::m_TruncatedEncTables[] = ULONG CMiniMdRW::GetTableForToken( // Table index, or -1. mdToken tkn) // Token to find. { - ULONG ixTbl; // Loop control. ULONG type = TypeFromToken(tkn); // Get the type -- if a string, no associated table. if (type >= mdtString) return (ULONG) -1; // Table number is same as high-byte of token. - ixTbl = type >> 24; + ULONG ixTbl = type >> 24; // Make sure. - _ASSERTE(g_TblIndex[ixTbl].m_Token == type); + _ASSERTE(ixTbl < TBL_COUNT); return ixTbl; } // CMiniMdRW::GetTableForToken diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets index 18258d4288b01f..ae6229a0a7afe6 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -48,7 +48,7 @@ - + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 1a3b4a2f740b41..529de6be54f554 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -40,8 +40,6 @@ The .NET Foundation licenses this file to you under the MIT license. true true - true - copyused @@ -132,13 +130,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - - true - - - @@ -200,35 +191,6 @@ The .NET Foundation licenses this file to you under the MIT license. Outputs="%(ManagedBinary.IlcRspFile)" DependsOnTargets="$(IlcCompileDependsOn)"> - - - true - - - - - - - <__SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <__SingleWarnIntermediateAssembly Remove="@(IntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <_SingleWarnIntermediateAssembly Remove="@(__SingleWarnIntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly> - false - - - - - - - - false - - - <_IlcRootedAssemblies Include="@(TrimmerRootAssembly)" /> <_IlcRootedAssemblies Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimMode) == 'copy'" /> @@ -247,6 +209,7 @@ The .NET Foundation licenses this file to you under the MIT license. + @@ -279,6 +242,7 @@ The .NET Foundation licenses this file to you under the MIT license. + @@ -286,9 +250,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - diff --git a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp index e1025ce27e664c..991f67bb9b2274 100644 --- a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp +++ b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp @@ -109,7 +109,8 @@ struct DotNetRuntimeDebugHeader #ifdef TARGET_WINDOWS #pragma comment (linker, "/EXPORT:DotNetRuntimeDebugHeader,DATA") #endif -extern "C" DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader = {}; +extern "C" struct DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader; +struct DotNetRuntimeDebugHeader DotNetRuntimeDebugHeader = {}; #define MAKE_DEBUG_ENTRY(TypeName, FieldName, Value) \ do \ @@ -138,8 +139,8 @@ extern "C" void PopulateDebugHeaders() size_t currentDebugPos = 0; size_t currentGlobalPos = 0; - ZeroMemory(s_DebugEntries, DebugTypeEntriesArraySize); - ZeroMemory(s_GlobalEntries, GlobalEntriesArraySize); + ZeroMemory(s_DebugEntries, sizeof(s_DebugEntries)); + ZeroMemory(s_GlobalEntries, sizeof(s_GlobalEntries)); MAKE_SIZE_ENTRY(GcDacVars); MAKE_DEBUG_FIELD_ENTRY(GcDacVars, major_version_number); diff --git a/src/coreclr/nativeaot/Runtime/MethodTable.cpp b/src/coreclr/nativeaot/Runtime/MethodTable.cpp index 4197cd8ba36237..4d3ace8dcf089a 100644 --- a/src/coreclr/nativeaot/Runtime/MethodTable.cpp +++ b/src/coreclr/nativeaot/Runtime/MethodTable.cpp @@ -20,10 +20,6 @@ bool MethodTable::Validate(bool assertOnFail /* default: true */) { #define REPORT_FAILURE() do { if (assertOnFail) { ASSERT_UNCONDITIONALLY("MethodTable::Validate check failed"); } return false; } while (false) - // Deal with the most common case of a bad pointer without an exception. - if (this == NULL) - REPORT_FAILURE(); - // MethodTable structures should be at least pointer aligned. if (dac_cast(this) & (sizeof(TADDR)-1)) REPORT_FAILURE(); diff --git a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S index f66851461f278f..4d3fbbbce2216e 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S +++ b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.S @@ -188,7 +188,7 @@ NoAbort: EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 0xA0 EPILOG_RETURN - NESTED_END RhpReversePInvokeTrapThread + NESTED_END RhpReversePInvokeAttachOrTrapThread, _TEXT // // RhpPInvoke diff --git a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm index 7692bfa8341beb..4bc165aef04505 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/PInvoke.asm @@ -180,7 +180,7 @@ NoAbort EPILOG_RESTORE_REG_PAIR fp, lr, #0xA0! EPILOG_RETURN - NESTED_END RhpReversePInvokeTrapThread + NESTED_END RhpReversePInvokeAttachOrTrapThread ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/coreclr/nativeaot/Runtime/eventtrace.cpp b/src/coreclr/nativeaot/Runtime/eventtrace.cpp index 23dd9726b5ed2d..0f4646152165b1 100644 --- a/src/coreclr/nativeaot/Runtime/eventtrace.cpp +++ b/src/coreclr/nativeaot/Runtime/eventtrace.cpp @@ -35,9 +35,9 @@ #define Win32EventWrite EventWrite // Flags used to store some runtime information for Event Tracing -BOOL g_fEEOtherStartup=FALSE; -BOOL g_fEEComActivatedStartup=FALSE; -LPCGUID g_fEEComObjectGuid=&GUID_NULL; +BOOL g_fEEOtherStartup = FALSE; +BOOL g_fEEComActivatedStartup = FALSE; +LPCGUID g_fEEComObjectGuid = &GUID_NULL; BOOL g_fEEHostedStartup = FALSE; @@ -188,16 +188,16 @@ BOOL IsRuntimeNgenKeywordEnabledAndNotSuppressed() LIMITED_METHOD_CONTRACT; return - ( - ETW_TRACING_CATEGORY_ENABLED( - MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_NGEN_KEYWORD) - && ! ( ETW_TRACING_CATEGORY_ENABLED( + ( + ETW_TRACING_CATEGORY_ENABLED( MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, - CLR_OVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD) ) - ); + CLR_NGEN_KEYWORD) + && !(ETW_TRACING_CATEGORY_ENABLED( + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_OVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD)) + ); } // Same as above, but for the rundown provider @@ -206,16 +206,16 @@ BOOL IsRundownNgenKeywordEnabledAndNotSuppressed() LIMITED_METHOD_CONTRACT; return - ( - ETW_TRACING_CATEGORY_ENABLED( - MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNNGEN_KEYWORD) - && ! ( ETW_TRACING_CATEGORY_ENABLED( + ( + ETW_TRACING_CATEGORY_ENABLED( + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNNGEN_KEYWORD) + && !(ETW_TRACING_CATEGORY_ENABLED( MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNOVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD) ) - ); + CLR_RUNDOWNOVERRIDEANDSUPPRESSNGENEVENTS_KEYWORD)) + ); } /*******************************************************/ @@ -226,7 +226,7 @@ extern "C" { CallStackFrame* GetEbp() { - CallStackFrame *frame=NULL; + CallStackFrame* frame = NULL; __asm { mov frame, ebp @@ -244,8 +244,8 @@ extern "C" void ETW::SamplingLog::Append(SIZE_T currentFrame) { LIMITED_METHOD_CONTRACT; - if(m_FrameCount < (ETW::SamplingLog::s_MaxStackSize-1) && - currentFrame != 0) + if (m_FrameCount < (ETW::SamplingLog::s_MaxStackSize - 1) && + currentFrame != 0) { m_EBPStack[m_FrameCount] = currentFrame; m_FrameCount++; @@ -255,7 +255,7 @@ void ETW::SamplingLog::Append(SIZE_T currentFrame) /********************************************************/ /* Function to get the callstack on the current thread */ /********************************************************/ -ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack) +ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStack(UINT32* frameCount, PVOID** Stack) { CONTRACTL { @@ -278,17 +278,17 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::GetCurrentThreadsCallStac // this not really needed, but let's do it // because we use the framecount while dumping the stack event - for(int i=m_FrameCount; im_Next; // Skip the top N frames - if(skipTopNFrames) { + if (skipTopNFrames) { skipTopNFrames--; continue; } @@ -358,16 +358,16 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip Append(lastEBP->m_ReturnAddress); // Check for stack limits - if((SIZE_T)currentEBP < (SIZE_T)Thread::GetStackLowerBound() || (SIZE_T)currentEBP > (SIZE_T)Thread::GetStackUpperBound()) + if ((SIZE_T)currentEBP < (SIZE_T)Thread::GetStackLowerBound() || (SIZE_T)currentEBP >(SIZE_T)Thread::GetStackUpperBound()) { break; } // If we have a too small address, we are probably bad - if((SIZE_T)currentEBP < (SIZE_T)0x10000) + if ((SIZE_T)currentEBP < (SIZE_T)0x10000) break; - if((SIZE_T)currentEBP < (SIZE_T)lastEBP) + if ((SIZE_T)currentEBP < (SIZE_T)lastEBP) { break; } @@ -378,7 +378,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip UINT_PTR ControlPc = 0; UINT_PTR CurrentSP = 0, PrevSP = 0; - while(1) + while (1) { // Unwind to the caller ControlPc = Thread::VirtualUnwindCallFrame(&ctx); @@ -387,13 +387,13 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip CurrentSP = (UINT_PTR)GetSP(&ctx); // when to break from this loop - if ( ControlPc == 0 || ( PrevSP == CurrentSP ) ) + if (ControlPc == 0 || (PrevSP == CurrentSP)) { break; } // Skip the top N frames - if ( skipTopNFrames ) { + if (skipTopNFrames) { skipTopNFrames--; continue; } @@ -404,7 +404,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip PrevSP = CurrentSP; } #endif //TARGET_X86 - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); pThread->MarkEtwStackWalkCompleted(); #endif //!DACCESS_COMPILE @@ -431,7 +431,7 @@ ETW::SamplingLog::EtwStackWalkStatus ETW::SamplingLog::SaveCurrentStack(int skip /***************************************************************************/ /* This function should be called from the event tracing callback routine when the private CLR provider is enabled */ -/***************************************************************************/ + /***************************************************************************/ #ifndef FEATURE_REDHAWK @@ -440,13 +440,13 @@ void ETW::GCLog::GCSettingsEvent() if (GCHeapUtilities::IsGCHeapInitialized()) { if (ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - GCSettings)) + GCSettings)) { ETW::GCLog::ETW_GC_INFO Info; - Info.GCSettings.ServerGC = GCHeapUtilities::IsServerHeap (); - Info.GCSettings.SegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (FALSE); - Info.GCSettings.LargeObjectSegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize (TRUE); + Info.GCSettings.ServerGC = GCHeapUtilities::IsServerHeap(); + Info.GCSettings.SegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(FALSE); + Info.GCSettings.LargeObjectSegmentSize = GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(TRUE); FireEtwGCSettings_V1(Info.GCSettings.SegmentSize, Info.GCSettings.LargeObjectSegmentSize, Info.GCSettings.ServerGC, GetClrInstanceId()); } GCHeapUtilities::GetGCHeap()->TraceGCSegments(); @@ -518,13 +518,13 @@ struct EtwGcMovementContext // else, a new EtwGcMovementContext is allocated, stored in that pointer, and // then returned. Callers should test for NULL, which can be returned if out of // memory - static EtwGcMovementContext * GetOrCreateInGCContext(EtwGcMovementContext ** ppContext) + static EtwGcMovementContext* GetOrCreateInGCContext(EtwGcMovementContext** ppContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(ppContext != NULL); - EtwGcMovementContext * pContext = *ppContext; + EtwGcMovementContext* pContext = *ppContext; if (pContext == NULL) { pContext = new (nothrow) EtwGcMovementContext; @@ -597,13 +597,13 @@ struct MovedReferenceContextForEtwAndProfapi // returned; else, a new MovedReferenceContextForEtwAndProfapi is allocated, stored // in that pointer, and then returned. Callers should test for NULL, which can be // returned if out of memory - static MovedReferenceContextForEtwAndProfapi * CreateInGCContext(LPVOID pvContext) + static MovedReferenceContextForEtwAndProfapi* CreateInGCContext(LPVOID pvContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(pvContext != NULL); - MovedReferenceContextForEtwAndProfapi * pContext = *(MovedReferenceContextForEtwAndProfapi **) pvContext; + MovedReferenceContextForEtwAndProfapi* pContext = *(MovedReferenceContextForEtwAndProfapi**)pvContext; // Shouldn't be called if the context was already created. Perhaps someone made // one too many BeginMovedReferences calls, or didn't have an EndMovedReferences @@ -611,7 +611,7 @@ struct MovedReferenceContextForEtwAndProfapi _ASSERTE(pContext == NULL); pContext = new (nothrow) MovedReferenceContextForEtwAndProfapi; - *(MovedReferenceContextForEtwAndProfapi **) pvContext = pContext; + *(MovedReferenceContextForEtwAndProfapi**)pvContext = pContext; return pContext; } @@ -626,7 +626,7 @@ struct MovedReferenceContextForEtwAndProfapi } LPVOID pctxProfAPI; - EtwGcMovementContext * pctxEtw; + EtwGcMovementContext* pctxEtw; }; @@ -648,8 +648,8 @@ struct MovedReferenceContextForEtwAndProfapi // static void ETW::GCLog::MovedReference( - BYTE * pbMemBlockStart, - BYTE * pbMemBlockEnd, + BYTE* pbMemBlockStart, + BYTE* pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, @@ -665,8 +665,8 @@ void ETW::GCLog::MovedReference( } CONTRACTL_END; - MovedReferenceContextForEtwAndProfapi * pCtxForEtwAndProfapi = - (MovedReferenceContextForEtwAndProfapi *) profilingContext; + MovedReferenceContextForEtwAndProfapi* pCtxForEtwAndProfapi = + (MovedReferenceContextForEtwAndProfapi*)profilingContext; if (pCtxForEtwAndProfapi == NULL) { _ASSERTE(!"MovedReference() encountered a NULL profilingContext"); @@ -678,10 +678,10 @@ void ETW::GCLog::MovedReference( { BEGIN_PIN_PROFILER(CORProfilerTrackGC()); g_profControlBlock.pProfInterface->MovedReference(pbMemBlockStart, - pbMemBlockEnd, - cbRelocDistance, - &(pCtxForEtwAndProfapi->pctxProfAPI), - fCompacting); + pbMemBlockEnd, + cbRelocDistance, + &(pCtxForEtwAndProfapi->pctxProfAPI), + fCompacting); END_PIN_PROFILER(); } #endif // PROFILING_SUPPORTED @@ -691,7 +691,7 @@ void ETW::GCLog::MovedReference( if (!ShouldTrackMovementForEtw()) return; - EtwGcMovementContext * pContext = + EtwGcMovementContext* pContext = EtwGcMovementContext::GetOrCreateInGCContext(&pCtxForEtwAndProfapi->pctxEtw); if (pContext == NULL) return; @@ -701,7 +701,7 @@ void ETW::GCLog::MovedReference( // Moved references _ASSERTE(pContext->cBulkMovedObjectRanges < _countof(pContext->rgGCBulkMovedObjectRanges)); - EventStructGCBulkMovedObjectRangesValue * pValue = + EventStructGCBulkMovedObjectRangesValue* pValue = &pContext->rgGCBulkMovedObjectRanges[pContext->cBulkMovedObjectRanges]; pValue->OldRangeBase = pbMemBlockStart; pValue->NewRangeBase = pbMemBlockStart + cbRelocDistance; @@ -727,7 +727,7 @@ void ETW::GCLog::MovedReference( // Surviving references _ASSERTE(pContext->cBulkSurvivingObjectRanges < _countof(pContext->rgGCBulkSurvivingObjectRanges)); - EventStructGCBulkSurvivingObjectRangesValue * pValue = + EventStructGCBulkSurvivingObjectRangesValue* pValue = &pContext->rgGCBulkSurvivingObjectRanges[pContext->cBulkSurvivingObjectRanges]; pValue->RangeBase = pbMemBlockStart; pValue->RangeLength = pbMemBlockEnd - pbMemBlockStart; @@ -763,7 +763,7 @@ void ETW::GCLog::MovedReference( // // static -void ETW::GCLog::BeginMovedReferences(size_t * pProfilingContext) +void ETW::GCLog::BeginMovedReferences(size_t* pProfilingContext) { LIMITED_METHOD_CONTRACT; @@ -794,7 +794,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext, } CONTRACTL_END; - MovedReferenceContextForEtwAndProfapi * pCtxForEtwAndProfapi = (MovedReferenceContextForEtwAndProfapi *) profilingContext; + MovedReferenceContextForEtwAndProfapi* pCtxForEtwAndProfapi = (MovedReferenceContextForEtwAndProfapi*)profilingContext; if (pCtxForEtwAndProfapi == NULL) { _ASSERTE(!"EndMovedReferences() encountered a NULL profilingContext"); @@ -817,7 +817,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext, // If context isn't already set up for us, then we haven't been collecting any data // for ETW events. - EtwGcMovementContext * pContext = pCtxForEtwAndProfapi->pctxEtw; + EtwGcMovementContext* pContext = pCtxForEtwAndProfapi->pctxEtw; if (pContext == NULL) return; @@ -893,7 +893,7 @@ void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) // // static -void ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo) +void ETW::GCLog::FireGcStart(ETW_GC_INFO* pGcInfo) { LIMITED_METHOD_CONTRACT; @@ -924,7 +924,7 @@ void ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo) FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog); #elif defined(FEATURE_DTRACE) - FireEtwGCStart(pGcInfo->GCStart.Count,pGcInfo->GCStart.Reason); + FireEtwGCStart(pGcInfo->GCStart.Count, pGcInfo->GCStart.Reason); #endif } @@ -990,7 +990,7 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() _ASSERTE(GCHeapUtilities::IsGCHeapInitialized()); ThreadStore::AttachCurrentThread(); - Thread * pThread = ThreadStore::GetCurrentThread(); + Thread* pThread = ThreadStore::GetCurrentThread(); // Doing this prevents the GC from trying to walk this thread's stack for roots. pThread->SetGCSpecial(true); @@ -1011,11 +1011,11 @@ HRESULT ETW::GCLog::ForceGCForDiagnostics() pThread->EnablePreemptiveMode(); #else // !FEATURE_REDHAWK } - EX_CATCH { } - EX_END_CATCH(RethrowCorruptingExceptions); +EX_CATCH{ } +EX_END_CATCH(RethrowCorruptingExceptions); #endif // FEATURE_REDHAWK - return hr; +return hr; } @@ -1142,7 +1142,7 @@ void BulkTypeEventLogger::FireBulkTypeEvent() #ifdef FEATURE_REDHAWK ((m_rgBulkTypeValues[iTypeData].cTypeParameters == 1) ? &(m_rgBulkTypeValues[iTypeData].ullSingleTypeParameter) : - (ULONGLONG *) (m_rgBulkTypeValues[iTypeData].rgTypeParameters)), + (ULONGLONG*)(m_rgBulkTypeValues[iTypeData].rgTypeParameters)), #else m_rgBulkTypeValues[iTypeData].rgTypeParameters.GetElements(), #endif @@ -1200,7 +1200,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) return -1; } - BulkTypeValue * pVal = &m_rgBulkTypeValues[m_nBulkTypeValueCount]; + BulkTypeValue* pVal = &m_rgBulkTypeValues[m_nBulkTypeValueCount]; // Clear out pVal before filling it out (array elements can get reused if there // are enough types that we need to flush to multiple events). Clearing the @@ -1211,7 +1211,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) pVal->Clear(); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1219,11 +1219,11 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) if (!fSucceeded) return -1; - pVal->fixedSizedData.TypeID = (ULONGLONG) th.AsTAddr(); - pVal->fixedSizedData.ModuleID = (ULONGLONG) (TADDR) th.GetModule(); + pVal->fixedSizedData.TypeID = (ULONGLONG)th.AsTAddr(); + pVal->fixedSizedData.ModuleID = (ULONGLONG)(TADDR)th.GetModule(); pVal->fixedSizedData.TypeNameID = (th.GetMethodTable() == NULL) ? 0 : th.GetCl(); pVal->fixedSizedData.Flags = 0; - pVal->fixedSizedData.CorElementType = (BYTE) th.GetInternalCorElementType(); + pVal->fixedSizedData.CorElementType = (BYTE)th.GetInternalCorElementType(); if (th.IsArray()) { @@ -1234,10 +1234,10 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - pVal->rgTypeParameters.Append((ULONGLONG) th.AsArray()->GetArrayElementTypeHandle().AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)th.AsArray()->GetArrayElementTypeHandle().AsTAddr()); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1254,10 +1254,10 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - pVal->rgTypeParameters.Append((ULONGLONG) pTypeDesc->GetTypeParam().AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)pTypeDesc->GetTypeParam().AsTAddr()); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1290,13 +1290,13 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) fSucceeded = FALSE; EX_TRY { - for (DWORD i=0; i < cTypeParameters; i++) + for (DWORD i = 0; i < cTypeParameters; i++) { - pVal->rgTypeParameters.Append((ULONGLONG) inst[i].AsTAddr()); + pVal->rgTypeParameters.Append((ULONGLONG)inst[i].AsTAddr()); } fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1332,7 +1332,7 @@ int BulkTypeEventLogger::LogSingleType(TypeHandle th) } pVal->sName.Normalize(); } - EX_CATCH + EX_CATCH { // If this failed, the name remains empty, which is ok; the event just // won't have a name in it. @@ -1397,7 +1397,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } CONTRACTL_END; - TypeHandle th = TypeHandle::FromTAddr((TADDR) thAsAddr); + TypeHandle th = TypeHandle::FromTAddr((TADDR)thAsAddr); // Batch up this type. This grabs useful info about the type, including any // type parameters it may have, and sticks it in m_rgBulkTypeValues @@ -1410,7 +1410,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } // Look at the type info we just batched, so we can get the type parameters - BulkTypeValue * pVal = &m_rgBulkTypeValues[iBulkTypeEventData]; + BulkTypeValue* pVal = &m_rgBulkTypeValues[iBulkTypeEventData]; // We're about to recursively call ourselves for the type parameters, so make a // local copy of their type handles first (else, as we log them we could flush @@ -1428,7 +1428,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst } fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -1443,7 +1443,7 @@ void BulkTypeEventLogger::LogTypeAndParameters(ULONGLONG thAsAddr, ETW::TypeSyst typeLogBehavior = ETW::TypeSystemLog::kTypeLogBehaviorAssumeLockAndLogIfFirstTime; // Recursively log any referenced parameter types - for (COUNT_T i=0; i < cParams; i++) + for (COUNT_T i = 0; i < cParams; i++) { ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(this, rgTypeParameters[i], typeLogBehavior); } @@ -1463,13 +1463,13 @@ class EtwGcHeapDumpContext // ProfilerWalkHeapContext::pvEtwContext; if non-NULL it gets returned; else, a new // EtwGcHeapDumpContext is allocated, stored in that pointer, and then returned. // Callers should test for NULL, which can be returned if out of memory - static EtwGcHeapDumpContext * GetOrCreateInGCContext(LPVOID * ppvEtwContext) + static EtwGcHeapDumpContext* GetOrCreateInGCContext(LPVOID* ppvEtwContext) { LIMITED_METHOD_CONTRACT; _ASSERTE(ppvEtwContext != NULL); - EtwGcHeapDumpContext * pContext = (EtwGcHeapDumpContext *) *ppvEtwContext; + EtwGcHeapDumpContext* pContext = (EtwGcHeapDumpContext*)*ppvEtwContext; if (pContext == NULL) { pContext = new (nothrow) EtwGcHeapDumpContext; @@ -1644,10 +1644,10 @@ class EtwGcHeapDumpContext // static void ETW::GCLog::RootReference( LPVOID pvHandle, - Object * pRootedNode, - Object * pSecondaryNodeForDependentHandle, + Object* pRootedNode, + Object* pSecondaryNodeForDependentHandle, BOOL fDependentHandle, - ProfilingScanContext * profilingScanContext, + ProfilingScanContext* profilingScanContext, DWORD dwGCFlags, DWORD rootFlags) { @@ -1657,14 +1657,14 @@ void ETW::GCLog::RootReference( if (pRootedNode == NULL) return; - EtwGcHeapDumpContext * pContext = + EtwGcHeapDumpContext* pContext = EtwGcHeapDumpContext::GetOrCreateInGCContext(&profilingScanContext->pvEtwContext); if (pContext == NULL) return; // Determine root kind, root ID, and handle-specific flags LPVOID pvRootID = NULL; - BYTE nRootKind = (BYTE) profilingScanContext->dwEtwRootKind; + BYTE nRootKind = (BYTE)profilingScanContext->dwEtwRootKind; switch (nRootKind) { case kEtwGCRootKindStack: @@ -1699,7 +1699,7 @@ void ETW::GCLog::RootReference( { _ASSERTE(pContext->cGCBulkRootConditionalWeakTableElementEdges < _countof(pContext->rgGCBulkRootConditionalWeakTableElementEdges)); - EventStructGCBulkRootConditionalWeakTableElementEdgeValue * pRCWTEEdgeValue = + EventStructGCBulkRootConditionalWeakTableElementEdgeValue* pRCWTEEdgeValue = &pContext->rgGCBulkRootConditionalWeakTableElementEdges[pContext->cGCBulkRootConditionalWeakTableElementEdges]; pRCWTEEdgeValue->GCKeyNodeID = pRootedNode; pRCWTEEdgeValue->GCValueNodeID = pSecondaryNodeForDependentHandle; @@ -1724,7 +1724,7 @@ void ETW::GCLog::RootReference( else { _ASSERTE(pContext->cGcBulkRootEdges < _countof(pContext->rgGcBulkRootEdges)); - EventStructGCBulkRootEdgeValue * pBulkRootEdgeValue = &pContext->rgGcBulkRootEdges[pContext->cGcBulkRootEdges]; + EventStructGCBulkRootEdgeValue* pBulkRootEdgeValue = &pContext->rgGcBulkRootEdges[pContext->cGcBulkRootEdges]; pBulkRootEdgeValue->RootedNodeAddress = pRootedNode; pBulkRootEdgeValue->GCRootKind = nRootKind; pBulkRootEdgeValue->GCRootFlag = rootFlags; @@ -1765,11 +1765,11 @@ void ETW::GCLog::RootReference( // static void ETW::GCLog::ObjectReference( - ProfilerWalkHeapContext * profilerWalkHeapContext, - Object * pObjReferenceSource, + ProfilerWalkHeapContext* profilerWalkHeapContext, + Object* pObjReferenceSource, ULONGLONG typeID, ULONGLONG cRefs, - Object ** rgObjReferenceTargets) + Object** rgObjReferenceTargets) { #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT CONTRACTL @@ -1783,7 +1783,7 @@ void ETW::GCLog::ObjectReference( } CONTRACTL_END; - EtwGcHeapDumpContext * pContext = + EtwGcHeapDumpContext* pContext = EtwGcHeapDumpContext::GetOrCreateInGCContext(&profilerWalkHeapContext->pvEtwContext); if (pContext == NULL) return; @@ -1794,7 +1794,7 @@ void ETW::GCLog::ObjectReference( // Add Node (pObjReferenceSource) to buffer _ASSERTE(pContext->cGcBulkNodeValues < _countof(pContext->rgGcBulkNodeValues)); - EventStructGCBulkNodeValue * pBulkNodeValue = &pContext->rgGcBulkNodeValues[pContext->cGcBulkNodeValues]; + EventStructGCBulkNodeValue* pBulkNodeValue = &pContext->rgGcBulkNodeValues[pContext->cGcBulkNodeValues]; pBulkNodeValue->Address = pObjReferenceSource; pBulkNodeValue->Size = pObjReferenceSource->GetSize(); pBulkNodeValue->TypeID = typeID; @@ -1830,7 +1830,7 @@ void ETW::GCLog::ObjectReference( // During heap walk, GC holds the lock for us, so we can directly enter the // hash to see if the type has already been logged ETW::TypeSystemLog::kTypeLogBehaviorAssumeLockAndLogIfFirstTime - ); + ); } //--------------------------------------------------------------------------------------- @@ -1842,10 +1842,10 @@ void ETW::GCLog::ObjectReference( // a lot of edges), so empty Edge buffer into ETW as we go along, as many times as we // need. - for (ULONGLONG i=0; i < cRefs; i++) + for (ULONGLONG i = 0; i < cRefs; i++) { _ASSERTE(pContext->cGcBulkEdgeValues < _countof(pContext->rgGcBulkEdgeValues)); - EventStructGCBulkEdgeValue * pBulkEdgeValue = &pContext->rgGcBulkEdgeValues[pContext->cGcBulkEdgeValues]; + EventStructGCBulkEdgeValue* pBulkEdgeValue = &pContext->rgGcBulkEdgeValues[pContext->cGcBulkEdgeValues]; pBulkEdgeValue->Value = rgObjReferenceTargets[i]; // FUTURE: ReferencingFieldID pBulkEdgeValue->ReferencingFieldID = 0; @@ -1878,14 +1878,14 @@ void ETW::GCLog::ObjectReference( // // static -void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext) +void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext* profilerWalkHeapContext) { #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT LIMITED_METHOD_CONTRACT; // If context isn't already set up for us, then we haven't been collecting any data // for ETW events. - EtwGcHeapDumpContext * pContext = (EtwGcHeapDumpContext *) profilerWalkHeapContext->pvEtwContext; + EtwGcHeapDumpContext* pContext = (EtwGcHeapDumpContext*)profilerWalkHeapContext->pvEtwContext; if (pContext == NULL) return; @@ -1969,7 +1969,7 @@ void ETW::GCLog::EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext) // // static -void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) +void ETW::GCLog::SendFinalizeObjectEvent(MethodTable* pMT, Object* pObj) { CONTRACTL { @@ -1991,12 +1991,12 @@ void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) // finalized object's type (and parameter types, if any) ETW::TypeSystemLog::LogTypeAndParametersIfNecessary( NULL, // Not batching this type with others - (TADDR) pMT, + (TADDR)pMT, // Don't spend the time entering the lock and checking the hash table to see // if we've already logged the type; just log it (if type events are enabled). ETW::TypeSystemLog::kTypeLogBehaviorAlwaysLog - ); + ); } // Send private finalize object event, if it's enabled @@ -2007,14 +2007,14 @@ void ETW::GCLog::SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj) DefineFullyQualifiedNameForClassWOnStack(); FireEtwPrvFinalizeObject(pMT, pObj, GetClrInstanceId(), GetFullyQualifiedNameForClassNestedAwareW(pMT)); } - EX_CATCH + EX_CATCH { } EX_END_CATCH(RethrowCorruptingExceptions); } } -DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread * pThread) +DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2037,7 +2037,7 @@ DWORD ETW::ThreadLog::GetEtwThreadFlags(Thread * pThread) return dwEtwThreadFlags; } -void ETW::ThreadLog::FireThreadCreated(Thread * pThread) +void ETW::ThreadLog::FireThreadCreated(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2050,7 +2050,7 @@ void ETW::ThreadLog::FireThreadCreated(Thread * pThread) GetClrInstanceId()); } -void ETW::ThreadLog::FireThreadDC(Thread * pThread) +void ETW::ThreadLog::FireThreadDC(Thread* pThread) { LIMITED_METHOD_CONTRACT; @@ -2088,7 +2088,7 @@ class LoggedTypesFromModuleTraits : public NoRemoveSHashTraits< DefaultSHashTrai typedef TypeHandle key_t; - static key_t GetKey(const element_t &e) + static key_t GetKey(const element_t& e) { LIMITED_METHOD_CONTRACT; return e.th; @@ -2103,10 +2103,10 @@ class LoggedTypesFromModuleTraits : public NoRemoveSHashTraits< DefaultSHashTrai static count_t Hash(key_t k) { LIMITED_METHOD_CONTRACT; - return (count_t) k.AsTAddr(); + return (count_t)k.AsTAddr(); } - static bool IsNull(const element_t &e) + static bool IsNull(const element_t& e) { LIMITED_METHOD_CONTRACT; return (e.th.AsTAddr() == NULL); @@ -2125,23 +2125,23 @@ typedef SHash LoggedTypesFromModuleHash; class ETW::LoggedTypesFromModule { public: - Module * pModule; + Module* pModule; LoggedTypesFromModuleHash loggedTypesFromModuleHash; // These are used by the outer hash table (mapping Module*'s to instances of // LoggedTypesFromModule). - static COUNT_T Hash(Module * pModule) + static COUNT_T Hash(Module* pModule) { LIMITED_METHOD_CONTRACT; - return (COUNT_T) (SIZE_T) pModule; + return (COUNT_T)(SIZE_T)pModule; } - Module * GetKey() + Module* GetKey() { LIMITED_METHOD_CONTRACT; return pModule; } - LoggedTypesFromModule(Module * pModuleParam) : loggedTypesFromModuleHash() + LoggedTypesFromModule(Module* pModuleParam) : loggedTypesFromModuleHash() { LIMITED_METHOD_CONTRACT; pModule = pModuleParam; @@ -2156,19 +2156,19 @@ class ETW::LoggedTypesFromModule // The following define the outer hash table (mapping Module*'s to instances of // LoggedTypesFromModule). -class AllLoggedTypesTraits : public DefaultSHashTraits +class AllLoggedTypesTraits : public DefaultSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused - typedef DefaultSHashTraits PARENT; + typedef DefaultSHashTraits PARENT; typedef PARENT::element_t element_t; typedef PARENT::count_t count_t; - typedef Module * key_t; + typedef Module* key_t; - static key_t GetKey(const element_t &e) + static key_t GetKey(const element_t& e) { LIMITED_METHOD_CONTRACT; return e->pModule; @@ -2183,10 +2183,10 @@ class AllLoggedTypesTraits : public DefaultSHashTraitsloggedTypesFromModuleHash.AddOrReplace(*pTypeLoggingInfo); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2447,7 +2447,7 @@ BOOL ETW::TypeSystemLog::AddOrReplaceTypeLoggingInfo(ETW::LoggedTypesFromModule // // static -void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) +void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object* pObject) { CONTRACTL { @@ -2465,7 +2465,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) TypeHandle th = pObject->GetTypeHandle(); SIZE_T size = pObject->GetSize(); - if(size < MIN_OBJECT_SIZE) + if (size < MIN_OBJECT_SIZE) { size = PtrAlign(size); } @@ -2481,7 +2481,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Get stats for type TypeLoggingInfo typeLoggingInfo(NULL); - LoggedTypesFromModule * pLoggedTypesFromModule = NULL; + LoggedTypesFromModule* pLoggedTypesFromModule = NULL; BOOL fCreatedNew = FALSE; typeLoggingInfo = LookupOrCreateTypeLoggingInfo(th, &fCreatedNew, &pLoggedTypesFromModule); if (typeLoggingInfo.th.IsNull()) @@ -2524,19 +2524,19 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) int nMinAllocPerMSec = typeLoggingInfo.dwAllocCountInCurrentBucket / 16; // This is an underestimation of the true rate. if (delta >= 16 || (nMinAllocPerMSec > 2 && nMinAllocPerMSec > typeLoggingInfo.flAllocPerMSec * 1.5F)) { - float flNewAllocPerMSec = 0; + float flNewAllocPerMSec = 0; if (delta >= 16) { // This is the normal case, our allocation rate is under control with the current throttling. - flNewAllocPerMSec = ((float) typeLoggingInfo.dwAllocCountInCurrentBucket) / delta; + flNewAllocPerMSec = ((float)typeLoggingInfo.dwAllocCountInCurrentBucket) / delta; // Do a exponential decay window that is 5 * max(16, AllocationInterval) - typeLoggingInfo.flAllocPerMSec = 0.8F * typeLoggingInfo.flAllocPerMSec + 0.2F * flNewAllocPerMSec; + typeLoggingInfo.flAllocPerMSec = 0.8F * typeLoggingInfo.flAllocPerMSec + 0.2F * flNewAllocPerMSec; typeLoggingInfo.dwTickOfCurrentTimeBucket = dwTickNow; typeLoggingInfo.dwAllocCountInCurrentBucket = 0; } else { - flNewAllocPerMSec = (float) nMinAllocPerMSec; + flNewAllocPerMSec = (float)nMinAllocPerMSec; // This means the second clause above is true, which means our sampling rate is too low // so we need to throttle quickly. typeLoggingInfo.flAllocPerMSec = flNewAllocPerMSec; @@ -2546,7 +2546,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Obey the desired sampling rate, but don't ignore > 1000 allocations per second // per type int nDesiredMsBetweenEvents = (s_nCustomMsBetweenEvents == 0) ? GetDefaultMsBetweenEvents() : s_nCustomMsBetweenEvents; - typeLoggingInfo.dwAllocsToSkipPerSample = min((int) (typeLoggingInfo.flAllocPerMSec * nDesiredMsBetweenEvents), 1000); + typeLoggingInfo.dwAllocsToSkipPerSample = min((int)(typeLoggingInfo.flAllocPerMSec * nDesiredMsBetweenEvents), 1000); if (typeLoggingInfo.dwAllocsToSkipPerSample == 1) typeLoggingInfo.dwAllocsToSkipPerSample = 0; } @@ -2586,11 +2586,11 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // Now log the allocation if (s_fHeapAllocHighEventEnabledNow) { - FireEtwGCSampledObjectAllocationHigh(pObject, (LPVOID) th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); + FireEtwGCSampledObjectAllocationHigh(pObject, (LPVOID)th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); } else { - FireEtwGCSampledObjectAllocationLow(pObject, (LPVOID) th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); + FireEtwGCSampledObjectAllocationLow(pObject, (LPVOID)th.AsTAddr(), dwObjectCountForTypeSample, nTotalSizeForTypeSample, GetClrInstanceId()); } } @@ -2603,7 +2603,7 @@ void ETW::TypeSystemLog::SendObjectAllocatedEvent(Object * pObject) // // static -CrstBase * ETW::TypeSystemLog::GetHashCrst() +CrstBase* ETW::TypeSystemLog::GetHashCrst() { LIMITED_METHOD_CONTRACT; return &AllLoggedTypes::s_cs; @@ -2629,7 +2629,7 @@ CrstBase * ETW::TypeSystemLog::GetHashCrst() // // static -void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * pLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior) +void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger* pLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior) { CONTRACTL { @@ -2650,7 +2650,7 @@ void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * p return; } - TypeHandle th = TypeHandle::FromTAddr((TADDR) thAsAddr); + TypeHandle th = TypeHandle::FromTAddr((TADDR)thAsAddr); if (!th.IsRestored()) { return; @@ -2661,11 +2661,11 @@ void ETW::TypeSystemLog::LogTypeAndParametersIfNecessary(BulkTypeEventLogger * p // through to the logging code below. If caller doesn't care, then don't even // check; just log the type BOOL fShouldLogType = ((typeLogBehavior == kTypeLogBehaviorAlwaysLog) || - (typeLogBehavior == kTypeLogBehaviorAssumeLockAndAlwaysLogTopLevelType)) ? - TRUE : - ((typeLogBehavior == kTypeLogBehaviorTakeLockAndLogIfFirstTime) ? - ShouldLogType(th) : - ShouldLogTypeNoLock(th)); + (typeLogBehavior == kTypeLogBehaviorAssumeLockAndAlwaysLogTopLevelType)) ? + TRUE : + ((typeLogBehavior == kTypeLogBehaviorTakeLockAndLogIfFirstTime) ? + ShouldLogType(th) : + ShouldLogTypeNoLock(th)); if (!fShouldLogType) return; @@ -2767,7 +2767,7 @@ BOOL ETW::TypeSystemLog::ShouldLogTypeNoLock(TypeHandle th) // // static -ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL * pfCreatedNew, LoggedTypesFromModule ** ppLoggedTypesFromModule /* = NULL */) +ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL* pfCreatedNew, LoggedTypesFromModule** ppLoggedTypesFromModule /* = NULL */) { LIMITED_METHOD_CONTRACT; @@ -2794,9 +2794,9 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl // Step 1: go from LoaderModule to hash of types. - Module * pLoaderModule = th.GetLoaderModule(); + Module* pLoaderModule = th.GetLoaderModule(); _ASSERTE(pLoaderModule != NULL); - LoggedTypesFromModule * pLoggedTypesFromModule = s_pAllLoggedTypes->allLoggedTypesHash.Lookup(pLoaderModule); + LoggedTypesFromModule* pLoggedTypesFromModule = s_pAllLoggedTypes->allLoggedTypesHash.Lookup(pLoaderModule); if (pLoggedTypesFromModule == NULL) { pLoggedTypesFromModule = new (nothrow) LoggedTypesFromModule(pLoaderModule); @@ -2813,7 +2813,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl s_pAllLoggedTypes->allLoggedTypesHash.Add(pLoggedTypesFromModule); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2850,7 +2850,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl pLoggedTypesFromModule->loggedTypesFromModuleHash.Add(typeLoggingInfoNew); fSucceeded = TRUE; } - EX_CATCH + EX_CATCH { fSucceeded = FALSE; } @@ -2876,7 +2876,7 @@ ETW::TypeLoggingInfo ETW::TypeSystemLog::LookupOrCreateTypeLoggingInfo(TypeHandl // // static -void ETW::TypeSystemLog::OnModuleUnload(Module * pModule) +void ETW::TypeSystemLog::OnModuleUnload(Module* pModule) { CONTRACTL { @@ -2895,7 +2895,7 @@ void ETW::TypeSystemLog::OnModuleUnload(Module * pModule) return; } - LoggedTypesFromModule * pLoggedTypesFromModule = NULL; + LoggedTypesFromModule* pLoggedTypesFromModule = NULL; { CrstHolder _crst(GetHashCrst()); @@ -2943,12 +2943,12 @@ void ETW::TypeSystemLog::OnTypesKeywordTurnedOff() return; // Destruct each of the per-module TypesHashes - AllLoggedTypesHash * pLoggedTypesHash = &s_pAllLoggedTypes->allLoggedTypesHash; + AllLoggedTypesHash* pLoggedTypesHash = &s_pAllLoggedTypes->allLoggedTypesHash; for (AllLoggedTypesHash::Iterator iter = pLoggedTypesHash->Begin(); - iter != pLoggedTypesHash->End(); - ++iter) + iter != pLoggedTypesHash->End(); + ++iter) { - LoggedTypesFromModule * pLoggedTypesFromModule = *iter; + LoggedTypesFromModule* pLoggedTypesFromModule = *iter; delete pLoggedTypesFromModule; } @@ -2962,10 +2962,10 @@ void ETW::TypeSystemLog::OnTypesKeywordTurnedOff() /****************************************************************************/ /* Called when ETW is turned ON on an existing process and ModuleRange events are to be fired */ -/****************************************************************************/ + /****************************************************************************/ void ETW::EnumerationLog::ModuleRangeRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -2978,7 +2978,7 @@ void ETW::EnumerationLog::ModuleRangeRundown() { ETW::EnumerationLog::EnumerationHelper(NULL, NULL, ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -2986,7 +2986,7 @@ void ETW::EnumerationLog::ModuleRangeRundown() /****************************************************************************/ void ETW::EnumerationLog::StartRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -3004,7 +3004,7 @@ void ETW::EnumerationLog::StartRundown() TRACE_LEVEL_INFORMATION, CLR_RUNDOWNTHREADING_KEYWORD); - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD) || @@ -3028,30 +3028,30 @@ void ETW::EnumerationLog::StartRundown() FireEtwDCStartInit_V1(GetClrInstanceId()); // The rundown flag is expected to be checked in the caller, so no need to check here again - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNLOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart; } - if(IsRundownNgenKeywordEnabledAndNotSuppressed()) + if (IsRundownNgenKeywordEnabledAndNotSuppressed()) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJITTEDMETHODILTONATIVEMAP_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::MethodDCStartILToNativeMap; } - if(bIsPerfTrackRundownEnabled) + if (bIsPerfTrackRundownEnabled) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart; } @@ -3076,7 +3076,7 @@ void ETW::EnumerationLog::StartRundown() // end marker event will go to the rundown provider FireEtwDCStartComplete_V1(GetClrInstanceId()); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } //--------------------------------------------------------------------------------------- @@ -3094,26 +3094,26 @@ DWORD ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords() { LIMITED_METHOD_CONTRACT; - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_LOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD) && ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_ENDENUMERATION_KEYWORD)) + TRACE_LEVEL_INFORMATION, + CLR_ENDENUMERATION_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodUnload; } - if(IsRuntimeNgenKeywordEnabledAndNotSuppressed() && + if (IsRuntimeNgenKeywordEnabledAndNotSuppressed() && ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_ENDENUMERATION_KEYWORD)) + TRACE_LEVEL_INFORMATION, + CLR_ENDENUMERATION_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload; } @@ -3149,7 +3149,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); @@ -3165,7 +3165,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() SendThreadRundownEvent(); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**************************************************************************************/ @@ -3173,7 +3173,7 @@ void ETW::EnumerationLog::EnumerateForCaptureState() /**************************************************************************************/ void ETW::EnumerationLog::EndRundown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -3187,7 +3187,7 @@ void ETW::EnumerationLog::EndRundown() MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNTHREADING_KEYWORD); - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD) || @@ -3210,30 +3210,30 @@ void ETW::EnumerationLog::EndRundown() FireEtwDCEndInit_V1(GetClrInstanceId()); // The rundown flag is expected to be checked in the caller, so no need to check here again - DWORD enumerationOptions=ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNLOADER_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJIT_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd; } - if(IsRundownNgenKeywordEnabledAndNotSuppressed()) + if (IsRundownNgenKeywordEnabledAndNotSuppressed()) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd; } - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_RUNDOWNJITTEDMETHODILTONATIVEMAP_KEYWORD)) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap; } - if(bIsPerfTrackRundownEnabled) + if (bIsPerfTrackRundownEnabled) { enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd; } @@ -3248,7 +3248,7 @@ void ETW::EnumerationLog::EndRundown() // end marker event will go to the rundown provider FireEtwDCEndComplete_V1(GetClrInstanceId()); } - } EX_CATCH { + } EX_CATCH{ STRESS_LOG1(LF_ALWAYS, LL_ERROR, "Exception during Rundown Enumeration, EIP of last AV = %p", g_LastAccessViolationEIP); } EX_END_CATCH(SwallowAllExceptions); } @@ -3290,9 +3290,9 @@ void InitializeEventTracing() // Register CLR providers with the OS if (g_pEtwTracer == NULL) { - NewHolder tempEtwTracer (new (nothrow) ETW::CEtwTracer()); - if (tempEtwTracer != NULL && tempEtwTracer->Register () == ERROR_SUCCESS) - g_pEtwTracer = tempEtwTracer.Extract (); + NewHolder tempEtwTracer(new (nothrow) ETW::CEtwTracer()); + if (tempEtwTracer != NULL && tempEtwTracer->Register() == ERROR_SUCCESS) + g_pEtwTracer = tempEtwTracer.Extract(); } g_nClrInstanceId = GetRuntimeId() & 0x0000FFFF; // This will give us duplicate ClrInstanceId after UINT16_MAX @@ -3375,37 +3375,44 @@ HRESULT ETW::CEtwTracer::UnRegister() extern "C" { ETW_INLINE - void EtwCallout(REGHANDLE RegHandle, - PCEVENT_DESCRIPTOR Descriptor, - ULONG ArgumentCount, - PEVENT_DATA_DESCRIPTOR EventData) + void EtwCallout(REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR Descriptor, + ULONG ArgumentCount, + PEVENT_DATA_DESCRIPTOR EventData) { WRAPPER_NO_CONTRACT; UINT8 providerIndex = 0; - if(RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { + if (RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { providerIndex = 0; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { providerIndex = 1; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { providerIndex = 2; - } else if(RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { providerIndex = 3; - } else { + } + else { _ASSERTE(!"Provider not one of Runtime, Rundown, Private and Stress"); return; } // stacks are supposed to be fired for only the events with a bit set in the etwStackSupportedEvents bitmap - if(((etwStackSupportedEvents[providerIndex][Descriptor->Id/8]) & - (1<<(Descriptor->Id%8))) != 0) + if (((etwStackSupportedEvents[providerIndex][Descriptor->Id / 8]) & + (1 << (Descriptor->Id % 8))) != 0) { - if(RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { + if (RegHandle == Microsoft_Windows_DotNETRuntimeHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, &CLRStackWalk, &CLRStackId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeRundownHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, &CLRStackWalkDCStart, &CLRStackRundownId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimePrivateHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, &CLRStackWalkPrivate, &CLRStackPrivateId); - } else if(RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { + } + else if (RegHandle == Microsoft_Windows_DotNETRuntimeStressHandle) { ETW::SamplingLog::SendStackTrace(MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_Context, &CLRStackWalkStress, &CLRStackStressId); } } @@ -3430,22 +3437,23 @@ extern "C" // action in this class, we pass "this" during provider registration and modify the // context to the relevant context in the C callback later. ETW_INLINE - void EtwCallback( - _In_ LPCGUID SourceId, - _In_ ULONG ControlCode, - _In_ UCHAR Level, - _In_ ULONGLONG MatchAnyKeyword, - _In_ ULONGLONG MatchAllKeyword, - _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, - _Inout_opt_ PVOID CallbackContext) - { - CONTRACTL { + void EtwCallback( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext) + { + CONTRACTL{ NOTHROW; - if(g_fEEStarted) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}; - MODE_ANY; - CAN_TAKE_LOCK; - STATIC_CONTRACT_FAULT; - SO_NOT_MAINLINE; + if (g_fEEStarted) { GC_TRIGGERS; } + else { DISABLED(GC_NOTRIGGER); }; +MODE_ANY; +CAN_TAKE_LOCK; +STATIC_CONTRACT_FAULT; +SO_NOT_MAINLINE; } CONTRACTL_END; // Mark that we are the special ETWRundown thread. Currently all this does @@ -3459,21 +3467,21 @@ extern "C" BOOLEAN bIsPublicTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimeHandle); BOOLEAN bIsPrivateTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimePrivateHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimePrivateHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimePrivateHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimePrivateHandle); BOOLEAN bIsRundownTraceHandle = #ifdef WINXP_AND_WIN2K3_BUILD_SUPPORT - McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeRundownHandle==(ULONGLONG)context) : + McGenPreVista ? ((ULONGLONG)Microsoft_Windows_DotNETRuntimeRundownHandle == (ULONGLONG)context) : #endif - (context->RegistrationHandle==Microsoft_Windows_DotNETRuntimeRundownHandle); + (context->RegistrationHandle == Microsoft_Windows_DotNETRuntimeRundownHandle); // A manifest based provider can be enabled to multiple event tracing sessions @@ -3482,8 +3490,8 @@ extern "C" // IsEnabled will be TRUE when it is enabled and FALSE when disabled BOOL bEnabled = ((ControlCode == EVENT_CONTROL_CODE_ENABLE_PROVIDER) || - (ControlCode == EVENT_CONTROL_CODE_CAPTURE_STATE)); - if(bEnabled) + (ControlCode == EVENT_CONTROL_CODE_CAPTURE_STATE)); + if (bEnabled) { // TypeSystemLog needs a notification when certain keywords are modified, so // give it a hook here. @@ -3495,7 +3503,7 @@ extern "C" if (bIsPrivateTraceHandle) { ETW::GCLog::GCSettingsEvent(); - if(g_fEEStarted && !g_fEEShutDown) + if (g_fEEStarted && !g_fEEShutDown) { ETW::EnumerationLog::ModuleRangeRundown(); } @@ -3505,10 +3513,10 @@ extern "C" // If we have turned on the JIT keyword to the VERBOSE setting (needed to get JIT names) then // we assume that we also want good stack traces so we need to publish unwind information so // ETW can get at it - if(bIsPublicTraceHandle && ETW_CATEGORY_ENABLED((*context), TRACE_LEVEL_VERBOSE, CLR_RUNDOWNJIT_KEYWORD)) + if (bIsPublicTraceHandle && ETW_CATEGORY_ENABLED((*context), TRACE_LEVEL_VERBOSE, CLR_RUNDOWNJIT_KEYWORD)) UnwindInfoTable::PublishUnwindInfo(g_fEEStarted != FALSE); #endif - if(g_fEEStarted && !g_fEEShutDown && bIsRundownTraceHandle) + if (g_fEEStarted && !g_fEEShutDown && bIsRundownTraceHandle) { // Fire the runtime information event ETW::InfoLog::RuntimeInformation(ETW::InfoLog::InfoStructs::Callback); @@ -3516,15 +3524,15 @@ extern "C" // Start and End Method/Module Rundowns // Used to fire events that we missed since we started the controller after the process started // flags for immediate start rundown - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNSTART_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNSTART_KEYWORD)) ETW::EnumerationLog::StartRundown(); // flags delayed end rundown - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_RUNDOWNEND_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_RUNDOWNEND_KEYWORD)) ETW::EnumerationLog::EndRundown(); } @@ -3545,7 +3553,7 @@ extern "C" (FilterData->Type == 1) && (FilterData->Size == sizeof(l64ClientSequenceNumber))) { - l64ClientSequenceNumber = *(LONGLONG *) (FilterData->Ptr); + l64ClientSequenceNumber = *(LONGLONG*)(FilterData->Ptr); } ETW::GCLog::ForceGC(l64ClientSequenceNumber); } @@ -3566,7 +3574,7 @@ extern "C" /* in its printf API, we cast the unicode string to UFT8 string and then output them. */ /**************************************************************************************/ #define DTRACE_OUTPUT_STRING_LEN 512 -const CHAR szDtraceOutputNULL[]="NULL"; +const CHAR szDtraceOutputNULL[] = "NULL"; INT32 WideCharToMultiByte(LPCWSTR wszSrcStr, LPSTR szDstStr); #include @@ -3586,7 +3594,7 @@ ULONG ETW::CEtwTracer::Register() // Get Env Var COMPlus_ETWEnabled char szETWEnabled[SIZE_ETWEnabled]; DWORD newLen = GetEnvironmentVariableA("COMPlus_ETWEnabled", szETWEnabled, SIZE_ETWEnabled); - if (newLen == 0 || newLen >= SIZE_ETWEnabled || strcmp(szETWEnabled, "1") != 0) + if (newLen == 0 || newLen >= SIZE_ETWEnabled || strcmp(szETWEnabled, "1") != 0) return 0; // Get Env Var COMPlus_EventInfo @@ -3621,12 +3629,12 @@ INT32 WideCharToMultiByte(LPCWSTR wszSrcStr, LPSTR szDstStr) { return 0; } - if (nSize > DTRACE_OUTPUT_STRING_LEN-1) + if (nSize > DTRACE_OUTPUT_STRING_LEN - 1) { - nSize = DTRACE_OUTPUT_STRING_LEN-1; + nSize = DTRACE_OUTPUT_STRING_LEN - 1; } - INT32 nSize2 = WideCharToMultiByte(CP_UTF8, 0, wszSrcStr, -1, szDstStr, nSize, NULL, NULL); - if(nSize2 != nSize || nSize2 <=0 ) + INT32 nSize2 = WideCharToMultiByte(CP_UTF8, 0, wszSrcStr, -1, szDstStr, nSize, NULL, NULL); + if (nSize2 != nSize || nSize2 <= 0) { return 0; } @@ -3801,20 +3809,20 @@ void SecurityCatchCallEnd_V1() /****************************************************************************/ /* This is called by the runtime when an exception is thrown */ /****************************************************************************/ -void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) +void ETW::ExceptionLog::ExceptionThrown(CrawlFrame* pCf, BOOL bIsReThrownException, BOOL bIsNewException) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(GetThread() != NULL); PRECONDITION(GetThread()->GetThrowable() != NULL); } CONTRACTL_END; - if(!(bIsReThrownException || bIsNewException)) + if (!(bIsReThrownException || bIsNewException)) { return; } - if(!ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ExceptionThrown_V1)) + if (!ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, ExceptionThrown_V1)) { return; } @@ -3822,11 +3830,11 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept { SString exceptionType(L""); LPWSTR exceptionMessage = NULL; - BOOL bIsCLSCompliant=FALSE, bIsCSE=FALSE, bIsNestedException=FALSE, bHasInnerException=FALSE; - UINT16 exceptionFlags=0; - PVOID exceptionEIP=0; + BOOL bIsCLSCompliant = FALSE, bIsCSE = FALSE, bIsNestedException = FALSE, bHasInnerException = FALSE; + UINT16 exceptionFlags = 0; + PVOID exceptionEIP = 0; - Thread *pThread = GetThread(); + Thread* pThread = GetThread(); struct { @@ -3840,7 +3848,7 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept gc.exceptionObj = pThread->GetThrowable(); gc.innerExceptionObj = ((EXCEPTIONREF)gc.exceptionObj)->GetInnerException(); - ThreadExceptionState *pExState = pThread->GetExceptionState(); + ThreadExceptionState* pExState = pThread->GetExceptionState(); #ifndef WIN64EXCEPTIONS PTR_ExInfo pExInfo = NULL; #else @@ -3855,7 +3863,7 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept // A rethrown exception is also a nested exception // but since we have a separate flag for it, lets unset the nested flag - if(bIsReThrownException) + if (bIsReThrownException) { bIsNestedException = FALSE; } @@ -3887,12 +3895,12 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept exceptionEIP = (PVOID)((UINT_PTR)exceptionEIP - 1); } - gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); + gc.exceptionMessageRef = ((EXCEPTIONREF)gc.exceptionObj)->GetMessage(); TypeHandle exceptionTypeHandle = (gc.exceptionObj)->GetTypeHandle(); exceptionTypeHandle.GetName(exceptionType); - WCHAR *exceptionTypeName = (WCHAR *)exceptionType.GetUnicode(); + WCHAR* exceptionTypeName = (WCHAR*)exceptionType.GetUnicode(); - if(gc.exceptionMessageRef != NULL) + if (gc.exceptionMessageRef != NULL) { exceptionMessage = (gc.exceptionMessageRef)->GetBuffer(); } @@ -3906,53 +3914,53 @@ void ETW::ExceptionLog::ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownExcept exceptionFlags, GetClrInstanceId()); GCPROTECT_END(); - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when a domain is loaded */ /****************************************************************************/ -void ETW::LoaderLog::DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName) +void ETW::LoaderLog::DomainLoadReal(BaseDomain* pDomain, _In_opt_ LPWSTR wszFriendlyName) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_LOADER_KEYWORD)) { DWORD dwEventOptions = ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad; ETW::LoaderLog::SendDomainEvent(pDomain, dwEventOptions, wszFriendlyName); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when an AppDomain is unloaded */ /****************************************************************************/ -void ETW::LoaderLog::DomainUnload(AppDomain *pDomain) +void ETW::LoaderLog::DomainUnload(AppDomain* pDomain) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { - if(!pDomain->NoAccessToHandleTable()) + if (!pDomain->NoAccessToHandleTable()) { DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords(); // Domain unload also causes type unload events - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_TYPE_KEYWORD)) { @@ -3962,29 +3970,29 @@ void ETW::LoaderLog::DomainUnload(AppDomain *pDomain) ETW::EnumerationLog::EnumerationHelper(NULL, pDomain, enumerationOptions); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when a LoaderAllocator is unloaded */ /****************************************************************************/ -void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) +void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator* pLoaderAllocator) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = ETW::EnumerationLog::GetEnumerationOptionsFromRuntimeKeywords(); // Collectible Loader Allocator unload also causes type unload events - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_TYPE_KEYWORD)) { @@ -3993,23 +4001,23 @@ void ETW::LoaderLog::CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *p ETW::EnumerationLog::IterateCollectibleLoaderAllocator(pLoaderAllocator, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ /* This is called by the runtime when the runtime is loaded Function gets called by both the Callback mechanism and regular ETW events. Type is used to differentiate whether its a callback or a normal call*/ -/****************************************************************************/ + /****************************************************************************/ void ETW::InfoLog::RuntimeInformation(INT32 type) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; - EX_TRY { - if((type == ETW::InfoLog::InfoStructs::Normal && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, RuntimeInformationStart)) + EX_TRY{ + if ((type == ETW::InfoLog::InfoStructs::Normal && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, RuntimeInformationStart)) #ifndef FEATURE_PAL || (type == ETW::InfoLog::InfoStructs::Callback && ETW_EVENT_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, RuntimeInformationDCStart)) @@ -4017,21 +4025,21 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) ) { #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L""; + PCWSTR szDtraceOutput1 = L"",szDtraceOutput2 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE UINT8 startupMode = 0; UINT startupFlags = 0; - WCHAR dllPath[MAX_PATH+1] = {0}; + WCHAR dllPath[MAX_PATH + 1] = {0}; UINT8 Sku = 0; _ASSERTE(g_fEEManagedEXEStartup || //CLR started due to a managed exe g_fEEIJWStartup || //CLR started as a mixed mode Assembly CLRHosted() || g_fEEHostedStartup || //CLR started through one of the Hosting API CLRHosted() returns true if CLR started through the V2 Interface while // g_fEEHostedStartup is true if CLR is hosted through the V1 API. g_fEEComActivatedStartup || //CLR started as a COM object - g_fEEOtherStartup ); //In case none of the 4 above mentioned cases are true for example ngen, ildasm then we asssume its a "other" startup + g_fEEOtherStartup); //In case none of the 4 above mentioned cases are true for example ngen, ildasm then we asssume its a "other" startup #ifdef FEATURE_CORECLR Sku = ETW::InfoLog::InfoStructs::CoreCLR; @@ -4052,9 +4060,9 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) USHORT bclQfeVersion = VER_ASSEMBLYBUILD_QFE; #ifndef FEATURE_PAL - LPCGUID comGUID=g_fEEComObjectGuid; + LPCGUID comGUID = g_fEEComObjectGuid; #else - unsigned int comGUID=0; + unsigned int comGUID = 0; #endif //!FEATURE_PAL #ifndef FEATURE_DTRACE @@ -4070,12 +4078,12 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) #endif //!FEATURE_CORECLR // Determine the startupmode - if(g_fEEIJWStartup) + if (g_fEEIJWStartup) { //IJW Mode startupMode = ETW::InfoLog::InfoStructs::IJW; } - else if(g_fEEManagedEXEStartup) + else if (g_fEEManagedEXEStartup) { //managed exe startupMode = ETW::InfoLog::InfoStructs::ManagedExe; @@ -4083,7 +4091,7 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) lpwszCommandLine = WszGetCommandLine(); #else INT32 nSize = WideCharToMultiByte(WszGetCommandLine(), szDtraceOutput1); - if(nSize > 0) { + if (nSize > 0) { lpwszCommandLine = (SIZE_T)szDtraceOutput1; } #endif //!FEATURE_DTRACE @@ -4093,34 +4101,34 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) //Hosted CLR startupMode = ETW::InfoLog::InfoStructs::HostedCLR; } - else if(g_fEEComActivatedStartup) + else if (g_fEEComActivatedStartup) { //com activated startupMode = ETW::InfoLog::InfoStructs::COMActivated; } - else if(g_fEEOtherStartup) + else if (g_fEEOtherStartup) { //startup type is other startupMode = ETW::InfoLog::InfoStructs::Other; } - _ASSERTE (NumItems(dllPath) > MAX_PATH); + _ASSERTE(NumItems(dllPath) > MAX_PATH); // if WszGetModuleFileName fails, we return an empty string if (!WszGetModuleFileName(GetCLRModule(), dllPath, MAX_PATH)) { dllPath[0] = 0; } dllPath[MAX_PATH] = 0; #ifdef FEATURE_DTRACE - _ASSERTE (NumItems(szDtraceOutput2) >= NumItems(dllPath)); + _ASSERTE(NumItems(szDtraceOutput2) >= NumItems(dllPath)); INT32 nSize = WideCharToMultiByte(dllPath, szDtraceOutput2); - if(nSize > 0) { + if (nSize > 0) { lpwszRuntimeDllPath = (SIZE_T)szDtraceOutput2; } #endif // FEATURE_DTRACE - if(type == ETW::InfoLog::InfoStructs::Callback) + if (type == ETW::InfoLog::InfoStructs::Callback) { - FireEtwRuntimeInformationDCStart( GetClrInstanceId(), + FireEtwRuntimeInformationDCStart(GetClrInstanceId(), Sku, bclMajorVersion, bclMinorVersion, @@ -4134,11 +4142,11 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) startupMode, lpwszCommandLine, comGUID, - lpwszRuntimeDllPath ); + lpwszRuntimeDllPath); } else { - FireEtwRuntimeInformationStart( GetClrInstanceId(), + FireEtwRuntimeInformationStart(GetClrInstanceId(), Sku, bclMajorVersion, bclMinorVersion, @@ -4152,32 +4160,32 @@ void ETW::InfoLog::RuntimeInformation(INT32 type) startupMode, lpwszCommandLine, comGUID, - lpwszRuntimeDllPath ); + lpwszRuntimeDllPath); } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /*******************************************************/ /* This is called by the runtime when a method is jitted completely */ /*******************************************************/ -void ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +void ETW::MethodLog::MethodJitted(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature, SIZE_T pCode, ReJITID rejitID) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD)) { ETW::MethodLog::SendMethodEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodLoad, TRUE, namespaceOrClassName, methodName, methodSignature, pCode, rejitID); } #ifndef WINXP_AND_WIN2K3_BUILD_SUPPORT - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JITTEDMETHODILTONATIVEMAP_KEYWORD)) { @@ -4192,15 +4200,15 @@ void ETW::MethodLog::MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrC ETW::MethodLog::SendMethodILToNativeMapEvent(pMethodDesc, ETW::EnumerationLog::EnumerationStructs::JitMethodILToNativeMap, rejitID); } #endif // WINXP_AND_WIN2K3_BUILD_SUPPORT - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /*************************************************/ /* This is called by the runtime when method jitting started */ /*************************************************/ -void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +void ETW::MethodLog::MethodJitting(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(pMethodDesc != NULL); @@ -4208,14 +4216,14 @@ void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_VERBOSE, CLR_JIT_KEYWORD)) { pMethodDesc->GetMethodInfo(*namespaceOrClassName, *methodName, *methodSignature); ETW::MethodLog::SendMethodJitStartEvent(pMethodDesc, namespaceOrClassName, methodName, methodSignature); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**********************************************************************/ @@ -4223,7 +4231,7 @@ void ETW::MethodLog::MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOr /**********************************************************************/ void ETW::MethodLog::StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; PRECONDITION(ullHelperStartAddress != 0); @@ -4231,31 +4239,31 @@ void ETW::MethodLog::StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pH EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_JIT_KEYWORD)) { - DWORD dwHelperSize=0; + DWORD dwHelperSize = 0; Stub::RecoverStubAndSize((TADDR)ullHelperStartAddress, &dwHelperSize); ETW::MethodLog::SendHelperEvent(ullHelperStartAddress, dwHelperSize, pHelperName); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /**********************************************************/ /* This is called by the runtime when helpers with stubs are initialized */ /**********************************************************/ -void ETW::MethodLog::StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG lNoOfHelpers) +void ETW::MethodLog::StubsInitialized(PVOID* pHelperStartAddresss, PVOID* pHelperNames, LONG lNoOfHelpers) { WRAPPER_NO_CONTRACT; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_JIT_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_JIT_KEYWORD)) { - for(int i=0; iIsThunking()) + if (!pMethodTable->IsThunking()) #endif { MethodTable::MethodIterator iter(pMethodTable); for (; iter.IsValid(); iter.Next()) { - MethodDesc *pMD = (MethodDesc *)(iter.GetMethodDesc()); - if(pMD && pMD->IsRestored() && pMD->GetMethodTable_NoLogging() == pMethodTable) + MethodDesc* pMD = (MethodDesc*)(iter.GetMethodDesc()); + if (pMD && pMD->IsRestored() && pMD->GetMethodTable_NoLogging() == pMethodTable) ETW::MethodLog::SendMethodEvent(pMD, ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad, FALSE); } } } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } @@ -4362,7 +4370,7 @@ void ETW::SecurityLog::StrongNameVerificationStart(DWORD dwInFlags, _In_ LPWSTR /****************************************************************************/ /* This is called by the runtime when a Strong Name Verification Ends */ /****************************************************************************/ -void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_ LPWSTR strFullyQualifiedAssemblyName) +void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags, ULONG result, _In_ LPWSTR strFullyQualifiedAssemblyName) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_CORECLR @@ -4382,8 +4390,8 @@ void ETW::SecurityLog::StrongNameVerificationStop(DWORD dwInFlags,ULONG result, /* This is called by the runtime when field transparency calculations begin */ /****************************************************************************/ void ETW::SecurityLog::FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4404,10 +4412,10 @@ void ETW::SecurityLog::FireFieldTransparencyComputationStart(LPCWSTR wszFieldNam /* This is called by the runtime when field transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4428,8 +4436,8 @@ void ETW::SecurityLog::FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, /* This is called by the runtime when method transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4450,10 +4458,10 @@ void ETW::SecurityLog::FireMethodTransparencyComputationStart(LPCWSTR wszMethodN /* This is called by the runtime when method transparency calculations end */ /********************************************(********************************/ void ETW::SecurityLog::FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4474,7 +4482,7 @@ void ETW::SecurityLog::FireMethodTransparencyComputationEnd(LPCWSTR wszMethodNam /* This is called by the runtime when module transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, - DWORD dwAppDomain) + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4493,12 +4501,12 @@ void ETW::SecurityLog::FireModuleTransparencyComputationStart(LPCWSTR wszModuleN /* This is called by the runtime when module transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsAllCritical, - BOOL fIsAllTransparent, - BOOL fIsTreatAsSafe, - BOOL fIsOpportunisticallyCritical, - DWORD dwSecurityRuleSet) + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4517,8 +4525,8 @@ void ETW::SecurityLog::FireModuleTransparencyComputationEnd(LPCWSTR wszModuleNam /* This is called by the runtime when token transparency calculations begin */ /****************************************************************************/ void ETW::SecurityLog::FireTokenTransparencyComputationStart(DWORD dwToken, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4537,10 +4545,10 @@ void ETW::SecurityLog::FireTokenTransparencyComputationStart(DWORD dwToken, /* This is called by the runtime when token transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireTokenTransparencyComputationEnd(DWORD dwToken, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4559,8 +4567,8 @@ void ETW::SecurityLog::FireTokenTransparencyComputationEnd(DWORD dwToken, /* This is called by the runtime when type transparency calculations begin */ /*****************************************************************************/ void ETW::SecurityLog::FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, - LPCWSTR wszModuleName, - DWORD dwAppDomain) + LPCWSTR wszModuleName, + DWORD dwAppDomain) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4581,12 +4589,12 @@ void ETW::SecurityLog::FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, /* This is called by the runtime when type transparency calculations end */ /****************************************************************************/ void ETW::SecurityLog::FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, - LPCWSTR wszModuleName, - DWORD dwAppDomain, - BOOL fIsAllCritical, - BOOL fIsAllTransparent, - BOOL fIsCritical, - BOOL fIsTreatAsSafe) + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) { WRAPPER_NO_CONTRACT; #ifndef FEATURE_DTRACE @@ -4607,9 +4615,9 @@ void ETW::SecurityLog::FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, /* This is called by the runtime when a module is loaded */ /* liReportedSharedModule will be 0 when this module is reported for the 1st time */ /**********************************************************************************/ -void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) +void ETW::LoaderLog::ModuleLoad(Module* pModule, LONG liReportedSharedModule) { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; @@ -4617,7 +4625,7 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) EX_TRY { DWORD enumerationOptions = ETW::EnumerationLog::EnumerationStructs::None; - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { @@ -4632,27 +4640,27 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) TRACE_LEVEL_INFORMATION, CLR_PERFTRACK_KEYWORD); - if(liReportedSharedModule == 0) + if (liReportedSharedModule == 0) { - if(bTraceFlagLoaderSet) + if (bTraceFlagLoaderSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad; if (bTraceFlagPerfTrackSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad; - if(bTraceFlagNgenMethodSet && bTraceFlagStartRundownSet) + if (bTraceFlagNgenMethodSet && bTraceFlagStartRundownSet) enumerationOptions |= ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad; - if(pModule->IsManifest() && bTraceFlagLoaderSet) + if (pModule->IsManifest() && bTraceFlagLoaderSet) ETW::LoaderLog::SendAssemblyEvent(pModule->GetAssembly(), enumerationOptions); - if(bTraceFlagLoaderSet || bTraceFlagPerfTrackSet) + if (bTraceFlagLoaderSet || bTraceFlagPerfTrackSet) ETW::LoaderLog::SendModuleEvent(pModule, ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad | ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad); ETW::EnumerationLog::EnumerationHelper(pModule, NULL, enumerationOptions); } // we want to report domainmodule events whenever they are loaded in any AppDomain - if(bTraceFlagLoaderSet) + if (bTraceFlagLoaderSet) ETW::LoaderLog::SendModuleEvent(pModule, ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad, TRUE); } @@ -4668,7 +4676,7 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) } } #endif - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -4676,14 +4684,14 @@ void ETW::LoaderLog::ModuleLoad(Module *pModule, LONG liReportedSharedModule) /****************************************************************************/ void ETW::EnumerationLog::ProcessShutdown() { - CONTRACTL { + CONTRACTL{ NOTHROW; GC_TRIGGERS; } CONTRACTL_END; EX_TRY { - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_INFORMATION, KEYWORDZERO)) { DWORD enumerationOptions = GetEnumerationOptionsFromRuntimeKeywords(); @@ -4691,7 +4699,7 @@ void ETW::EnumerationLog::ProcessShutdown() // default domain. ETW::EnumerationLog::EnumerationHelper(NULL /* module filter */, NULL /* domain filter */, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /****************************************************************************/ @@ -4703,18 +4711,18 @@ void ETW::EnumerationLog::ProcessShutdown() /****************************************************************************/ /* This routine is used to send a domain load/unload or rundown event */ /****************************************************************************/ -void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName) +void ETW::LoaderLog::SendDomainEvent(BaseDomain* pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pBaseDomain) + if (!pBaseDomain) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE @@ -4722,22 +4730,22 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio BOOL bIsAppDomain = pBaseDomain->IsAppDomain(); BOOL bIsExecutable = bIsAppDomain ? !(pBaseDomain->AsAppDomain()->IsPassiveDomain()) : FALSE; BOOL bIsSharedDomain = pBaseDomain->IsSharedDomain(); - UINT32 uSharingPolicy = bIsAppDomain?(pBaseDomain->AsAppDomain()->GetSharePolicy()):0; + UINT32 uSharingPolicy = bIsAppDomain ? (pBaseDomain->AsAppDomain()->GetSharePolicy()) : 0; ULONGLONG ullDomainId = (ULONGLONG)pBaseDomain; ULONG ulDomainFlags = ((bIsDefaultDomain ? ETW::LoaderLog::LoaderStructs::DefaultDomain : 0) | - (bIsExecutable ? ETW::LoaderLog::LoaderStructs::ExecutableDomain : 0) | - (bIsSharedDomain ? ETW::LoaderLog::LoaderStructs::SharedDomain : 0) | - (uSharingPolicy<<28)); + (bIsExecutable ? ETW::LoaderLog::LoaderStructs::ExecutableDomain : 0) | + (bIsSharedDomain ? ETW::LoaderLog::LoaderStructs::SharedDomain : 0) | + (uSharingPolicy << 28)); LPCWSTR wsEmptyString = L""; LPCWSTR wsSharedString = L"SharedDomain"; LPWSTR lpswzDomainName = (LPWSTR)wsEmptyString; - if(bIsAppDomain) + if (bIsAppDomain) { - if(wszFriendlyName) + if (wszFriendlyName) lpswzDomainName = (PWCHAR)wszFriendlyName; else lpswzDomainName = (PWCHAR)pBaseDomain->AsAppDomain()->GetFriendlyName(); @@ -4755,28 +4763,28 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio return; #endif // !FEATURE_DTRACE - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwAppDomainLoad_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwAppDomainUnload_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwAppDomainDCStart_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwAppDomainDCEnd_V1(ullDomainId, ulDomainFlags, szDtraceOutput1, pBaseDomain->GetId().m_dwId, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } @@ -4785,13 +4793,13 @@ void ETW::LoaderLog::SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptio /********************************************************/ void ETW::EnumerationLog::SendThreadRundownEvent() { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; #ifndef DACCESS_COMPILE - Thread *pThread = NULL; + Thread* pThread = NULL; // Take the thread store lock while we enumerate threads. ThreadStoreLockHolder tsl; @@ -4811,24 +4819,24 @@ void ETW::EnumerationLog::SendThreadRundownEvent() /****************************************************************************/ /* This routine is used to send an assembly load/unload or rundown event ****/ /****************************************************************************/ -void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions) +void ETW::LoaderLog::SendAssemblyEvent(Assembly* pAssembly, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pAssembly) + if (!pAssembly) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE BOOL bIsDynamicAssembly = pAssembly->IsDynamic(); BOOL bIsCollectibleAssembly = pAssembly->IsCollectible(); - BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral() ; + BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); BOOL bHasNativeImage = pAssembly->GetManifestFile()->HasNativeImage(); ULONGLONG ullAssemblyId = (ULONGLONG)pAssembly; @@ -4838,15 +4846,15 @@ void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions ullBindingID = pAssembly->GetManifestFile()->GetBindingID(); #endif ULONG ulAssemblyFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralAssembly : 0) | - (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicAssembly : 0) | - (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeAssembly : 0) | - (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0)); + (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicAssembly : 0) | + (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeAssembly : 0) | + (bIsCollectibleAssembly ? ETW::LoaderLog::LoaderStructs::CollectibleAssembly : 0)); SString sAssemblyPath; pAssembly->GetDisplayName(sAssemblyPath); LPWSTR lpszAssemblyPath = (LPWSTR)sAssemblyPath.GetUnicode(); -/* prepare events args for ETW and ETM */ + /* prepare events args for ETW and ETM */ #ifndef FEATURE_DTRACE szDtraceOutput1 = (PCWSTR)lpszAssemblyPath; #else // !FEATURE_DTRACE @@ -4856,36 +4864,36 @@ void ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions return; #endif // !FEATURE_DTRACE - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwAssemblyLoad_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwAssemblyUnload_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwAssemblyDCStart_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwAssemblyDCEnd_V1(ullAssemblyId, ullDomainId, ullBindingID, ulAssemblyFlags, szDtraceOutput1, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } #if !defined(FEATURE_PAL) ETW_INLINE - ULONG - ETW::LoaderLog::SendModuleRange( - _In_ Module *pModule, +ULONG +ETW::LoaderLog::SendModuleRange( + _In_ Module* pModule, _In_ DWORD dwEventOptions) { @@ -4895,22 +4903,22 @@ ETW_INLINE // do not fire the ETW event when: // 1. We did not load the native image // 2. We do not have IBC data for the native image - if( !pModule || !pModule->HasNativeImage() || !pModule->IsIbcOptimized() ) + if (!pModule || !pModule->HasNativeImage() || !pModule->IsIbcOptimized()) { return Result; } // get information about the hot sections from the native image that has been loaded COUNT_T cbSizeOfSectionTable; - CORCOMPILE_VIRTUAL_SECTION_INFO* pVirtualSectionsTable = (CORCOMPILE_VIRTUAL_SECTION_INFO* )pModule->GetNativeImage()->GetVirtualSectionsTable(&cbSizeOfSectionTable); + CORCOMPILE_VIRTUAL_SECTION_INFO* pVirtualSectionsTable = (CORCOMPILE_VIRTUAL_SECTION_INFO*)pModule->GetNativeImage()->GetVirtualSectionsTable(&cbSizeOfSectionTable); - COUNT_T RangeCount = cbSizeOfSectionTable/sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); + COUNT_T RangeCount = cbSizeOfSectionTable / sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); // if we do not have any hot ranges, we do not fire the ETW event // Figure out the rest of the event data UINT16 ClrInstanceId = GetClrInstanceId(); - UINT64 ModuleID = (ULONGLONG)(TADDR) pModule; + UINT64 ModuleID = (ULONGLONG)(TADDR)pModule; for (COUNT_T i = 0; i < RangeCount; ++i) { @@ -4972,13 +4980,13 @@ ETW_INLINE // untrusted, and reported sizes of buffers are verified against their data. // -static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO_PDB70 * pCvInfoNative) +static void GetCodeViewInfo(Module* pModule, CV_INFO_PDB70* pCvInfoIL, CV_INFO_PDB70* pCvInfoNative) { LIMITED_METHOD_CONTRACT; - _ASSERTE (pModule != NULL); - _ASSERTE (pCvInfoIL != NULL); - _ASSERTE (pCvInfoNative != NULL); + _ASSERTE(pModule != NULL); + _ASSERTE(pCvInfoIL != NULL); + _ASSERTE(pCvInfoNative != NULL); ZeroMemory(pCvInfoIL, sizeof(*pCvInfoIL)); ZeroMemory(pCvInfoNative, sizeof(*pCvInfoNative)); @@ -5013,8 +5021,8 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO return; COUNT_T cbDebugEntries; - IMAGE_DEBUG_DIRECTORY * rgDebugEntries = - (IMAGE_DEBUG_DIRECTORY *) pLayout->GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &cbDebugEntries); + IMAGE_DEBUG_DIRECTORY* rgDebugEntries = + (IMAGE_DEBUG_DIRECTORY*)pLayout->GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &cbDebugEntries); if (cbDebugEntries < sizeof(IMAGE_DEBUG_DIRECTORY)) return; @@ -5028,15 +5036,15 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO // sizeof(CV_INFO_PDB70); see below). struct PdbInfo { - CV_INFO_PDB70 * m_pPdb70; + CV_INFO_PDB70* m_pPdb70; ULONG m_cbPdb70; }; // Iterate through all debug directory entries. The very last one will be the // managed PDB entry. The next to last one (if it exists) will be the (native) NGEN // PDB entry. Treat raw bytes we read as untrusted. - PdbInfo pdbInfoLast = {0}; - PdbInfo pdbInfoNextToLast = {0}; + PdbInfo pdbInfoLast = { 0 }; + PdbInfo pdbInfoNextToLast = { 0 }; int cEntries = cbDebugEntries / sizeof(IMAGE_DEBUG_DIRECTORY); for (int i = 0; i < cEntries; i++) { @@ -5068,7 +5076,7 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO } // Verify the magic number is as expected - CV_INFO_PDB70 * pPdb70 = (CV_INFO_PDB70 *) pLayout->GetRvaData(rvaOfRawData); + CV_INFO_PDB70* pPdb70 = (CV_INFO_PDB70*)pLayout->GetRvaData(rvaOfRawData); if (pPdb70->magic != CV_SIGNATURE_RSDS) { // Unrecognized magic number. Skip @@ -5143,18 +5151,18 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO // * bFireDomainModuleEvents - nonzero if we are to fire DomainModule events; zero // if we are to fire Module events // -void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents) +void ETW::LoaderLog::SendModuleEvent(Module* pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - if(!pModule) + if (!pModule) return; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; @@ -5166,35 +5174,35 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL #endif // FEATURE_PREJIT BOOL bIsManifestModule = pModule->IsManifest(); ULONGLONG ullAppDomainId = 0; // This is used only with DomainModule events - ULONGLONG ullModuleId = (ULONGLONG)(TADDR) pModule; + ULONGLONG ullModuleId = (ULONGLONG)(TADDR)pModule; ULONGLONG ullAssemblyId = (ULONGLONG)pModule->GetAssembly(); BOOL bIsDomainNeutral = pModule->GetAssembly()->IsDomainNeutral(); BOOL bIsIbcOptimized = FALSE; - if(bHasNativeImage) + if (bHasNativeImage) { bIsIbcOptimized = pModule->IsIbcOptimized(); } ULONG ulReservedFlags = 0; ULONG ulFlags = ((bIsDomainNeutral ? ETW::LoaderLog::LoaderStructs::DomainNeutralModule : 0) | - (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeModule : 0) | - (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicModule : 0) | - (bIsManifestModule ? ETW::LoaderLog::LoaderStructs::ManifestModule : 0) | - (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0)); + (bHasNativeImage ? ETW::LoaderLog::LoaderStructs::NativeModule : 0) | + (bIsDynamicAssembly ? ETW::LoaderLog::LoaderStructs::DynamicModule : 0) | + (bIsManifestModule ? ETW::LoaderLog::LoaderStructs::ManifestModule : 0) | + (bIsIbcOptimized ? ETW::LoaderLog::LoaderStructs::IbcOptimized : 0)); #ifndef FEATURE_DTRACE // Grab PDB path, guid, and age for managed PDB and native (NGEN) PDB when // available. Any failures are not fatal. The corresponding PDB info will remain // zeroed out, and that's what we'll include in the event. - CV_INFO_PDB70 cvInfoIL = {0}; - CV_INFO_PDB70 cvInfoNative = {0}; + CV_INFO_PDB70 cvInfoIL = { 0 }; + CV_INFO_PDB70 cvInfoNative = { 0 }; GetCodeViewInfo(pModule, &cvInfoIL, &cvInfoNative); #endif // FEATURE_DTRACE - PWCHAR ModuleILPath=L"", ModuleNativePath=L""; + PWCHAR ModuleILPath = L"", ModuleNativePath = L""; - if(bFireDomainModuleEvents) + if (bFireDomainModuleEvents) { - if(pModule->GetDomain()->IsSharedDomain()) // for shared domains, we do not fire domainmodule event + if (pModule->GetDomain()->IsSharedDomain()) // for shared domains, we do not fire domainmodule event return; ullAppDomainId = (ULONGLONG)pModule->FindDomainAssembly(pModule->GetDomain()->AsAppDomain())->GetAppDomain(); } @@ -5205,19 +5213,19 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL #else // !FEATURE_PAL SString moduleName; #endif // !FEATURE_PAL - if(!bIsDynamicAssembly) + if (!bIsDynamicAssembly) { ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetILimage()->GetPath().GetUnicode(); ModuleNativePath = (PWCHAR)pEmptyString; #ifdef FEATURE_PREJIT - if(bHasNativeImage) + if (bHasNativeImage) ModuleNativePath = (PWCHAR)pModule->GetNativeImage()->GetPath().GetUnicode(); #endif // FEATURE_PREJIT } // if we do not have a module path yet, we put the module name - if(bIsDynamicAssembly || ModuleILPath==NULL || wcslen(ModuleILPath) <= 2) + if (bIsDynamicAssembly || ModuleILPath == NULL || wcslen(ModuleILPath) <= 2) { moduleName.SetUTF8(pModule->GetSimpleName()); ModuleILPath = (PWCHAR)moduleName.GetUnicode(); @@ -5242,52 +5250,52 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL return; #endif // !FEATURE_DTRACE - if(bFireDomainModuleEvents) + if (bFireDomainModuleEvents) { - if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) + if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) { FireEtwDomainModuleLoad_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { FireEtwDomainModuleDCStart_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) { FireEtwDomainModuleDCEnd_V1(ullModuleId, ullAssemblyId, ullAppDomainId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId()); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd)); } } else { - if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad)) + if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoad)) { FireEtwModuleLoad_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if(dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) + else if (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { FireEtwModuleUnload_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) { FireEtwModuleDCStart_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) { FireEtwModuleDCEnd_V1_or_V2(ullModuleId, ullAssemblyId, ulFlags, ulReservedFlags, szDtraceOutput1, szDtraceOutput2, GetClrInstanceId(), &cvInfoIL.signature, cvInfoIL.age, managedPdbPath, &cvInfoNative.signature, cvInfoNative.age, nativePdbPath); } else { _ASSERTE((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeEnabledAny)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeEnabledAny)); } #if !defined(FEATURE_PAL) @@ -5303,55 +5311,55 @@ void ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL /*****************************************************************/ /* This routine is used to send an ETW event just before a method starts jitting*/ /*****************************************************************/ -void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature) +void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc* pMethodDesc, SString* namespaceOrClassName, SString* methodName, SString* methodSignature) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; - Module *pModule = NULL; - Module *pLoaderModule = NULL; // This must not be used except for getting the ModuleID + Module* pModule = NULL; + Module* pLoaderModule = NULL; // This must not be used except for getting the ModuleID - ULONGLONG ullMethodIdentifier=0; - ULONGLONG ullModuleID=0; - ULONG ulMethodToken=0; - ULONG ulMethodILSize=0; + ULONGLONG ullMethodIdentifier = 0; + ULONGLONG ullModuleID = 0; + ULONG ulMethodToken = 0; + ULONG ulMethodILSize = 0; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L"",szDtraceOutput3=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L"", szDtraceOutput3 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput3[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE - if(pMethodDesc) { + if (pMethodDesc) { pModule = pMethodDesc->GetModule_NoLogging(); - if(!pMethodDesc->IsRestored()) { - return; + if (!pMethodDesc->IsRestored()) { + return; } bool bIsDynamicMethod = pMethodDesc->IsDynamicMethod(); BOOL bIsGenericMethod = FALSE; - if(pMethodDesc->GetMethodTable_NoLogging()) + if (pMethodDesc->GetMethodTable_NoLogging()) bIsGenericMethod = pMethodDesc->HasClassOrMethodInstantiation_NoLogging(); - ullModuleID = (ULONGLONG)(TADDR) pModule; + ullModuleID = (ULONGLONG)(TADDR)pModule; ullMethodIdentifier = (ULONGLONG)pMethodDesc; // Use MethodDesc if Dynamic or Generic methods - if( bIsDynamicMethod || bIsGenericMethod) + if (bIsDynamicMethod || bIsGenericMethod) { - if(bIsGenericMethod) + if (bIsGenericMethod) ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 + if (bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 ulMethodToken = (ULONG)0; } else ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(pMethodDesc->IsIL()) + if (pMethodDesc->IsIL()) { COR_ILMETHOD_DECODER::DecoderStatus decoderstatus = COR_ILMETHOD_DECODER::FORMAT_ERROR; COR_ILMETHOD_DECODER ILHeader(pMethodDesc->GetILHeader(), pMethodDesc->GetMDImport(), &decoderstatus); @@ -5359,7 +5367,7 @@ void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n } SString tNamespace, tMethodName, tMethodSignature; - if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) + if (!namespaceOrClassName || !methodName || !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) { pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); namespaceOrClassName = &tNamespace; @@ -5387,35 +5395,35 @@ void ETW::MethodLog::SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *n #endif // !FEATURE_DTRACE FireEtwMethodJittingStarted_V1(ullMethodIdentifier, - ullModuleID, - ulMethodToken, - ulMethodILSize, - szDtraceOutput1, - szDtraceOutput2, - szDtraceOutput3, - GetClrInstanceId()); + ullModuleID, + ulMethodToken, + ulMethodILSize, + szDtraceOutput1, + szDtraceOutput2, + szDtraceOutput3, + GetClrInstanceId()); } } /****************************************************************************/ /* This routine is used to send a method load/unload or rundown event */ /****************************************************************************/ -void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, SIZE_T pCode, ReJITID rejitID) +void ETW::MethodLog::SendMethodEvent(MethodDesc* pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString* namespaceOrClassName, SString* methodName, SString* methodSignature, SIZE_T pCode, ReJITID rejitID) { - CONTRACTL { + CONTRACTL{ THROWS; GC_NOTRIGGER; SO_NOT_MAINLINE; } CONTRACTL_END; - Module *pModule = NULL; - Module *pLoaderModule = NULL; // This must not be used except for getting the ModuleID - ULONGLONG ullMethodStartAddress=0, ullColdMethodStartAddress=0, ullModuleID=0, ullMethodIdentifier=0; - ULONG ulMethodSize=0, ulColdMethodSize=0, ulMethodToken=0, ulMethodFlags=0, ulColdMethodFlags=0; - PWCHAR pMethodName=NULL, pNamespaceName=NULL, pMethodSignature=NULL; + Module* pModule = NULL; + Module* pLoaderModule = NULL; // This must not be used except for getting the ModuleID + ULONGLONG ullMethodStartAddress = 0, ullColdMethodStartAddress = 0, ullModuleID = 0, ullMethodIdentifier = 0; + ULONG ulMethodSize = 0, ulColdMethodSize = 0, ulMethodToken = 0, ulMethodFlags = 0, ulColdMethodFlags = 0; + PWCHAR pMethodName = NULL, pNamespaceName = NULL, pMethodSignature = NULL; BOOL bHasNativeImage = FALSE, bShowVerboseOutput = FALSE, bIsDynamicMethod = FALSE, bHasSharedGenericCode = FALSE, bIsGenericMethod = FALSE; #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L"",szDtraceOutput2=L"",szDtraceOutput3=L""; + PCWSTR szDtraceOutput1 = L"", szDtraceOutput2 = L"", szDtraceOutput3 = L""; #else CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; CHAR szDtraceOutput2[DTRACE_OUTPUT_STRING_LEN]; @@ -5423,25 +5431,25 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio #endif // !FEATURE_DTRACE BOOL bIsRundownProvider = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)); BOOL bIsRuntimeProvider = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || - (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)); + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || + (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)); if (pMethodDesc == NULL) return; - if(!pMethodDesc->IsRestored()) + if (!pMethodDesc->IsRestored()) { // Forcibly restoring ngen methods can cause all sorts of deadlocks and contract violations // These events are therefore put under the private provider - if(ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_PRIVATENGENFORCERESTORE_KEYWORD)) + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_PRIVATENGENFORCERESTORE_KEYWORD)) { PERMANENT_CONTRACT_VIOLATION(GCViolation, ReasonNonShippingCode); pMethodDesc->CheckRestore(); @@ -5453,13 +5461,13 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } - if(bIsRundownProvider) + if (bIsRundownProvider) { bShowVerboseOutput = ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_Context, TRACE_LEVEL_VERBOSE, KEYWORDZERO); } - else if(bIsRuntimeProvider) + else if (bIsRuntimeProvider) { bShowVerboseOutput = ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, TRACE_LEVEL_VERBOSE, @@ -5473,7 +5481,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio bIsDynamicMethod = (BOOL)pMethodDesc->IsDynamicMethod(); bHasSharedGenericCode = pMethodDesc->IsSharedByGenericInstantiations(); - if(pMethodDesc->GetMethodTable_NoLogging()) + if (pMethodDesc->GetMethodTable_NoLogging()) bIsGenericMethod = pMethodDesc->HasClassOrMethodInstantiation_NoLogging(); ulMethodFlags = ((ulMethodFlags | @@ -5489,7 +5497,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // MethodDesc ==> Code Address ==>JitMananger TADDR start = pCode ? pCode : PCODEToPINSTR(pMethodDesc->GetNativeCode()); - if(start == 0) { + if (start == 0) { // this method hasn't been jitted return; } @@ -5505,22 +5513,22 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio ullMethodStartAddress = (ULONGLONG)methodRegionInfo.hotStartAddress; ulMethodSize = (ULONG)methodRegionInfo.hotSize; - ullModuleID = (ULONGLONG)(TADDR) pModule; + ullModuleID = (ULONGLONG)(TADDR)pModule; ullMethodIdentifier = (ULONGLONG)pMethodDesc; // Use MethodDesc if Dynamic or Generic methods - if( bIsDynamicMethod || bIsGenericMethod) + if (bIsDynamicMethod || bIsGenericMethod) { bShowVerboseOutput = TRUE; - if(bIsGenericMethod) + if (bIsGenericMethod) ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 + if (bIsDynamicMethod) // if its a generic and a dynamic method, we would set the methodtoken to 0 ulMethodToken = (ULONG)0; } else ulMethodToken = (ULONG)pMethodDesc->GetMemberDef_NoLogging(); - if(bHasNativeImage) + if (bHasNativeImage) { ullColdMethodStartAddress = (ULONGLONG)methodRegionInfo.coldStartAddress; ulColdMethodSize = (ULONG)methodRegionInfo.coldSize; // methodRegionInfo.coldSize is size_t and info.MethodLoadInfo.MethodSize is 32 bit; will give incorrect values on a 64-bit machine @@ -5530,9 +5538,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // if verbose method load info needed, only then // find method name and signature and fire verbose method load info - if(bShowVerboseOutput) + if (bShowVerboseOutput) { - if(!namespaceOrClassName|| !methodName|| !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) + if (!namespaceOrClassName || !methodName || !methodSignature || (methodName->IsEmpty() && namespaceOrClassName->IsEmpty() && methodSignature->IsEmpty())) { pMethodDesc->GetMethodInfo(tNamespace, tMethodName, tMethodSignature); namespaceOrClassName = &tNamespace; @@ -5564,10 +5572,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio return; #endif // !FEATURE_DTRACE - if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || + if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoad) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5592,9 +5600,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodLoadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5621,10 +5629,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnload) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5649,9 +5657,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodUnloadVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5678,10 +5686,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5706,9 +5714,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCStartVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5735,10 +5743,10 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio } } } - else if((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || + else if ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd) || (dwEventOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5763,9 +5771,9 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio GetClrInstanceId(), rejitID); } - if(bFireEventForColdSection) + if (bFireEventForColdSection) { - if(bShowVerboseOutput) + if (bShowVerboseOutput) { FireEtwMethodDCEndVerbose_V1_or_V2(ullMethodIdentifier, ullModuleID, @@ -5822,7 +5830,7 @@ void ETW::MethodLog::SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptio // // static -void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, ReJITID rejitID) +void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc* pMethodDesc, DWORD dwEventOptions, ReJITID rejitID) { CONTRACTL { @@ -5899,42 +5907,42 @@ void ETW::MethodLog::SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWOR void ETW::MethodLog::SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName) { WRAPPER_NO_CONTRACT; - if(pHelperName) + if (pHelperName) { #ifndef FEATURE_DTRACE - PCWSTR szDtraceOutput1=L""; + PCWSTR szDtraceOutput1 = L""; #else - CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; + CHAR szDtraceOutput1[DTRACE_OUTPUT_STRING_LEN]; #endif // !FEATURE_DTRACE - ULONG methodFlags = ETW::MethodLog::MethodStructs::JitHelperMethod; // helper flag set + ULONG methodFlags = ETW::MethodLog::MethodStructs::JitHelperMethod; // helper flag set #ifndef FEATURE_DTRACE - FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, - 0, - ullHelperStartAddress, - ulHelperSize, - 0, - methodFlags, - NULL, - pHelperName, - NULL, - GetClrInstanceId()); + FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, + 0, + ullHelperStartAddress, + ulHelperSize, + 0, + methodFlags, + NULL, + pHelperName, + NULL, + GetClrInstanceId()); #else // !FEATURE_DTRACE // since DTrace do not support UNICODE string, they need to be converted to ANSI string - INT32 nTempHelperName = WideCharToMultiByte(pHelperName, szDtraceOutput1); - if (nTempHelperName == 0) - return; - // in the action, printf, of DTtrace, it cannot print an arg with value NULL when the format is set %s. - // Dtrace does not provide the condition statement so that we give a string "NULL" to it. - FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, - 0, - ullHelperStartAddress, - ulHelperSize, - 0, - methodFlags, - szDtraceOutputNULL, - szDtraceOutput1, - szDtraceOutputNULL, - GetClrInstanceId()); + INT32 nTempHelperName = WideCharToMultiByte(pHelperName, szDtraceOutput1); + if (nTempHelperName == 0) + return; + // in the action, printf, of DTtrace, it cannot print an arg with value NULL when the format is set %s. + // Dtrace does not provide the condition statement so that we give a string "NULL" to it. + FireEtwMethodLoadVerbose_V1(ullHelperStartAddress, + 0, + ullHelperStartAddress, + ulHelperSize, + 0, + methodFlags, + szDtraceOutputNULL, + szDtraceOutput1, + szDtraceOutputNULL, + GetClrInstanceId()); #endif // !FEATURE_DTRACE } } @@ -5943,23 +5951,23 @@ void ETW::MethodLog::SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHe /****************************************************************************/ /* This routine sends back method events of type 'dwEventOptions', for all NGEN methods in pModule */ -/****************************************************************************/ -void ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions) + /****************************************************************************/ +void ETW::MethodLog::SendEventsForNgenMethods(Module* pModule, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; #ifdef FEATURE_PREJIT - if(!pModule || !pModule->HasNativeImage()) + if (!pModule || !pModule->HasNativeImage()) return; MethodIterator mi(pModule); - while(mi.Next()) + while (mi.Next()) { - MethodDesc *hotDesc = (MethodDesc *)mi.GetMethodDesc(); + MethodDesc* hotDesc = (MethodDesc*)mi.GetMethodDesc(); ETW::MethodLog::SendMethodEvent(hotDesc, dwEventOptions, FALSE); } #endif // FEATURE_PREJIT @@ -5970,10 +5978,10 @@ void ETW::MethodLog::SendEventsForNgenMethods(Module *pModule, DWORD dwEventOpti JITed methods in either a given LoaderAllocator (if pLoaderAllocatorFilter is non NULL) or in a given Domain (if pDomainFilter is non NULL) or for all methods (if both filters are null) */ -/****************************************************************************/ -void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions) + /****************************************************************************/ +void ETW::MethodLog::SendEventsForJitMethods(BaseDomain* pDomainFilter, LoaderAllocator* pLoaderAllocatorFilter, DWORD dwEventOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; @@ -5983,19 +5991,19 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // This is only called for JITted methods loading xor unloading BOOL fLoadOrDCStart = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) != 0); BOOL fUnloadOrDCEnd = ((dwEventOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) != 0); - _ASSERTE((fLoadOrDCStart || fUnloadOrDCEnd) && !(fLoadOrDCStart && fUnloadOrDCEnd)); + _ASSERTE((fLoadOrDCStart || fUnloadOrDCEnd) && !(fLoadOrDCStart&& fUnloadOrDCEnd)); BOOL fSendMethodEvent = (dwEventOptions & (ETW::EnumerationLog::EnumerationStructs::JitMethodLoad | - ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart | - ETW::EnumerationLog::EnumerationStructs::JitMethodUnload | - ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd)) != 0; + ETW::EnumerationLog::EnumerationStructs::JitMethodDCStart | + ETW::EnumerationLog::EnumerationStructs::JitMethodUnload | + ETW::EnumerationLog::EnumerationStructs::JitMethodDCEnd)) != 0; BOOL fSendILToNativeMapEvent = (dwEventOptions & (ETW::EnumerationLog::EnumerationStructs::MethodDCStartILToNativeMap | - ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap)) != 0; + ETW::EnumerationLog::EnumerationStructs::MethodDCEndILToNativeMap)) != 0; BOOL fCollectibleLoaderAllocatorFilter = ((pLoaderAllocatorFilter != NULL) && (pLoaderAllocatorFilter->IsCollectible())); @@ -6014,9 +6022,9 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl #endif // WINXP_AND_WIN2K3_BUILD_SUPPORT EEJitManager::CodeHeapIterator heapIterator(pDomainFilter, pLoaderAllocatorFilter); - while(heapIterator.Next()) + while (heapIterator.Next()) { - MethodDesc * pMD = heapIterator.GetMethod(); + MethodDesc* pMD = heapIterator.GetMethod(); if (pMD == NULL) continue; @@ -6103,7 +6111,7 @@ void ETW::MethodLog::SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAl // enumerationOptions - Flags indicating what to enumerate. Just passed // straight through to IterateDomain // -void ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions) +void ETW::EnumerationLog::IterateAppDomain(AppDomain* pAppDomain, DWORD enumerationOptions) { CONTRACTL { @@ -6143,10 +6151,10 @@ void ETW::EnumerationLog::IterateAppDomain(AppDomain * pAppDomain, DWORD enumera JIT methods in them, and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateDomain(BaseDomain* pDomain, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pDomain != NULL); @@ -6166,86 +6174,86 @@ void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp EX_TRY { // DC Start events for Domain - if(enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); } - // DC End or Unload Jit Method events - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) - { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); - } + // DC End or Unload Jit Method events + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodUnloadOrDCEndAny) + { + ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + } - if (pDomain->IsAppDomain()) + if (pDomain->IsAppDomain()) + { + AppDomain::AssemblyIterator assemblyIterator = pDomain->AsAppDomain()->IterateAssembliesEx( + (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); + CollectibleAssemblyHolder pDomainAssembly; + while (assemblyIterator.Next(pDomainAssembly.This())) { - AppDomain::AssemblyIterator assemblyIterator = pDomain->AsAppDomain()->IterateAssembliesEx( - (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); - CollectibleAssemblyHolder pDomainAssembly; - while (assemblyIterator.Next(pDomainAssembly.This())) + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); + if (bIsDomainNeutral) + continue; + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); - BOOL bIsDomainNeutral = pAssembly->IsDomainNeutral(); - if (bIsDomainNeutral) - continue; - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); + } - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); + while (domainModuleIterator.Next()) + { + Module* pModule = domainModuleIterator.GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); + } - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } } - else + } + else + { + SharedDomain::SharedAssemblyIterator sharedDomainIterator; + while (sharedDomainIterator.Next()) { - SharedDomain::SharedAssemblyIterator sharedDomainIterator; - while (sharedDomainIterator.Next()) + Assembly* pAssembly = sharedDomainIterator.GetAssembly(); + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { - Assembly * pAssembly = sharedDomainIterator.GetAssembly(); - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); + } - ModuleIterator domainModuleIterator = pAssembly->IterateModules(); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + ModuleIterator domainModuleIterator = pAssembly->IterateModules(); + while (domainModuleIterator.Next()) + { + Module* pModule = domainModuleIterator.GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); + } - if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); - } + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } } + } - // DC Start or Load Jit Method events - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) - { - ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); - } + // DC Start or Load Jit Method events + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::JitMethodLoadOrDCStartAny) + { + ETW::MethodLog::SendEventsForJitMethods(pDomain, NULL, enumerationOptions); + } - // DC End or Unload events for Domain - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // DC End or Unload events for Domain + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::LoaderLog::SendDomainEvent(pDomain, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } @@ -6257,10 +6265,10 @@ void ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp JIT methods in them, and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator* pLoaderAllocator, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pLoaderAllocator != NULL); @@ -6274,13 +6282,13 @@ void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); } - Assembly *pAssembly = pLoaderAllocator->Id()->GetDomainAssembly()->GetAssembly(); + Assembly* pAssembly = pLoaderAllocator->Id()->GetDomainAssembly()->GetAssembly(); _ASSERTE(!pAssembly->IsDomainNeutral()); // Collectible Assemblies are not domain neutral. DomainModuleIterator domainModuleIterator = pLoaderAllocator->Id()->GetDomainAssembly()->IterateModules(kModIterIncludeLoaded); while (domainModuleIterator.Next()) { - Module *pModule = domainModuleIterator.GetModule(); + Module* pModule = domainModuleIterator.GetModule(); ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); } @@ -6294,16 +6302,16 @@ void ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca { ETW::MethodLog::SendEventsForJitMethods(NULL, pLoaderAllocator, enumerationOptions); } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /********************************************************************************/ /* This routine fires ETW events for Assembly and the DomainModule's in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateAssembly(Assembly* pAssembly, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pAssembly != NULL); @@ -6312,41 +6320,41 @@ void ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumeration EX_TRY { // DC Start events for Assembly - if(enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); } - // DC Start, DCEnd, events for DomainModule - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart)) + // DC Start, DCEnd, events for DomainModule + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart)) + { + if (pAssembly->GetDomain()->IsAppDomain()) { - if(pAssembly->GetDomain()->IsAppDomain()) + DomainModuleIterator dmIterator = pAssembly->FindDomainAssembly(pAssembly->GetDomain()->AsAppDomain())->IterateModules(kModIterIncludeLoaded); + while (dmIterator.Next()) { - DomainModuleIterator dmIterator = pAssembly->FindDomainAssembly(pAssembly->GetDomain()->AsAppDomain())->IterateModules(kModIterIncludeLoaded); - while (dmIterator.Next()) - { - ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); - } + ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); } } + } - // DC End or Unload events for Assembly - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) - { - ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // DC End or Unload events for Assembly + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) + { + ETW::LoaderLog::SendAssemblyEvent(pAssembly, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } /********************************************************************************/ /* This routine fires ETW events for Module, their range information and the NGEN methods in them based on enumerationOptions.*/ -/********************************************************************************/ -void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOptions) + /********************************************************************************/ +void ETW::EnumerationLog::IterateModule(Module* pModule, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; PRECONDITION(pModule != NULL); @@ -6355,45 +6363,45 @@ void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOption EX_TRY { // DC Start events for Module - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) || (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCStart)) { ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); } - // DC Start or Load or DC End or Unload Ngen Method events - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) - { - ETW::MethodLog::SendEventsForNgenMethods(pModule, enumerationOptions); - } + // DC Start or Load or DC End or Unload Ngen Method events + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodLoad) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCStart) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodUnload) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::NgenMethodDCEnd)) + { + ETW::MethodLog::SendEventsForNgenMethods(pModule, enumerationOptions); + } - // DC End or Unload events for Module - if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) - { - ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); - } + // DC End or Unload events for Module + if ((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) || + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeDCEnd)) + { + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); + } - // If we're logging types, then update the internal Type hash table to account - // for the module's unloading - if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::TypeUnload) - { - ETW::TypeSystemLog::OnModuleUnload(pModule); - } + // If we're logging types, then update the internal Type hash table to account + // for the module's unloading + if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::TypeUnload) + { + ETW::TypeSystemLog::OnModuleUnload(pModule); + } - // ModuleRangeLoadPrivate events for module range information from attach/detach scenarios - if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, - TRACE_LEVEL_INFORMATION, - CLR_PERFTRACK_PRIVATE_KEYWORD) && - (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate)) - { - ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); - } - } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); + // ModuleRangeLoadPrivate events for module range information from attach/detach scenarios + if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, + TRACE_LEVEL_INFORMATION, + CLR_PERFTRACK_PRIVATE_KEYWORD) && + (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::ModuleRangeLoadPrivate)) + { + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions); + } + } EX_CATCH{ } EX_END_CATCH(SwallowAllExceptions); } //--------------------------------------------------------------------------------------- @@ -6429,9 +6437,9 @@ void ETW::EnumerationLog::IterateModule(Module *pModule, DWORD enumerationOption // // static -void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions) +void ETW::EnumerationLog::EnumerationHelper(Module* moduleFilter, BaseDomain* domainFilter, DWORD enumerationOptions) { - CONTRACTL { + CONTRACTL{ THROWS; GC_TRIGGERS; } CONTRACTL_END; @@ -6444,7 +6452,7 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrSharedDomain(SharedDomain::GetDomain()->GetReJitManager()); - if(moduleFilter) + if (moduleFilter) { // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrModule(moduleFilter->GetReJitManager()); @@ -6466,12 +6474,12 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do } else { - if(domainFilter) + if (domainFilter) { // See code:#TableLockHolder ReJitManager::TableLockHolder lkRejitMgrAD(domainFilter->GetReJitManager()); - if(domainFilter->IsAppDomain()) + if (domainFilter->IsAppDomain()) { ETW::EnumerationLog::IterateAppDomain(domainFilter->AsAppDomain(), enumerationOptions); } @@ -6483,9 +6491,9 @@ void ETW::EnumerationLog::EnumerationHelper(Module *moduleFilter, BaseDomain *do else { AppDomainIterator appDomainIterator(FALSE); - while(appDomainIterator.Next()) + while (appDomainIterator.Next()) { - AppDomain *pDomain = appDomainIterator.GetDomain(); + AppDomain* pDomain = appDomainIterator.GetDomain(); if (pDomain != NULL) { // See code:#TableLockHolder diff --git a/src/coreclr/nativeaot/Runtime/eventtracebase.h b/src/coreclr/nativeaot/Runtime/eventtracebase.h index 79b8fac860612c..e4a16fd87d6e08 100644 --- a/src/coreclr/nativeaot/Runtime/eventtracebase.h +++ b/src/coreclr/nativeaot/Runtime/eventtracebase.h @@ -147,13 +147,6 @@ struct ProfilingScanContext; #ifndef FEATURE_REDHAWK -#if defined(FEATURE_CORECLR) && !defined(FEATURE_CORESYSTEM) -// For Silverlight non-CoreSys builds we still use an older toolset, -// headers/libs, and a different value for WINVER. We use this symbol -// to distinguish between whether we built the ETW header files from -// the ETW manifest using the -mof command line or not. -#define WINXP_AND_WIN2K3_BUILD_SUPPORT -#endif #include "corprof.h" // g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. diff --git a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp index 2f6f6ea4f7c0c0..0001de5370c1db 100644 --- a/src/coreclr/nativeaot/Runtime/gcrhenv.cpp +++ b/src/coreclr/nativeaot/Runtime/gcrhenv.cpp @@ -585,7 +585,8 @@ void RedhawkGCInterface::UnregisterFrozenSegment(GcSegmentHandle segment) GCHeapUtilities::GetGCHeap()->UnregisterFrozenSegment((segment_handle)segment); } -EXTERN_C UInt32_BOOL g_fGcStressStarted = UInt32_FALSE; // UInt32_BOOL because asm code reads it +EXTERN_C UInt32_BOOL g_fGcStressStarted; +UInt32_BOOL g_fGcStressStarted = UInt32_FALSE; // UInt32_BOOL because asm code reads it #ifdef FEATURE_GC_STRESS // static void RedhawkGCInterface::StressGc() diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index ada010f8a573e6..9f82aebdbf39eb 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -45,14 +45,17 @@ static bool DetectCPUFeatures(); extern RhConfig * g_pRhConfig; -EXTERN_C bool g_fHasFastFxsave = false; +EXTERN_C bool g_fHasFastFxsave; +bool g_fHasFastFxsave = false; CrstStatic g_CastCacheLock; CrstStatic g_ThunkPoolLock; #if defined(HOST_X86) || defined(HOST_AMD64) || defined(HOST_ARM64) // This field is inspected from the generated code to determine what intrinsics are available. -EXTERN_C int g_cpuFeatures = 0; +EXTERN_C int g_cpuFeatures; +int g_cpuFeatures = 0; + // This field is defined in the generated code and sets the ISA expectations. EXTERN_C int g_requiredCpuFeatures; #endif diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index e0a7d528358ab5..36bf43c1a359f0 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -27,7 +27,8 @@ #include "slist.inl" #include "GCMemoryHelpers.h" -EXTERN_C volatile uint32_t RhpTrapThreads = (uint32_t)TrapThreadsFlags::None; +EXTERN_C volatile uint32_t RhpTrapThreads; +volatile uint32_t RhpTrapThreads = (uint32_t)TrapThreadsFlags::None; GVAL_IMPL_INIT(PTR_Thread, RhpSuspendingThread, 0); @@ -373,7 +374,8 @@ COOP_PINVOKE_HELPER(void, RhpCancelThreadAbort, (void* thread)) C_ASSERT(sizeof(Thread) == sizeof(ThreadBuffer)); -EXTERN_C DECLSPEC_THREAD ThreadBuffer tls_CurrentThread = +EXTERN_C DECLSPEC_THREAD ThreadBuffer tls_CurrentThread; +DECLSPEC_THREAD ThreadBuffer tls_CurrentThread = { { 0 }, // m_rgbAllocContextBuffer Thread::TSF_Unknown, // m_ThreadStateFlags diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 2cc2f40a841f89..198172362464a0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -1091,5 +1091,10 @@ public static bool IsPrimitive(RuntimeTypeHandle typeHandle) { return typeHandle.ToEETypePtr().IsPrimitive && !typeHandle.ToEETypePtr().IsEnum; } + + public static byte[] ComputePublicKeyToken(byte[] publicKey) + { + return System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(publicKey); + } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index cf0cab0700ebac..2284e13f661357 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -123,15 +123,12 @@ - - - - + + - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs index 3714e7ce510fba..d1bb831f347729 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -6,7 +6,7 @@ namespace System { - public struct ModuleHandle + public struct ModuleHandle : IEquatable { public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs deleted file mode 100644 index bc3ef378043153..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreRT.cs +++ /dev/null @@ -1,34 +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.Runtime.Serialization; - -namespace System.Reflection -{ - public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable - { - public AssemblyName(string assemblyName) - : this() - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - RuntimeAssemblyName runtimeAssemblyName = AssemblyNameParser.Parse(_name); - runtimeAssemblyName.CopyToAssemblyName(this); - } - - private byte[] ComputePublicKeyToken() - { - return AssemblyNameHelpers.ComputePublicKeyToken(_publicKey); - } - - private static AssemblyName GetFileInformationCore(string assemblyFile) - { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_AssemblyName_GetAssemblyName); - } - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs index b259e2b6bfbdc3..a79f9f7f653071 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.cs @@ -9,41 +9,8 @@ namespace System.Reflection { - [System.Runtime.CompilerServices.ReflectionBlocked] - public static partial class AssemblyNameHelpers + internal static partial class AssemblyNameHelpers { - // - // Converts an AssemblyName to a RuntimeAssemblyName that is free from any future mutations on the AssemblyName. - // - public static RuntimeAssemblyName ToRuntimeAssemblyName(this AssemblyName assemblyName) - { - if (assemblyName.Name == null) - throw new ArgumentException(); - - AssemblyNameFlags flags = assemblyName.Flags; - AssemblyContentType contentType = assemblyName.ContentType; -#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - ProcessorArchitecture processorArchitecture = assemblyName.ProcessorArchitecture; -#pragma warning restore SYSLIB0037 - AssemblyNameFlags combinedFlags = CombineAssemblyNameFlags(flags, contentType, processorArchitecture); - byte[]? pkOriginal; - if (0 != (flags & AssemblyNameFlags.PublicKey)) - pkOriginal = assemblyName.GetPublicKey(); - else - pkOriginal = assemblyName.GetPublicKeyToken(); - - // AssemblyName's PKT property getters do NOT copy the array before giving it out. Make our own copy - // as the original is wide open to tampering by anyone. - byte[]? pkCopy = null; - if (pkOriginal != null) - { - pkCopy = new byte[pkOriginal.Length]; - ((ICollection)pkOriginal).CopyTo(pkCopy, 0); - } - - return new RuntimeAssemblyName(assemblyName.Name, assemblyName.Version, assemblyName.CultureName, combinedFlags, pkCopy); - } - // // These helpers convert between the combined flags+contentType+processorArchitecture value and the separated parts. // @@ -55,19 +22,9 @@ internal static AssemblyContentType ExtractAssemblyContentType(this AssemblyName return (AssemblyContentType)((((int)flags) >> 9) & 0x7); } - internal static ProcessorArchitecture ExtractProcessorArchitecture(this AssemblyNameFlags flags) - { - return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); - } - - public static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags) + internal static AssemblyNameFlags ExtractAssemblyNameFlags(this AssemblyNameFlags combinedFlags) { return combinedFlags & unchecked((AssemblyNameFlags)0xFFFFF10F); } - - internal static AssemblyNameFlags CombineAssemblyNameFlags(AssemblyNameFlags flags, AssemblyContentType contentType, ProcessorArchitecture processorArchitecture) - { - return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4)); - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs deleted file mode 100644 index 84555ab310d454..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs +++ /dev/null @@ -1,136 +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; -using System.Text; -using System.Globalization; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace System.Reflection -{ - // - // A simple lexer for assembly display names. - // - internal struct AssemblyNameLexer - { - internal AssemblyNameLexer(string s) - { - // Convert string to char[] with NUL terminator. (An actual NUL terminator in the input string will be treated - // as an actual end of string: this is compatible with desktop behavior.) - char[] chars = new char[s.Length + 1]; - s.CopyTo(0, chars, 0, s.Length); - _chars = chars; - _index = 0; - } - - // - // Return the next token in assembly name. If you expect the result to be DisplayNameToken.String, - // use GetNext(out String) instead. - // - internal Token GetNext() - { - return GetNext(out _); - } - - // - // Return the next token in assembly name. If the result is DisplayNameToken.String, - // sets "tokenString" to the tokenized string. - // - internal Token GetNext(out string tokenString) - { - tokenString = null; - while (char.IsWhiteSpace(_chars[_index])) - _index++; - - char c = _chars[_index++]; - if (c == 0) - return Token.End; - if (c == ',') - return Token.Comma; - if (c == '=') - return Token.Equals; - - StringBuilder sb = new StringBuilder(); - - char quoteChar = (char)0; - if (c == '\'' || c == '\"') - { - quoteChar = c; - c = _chars[_index++]; - } - - for (;;) - { - if (c == 0) - { - _index--; - break; // Terminate: End of string (desktop compat: if string was quoted, permitted to terminate without end-quote.) - } - - if (quoteChar != 0 && c == quoteChar) - break; // Terminate: Found closing quote of quoted string. - - if (quoteChar == 0 && (c == ',' || c == '=')) - { - _index--; - break; // Terminate: Found start of a new ',' or '=' token. - } - - if (quoteChar == 0 && (c == '\'' || c == '\"')) - throw new FileLoadException(); // Desktop compat: Unescaped quote illegal unless entire string is quoted. - - if (c == '\\') - { - c = _chars[_index++]; - - switch (c) - { - case '\\': - case ',': - case '=': - case '\'': - case '"': - sb.Append(c); - break; - case 't': - sb.Append('\t'); - break; - case 'r': - sb.Append('\r'); - break; - case 'n': - sb.Append('\n'); - break; - default: - throw new FileLoadException(); // Unrecognized escape - } - } - else - { - sb.Append(c); - } - - c = _chars[_index++]; - } - - tokenString = sb.ToString(); - if (quoteChar == 0) - tokenString = tokenString.Trim(); // Unless quoted, whitespace at beginning or end doesn't count. - return Token.String; - } - - // Token categories for display name lexer. - internal enum Token - { - Equals = 1, - Comma = 2, - String = 3, - End = 4, - } - - private readonly char[] _chars; - private int _index; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs deleted file mode 100644 index 5d8f2ef1c34b0a..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs +++ /dev/null @@ -1,230 +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; -using System.Text; -using System.Diagnostics; -using System.Globalization; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace System.Reflection -{ - // - // Parses an assembly name. - // - [System.Runtime.CompilerServices.ReflectionBlocked] - public static class AssemblyNameParser - { - public static void Parse(AssemblyName blank, string s) - { - if (s == null) - throw new ArgumentNullException(nameof(s)); - RuntimeAssemblyName runtimeAssemblyName = Parse(s); - runtimeAssemblyName.CopyToAssemblyName(blank); - } - - public static RuntimeAssemblyName Parse(string s) - { - Debug.Assert(s != null); - - int indexOfNul = s.IndexOf((char)0); - if (indexOfNul != -1) - s = s.Substring(0, indexOfNul); - if (s.Length == 0) - throw new ArgumentException(SR.Format_StringZeroLength); - - AssemblyNameLexer lexer = new AssemblyNameLexer(s); - - // Name must come first. - string name; - AssemblyNameLexer.Token token = lexer.GetNext(out name); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - - if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1) - throw new FileLoadException(SR.InvalidAssemblyName); - - Version? version = null; - string? cultureName = null; - byte[]? pkt = null; - AssemblyNameFlags flags = 0; - - LowLevelList alreadySeen = new LowLevelList(); - token = lexer.GetNext(); - while (token != AssemblyNameLexer.Token.End) - { - if (token != AssemblyNameLexer.Token.Comma) - throw new FileLoadException(SR.InvalidAssemblyName); - string attributeName; - - token = lexer.GetNext(out attributeName); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - token = lexer.GetNext(); - - // Compat note: Inside AppX apps, the desktop CLR's AssemblyName parser skips past any elements that don't follow the "=" pattern. - // (when running classic Windows apps, such an illegal construction throws an exception as expected.) - // Naturally, at least one app unwittingly takes advantage of this. - if (token == AssemblyNameLexer.Token.Comma || token == AssemblyNameLexer.Token.End) - continue; - - if (token != AssemblyNameLexer.Token.Equals) - throw new FileLoadException(SR.InvalidAssemblyName); - string attributeValue; - token = lexer.GetNext(out attributeValue); - if (token != AssemblyNameLexer.Token.String) - throw new FileLoadException(SR.InvalidAssemblyName); - - if (attributeName == string.Empty) - throw new FileLoadException(SR.InvalidAssemblyName); - - for (int i = 0; i < alreadySeen.Count; i++) - { - if (alreadySeen[i].Equals(attributeName, StringComparison.OrdinalIgnoreCase)) - throw new FileLoadException(SR.InvalidAssemblyName); // Cannot specify the same attribute twice. - } - alreadySeen.Add(attributeName); - - if (attributeName.Equals("Version", StringComparison.OrdinalIgnoreCase)) - { - version = ParseVersion(attributeValue); - } - - if (attributeName.Equals("Culture", StringComparison.OrdinalIgnoreCase)) - { - cultureName = ParseCulture(attributeValue); - } - - if (attributeName.Equals("PublicKeyToken", StringComparison.OrdinalIgnoreCase)) - { - pkt = ParsePKT(attributeValue); - } - - if (attributeName.Equals("ProcessorArchitecture", StringComparison.OrdinalIgnoreCase)) - { - flags |= (AssemblyNameFlags)(((int)ParseProcessorArchitecture(attributeValue)) << 4); - } - - if (attributeName.Equals("Retargetable", StringComparison.OrdinalIgnoreCase)) - { - if (attributeValue.Equals("Yes", StringComparison.OrdinalIgnoreCase)) - flags |= AssemblyNameFlags.Retargetable; - else if (attributeValue.Equals("No", StringComparison.OrdinalIgnoreCase)) - { - // nothing to do - } - else - throw new FileLoadException(SR.InvalidAssemblyName); - } - - if (attributeName.Equals("ContentType", StringComparison.OrdinalIgnoreCase)) - { - if (attributeValue.Equals("WindowsRuntime", StringComparison.OrdinalIgnoreCase)) - flags |= (AssemblyNameFlags)(((int)AssemblyContentType.WindowsRuntime) << 9); - else - throw new FileLoadException(SR.InvalidAssemblyName); - } - - // Desktop compat: If we got here, the attribute name is unknown to us. Ignore it (as long it's not duplicated.) - token = lexer.GetNext(); - } - return new RuntimeAssemblyName(name, version, cultureName, flags, pkt); - } - - private static Version ParseVersion(string attributeValue) - { - string[] parts = attributeValue.Split('.'); - if (parts.Length > 4) - throw new FileLoadException(SR.InvalidAssemblyName); - ushort[] versionNumbers = new ushort[4]; - for (int i = 0; i < versionNumbers.Length; i++) - { - if (i >= parts.Length) - versionNumbers[i] = ushort.MaxValue; - else - { - // Desktop compat: TryParse is a little more forgiving than Fusion. - for (int j = 0; j < parts[i].Length; j++) - { - if (!char.IsDigit(parts[i][j])) - throw new FileLoadException(SR.InvalidAssemblyName); - } - if (!(ushort.TryParse(parts[i], out versionNumbers[i]))) - { - throw new FileLoadException(SR.InvalidAssemblyName); - } - } - } - - if (versionNumbers[0] == ushort.MaxValue || versionNumbers[1] == ushort.MaxValue) - throw new FileLoadException(SR.InvalidAssemblyName); - if (versionNumbers[2] == ushort.MaxValue) - return new Version(versionNumbers[0], versionNumbers[1]); - if (versionNumbers[3] == ushort.MaxValue) - return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2]); - return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]); - } - - private static string ParseCulture(string attributeValue) - { - if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase)) - { - return ""; - } - else - { - CultureInfo culture = CultureInfo.GetCultureInfo(attributeValue); // Force a CultureNotFoundException if not a valid culture. - return culture.Name; - } - } - - private static byte[] ParsePKT(string attributeValue) - { - if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty) - return Array.Empty(); - - if (attributeValue.Length != 8 * 2) - throw new FileLoadException(SR.InvalidAssemblyName); - - byte[] pkt = new byte[8]; - int srcIndex = 0; - for (int i = 0; i < 8; i++) - { - char hi = attributeValue[srcIndex++]; - char lo = attributeValue[srcIndex++]; - pkt[i] = (byte)((ParseHexNybble(hi) << 4) | ParseHexNybble(lo)); - } - return pkt; - } - - private static ProcessorArchitecture ParseProcessorArchitecture(string attributeValue) - { - if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.MSIL; - if (attributeValue.Equals("x86", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.X86; - if (attributeValue.Equals("ia64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.IA64; - if (attributeValue.Equals("amd64", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Amd64; - if (attributeValue.Equals("arm", StringComparison.OrdinalIgnoreCase)) - return ProcessorArchitecture.Arm; - throw new FileLoadException(SR.InvalidAssemblyName); - } - - private static byte ParseHexNybble(char c) - { - if (c >= '0' && c <= '9') - return (byte)(c - '0'); - if (c >= 'a' && c <= 'f') - return (byte)(c - 'a' + 10); - if (c >= 'A' && c <= 'F') - return (byte)(c - 'A' + 10); - throw new FileLoadException(SR.InvalidAssemblyName); - } - - private static readonly char[] s_illegalCharactersInSimpleName = { '/', '\\', ':' }; - } -} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs new file mode 100644 index 00000000000000..fc4ed2816e5802 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/AssemblyRuntimeNameHelpers.cs @@ -0,0 +1,52 @@ +// 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.Globalization; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace System.Reflection +{ + [System.Runtime.CompilerServices.ReflectionBlocked] + public static class AssemblyRuntimeNameHelpers + { + // + // Converts an AssemblyName to a RuntimeAssemblyName that is free from any future mutations on the AssemblyName. + // + public static RuntimeAssemblyName ToRuntimeAssemblyName(this AssemblyName assemblyName) + { + if (assemblyName.Name == null) + throw new ArgumentException(SR.InvalidAssemblyName); + + AssemblyNameFlags flags = assemblyName.Flags; + AssemblyContentType contentType = assemblyName.ContentType; +#pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete + ProcessorArchitecture processorArchitecture = assemblyName.ProcessorArchitecture; +#pragma warning restore SYSLIB0037 + AssemblyNameFlags combinedFlags = CombineAssemblyNameFlags(flags, contentType, processorArchitecture); + byte[]? pkOriginal; + if (0 != (flags & AssemblyNameFlags.PublicKey)) + pkOriginal = assemblyName.GetPublicKey(); + else + pkOriginal = assemblyName.GetPublicKeyToken(); + + // AssemblyName's PKT property getters do NOT copy the array before giving it out. Make our own copy + // as the original is wide open to tampering by anyone. + byte[]? pkCopy = null; + if (pkOriginal != null) + { + pkCopy = new byte[pkOriginal.Length]; + Array.Copy(pkOriginal, pkCopy, pkOriginal.Length); + } + + return new RuntimeAssemblyName(assemblyName.Name, assemblyName.Version, assemblyName.CultureName, combinedFlags, pkCopy); + } + + internal static AssemblyNameFlags CombineAssemblyNameFlags(AssemblyNameFlags flags, AssemblyContentType contentType, ProcessorArchitecture processorArchitecture) + { + return (AssemblyNameFlags)(((int)flags) | (((int)contentType) << 9) | ((int)processorArchitecture << 4)); + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs index 90c0fe5ff824a8..f4dbc0d667140d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs @@ -16,7 +16,7 @@ namespace System.Reflection // public sealed class RuntimeAssemblyName : IEquatable { - public RuntimeAssemblyName(string name, Version version, string cultureName, AssemblyNameFlags flags, byte[] publicKeyOrToken) + public RuntimeAssemblyName(string name, Version? version, string? cultureName, AssemblyNameFlags flags, byte[]? publicKeyOrToken) { Debug.Assert(name != null); this.Name = name; @@ -34,20 +34,26 @@ public RuntimeAssemblyName(string name, Version version, string cultureName, Ass this.PublicKeyOrToken = publicKeyOrToken; } + public static RuntimeAssemblyName Parse(string name) + { + AssemblyNameParser.AssemblyNameParts parts = AssemblyNameParser.Parse(name); + return new RuntimeAssemblyName(parts._name, parts._version, parts._cultureName, parts._flags, parts._publicKeyOrToken); + } + // Simple name. public string Name { get; } // Optional version. - public Version Version { get; } + public Version? Version { get; } // Optional culture name. - public string CultureName { get; } + public string? CultureName { get; } // Optional flags (this is actually an OR of the classic flags and the ContentType.) public AssemblyNameFlags Flags { get; } // Optional public key (if Flags.PublicKey == true) or public key token. - public byte[] PublicKeyOrToken { get; } + public byte[]? PublicKeyOrToken { get; } // Equality - this compares every bit of data in the RuntimeAssemblyName which is acceptable for use as keys in a cache // where semantic duplication is permissible. This method is *not* meant to define ref->def binding rules or @@ -73,8 +79,8 @@ public bool Equals(RuntimeAssemblyName? other) if (this.Flags != other.Flags) return false; - byte[] thisPK = this.PublicKeyOrToken; - byte[] otherPK = other.PublicKeyOrToken; + byte[]? thisPK = this.PublicKeyOrToken; + byte[]? otherPK = other.PublicKeyOrToken; if (thisPK == null) { if (otherPK != null) @@ -139,7 +145,7 @@ public void CopyToAssemblyName(AssemblyName blank) blank.Flags = this.Flags.ExtractAssemblyNameFlags(); blank.ContentType = this.Flags.ExtractAssemblyContentType(); #pragma warning disable SYSLIB0037 // AssemblyName.ProcessorArchitecture is obsolete - blank.ProcessorArchitecture = this.Flags.ExtractProcessorArchitecture(); + blank.ProcessorArchitecture = ExtractProcessorArchitecture(this.Flags); #pragma warning restore SYSLIB0037 if (this.PublicKeyOrToken != null) @@ -162,9 +168,14 @@ public string FullName { get { - byte[] pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; + byte[]? pkt = (0 != (Flags & AssemblyNameFlags.PublicKey)) ? AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrToken) : PublicKeyOrToken; return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags.ExtractAssemblyNameFlags(), Flags.ExtractAssemblyContentType()); } } + + internal static ProcessorArchitecture ExtractProcessorArchitecture(AssemblyNameFlags flags) + { + return (ProcessorArchitecture)((((int)flags) >> 4) & 0x7); + } } } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs index 53edc6a6ec5e49..2227d4a59682b4 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs @@ -89,7 +89,7 @@ private static CoreTypeResolver CreateCoreTypeResolver(Func + namespace System.Reflection.Runtime.General { internal static partial class TypeUnifier diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs index 209a91e0cb1028..fdbcf0b53685d3 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs @@ -10,6 +10,8 @@ using Internal.Reflection.Tracing; +#pragma warning disable CA1067 // override Equals because it implements IEquatable + namespace System.Reflection.Runtime.TypeInfos { // diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs index dfebfcacea21d1..2dc289a7c2fa42 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs @@ -139,7 +139,7 @@ public RuntimeAssemblyName GetNextAssemblyName() } _index = src; string fullName = new string(buffer, 0, dst); - return AssemblyNameParser.Parse(fullName); + return RuntimeAssemblyName.Parse(fullName); } // @@ -173,7 +173,7 @@ public RuntimeAssemblyName GetNextEmbeddedAssemblyName() } _index = src; string fullName = new string(buffer, 0, dst); - return AssemblyNameParser.Parse(fullName); + return RuntimeAssemblyName.Parse(fullName); } // diff --git a/src/coreclr/pal/inc/unixasmmacros.inc b/src/coreclr/pal/inc/unixasmmacros.inc index 1fe285eef162d2..a1bad6300f3cff 100644 --- a/src/coreclr/pal/inc/unixasmmacros.inc +++ b/src/coreclr/pal/inc/unixasmmacros.inc @@ -39,6 +39,8 @@ #include "unixasmmacrosamd64.inc" #elif defined(HOST_ARM) #include "unixasmmacrosarm.inc" +#elif defined(HOST_ARMV6) +#include "unixasmmacrosarm.inc" #elif defined(HOST_ARM64) #include "unixasmmacrosarm64.inc" #elif defined(HOST_S390X) diff --git a/src/coreclr/pal/inc/unixasmmacrosarm.inc b/src/coreclr/pal/inc/unixasmmacrosarm.inc index e0c0016cc26ab2..d323ccc49fbd2d 100644 --- a/src/coreclr/pal/inc/unixasmmacrosarm.inc +++ b/src/coreclr/pal/inc/unixasmmacrosarm.inc @@ -197,7 +197,11 @@ C_FUNC(\Name\()_End): .endm .macro EMIT_BREAKPOINT +#ifdef __armv6__ + .inst 0xe7f001f0 +#else .inst.w 0xde01 +#endif .endm .macro PROLOG_PUSH RegList diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index a9beb759b892ff..29765f81ea77ac 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -45,6 +45,9 @@ if(CLR_CMAKE_HOST_ARCH_AMD64) set(PAL_ARCH_SOURCES_DIR amd64) elseif(CLR_CMAKE_HOST_ARCH_ARM) set(PAL_ARCH_SOURCES_DIR arm) +elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + set(PAL_ARCH_SOURCES_DIR arm) + add_definitions(-D__armv6__) elseif(CLR_CMAKE_HOST_ARCH_ARM64) set(PAL_ARCH_SOURCES_DIR arm64) elseif(CLR_CMAKE_HOST_ARCH_I386) diff --git a/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S index 4179f61e16276d..a7c92e93188e46 100644 --- a/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S +++ b/src/coreclr/pal/src/arch/arm/callsignalhandlerwrapper.S @@ -5,7 +5,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif .macro CALL_SIGNAL_HANDLER_WRAPPER Alignment diff --git a/src/coreclr/pal/src/arch/arm/context2.S b/src/coreclr/pal/src/arch/arm/context2.S index 1cd7684a953e8e..edb5d35bf1e40c 100644 --- a/src/coreclr/pal/src/arch/arm/context2.S +++ b/src/coreclr/pal/src/arch/arm/context2.S @@ -10,7 +10,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif #define CONTEXT_ARM 0x00200000 diff --git a/src/coreclr/pal/src/arch/arm/debugbreak.S b/src/coreclr/pal/src/arch/arm/debugbreak.S index dd8a9348352dcc..88301b98548c35 100644 --- a/src/coreclr/pal/src/arch/arm/debugbreak.S +++ b/src/coreclr/pal/src/arch/arm/debugbreak.S @@ -4,7 +4,9 @@ #include "unixasmmacros.inc" .syntax unified +#ifndef __armv6__ .thumb +#endif LEAF_ENTRY DBG_DebugBreak, _TEXT EMIT_BREAKPOINT diff --git a/src/coreclr/pal/src/arch/arm/exceptionhelper.S b/src/coreclr/pal/src/arch/arm/exceptionhelper.S index f733aad613379d..a43ed14be7d983 100644 --- a/src/coreclr/pal/src/arch/arm/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/arm/exceptionhelper.S @@ -5,7 +5,9 @@ #include "asmconstants.h" .syntax unified +#ifndef __armv6__ .thumb +#endif // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/cruntime/printfcpp.cpp b/src/coreclr/pal/src/cruntime/printfcpp.cpp index d7e992c090a00b..fee79c91df12b4 100644 --- a/src/coreclr/pal/src/cruntime/printfcpp.cpp +++ b/src/coreclr/pal/src/cruntime/printfcpp.cpp @@ -86,7 +86,7 @@ static int Internal_Convertfwrite(CPalThread *pthrCurrent, const void *buffer, s free(newBuff); return -1; } - ret = InternalFwrite(newBuff, 1, count, stream, &iError); + ret = InternalFwrite(newBuff, 1, nsize, stream, &iError); if (iError != 0) { ERROR("InternalFwrite did not write the whole buffer. Error is %d\n", iError); diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 5469b4bebd483a..951680114d8868 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -1242,7 +1242,7 @@ static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv) return NULL; } - if(!MultiByteToWideChar(CP_ACP, 0,command_line, i, retval, i)) + if(!MultiByteToWideChar(CP_ACP, 0,command_line, -1, retval, i)) { ASSERT("MultiByteToWideChar failure\n"); free(retval); diff --git a/src/coreclr/pal/src/libunwind/CMakeLists.txt b/src/coreclr/pal/src/libunwind/CMakeLists.txt index 17659432fd0e4d..dfcd140a89a5be 100644 --- a/src/coreclr/pal/src/libunwind/CMakeLists.txt +++ b/src/coreclr/pal/src/libunwind/CMakeLists.txt @@ -19,6 +19,7 @@ add_definitions(-D_GNU_SOURCE) add_definitions(-DPACKAGE_STRING="") add_definitions(-DPACKAGE_BUGREPORT="") + if(CLR_CMAKE_HOST_UNIX) if (CLR_CMAKE_HOST_ARCH_AMD64) set(arch x86_64) @@ -26,6 +27,8 @@ if(CLR_CMAKE_HOST_UNIX) set(arch aarch64) elseif(CLR_CMAKE_HOST_ARCH_ARM) set(arch arm) + elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + set(arch arm) elseif(CLR_CMAKE_HOST_ARCH_I386) set(arch x86) elseif(CLR_CMAKE_HOST_ARCH_S390X) @@ -45,7 +48,7 @@ if(CLR_CMAKE_HOST_UNIX) add_compile_options(-Wno-incompatible-pointer-types) endif() - if(CLR_CMAKE_HOST_ARCH_ARM) + if(CLR_CMAKE_HOST_ARCH_ARM OR CLR_CMAKE_HOST_ARCH_ARMV6) # Ensure that the remote and local unwind code can reside in the same binary without name clashing add_definitions("-Darm_search_unwind_table=UNW_OBJ(arm_search_unwind_table)") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -109,6 +112,10 @@ if(CLR_CMAKE_HOST_WIN32) set(TARGET_ARM 1) set(arch arm) add_definitions(-D__arm__) + elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + set(TARGET_ARM 1) + set(arch arm) + add_definitions(-D__arm__) elseif(CLR_CMAKE_TARGET_ARCH_S390X) set(TARGET_S390X 1) set(arch s390x) @@ -155,7 +162,7 @@ if(CLR_CMAKE_HOST_WIN32) add_compile_options(-wd4477) # fprintf argument type endif (CLR_CMAKE_HOST_WIN32) -if(CLR_CMAKE_TARGET_ARCH_ARM) +if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARMV6) # The arm sources include ex_tables.h from include/tdep-arm without going through a redirection # in include/tdep like it works for similar files on other architectures. So we need to add # the include/tdep-arm to include directories diff --git a/src/coreclr/pal/src/libunwind/src/CMakeLists.txt b/src/coreclr/pal/src/libunwind/src/CMakeLists.txt index b6dee4f413a809..17a30e027e03e8 100644 --- a/src/coreclr/pal/src/libunwind/src/CMakeLists.txt +++ b/src/coreclr/pal/src/libunwind/src/CMakeLists.txt @@ -316,6 +316,11 @@ if(CLR_CMAKE_HOST_UNIX) SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) + elseif(CLR_CMAKE_HOST_ARCH_ARMV6) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm}) + SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) elseif(CLR_CMAKE_HOST_ARCH_I386) SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os}) SET(libunwind_remote_la_SOURCES ${libunwind_x86_la_SOURCES_x86}) @@ -363,6 +368,11 @@ else(CLR_CMAKE_HOST_UNIX) SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) + elseif(CLR_CMAKE_TARGET_ARCH_ARMV6) + SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_arm}) + SET(libunwind_remote_la_SOURCES ${libunwind_arm_la_SOURCES_arm}) + SET(libunwind_elf_la_SOURCES ${libunwind_elf32_la_SOURCES}) + list(APPEND libunwind_setjmp_la_SOURCES arm/siglongjmp.S) elseif(CLR_CMAKE_TARGET_ARCH_I386) SET(libunwind_la_SOURCES ${libunwind_la_SOURCES_x86} ${libunwind_x86_la_SOURCES_os}) SET(libunwind_remote_la_SOURCES ${libunwind_x86_la_SOURCES_x86}) diff --git a/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c b/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c index 74d42ffe2abb28..07bd4a73b276cc 100644 --- a/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c +++ b/src/coreclr/pal/src/libunwind/src/oop/_OOP_find_proc_info.c @@ -28,6 +28,8 @@ _OOP_find_proc_info ( int ret = 0; unw_dyn_info_t di; + memset(&di, 0, sizeof(di)); + di.start_ip = start_ip; di.end_ip = end_ip; di.gp = pi->gp; diff --git a/src/coreclr/scripts/jitrollingbuild.py b/src/coreclr/scripts/jitrollingbuild.py index 100aff85c35226..71e7d148a61d1d 100644 --- a/src/coreclr/scripts/jitrollingbuild.py +++ b/src/coreclr/scripts/jitrollingbuild.py @@ -74,6 +74,13 @@ git_hash_help = "git hash" +use_latest_jit_change_help = """\ +Starting with the given git hash, look backwards in the git log for the first change that includes any JIT +change. We want to ensure that any git hash uploaded to the JIT rolling build store is a JIT change. This +addresses a problem where Azure DevOps sometimes builds changes that come soon after a JIT change, instead of +the JIT change itself. +""" + target_dir_help = "Directory to put the downloaded JIT." skip_cleanup_help = "Skip intermediate file removal." @@ -97,6 +104,7 @@ upload_parser = subparsers.add_parser("upload", description=upload_description, parents=[common_parser]) upload_parser.add_argument("-git_hash", required=True, help=git_hash_help) +upload_parser.add_argument("--use_latest_jit_change", action="store_true", help=use_latest_jit_change_help) upload_parser.add_argument("-az_storage_key", help="Key for the clrjit Azure Storage location. Default: use the value of the CLRJIT_AZ_KEY environment variable.") upload_parser.add_argument("--skip_cleanup", action="store_true", help=skip_cleanup_help) @@ -458,6 +466,32 @@ def upload_blob(file, blob_name): # pdb_paths = [os.path.join(pdb_dir, item) for item in os.listdir(pdb_dir) if re.match(r'.*clrjit.*', item)] # files += pdb_paths + # Figure out which git hash to use for the upload. By default, it is the required coreclr_args.git_hash argument. + # However, if "--use_latest_jit_change" is passed, we look backwards in the git log for the nearest git commit + # with a JIT change (it could, and often will be, the same as the argument git_hash). + jit_git_hash = coreclr_args.git_hash + + if coreclr_args.use_latest_jit_change: + # Do all the remaining commands, including a number of 'git' commands including relative paths, + # from the root of the runtime repo. + + with ChangeDir(coreclr_args.runtime_repo_location): + # Enumerate the last change, starting with the jit_git_hash, that included JIT changes. + command = [ "git", "log", "--pretty=format:%H", jit_git_hash, "-1", "--", "src/coreclr/jit/*" ] + print("Invoking: {}".format(" ".join(command))) + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + stdout_change_list, _ = proc.communicate() + return_code = proc.returncode + change_list_hashes = [] + if return_code == 0: + change_list_hashes = stdout_change_list.decode('utf-8').strip().splitlines() + + if len(change_list_hashes) == 0: + print("Couldn't find any JIT changes! Just using the argument git_hash") + else: + jit_git_hash = change_list_hashes[0] + print("Using git_hash {}".format(jit_git_hash)) + print("Uploading:") for item in files: print(" {}".format(item)) @@ -472,7 +506,7 @@ def upload_blob(file, blob_name): raise RuntimeError("Missing azure storage package.") blob_service_client = BlobServiceClient(account_url=az_blob_storage_account_uri, credential=coreclr_args.az_storage_key) - blob_folder_name = "{}/{}/{}/{}/{}".format(az_builds_root_folder, coreclr_args.git_hash, coreclr_args.host_os, coreclr_args.arch, coreclr_args.build_type) + blob_folder_name = "{}/{}/{}/{}/{}".format(az_builds_root_folder, jit_git_hash, coreclr_args.host_os, coreclr_args.arch, coreclr_args.build_type) total_bytes_uploaded = 0 @@ -684,6 +718,11 @@ def setup_spmi_location_arg(spmi_location): lambda unused: True, "Unable to set git_hash") + coreclr_args.verify(args, + "use_latest_jit_change", + lambda unused: True, + "Unable to set use_latest_jit_change") + coreclr_args.verify(args, "az_storage_key", lambda item: item is not None, diff --git a/src/coreclr/scripts/jitutil.py b/src/coreclr/scripts/jitutil.py index 9552869dffa979..5df464da5fc0cb 100644 --- a/src/coreclr/scripts/jitutil.py +++ b/src/coreclr/scripts/jitutil.py @@ -85,12 +85,31 @@ def set_pipeline_variable(name, value): print(define_variable_format.format(name, value)) # set variable + ################################################################################ ## ## Helper functions ## ################################################################################ +def decode_string(str_to_decode): + """Decode a UTF-8 encoded bytes to string. + + Args: + str_to_decode (byte stream): Byte stream to decode + + Returns: + String output. If there any encoding/decoding errors, it will replace it with + UnicodeEncodeError. + """ + try: + output = str_to_decode.decode("utf-8", errors='replace') + except UnicodeEncodeError: + output = "UnicodeEncodeError" + except UnicodeDecodeError: + output = "UnicodeDecodeError" + return output + def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None): """ Runs the command. @@ -119,15 +138,15 @@ def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=Non if proc.poll() is not None: break if output: - output_str = output.strip().decode("utf-8", errors='replace') + output_str = decode_string(output.strip()) print(output_str) of.write(output_str + "\n") else: command_stdout, command_stderr = proc.communicate() if len(command_stdout) > 0: - print(command_stdout.decode("utf-8", errors='replace')) + print(decode_string(command_stdout)) if len(command_stderr) > 0: - print(command_stderr.decode("utf-8", errors='replace')) + print(decode_string(command_stderr)) return_code = proc.returncode if _exit_on_fail and return_code != 0: diff --git a/src/coreclr/scripts/superpmi-asmdiffs.proj b/src/coreclr/scripts/superpmi-asmdiffs.proj index aef782d769cb9e..661a60aca831a2 100644 --- a/src/coreclr/scripts/superpmi-asmdiffs.proj +++ b/src/coreclr/scripts/superpmi-asmdiffs.proj @@ -55,7 +55,8 @@ - + + diff --git a/src/coreclr/scripts/superpmi-collect.proj b/src/coreclr/scripts/superpmi-collect.proj index 046a699917fc62..8d59a8218ae884 100644 --- a/src/coreclr/scripts/superpmi-collect.proj +++ b/src/coreclr/scripts/superpmi-collect.proj @@ -42,6 +42,14 @@ PmiAssembliesPayload - Path that will be sent to helix machine to run collection on PmiAssembliesDirectory - Path on helix machine itself where superpmi.py will discover the sent assemblies. --> + + + + + + + + %HELIX_PYTHONPATH% $(WorkItemDirectory)\pmiAssembliesDirectory @@ -54,7 +62,7 @@ %HELIX_WORKITEM_UPLOAD_ROOT% $(BUILD_SOURCESDIRECTORY)\artifacts\helixresults - $(SuperPMIDirectory)\superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)\pmi.dll -pmi_path $(SuperPMIDirectory)\crossgen2 + $(SuperPMIDirectory)\superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)\pmi.dll -pmi_path @(PmiPathDirectories->'$(SuperPMIDirectory)\%(Identity)', ' ') $HELIX_PYTHONPATH @@ -68,7 +76,7 @@ $HELIX_WORKITEM_UPLOAD_ROOT $(BUILD_SOURCESDIRECTORY)/artifacts/helixresults - $(SuperPMIDirectory)/superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)/pmi.dll -pmi_path $(SuperPMIDirectory)/crossgen2 + $(SuperPMIDirectory)/superpmi.py collect -log_level DEBUG --$(CollectionType) -pmi_location $(SuperPMIDirectory)/pmi.dll -pmi_path @(PmiPathDirectories->'$(SuperPMIDirectory)/%(Identity)', ' ') diff --git a/src/coreclr/scripts/superpmi-replay.proj b/src/coreclr/scripts/superpmi-replay.proj index e76a4a3d810e5d..cac87c580fdde4 100644 --- a/src/coreclr/scripts/superpmi-replay.proj +++ b/src/coreclr/scripts/superpmi-replay.proj @@ -55,7 +55,8 @@ - + + diff --git a/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs b/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs index b246a9847f2274..5357e2f68234ba 100644 --- a/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs +++ b/src/coreclr/tools/Common/Compiler/CompilationBuilder.cs @@ -24,6 +24,7 @@ public abstract partial class CompilationBuilder protected IEnumerable _compilationRoots = Array.Empty(); protected OptimizationMode _optimizationMode = OptimizationMode.None; protected int _parallelism = -1; + protected bool _resilient; public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler) { @@ -72,6 +73,12 @@ public CompilationBuilder UseOptimizationMode(OptimizationMode mode) return this; } + public CompilationBuilder UseResilience(bool resilient) + { + _resilient = resilient; + return this; + } + public abstract CompilationBuilder UseBackendOptions(IEnumerable options); public abstract CompilationBuilder UseILProvider(ILProvider ilProvider); diff --git a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs index fa0828fc034e86..029949cda38468 100644 --- a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs +++ b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs @@ -157,7 +157,7 @@ public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAc try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); @@ -174,12 +174,9 @@ public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAc } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/tools/Common/Compiler/Logger.cs b/src/coreclr/tools/Common/Compiler/Logger.cs index eb77c7cd681e12..5ecd5e846c4be3 100644 --- a/src/coreclr/tools/Common/Compiler/Logger.cs +++ b/src/coreclr/tools/Common/Compiler/Logger.cs @@ -10,6 +10,7 @@ using Internal.TypeSystem.Ecma; using ILCompiler.Logging; +using ILLink.Shared; using ILSequencePoint = Internal.IL.ILSequencePoint; using MethodIL = Internal.IL.MethodIL; @@ -47,6 +48,13 @@ public Logger(TextWriter writer, bool isVerbose) { } + public void LogMessage(string message) + { + MessageContainer? messageContainer = MessageContainer.CreateInfoMessage(message); + if(messageContainer.HasValue) + Writer.WriteLine(messageContainer.Value.ToMSBuildString()); + } + public void LogWarning(string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { MessageContainer? warning = MessageContainer.CreateWarningMessage(this, text, code, origin, subcategory); @@ -54,14 +62,19 @@ public void LogWarning(string text, int code, MessageOrigin origin, string subca Writer.WriteLine(warning.Value.ToMSBuildString()); } - public void LogWarning(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) + public void LogWarning(MessageOrigin origin, DiagnosticId id, params string[] args) { - MessageOrigin messageOrigin = new MessageOrigin(origin); - MessageContainer? warning = MessageContainer.CreateWarningMessage(this, text, code, messageOrigin, subcategory); + MessageContainer? warning = MessageContainer.CreateWarningMessage(this, origin, id, args); if (warning.HasValue) Writer.WriteLine(warning.Value.ToMSBuildString()); } + public void LogWarning(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) => + LogWarning(text, code, new MessageOrigin(origin), subcategory); + + public void LogWarning(TypeSystemEntity origin, DiagnosticId id, params string[] args) => + LogWarning(new MessageOrigin(origin), id, args); + public void LogWarning(string text, int code, MethodIL origin, int ilOffset, string subcategory = MessageSubCategory.None) { string document = null; @@ -86,12 +99,62 @@ public void LogWarning(string text, int code, MethodIL origin, int ilOffset, str LogWarning(text, code, messageOrigin, subcategory); } + public void LogWarning(MethodIL origin, int ilOffset, DiagnosticId id, params string[] args) + { + string document = null; + int? lineNumber = null; + + IEnumerable sequencePoints = origin.GetDebugInfo()?.GetSequencePoints(); + if (sequencePoints != null) + { + foreach (var sequencePoint in sequencePoints) + { + if (sequencePoint.Offset <= ilOffset) + { + document = sequencePoint.Document; + lineNumber = sequencePoint.LineNumber; + } + } + } + + MethodDesc warnedMethod = CompilerGeneratedState.GetUserDefinedMethodForCompilerGeneratedMember(origin.OwningMethod) ?? origin.OwningMethod; + + MessageOrigin messageOrigin = new MessageOrigin(warnedMethod, document, lineNumber, null); + LogWarning(messageOrigin, id, args); + } + public void LogWarning(string text, int code, string origin, string subcategory = MessageSubCategory.None) { MessageOrigin _origin = new MessageOrigin(origin); LogWarning(text, code, _origin, subcategory); } + public void LogWarning(string origin, DiagnosticId id, params string[] args) + { + MessageOrigin _origin = new MessageOrigin(origin); + LogWarning(_origin, id, args); + } + + public void LogError(string text, int code, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null) + { + MessageContainer? error = MessageContainer.CreateErrorMessage(text, code, subcategory, origin); + if (error.HasValue) + Writer.WriteLine(error.Value.ToMSBuildString()); + } + + public void LogError(MessageOrigin? origin, DiagnosticId id, params string[] args) + { + MessageContainer? error = MessageContainer.CreateErrorMessage(origin, id, args); + if (error.HasValue) + Writer.WriteLine(error.Value.ToMSBuildString()); + } + + public void LogError(string text, int code, TypeSystemEntity origin, string subcategory = MessageSubCategory.None) => + LogError(text, code, subcategory, new MessageOrigin(origin)); + + public void LogError(TypeSystemEntity origin, DiagnosticId id, params string[] args) => + LogError(new MessageOrigin(origin), id, args); + internal bool IsWarningSuppressed(int code, MessageOrigin origin) { // This is causing too much noise @@ -167,7 +230,7 @@ internal bool IsSingleWarn(ModuleDesc owningModule, string messageSubcategory) { if (_trimWarnedAssemblies.Add(assemblyName)) { - LogWarning($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, GetModuleFileName(owningModule)); + LogWarning(GetModuleFileName(owningModule), DiagnosticId.AssemblyProducedTrimWarnings, assemblyName); } } } @@ -177,12 +240,12 @@ internal bool IsSingleWarn(ModuleDesc owningModule, string messageSubcategory) { if (_aotWarnedAssemblies.Add(assemblyName)) { - LogWarning($"Assembly '{assemblyName}' produced AOT analysis warnings.", 3053, GetModuleFileName(owningModule)); + LogWarning(GetModuleFileName(owningModule), DiagnosticId.AssemblyProducedAOTWarnings, assemblyName); } } } } - + return result; } @@ -198,11 +261,4 @@ private static string GetModuleFileName(ModuleDesc module) return assemblyName; } } - - public static class MessageSubCategory - { - public const string None = ""; - public const string TrimAnalysis = "Trim analysis"; - public const string AotAnalysis = "AOT analysis"; - } } diff --git a/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs b/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs index 95ed5bf04fa0cf..060315e3455558 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/MessageContainer.cs @@ -6,6 +6,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler.Logging @@ -65,6 +67,22 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin return new MessageContainer(MessageCategory.Error, text, code, subcategory, origin); } + /// + /// Create an error message. + /// + /// Filename, line, and column where the error was found + /// Unique error ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of errors and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Error' category + internal static MessageContainer CreateErrorMessage(MessageOrigin? origin, DiagnosticId id, params string[] args) + { + if (!((int)id >= 1000 && (int)id <= 2000)) + throw new ArgumentOutOfRangeException(nameof(id), $"The provided code '{(int)id}' does not fall into the error category, which is in the range of 1000 to 2000 (inclusive)."); + + return new MessageContainer(MessageCategory.Error, id, origin: origin, args: args); + } + /// /// Create a warning message. /// @@ -79,12 +97,29 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin /// New MessageContainer of 'Warning' category internal static MessageContainer? CreateWarningMessage(Logger context, string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { - //if (!(code > 2000 && code <= 6000)) - // throw new ArgumentOutOfRangeException(nameof(code), $"The provided code '{code}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + if (!(code > 2000 && code <= 6000)) + throw new ArgumentOutOfRangeException(nameof(code), $"The provided code '{code}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); return CreateWarningMessageContainer(context, text, code, origin, subcategory); } + /// + /// Create a warning message. + /// + /// Context with the relevant warning suppression info. + /// Filename or member where the warning is coming from + /// Unique warning ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of warnings and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Warning' category + internal static MessageContainer? CreateWarningMessage(Logger context, MessageOrigin origin, DiagnosticId id, params string[] args) + { + if (!((int)id > 2000 && (int)id <= 6000)) + throw new ArgumentOutOfRangeException(nameof(id), $"The provided code '{(int)id}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + + return CreateWarningMessageContainer(context, origin, id, id.GetDiagnosticSubcategory(), args); + } + private static MessageContainer? CreateWarningMessageContainer(Logger context, string text, int code, MessageOrigin origin, string subcategory = MessageSubCategory.None) { if (context.IsWarningSuppressed(code, origin)) @@ -99,6 +134,20 @@ internal static MessageContainer CreateErrorMessage(string text, int code, strin return new MessageContainer(MessageCategory.Warning, text, code, subcategory, origin); } + private static MessageContainer? CreateWarningMessageContainer(Logger context, MessageOrigin origin, DiagnosticId id, string subcategory, params string[] args) + { + if (context.IsWarningSuppressed((int)id, origin)) + return null; + + if (TryLogSingleWarning(context, (int)id, origin, subcategory)) + return null; + + if (context.IsWarningAsError((int)id)) + return new MessageContainer(MessageCategory.WarningAsError, id, subcategory, origin, args); + + return new MessageContainer(MessageCategory.Warning, id, subcategory, origin, args); + } + private static bool TryLogSingleWarning(Logger context, int code, MessageOrigin origin, string subcategory) { if (subcategory != MessageSubCategory.AotAnalysis && subcategory != MessageSubCategory.TrimAnalysis) @@ -135,7 +184,7 @@ private static bool TryLogSingleWarning(Logger context, int code, MessageOrigin private static bool IsTrimmableAssembly(ModuleDesc assembly) { if (assembly is EcmaAssembly ecmaAssembly) - { + { foreach (var attribute in ecmaAssembly.GetDecodedCustomAttributes("System.Reflection", "AssemblyMetadataAttribute")) { if (attribute.FixedArguments.Length != 2) @@ -193,6 +242,15 @@ private MessageContainer(MessageCategory category, string text, int? code, strin Text = text; } + private MessageContainer(MessageCategory category, DiagnosticId id, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null, params string[] args) + { + Code = (int)id; + Category = category; + Origin = origin; + SubCategory = subcategory; + Text = new DiagnosticString(id).GetMessage(args); + } + public override string ToString() => ToMSBuildString(); public string ToMSBuildString() @@ -238,7 +296,7 @@ public string ToMSBuildString() { if (Origin?.MemberDefinition is MethodDesc method) sb.Append(method.GetDisplayName()); - else + else sb.Append(Origin?.MemberDefinition.ToString()); sb.Append(": "); diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs index 34821288b76d9d..3c22da1f5478b1 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using ILLink.Shared; using Mono.Cecil; namespace Mono.Linker @@ -41,15 +42,11 @@ void PopulateCacheForType (TypeDefinition type) case "AsyncIteratorStateMachineAttribute": case "AsyncStateMachineAttribute": case "IteratorStateMachineAttribute": - TypeDefinition stateMachineType = GetFirstConstructorArgumentAsType (attribute); + TypeDefinition? stateMachineType = GetFirstConstructorArgumentAsType (attribute); if (stateMachineType != null) { if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd (stateMachineType, method)) { var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType]; - _context.LogWarning ( - $"Methods '{method.GetDisplayName ()}' and '{alreadyAssociatedMethod.GetDisplayName ()}' are both associated with state machine type '{stateMachineType.GetDisplayName ()}'. This is currently unsupported and may lead to incorrectly reported warnings.", - 2107, - new MessageOrigin (method), - MessageSubCategory.TrimAnalysis); + _context.LogWarning (new MessageOrigin (method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName (), alreadyAssociatedMethod.GetDisplayName (), stateMachineType.GetDisplayName ()); } } @@ -59,7 +56,7 @@ void PopulateCacheForType (TypeDefinition type) } } - static TypeDefinition GetFirstConstructorArgumentAsType (CustomAttribute attribute) + static TypeDefinition? GetFirstConstructorArgumentAsType (CustomAttribute attribute) { if (!attribute.HasConstructorArguments) return null; @@ -67,13 +64,13 @@ static TypeDefinition GetFirstConstructorArgumentAsType (CustomAttribute attribu return attribute.ConstructorArguments[0].Value as TypeDefinition; } - public MethodDefinition GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) + public MethodDefinition? GetUserDefinedMethodForCompilerGeneratedMember (IMemberDefinition sourceMember) { if (sourceMember == null) return null; TypeDefinition compilerGeneratedType = (sourceMember as TypeDefinition) ?? sourceMember.DeclaringType; - if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition userDefinedMethod)) + if (_compilerGeneratedTypeToUserCodeMethod.TryGetValue (compilerGeneratedType, out MethodDefinition? userDefinedMethod)) return userDefinedMethod; // Only handle async or iterator state machine diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs index ed4763b75cda81..65211abd93c074 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureGenerator.PartVisitor.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.Collections.Generic; @@ -147,7 +146,10 @@ public void VisitTypeReference (TypeReference typeReference, StringBuilder build } if (typeReference.IsNested) { - VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver), builder, resolver); + Debug.Assert (typeReference is not SentinelType && typeReference is not PinnedType); + // GetInflatedDeclaringType may return null for generic parameters, byrefs, and pointers, but these + // are separately handled above. + VisitTypeReference (typeReference.GetInflatedDeclaringType (resolver)!, builder, resolver); builder.Append ('.'); } diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs index 923197f58b6bf0..8a6594e47f2052 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/DocumentationSignatureParser.cs @@ -1,8 +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. - -#nullable enable using System; using System.Collections.Generic; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs index f0a4afd09b1875..69fb968c4ef9ce 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs @@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text; +using ILLink.Shared; using Mono.Cecil; namespace Mono.Linker @@ -54,6 +55,22 @@ internal static MessageContainer CreateErrorMessage (string text, int code, stri return new MessageContainer (MessageCategory.Error, text, code, subcategory, origin); } + /// + /// Create an error message. + /// + /// Filename, line, and column where the error was found + /// Unique error ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of errors and possibly add a new one + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Error' category + internal static MessageContainer CreateErrorMessage (MessageOrigin? origin, DiagnosticId id, params string[] args) + { + if (!((int) id >= 1000 && (int) id <= 2000)) + throw new ArgumentOutOfRangeException (nameof (id), $"The provided code '{(int) id}' does not fall into the error category, which is in the range of 1000 to 2000 (inclusive)."); + + return new MessageContainer (MessageCategory.Error, id, origin: origin, args: args); + } + /// /// Create a custom error message. /// @@ -96,6 +113,25 @@ internal static MessageContainer CreateWarningMessage (LinkContext context, stri return CreateWarningMessageContainer (context, text, code, origin, version, subcategory); } + /// + /// Create a warning message. + /// + /// Context with the relevant warning suppression info. + /// Filename or member where the warning is coming from + /// Unique warning ID. Please see https://github.com/dotnet/linker/blob/main/docs/error-codes.md + /// for the list of warnings and possibly add a new one + /// Optional warning version number. Versioned warnings can be controlled with the + /// warning wave option --warn VERSION. Unversioned warnings are unaffected by this option. + /// Additional arguments to form a humanly readable message describing the warning + /// New MessageContainer of 'Warning' category + internal static MessageContainer CreateWarningMessage (LinkContext context, MessageOrigin origin, DiagnosticId id, WarnVersion version, params string[] args) + { + if (!((int) id > 2000 && (int) id <= 6000)) + throw new ArgumentOutOfRangeException (nameof (id), $"The provided code '{(int) id}' does not fall into the warning category, which is in the range of 2001 to 6000 (inclusive)."); + + return CreateWarningMessageContainer (context, origin, id, version, id.GetDiagnosticSubcategory (), args); + } + /// /// Create a custom warning message. /// @@ -141,6 +177,26 @@ private static MessageContainer CreateWarningMessageContainer (LinkContext conte return new MessageContainer (MessageCategory.Warning, text, code, subcategory, origin); } + private static MessageContainer CreateWarningMessageContainer (LinkContext context, MessageOrigin origin, DiagnosticId id, WarnVersion version, string subcategory, params string[] args) + { + if (!(version >= WarnVersion.ILLink0 && version <= WarnVersion.Latest)) + throw new ArgumentException ($"The provided warning version '{version}' is invalid."); + + if (context.IsWarningSuppressed ((int) id, origin)) + return Empty; + + if (version > context.WarnVersion) + return Empty; + + if (TryLogSingleWarning (context, (int) id, origin, subcategory)) + return Empty; + + if (context.IsWarningAsError ((int) id)) + return new MessageContainer (MessageCategory.WarningAsError, id, subcategory, origin, args); + + return new MessageContainer (MessageCategory.Warning, id, subcategory, origin, args); + } + public bool IsWarningMessage ([NotNullWhen (true)] out int? code) { code = null; @@ -159,15 +215,16 @@ static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin or if (subcategory != MessageSubCategory.TrimAnalysis) return false; - Debug.Assert (origin.Provider != null); + // There are valid cases where we can't map the message to an assembly + // For example if it's caused by something in an xml file passed on the command line + // In that case, give up on single-warn collapse and just print out the warning on its own. var assembly = origin.Provider switch { AssemblyDefinition asm => asm, TypeDefinition type => type.Module.Assembly, IMemberDefinition member => member.DeclaringType.Module.Assembly, - _ => throw new NotSupportedException () + _ => null }; - Debug.Assert (assembly != null); if (assembly == null) return false; @@ -181,7 +238,7 @@ static bool TryLogSingleWarning (LinkContext context, int code, MessageOrigin or return false; if (context.AssembliesWithGeneratedSingleWarning.Add (assemblyName)) - context.LogWarning ($"Assembly '{assemblyName}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries", 2104, context.GetAssemblyLocation (assembly)); + context.LogWarning (context.GetAssemblyLocation (assembly), DiagnosticId.AssemblyProducedTrimWarnings, assemblyName); return true; } @@ -215,6 +272,15 @@ private MessageContainer (MessageCategory category, string text, int? code, stri Text = text; } + private MessageContainer (MessageCategory category, DiagnosticId id, string subcategory = MessageSubCategory.None, MessageOrigin? origin = null, params string[] args) + { + Code = (int) id; + Category = category; + Origin = origin; + SubCategory = subcategory; + Text = new DiagnosticString (id).GetMessage (args); + } + public override string ToString () => ToMSBuildString (); public string ToMSBuildString () @@ -256,6 +322,8 @@ public string ToMSBuildString () if (Origin?.Provider != null) { if (Origin?.Provider is MethodDefinition method) sb.Append (method.GetDisplayName ()); + else if (Origin?.Provider is MemberReference memberRef) + sb.Append (memberRef.GetDisplayName ()); else if (Origin?.Provider is IMemberDefinition member) sb.Append (member.FullName); else if (Origin?.Provider is AssemblyDefinition assembly) @@ -274,7 +342,7 @@ public string ToMSBuildString () public bool Equals (MessageContainer other) => (Category, Text, Code, SubCategory, Origin) == (other.Category, other.Text, other.Code, other.SubCategory, other.Origin); - public override bool Equals (object obj) => obj is MessageContainer messageContainer && Equals (messageContainer); + public override bool Equals (object? obj) => obj is MessageContainer messageContainer && Equals (messageContainer); public override int GetHashCode () => (Category, Text, Code, SubCategory, Origin).GetHashCode (); public int CompareTo (MessageContainer other) diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs index 84357b26ae221d..62de5fb3268fb0 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs @@ -12,49 +12,55 @@ namespace Mono.Linker { public readonly struct MessageOrigin : IComparable, IEquatable { -#nullable enable public string? FileName { get; } public ICustomAttributeProvider? Provider { get; } - readonly ICustomAttributeProvider _suppressionContextMember; + readonly ICustomAttributeProvider? _suppressionContextMember; public ICustomAttributeProvider? SuppressionContextMember { get { Debug.Assert (_suppressionContextMember == null || _suppressionContextMember is IMemberDefinition || _suppressionContextMember is AssemblyDefinition); return _suppressionContextMember ?? Provider; } } -#nullable disable + public int SourceLine { get; } public int SourceColumn { get; } public int? ILOffset { get; } const int HiddenLineNumber = 0xfeefee; - public MessageOrigin (IMemberDefinition memberDefinition, int? ilOffset = null) + public MessageOrigin (IMemberDefinition? memberDefinition, int? ilOffset = null) : this (memberDefinition as ICustomAttributeProvider, ilOffset) { } - public MessageOrigin (ICustomAttributeProvider provider) + public MessageOrigin (ICustomAttributeProvider? provider) : this (provider, null) { } public MessageOrigin (string fileName, int sourceLine = 0, int sourceColumn = 0) + : this (fileName, sourceLine, sourceColumn, null) + { + } + + // The assembly attribute should be specified if available as it allows assigning the diagnostic + // to a an assembly (we group based on assembly). + public MessageOrigin (string fileName, int sourceLine, int sourceColumn, AssemblyDefinition? assembly) { FileName = fileName; SourceLine = sourceLine; SourceColumn = sourceColumn; - Provider = null; + Provider = assembly; _suppressionContextMember = null; ILOffset = null; } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset) : this (provider, ilOffset, null) { } - public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset, ICustomAttributeProvider suppressionContextMember) + public MessageOrigin (ICustomAttributeProvider? provider, int? ilOffset, ICustomAttributeProvider? suppressionContextMember) { Debug.Assert (provider == null || provider is IMemberDefinition || provider is AssemblyDefinition); Debug.Assert (suppressionContextMember == null || suppressionContextMember is IMemberDefinition || provider is AssemblyDefinition); @@ -66,7 +72,7 @@ public MessageOrigin (ICustomAttributeProvider provider, int? ilOffset, ICustomA ILOffset = ilOffset; } - public MessageOrigin (MessageOrigin other, IMemberDefinition suppressionContextMember) + public MessageOrigin (MessageOrigin other, IMemberDefinition? suppressionContextMember) { FileName = other.FileName; Provider = other.Provider; @@ -76,21 +82,21 @@ public MessageOrigin (MessageOrigin other, IMemberDefinition suppressionContextM ILOffset = other.ILOffset; } - public override string ToString () + public override string? ToString () { int sourceLine = SourceLine, sourceColumn = SourceColumn; - string fileName = FileName; + string? fileName = FileName; if (Provider is MethodDefinition method && method.DebugInformation.HasSequencePoints) { var offset = ILOffset ?? 0; - SequencePoint correspondingSequencePoint = method.DebugInformation.SequencePoints + SequencePoint? correspondingSequencePoint = method.DebugInformation.SequencePoints .Where (s => s.Offset <= offset)?.Last (); // If the warning comes from hidden line (compiler generated code typically) // search for any sequence point with non-hidden line number and report that as a best effort. - if (correspondingSequencePoint.StartLine == HiddenLineNumber) { + if (correspondingSequencePoint?.StartLine == HiddenLineNumber) { correspondingSequencePoint = method.DebugInformation.SequencePoints - .Where (s => s.StartLine != HiddenLineNumber)?.FirstOrDefault (); + .Where (s => s.StartLine != HiddenLineNumber).FirstOrDefault (); } if (correspondingSequencePoint != null) { @@ -118,7 +124,7 @@ public override string ToString () public bool Equals (MessageOrigin other) => (FileName, Provider, SourceLine, SourceColumn, ILOffset) == (other.FileName, other.Provider, other.SourceLine, other.SourceColumn, other.ILOffset); - public override bool Equals (object obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); + public override bool Equals (object? obj) => obj is MessageOrigin messageOrigin && Equals (messageOrigin); public override int GetHashCode () => (FileName, Provider, SourceLine, SourceColumn).GetHashCode (); public static bool operator == (MessageOrigin lhs, MessageOrigin rhs) => lhs.Equals (rhs); public static bool operator != (MessageOrigin lhs, MessageOrigin rhs) => !lhs.Equals (rhs); @@ -128,12 +134,12 @@ public int CompareTo (MessageOrigin other) if (Provider != null && other.Provider != null) { var thisMember = Provider as IMemberDefinition; var otherMember = other.Provider as IMemberDefinition; - TypeDefinition thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; - TypeDefinition otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? thisTypeDef = (Provider as TypeDefinition) ?? (Provider as IMemberDefinition)?.DeclaringType; + TypeDefinition? otherTypeDef = (other.Provider as TypeDefinition) ?? (other.Provider as IMemberDefinition)?.DeclaringType; var thisAssembly = thisTypeDef?.Module.Assembly ?? Provider as AssemblyDefinition; var otherAssembly = otherTypeDef?.Module.Assembly ?? other.Provider as AssemblyDefinition; - int result = (thisAssembly.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo - ((otherAssembly.Name.Name, otherTypeDef?.Name, otherMember?.Name)); + int result = (thisAssembly?.Name.Name, thisTypeDef?.Name, thisMember?.Name).CompareTo + ((otherAssembly?.Name.Name, otherTypeDef?.Name, otherMember?.Name)); if (result != 0) return result; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md index 883332600e88d0..4fdfbf1c1fdac3 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/README.md @@ -1 +1 @@ -Sources from the dotnet/linker repo at commit c0567db0b9088e2ad4144cd0fe2a985611ec28f0. +Sources from the dotnet/linker repo at commit 2999a6a9dd884d554be18d3c86a4a9db4b61e156. diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs index 55b09b37b3431e..aa1a796bfaa0f1 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs @@ -20,6 +20,7 @@ public void EmitSource() WriteLine("#pragma warning disable 649"); WriteLine("#pragma warning disable 169"); WriteLine("#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct"); + WriteLine("#pragma warning disable CA1066 // IEquatable implementations aren't used"); WriteLine("#pragma warning disable IDE0059"); WriteLine(); diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs index 1d92be56771488..bbc23ec8784848 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs @@ -6,6 +6,7 @@ #pragma warning disable 649 #pragma warning disable 169 #pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used #pragma warning disable IDE0059 using System; diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs index 8eba905400e423..5b7921f972f97a 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - #pragma warning disable 169 - -// There is no defined ordering between fields in multiple declarations of partial class or struct -#pragma warning disable 282 - +#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used using System; using System.IO; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs b/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs index 1b067af21b476a..03a59a840e1ded 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/CastingHelper.cs @@ -263,7 +263,7 @@ private static bool CanCastParamTo(this ParameterizedType thisType, TypeDesc par else if (curTypesParm.IsGenericParameter) { var genericVariableFromParam = (GenericParameterDesc)curTypesParm; - if (genericVariableFromParam.HasReferenceTypeConstraint) + if (genericVariableFromParam.HasReferenceTypeConstraint || IsConstrainedAsGCPointer(genericVariableFromParam)) { return genericVariableFromParam.CanCastToInternal(paramType, protect); } @@ -281,6 +281,30 @@ private static bool CanCastParamTo(this ParameterizedType thisType, TypeDesc par return false; } + private static bool IsConstrainedAsGCPointer(GenericParameterDesc type) + { + foreach (var typeConstraint in type.TypeConstraints) + { + if (typeConstraint.IsGenericParameter) + { + if (IsConstrainedAsGCPointer((GenericParameterDesc)typeConstraint)) + return true; + } + + if (!typeConstraint.IsInterface && typeConstraint.IsGCPointer) + { + // Object, ValueType, and Enum are GCPointers but they do not constrain the type to GCPointer! + if (!typeConstraint.IsWellKnownType(WellKnownType.Object) && + !typeConstraint.IsWellKnownType(WellKnownType.ValueType) && + !typeConstraint.IsWellKnownType(WellKnownType.Enum)) + { + return true; + } + } + } + return false; + } + private static TypeFlags GetNormalizedIntegralArrayElementType(TypeDesc type) { Debug.Assert(!type.IsEnum); @@ -502,7 +526,7 @@ private static bool IsBoxedAndCanCastTo(this TypeDesc thisType, TypeDesc otherTy else if (thisType.IsGenericParameter) { var genericVariableFromParam = (GenericParameterDesc)thisType; - if (genericVariableFromParam.HasReferenceTypeConstraint) + if (genericVariableFromParam.HasReferenceTypeConstraint || IsConstrainedAsGCPointer(genericVariableFromParam)) { return genericVariableFromParam.CanCastToInternal(otherType, protect); } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs index 2ec3883af9f08b..c794377bf19712 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs @@ -12,7 +12,9 @@ namespace Internal.TypeSystem /// type system do not have a known size. This type is used to make such sizes viral through the type layout /// computations) /// +#pragma warning disable CA1066 // IEquatable implementation wouldn't be used public struct LayoutInt +#pragma warning restore CA1066 { private int _value; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 9973be45ff1308..637f1f7538ff88 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -37,12 +37,8 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp TypeDesc fieldType = field.FieldType; - // ByRef instance fields are not allowed. - if (fieldType.IsByRef) - ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); - - // ByRef-like instance fields on non-byref-like types are not allowed. - if (fieldType.IsByRefLike && !type.IsByRefLike) + // ByRef and byref-like instance fields on non-byref-like types are not allowed. + if ((fieldType.IsByRef || fieldType.IsByRefLike) && !type.IsByRefLike) ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); numInstanceFields++; @@ -481,7 +477,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, } else { - Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum); + Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _); instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++; @@ -815,7 +811,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, } else { - Debug.Assert(fieldType.IsPointer || fieldType.IsFunctionPointer); + Debug.Assert(fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsByRef); result.Size = fieldType.Context.Target.LayoutPointerSize; result.Alignment = fieldType.Context.Target.LayoutPointerSize; } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs index 48ca23cf1ea26f..537b494b0d6f9d 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs @@ -256,7 +256,8 @@ private TypeDesc ParseTypeImpl(SignatureTypeCode typeCode) else return null; default: - throw new BadImageFormatException(); + ThrowHelper.ThrowBadImageFormatException(); + return null; } } diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs index 5d8d4fd0f4c2b5..b270b73ab8d90b 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs @@ -26,7 +26,7 @@ private static unsafe MetadataReader TryOpenMetadataFile(string filePath, Metada try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); @@ -56,12 +56,9 @@ private static unsafe MetadataReader TryOpenMetadataFile(string filePath, Metada } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index b50d0406129ba6..d37f44971968b7 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -95,6 +95,9 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type, case MarshallerKind.OleDateTime: return context.GetWellKnownType(WellKnownType.Double); + case MarshallerKind.FailedTypeLoad: + return context.GetWellKnownType(WellKnownType.IntPtr); + case MarshallerKind.SafeHandle: case MarshallerKind.CriticalHandle: return context.GetWellKnownType(WellKnownType.IntPtr); @@ -456,7 +459,7 @@ internal static MarshallerKind GetMarshallerKind( case NativeTypeKind.Array: { if (isField) - return MarshallerKind.Invalid; + return MarshallerKind.FailedTypeLoad; var arrayType = (ArrayType)type; @@ -583,6 +586,8 @@ internal static MarshallerKind GetMarshallerKind( } else if (type.IsObject) { + if (nativeType == NativeTypeKind.AsAny && isField) + return MarshallerKind.FailedTypeLoad; if (nativeType == NativeTypeKind.AsAny) return isAnsi ? MarshallerKind.AsAnyA : MarshallerKind.AsAnyW; else diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs index 4244a04ab1810c..01b27026152389 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs @@ -86,6 +86,8 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind) return new OleDateTimeMarshaller(); case MarshallerKind.OleCurrency: return new OleCurrencyMarshaller(); + case MarshallerKind.FailedTypeLoad: + return new FailedTypeLoadMarshaller(); case MarshallerKind.Variant: return new VariantMarshaller(); default: @@ -1073,6 +1075,19 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream) } } + class FailedTypeLoadMarshaller : Marshaller + { + protected override void TransformManagedToNative(ILCodeStream codeStream) + { + ThrowHelper.ThrowTypeLoadException(ManagedType); + } + + protected override void TransformNativeToManaged(ILCodeStream codeStream) + { + ThrowHelper.ThrowTypeLoadException(ManagedType); + } + } + class VariantMarshaller : Marshaller { protected override void AllocManagedToNative(ILCodeStream codeStream) diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs index 37d09857b694ad..888a174ff38fcc 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs @@ -45,6 +45,7 @@ enum MarshallerKind LayoutClassPtr, AsAnyA, AsAnyW, + FailedTypeLoad, ComInterface, BlittableValueClassWithCopyCtor, Invalid diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index f3f780e87e060b..d19b60b104c242 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -143,8 +143,9 @@ public virtual ISymbolNode GetFieldRvaData(FieldDesc field) { // Use the typical field definition in case this is an instantiated generic type field = field.GetTypicalFieldDefinition(); + int fieldTypePack = (field.FieldType as MetadataType)?.GetClassLayout().PackingSize ?? 1; return NodeFactory.ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), - ((EcmaField)field).GetFieldRvaData(), NodeFactory.Target.PointerSize); + ((EcmaField)field).GetFieldRvaData(), Math.Max(NodeFactory.Target.PointerSize, fieldTypePack)); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs index fb4ad5ce51b7f6..232df5cd22d4e2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs @@ -24,6 +24,7 @@ partial class CompilationBuilder protected bool _methodBodyFolding; protected InstructionSetSupport _instructionSetSupport; protected SecurityMitigationOptions _mitigationOptions; + protected bool _useDwarf5; partial void InitializePartial() { @@ -103,6 +104,12 @@ public CompilationBuilder UseMethodImportationErrorProvider(MethodImportationErr return this; } + public CompilationBuilder UseDwarf5(bool value) + { + _useDwarf5 = value; + return this; + } + protected PreinitializationManager GetPreinitializationManager() { if (_preinitializationManager == null) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs index f3585e0e098f06..6e659a95eb7e79 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/FlowAnnotations.cs @@ -10,6 +10,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler.Dataflow @@ -287,9 +289,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(field.FieldType)) { // Already know that there's a non-empty annotation on a field which is not System.Type/String and we're about to ignore it - _logger.LogWarning( - $"Field '{field.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'.", - 2097, field, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(field, DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings, field.GetDisplayName()); continue; } @@ -341,9 +341,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) } else { - _logger.LogWarning( - $"The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters though.", - 2041, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods); } } @@ -362,9 +360,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) returnAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes()); if (returnAnnotation != DynamicallyAccessedMemberTypes.None && !IsTypeInterestingForDataflow(signature.ReturnType)) { - _logger.LogWarning( - $"Return type of method '{method.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'.", - 2106, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings, method.GetDisplayName()); } } else @@ -375,9 +371,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(signature[parameter.SequenceNumber - 1])) { - _logger.LogWarning( - $"Parameter #{parameter.SequenceNumber} of method '{method.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'.", - 2098, method, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings, $"#{parameter.SequenceNumber}", method.GetDisplayName()); continue; } @@ -433,9 +427,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (!IsTypeInterestingForDataflow(property.Signature.ReturnType)) { - _logger.LogWarning( - $"Property '{property.GetDisplayName()}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'.", - 2099, property, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings, property.GetDisplayName()); continue; } @@ -460,9 +452,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (annotatedMethods.Any(a => a.Method == setMethod)) { - _logger.LogWarning( - $"'DynamicallyAccessedMembersAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its accessor '{setMethod.GetDisplayName()}'.", - 2043, setMethod, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(setMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), setMethod.GetDisplayName()); } else { @@ -496,9 +486,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (annotatedMethods.Any(a => a.Method == getMethod)) { - _logger.LogWarning( - $"'DynamicallyAccessedMembersAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its accessor '{getMethod.GetDisplayName()}'.", - 2043, getMethod, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(getMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), getMethod.GetDisplayName()); } else { @@ -510,9 +498,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) if (backingFieldFromGetter != null && backingFieldFromSetter != null && backingFieldFromGetter != backingFieldFromSetter) { - _logger.LogWarning( - $"Could not find a unique backing field for property '{property.GetDisplayName()}' to propagate 'DynamicallyAccessedMembersAttribute'.", - 2042, property, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName()); backingField = null; } else @@ -524,9 +510,7 @@ protected override TypeAnnotations CreateValueFromKey(TypeDesc key) { if (annotatedFields.Any(a => a.Field == backingField)) { - _logger.LogWarning( - $"'DynamicallyAccessedMemberAttribute' on property '{property.GetDisplayName()}' conflicts with the same attribute on its backing field '{backingField.GetDisplayName()}'.", - 2056, backingField, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName()); } else { @@ -729,33 +713,23 @@ void LogValidationWarning(object provider, object baseProvider, MethodDesc origi switch (provider) { case int parameterNumber: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter #{parameterNumber} of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(origin)}' " + - $"don't match overridden parameter #{parameterNumber} of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2092, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides, + $"#{parameterNumber}", DiagnosticUtilities.GetMethodSignatureDisplayName(origin), + $"#{parameterNumber}", DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; case GenericParameterDesc genericParameterOverride: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the generic parameter '{genericParameterOverride.Name}' of '{DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin(genericParameterOverride))}' " + - $"don't match overridden generic parameter '{((GenericParameterDesc)baseProvider).Name}' of '{DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin((GenericParameterDesc)baseProvider))}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2095, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides, + genericParameterOverride.Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin(genericParameterOverride)), + ((GenericParameterDesc)baseProvider).Name, DiagnosticUtilities.GetGenericParameterDeclaringMemberDisplayName(new GenericParameterOrigin((GenericParameterDesc)baseProvider))); break; case TypeDesc methodReturnType: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(origin)}' " + - $"don't match overridden return value of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2093, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides, + DiagnosticUtilities.GetMethodSignatureDisplayName(origin), DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; // No fields - it's not possible to have a virtual field and override it case MethodDesc methodDefinition: - _logger.LogWarning( - $"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the implicit 'this' parameter of method '{DiagnosticUtilities.GetMethodSignatureDisplayName(methodDefinition)}' " + - $"don't match overridden implicit 'this' parameter of method '{DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)}'. " + - $"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.", - 2094, origin, subcategory: MessageSubCategory.TrimAnalysis); + _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMismatchOnImplicitThisBetweenOverrides, + DiagnosticUtilities.GetMethodSignatureDisplayName(methodDefinition), DiagnosticUtilities.GetMethodSignatureDisplayName((MethodDesc)baseProvider)); break; default: throw new NotImplementedException($"Unsupported provider type {provider.GetType()}"); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index 06d371cd17aea0..420dc07dcfa759 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -1029,8 +1029,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } RequireDynamicallyAccessedMembers( @@ -1048,8 +1048,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } RequireDynamicallyAccessedMembers( @@ -2162,8 +2162,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet // We don't know what method the `MakeGenericMethod` was called on, so we have to assume // that the method may have requirements which we can't fullfil -> warn. reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage( + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage( DiagnosticUtilities.GetMethodSignatureDisplayName(calledMethod))); } } @@ -2226,9 +2226,8 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet { string arg1 = MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(calledMethod, "RequiresUnreferencedCodeAttribute")); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg(DiagnosticUtilities.GetRequiresAttributeUrl(calledMethod, "RequiresUnreferencedCodeAttribute")); - string message = new DiagnosticString(DiagnosticId.RequiresUnreferencedCode).GetMessage(calledMethod.GetDisplayName(), arg1, arg2); - _logger.LogWarning(message, (int)DiagnosticId.RequiresUnreferencedCode, callingMethodBody, offset, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(callingMethodBody, offset, DiagnosticId.RequiresUnreferencedCode, calledMethod.GetDisplayName(), arg1, arg2); } if (shouldEnableAotWarnings && @@ -2241,9 +2240,8 @@ static void LogDynamicCodeWarning(Logger logger, MethodIL callingMethodBody, int { string arg1 = MessageFormat.FormatRequiresAttributeMessageArg(DiagnosticUtilities.GetRequiresAttributeMessage(calledMethod, "RequiresDynamicCodeAttribute")); string arg2 = MessageFormat.FormatRequiresAttributeUrlArg(DiagnosticUtilities.GetRequiresAttributeUrl(calledMethod, "RequiresDynamicCodeAttribute")); - string message = new DiagnosticString(DiagnosticId.RequiresDynamicCode).GetMessage(calledMethod.GetDisplayName(), arg1, arg2); - logger.LogWarning(message, (int)DiagnosticId.RequiresDynamicCode, callingMethodBody, offset, MessageSubCategory.AotAnalysis); + logger.LogWarning(callingMethodBody, offset, DiagnosticId.RequiresDynamicCode, calledMethod.GetDisplayName(), arg1, arg2); } // To get good reporting of errors we need to track the origin of the value for all method calls @@ -2933,32 +2931,20 @@ void WarnOnReflectionAccess(ref ReflectionPatternContext context, TypeSystemEnti // are not suppressed in RUC scopes. Here the scope represents the DynamicallyAccessedMembers // annotation on a type, not a callsite which uses the annotation. We always want to warn about // possible reflection access indicated by these annotations. - - var message = string.Format( - "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements.", - ((TypeOrigin)context.MemberWithRequirements).GetDisplayName(), - entity.GetDisplayName()); - _logger.LogWarning(message, 2115, context.Source, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers, + ((TypeOrigin)context.MemberWithRequirements).GetDisplayName(), entity.GetDisplayName()); } else { if (entity is FieldDesc && context.ReportingEnabled) { - _logger.LogWarning( - $"Field '{entity.GetDisplayName()}' with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field.", - 2110, - context.Source, - MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersFieldAccessedViaReflection, entity.GetDisplayName()); } else { Debug.Assert(entity is MethodDesc); - _logger.LogWarning( - $"Method '{entity.GetDisplayName()}' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.", - 2111, - context.Source, - MessageSubCategory.TrimAnalysis); + _logger.LogWarning(context.Source, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName()); } } } @@ -2969,11 +2955,8 @@ void MarkMethod(ref ReflectionPatternContext reflectionContext, MethodDesc metho { if (_purpose == ScanningPurpose.GetTypeDataflow) { - var message = string.Format( - "'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.", - ((TypeOrigin)reflectionContext.MemberWithRequirements).GetDisplayName(), - method.GetDisplayName()); - _logger.LogWarning(message, 2113, reflectionContext.Source, MessageSubCategory.TrimAnalysis); + _logger.LogWarning(reflectionContext.Source, DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode, + ((TypeOrigin)reflectionContext.MemberWithRequirements).GetDisplayName(), method.GetDisplayName()); } } @@ -3066,8 +3049,8 @@ void ValidateGenericMethodInstantiation( if (!AnalyzeGenericInstantiationTypeArray(genericParametersArray, ref reflectionContext, reflectionMethod, genericMethod.GetMethodDefinition().Instantiation)) { reflectionContext.RecordUnrecognizedPattern( - (int)DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed, - new DiagnosticString(DiagnosticId.MakeGenericMethodCannotBeStaticallyAnalyzed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(reflectionMethod))); + (int)DiagnosticId.MakeGenericMethod, + new DiagnosticString(DiagnosticId.MakeGenericMethod).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(reflectionMethod))); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs index 99d97784e78119..61a48fe965a0c4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionPatternContext.cs @@ -7,6 +7,8 @@ using Internal.IL; using Internal.TypeSystem; +using ILLink.Shared; + namespace ILCompiler.Dataflow { /// diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs index e690b5d420078e..5462b8fedc11ba 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs @@ -85,6 +85,9 @@ public class ObjectWriter : IDisposable, ITypesDebugInfoWriter [DllImport(NativeObjectWriterFileName)] private static extern void FinishObjWriter(IntPtr objWriter); + [DllImport(NativeObjectWriterFileName)] + private static extern void SetDwarfVersion(IntPtr objWriter, ushort v); + [DllImport(NativeObjectWriterFileName)] private static extern void SwitchSection(IntPtr objWriter, string sectionName, CustomSectionAttributes attributes = 0, string comdatName = null); @@ -884,6 +887,11 @@ public ObjectWriter(string objectFilePath, NodeFactory factory, ObjectWritingOpt _isSingleFileCompilation = _nodeFactory.CompilationModuleGroup.IsSingleFileCompilation; _userDefinedTypeDescriptor = new UserDefinedTypeDescriptor(this, factory); _options = options; + + if ((_options & ObjectWritingOptions.UseDwarf5) != 0) + { + SetDwarfVersion(_nativeObjectWriter, 5); + } } public void Dispose() @@ -1319,5 +1327,6 @@ public enum ObjectWritingOptions { GenerateDebugInfo = 0x01, ControlFlowGuard = 0x02, + UseDwarf5 = 0x4, } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs index 378af488af0208..cfbfe6d7a5e476 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/ModuleCycleInfo.cs @@ -8,6 +8,8 @@ using Internal.TypeSystem; using Internal.TypeSystem.Ecma; +using ILLink.Shared; + using Debug = System.Diagnostics.Debug; namespace ILCompiler @@ -232,14 +234,9 @@ public void LogWarnings(Logger logger) if (!reportedProblems.Add(new EntityPair(ownerDefinition, referentDefinition))) continue; - string message = $"Generic expansion to '{actualProblem.Key.Referent.GetDisplayName()}' was aborted " + - "due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. " + - "Generic recursion also negatively affects compilation speed and the size of the compilation output. " + - "It is advisable to remove the source of the generic recursion by restructuring the program around " + - "the source of recursion. The source of generic recursion might include: "; - ModuleCycleInfo cycleInfo = actualProblem.Value; bool first = true; + string message = ""; foreach (TypeSystemEntity cycleEntity in cycleInfo.EntitiesInCycles) { if (!first) @@ -250,7 +247,7 @@ public void LogWarnings(Logger logger) message += $"'{cycleEntity.GetDisplayName()}'"; } - logger.LogWarning(message, 3054, actualProblem.Key.Owner, MessageSubCategory.AotAnalysis); + logger.LogWarning(actualProblem.Key.Owner, DiagnosticId.GenericRecursionCycle, actualProblem.Key.Referent.GetDisplayName(), message); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs index e1c1362e109c02..430c77f98f9056 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs @@ -73,12 +73,7 @@ private void AddParameterMarshallingDependencies(ref DependencyList dependencies reportedMethod = delegateThunkMethod.InvokeMethod; } - var message = new DiagnosticString(DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(method)); - _logger.LogWarning( - message, - (int)DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, - reportedMethod, - MessageSubCategory.AotAnalysis); + _logger.LogWarning(reportedMethod, DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, DiagnosticUtilities.GetMethodSignatureDisplayName(method)); } // struct may contain delegate fields, hence we need to add dependencies for it diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index 439d4e014e6db3..46702412ba73a2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -15,6 +15,7 @@ using ILCompiler.Metadata; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; +using ILLink.Shared; using FlowAnnotations = ILCompiler.Dataflow.FlowAnnotations; using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; @@ -682,16 +683,12 @@ public override void NoteOverridingMethod(MethodDesc baseMethod, MethodDesc over if (baseMethodRequiresUnreferencedCode != overridingMethodRequiresUnreferencedCode) { - Logger.LogWarning( - $"Presence of 'RequiresUnreferencedCodeAttribute' on method '{overridingMethod.GetDisplayName()}' doesn't match overridden method '{baseMethod.GetDisplayName()}'. " + - $"All overridden methods must have 'RequiresUnreferencedCodeAttribute'.", 2046, overridingMethod, MessageSubCategory.TrimAnalysis); + Logger.LogWarning(overridingMethod, DiagnosticId.RequiresUnreferencedCodeAttributeMismatch, overridingMethod.GetDisplayName(), baseMethod.GetDisplayName()); } if (baseMethodRequiresDynamicCode != overridingMethodRequiresDynamicCode) { - Logger.LogWarning( - $"Presence of 'RequiresDynamicCodeAttribute' on method '{overridingMethod.GetDisplayName()}' doesn't match overridden method '{baseMethod.GetDisplayName()}'. " + - $"All overridden methods must have 'RequiresDynamicCodeAttribute'.", 2046, overridingMethod, MessageSubCategory.AotAnalysis); + Logger.LogWarning(overridingMethod, DiagnosticId.RequiresDynamicCodeAttributeMismatch, overridingMethod.GetDisplayName(), baseMethod.GetDisplayName()); } if (baseMethodRequiresDataflow || overridingMethodRequiresDataflow) diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj index 97c97bb7de720d..0d1b23ad73b3c8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj @@ -15,6 +15,7 @@ binaries are up to date and which are stale. --> false Debug;Release;Checked + true diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs new file mode 100644 index 00000000000000..d9972da41f76c6 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompilerComWrappers.cs @@ -0,0 +1,32 @@ + +using System; +using System.Collections; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Microsoft.DiaSymReader +{ + internal unsafe sealed class ILCompilerComWrappers : ComWrappers + { + protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + // passing the managed object to COM is not currently supported + throw new NotImplementedException(); + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flags) + { + // Assert use of the UniqueInstance flag since the returned Native Object Wrapper always + // supports IDisposable and its Dispose will always release and suppress finalization. + // If the wrapper doesn't always support IDisposable the assert can be relaxed. + Debug.Assert(flags.HasFlag(CreateObjectFlags.UniqueInstance)); + + // Throw an exception if the type is not supported by the implementation. + // Null can be returned as well, but an ArgumentNullException will be thrown for + // the consumer of this ComWrappers instance. + return SymNgenWriterWrapper.CreateIfSupported(externalComObject) ?? throw new NotSupportedException(); + } + + protected override void ReleaseObjects(IEnumerable objects) => throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs index 4c4b6b97d60a91..40702fd187a75a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs @@ -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. -#pragma warning disable 436 // SuppressUnmanagedCodeSecurityAttribute defined in source and mscorlib +#pragma warning disable 436 // SuppressUnmanagedCodeSecurityAttribute defined in source and mscorlib using System; using System.Collections.Generic; @@ -11,9 +11,39 @@ namespace Microsoft.DiaSymReader { - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D682FD12-43dE-411C-811B-BE8404CEA126"), SuppressUnmanagedCodeSecurity] + /// + /// IUnknown COM type for writing NGen PDBs + /// + /// + /// + /// [ + /// object, + /// uuid(d682fd12-43de-411c-811b-be8404cea126), + /// pointer_default(unique) + /// ] + /// interface ISymNGenWriter : IUnknown + /// { + /// /* + /// * Add a new public symbol to the NGEN PDB. + /// */ + /// HRESULT AddSymbol([in] BSTR pSymbol, + /// [in] USHORT iSection, + /// [in] ULONGLONG rva); + /// + /// /* + /// * Adds a new section to the NGEN PDB. + /// */ + /// HRESULT AddSection([in] USHORT iSection, + /// [in] USHORT flags, + /// [in] long offset, + /// [in] long cb); + /// }; + /// + /// internal interface ISymNGenWriter { + public static readonly Guid IID = new Guid("D682FD12-43dE-411C-811B-BE8404CEA126"); + // Add a new public symbol to the NGEN PDB. void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, ushort iSection, @@ -46,9 +76,46 @@ internal enum OMF : ushort } - [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4"), SuppressUnmanagedCodeSecurity] + /// + /// IUnknown COM type for writing NGen PDBs + /// + /// + /// + /// [ + /// object, + /// local, + /// uuid(B029E51B-4C55-4fe2-B993-9F7BC1F10DB4), + /// pointer_default(unique) + /// ] + /// interface ISymNGenWriter2 : ISymNGenWriter + /// { + /// HRESULT OpenModW([in] const wchar_t* wszModule, + /// [in] const wchar_t* wszObjFile, + /// [out] BYTE** ppmod); + /// + /// HRESULT CloseMod([in] BYTE* pmod); + /// + /// HRESULT ModAddSymbols([in] BYTE* pmod, [in] BYTE* pbSym, [in] long cb); + /// + /// HRESULT ModAddSecContribEx( + /// [in] BYTE* pmod, + /// [in] USHORT isect, + /// [in] long off, + /// [in] long cb, + /// [in] ULONG dwCharacteristics, + /// [in] DWORD dwDataCrc, + /// [in] DWORD dwRelocCrc); + /// + /// HRESULT QueryPDBNameExW( + /// [out, size_is(cchMax)] wchar_t wszPDB[], + /// [in] SIZE_T cchMax); + /// }; + /// + /// internal interface ISymNGenWriter2 : ISymNGenWriter { + public readonly static new Guid IID = new Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4"); + // Add a new public symbol to the NGEN PDB. new void AddSymbol([MarshalAs(UnmanagedType.BStr)] string pSymbol, ushort iSection, @@ -78,7 +145,7 @@ void ModAddSecContribEx( uint dwRelocCrc); void QueryPDBNameExW( - [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pdb, + [MarshalAs(UnmanagedType.LPWStr)] char[] pdb, IntPtr cchMax); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index a16d5bf19a8e67..be0d8af909f727 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -89,7 +89,7 @@ public class PdbWriter Dictionary _documentToChecksumOffsetMapping; UIntPtr _pdbMod; - ISymNGenWriter2 _ngenWriter; + SymNgenWriterWrapper _ngenWriter; static PdbWriter() { @@ -116,7 +116,7 @@ private static IntPtr DllImportResolver(string libraryName, Assembly assembly, D private extern static void CreateNGenPdbWriter( [MarshalAs(UnmanagedType.LPWStr)] string ngenImagePath, [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, - [MarshalAs(UnmanagedType.Interface)] out ISymNGenWriter2 ngenPdbWriter); + out IntPtr ngenPdbWriterPtr); public PdbWriter(string pdbPath, PDBExtraData pdbExtraData, TargetDetails target) { @@ -138,23 +138,14 @@ public void WritePDBData(string dllPath, IEnumerable methods) { try { - try - { - WritePDBDataHelper(dllPath, methods); - } - finally - { - if ((_ngenWriter != null) && (_pdbMod != UIntPtr.Zero)) - { - _ngenWriter.CloseMod(_pdbMod); - } - } + WritePDBDataHelper(dllPath, methods); } finally { - if (_ngenWriter != null) + if ((_ngenWriter != null) && (_pdbMod != UIntPtr.Zero)) { - Marshal.FinalReleaseComObject(_ngenWriter); + _ngenWriter.CloseMod(_pdbMod); + _ngenWriter?.Dispose(); } } @@ -217,14 +208,16 @@ private void WritePDBDataHelper(string dllPath, IEnumerable methods) // Delete any preexisting PDB file upfront, otherwise CreateNGenPdbWriter silently opens it File.Delete(_pdbFilePath); - CreateNGenPdbWriter(dllPath, _pdbFilePath, out _ngenWriter); + var comWrapper = new ILCompilerComWrappers(); + CreateNGenPdbWriter(dllPath, _pdbFilePath, out var pdbWriterInst); + _ngenWriter = (SymNgenWriterWrapper)comWrapper.GetOrCreateObjectForComInstance(pdbWriterInst, CreateObjectFlags.UniqueInstance); { // PDB file is now created. Get its path and update _pdbFilePath so the PDB file // can be deleted if we don't make it successfully to the end. - StringBuilder pdbFilePathBuilder = new StringBuilder(); - pdbFilePathBuilder.Capacity = 1024; - _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(pdbFilePathBuilder.Capacity)); + const int capacity = 1024; + var pdbFilePathBuilder = new char[capacity]; + _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(capacity - 1) /* remove 1 byte for null */); _pdbFilePath = pdbFilePathBuilder.ToString(); } @@ -428,9 +421,9 @@ private void WriteCompilerVersion() byte iLanguage = (byte)CV_CFL_LANG.CV_CFL_MSIL; writer.Write(iLanguage); // Write rest of flags - writer.Write((byte)0); - writer.Write((byte)0); - writer.Write((byte)0); + writer.Write((byte)0); + writer.Write((byte)0); + writer.Write((byte)0); switch (_target.Architecture) { diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs new file mode 100644 index 00000000000000..8a1166f43a39bf --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs @@ -0,0 +1,149 @@ + +using System; +using System.Runtime.InteropServices; +using System.Text; + +#nullable enable + +namespace Microsoft.DiaSymReader +{ + internal class SymNgenWriterWrapper : ISymNGenWriter2, IDisposable + { + private bool _isDisposed = false; + public IntPtr ISymNGenWriter2Inst { get; } + + private SymNgenWriterWrapper(IntPtr writer2Inst) + { + ISymNGenWriter2Inst = writer2Inst; + } + + public static SymNgenWriterWrapper? CreateIfSupported(IntPtr ptr) + { + var iid = ISymNGenWriter2.IID; + int hr = Marshal.QueryInterface(ptr, ref iid, out IntPtr ngenWriterInst); + if (hr != 0) + { + return null; + } + + return new SymNgenWriterWrapper(ngenWriterInst); + } + + ~SymNgenWriterWrapper() + { + DisposeInternal(); + } + + public void Dispose() + { + DisposeInternal(); + GC.SuppressFinalize(this); + } + + private void DisposeInternal() + { + if (_isDisposed) + { + return; + } + Marshal.Release(ISymNGenWriter2Inst); + _isDisposed = true; + } + + public unsafe void AddSymbol(string pSymbol, ushort iSection, ulong rva) + { + IntPtr strLocal = Marshal.StringToBSTR(pSymbol); + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 3 /* ISymNGenWriter2.AddSymbol slot */)); + int hr = func(inst, strLocal, iSection, rva); + Marshal.FreeBSTR(strLocal); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void AddSection(ushort iSection, OMF flags, int offset, int cb) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 4)); + int hr = func(inst, iSection, flags, offset, cb); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void OpenModW(string wszModule, string wszObjFile, out UIntPtr ppmod) + { + var inst = ISymNGenWriter2Inst; + fixed (char* wszModulePtr = wszModule) + fixed (char* wszObjFilePtr = wszObjFile) + { + UIntPtr ppmodPtr; + var func = (delegate* unmanaged)(*(*(void***)inst + 5)); + int hr = func(inst, wszModulePtr, wszObjFilePtr, &ppmodPtr); + ppmod = ppmodPtr; + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + public unsafe void CloseMod(UIntPtr pmod) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 6)); + int hr = func(inst, pmod); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void ModAddSymbols(UIntPtr pmod, byte[] pbSym, int cb) + { + fixed (byte* pbSymPtr = pbSym) + { + var pbSymLocal = (IntPtr)pbSymPtr; + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 7)); + int hr = func(inst, pmod, pbSymLocal, cb); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + public unsafe void ModAddSecContribEx(UIntPtr pmod, ushort isect, int off, int cb, uint dwCharacteristics, uint dwDataCrc, uint dwRelocCrc) + { + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 8)); + int hr = func(inst, pmod, isect, off, cb, dwCharacteristics, dwDataCrc, dwRelocCrc); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public unsafe void QueryPDBNameExW(char[] pdb, IntPtr cchMax) + { + fixed (char* pdbPtr = pdb) + { + var pdbLocal = (IntPtr)pdbPtr; + var inst = ISymNGenWriter2Inst; + var func = (delegate* unmanaged)(*(*(void***)inst + 9)); + int hr = func(inst, pdbPtr, cchMax); + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + + void ISymNGenWriter.AddSymbol(string pSymbol, ushort iSection, ulong rva) => AddSymbol(pSymbol, iSection, rva); + void ISymNGenWriter.AddSection(ushort iSection, OMF flags, int offset, int cb) => AddSection(iSection, flags, offset, cb); + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs index e8596cf24c894a..a8ff518ac7591e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs @@ -46,15 +46,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) } ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); - builder.RequireInitialPointerAlignment(); + byte[] rvaData = GetRvaData(factory.Target.PointerSize, out int requiredAlignment); + builder.RequireInitialAlignment(requiredAlignment); builder.AddSymbol(this); - builder.EmitBytes(GetRvaData(factory.Target.PointerSize)); + builder.EmitBytes(rvaData); return builder.ToObjectData(); } - private unsafe byte[] GetRvaData(int targetPointerSize) + private unsafe byte[] GetRvaData(int targetPointerSize, out int requiredAlignment) { int size = 0; + requiredAlignment = targetPointerSize; MetadataReader metadataReader = _module.MetadataReader; BlobReader metadataBlob = new BlobReader(_module.PEReader.GetMetadata().Pointer, _module.PEReader.GetMetadata().Length); @@ -80,6 +82,7 @@ private unsafe byte[] GetRvaData(int targetPointerSize) Debug.Assert(field.HasRva); int currentSize = field.FieldType.GetElementSize().AsInt; + requiredAlignment = Math.Max(requiredAlignment, (field.FieldType as MetadataType)?.GetClassLayout().PackingSize ?? 1); if (currentSize > size) { // We need to handle overlapping fields by reusing blobs based on the rva, and just update diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 8f468f78b39771..46ed11d236a953 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -24,7 +24,6 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private readonly IEnumerable _inputFiles; private readonly string _compositeRootPath; private bool _ibcTuning; - private bool _resilient; private bool _generateMapFile; private bool _generateMapCsvFile; private bool _generatePdbFile; @@ -117,12 +116,6 @@ public ReadyToRunCodegenCompilationBuilder UseIbcTuning(bool ibcTuning) return this; } - public ReadyToRunCodegenCompilationBuilder UseResilience(bool resilient) - { - _resilient = resilient; - return this; - } - public ReadyToRunCodegenCompilationBuilder UseProfileData(ProfileDataManager profileData) { _profileData = profileData; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 5154db358a8b8e..6c7d67517a9ee1 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -283,4 +283,5 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs index 0d8b11c51f82e2..7e2b624a3131fc 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs @@ -9,6 +9,7 @@ using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; +using ILLink.Shared; using Internal.IL; using Internal.IL.Stubs; @@ -92,6 +93,9 @@ protected override void CompileInternal(string outputFile, ObjectDumper dumper) NodeFactory.SetMarkingComplete(); ObjectWritingOptions options = default; + if ((_compilationOptions & RyuJitCompilationOptions.UseDwarf5) != 0) + options |= ObjectWritingOptions.UseDwarf5; + if (_debugInformationProvider is not NullDebugInformationProvider) options |= ObjectWritingOptions.GenerateDebugInfo; @@ -195,8 +199,6 @@ private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeN if (exception != null) { - // TODO: fail compilation if a switch was passed - // Try to compile the method again, but with a throwing method body this time. MethodIL throwingIL = TypeSystemThrowingILEmitter.EmitIL(method, exception); corInfo.CompileMethod(methodCodeNodeNeedingCode, throwingIL); @@ -205,12 +207,12 @@ private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeN && method.OwningType is MetadataType mdOwningType && mdOwningType.HasCustomAttribute("System.Runtime.InteropServices", "ClassInterfaceAttribute")) { - Logger.LogWarning("COM interop is not supported with full ahead of time compilation", 3052, method, MessageSubCategory.AotAnalysis); + Logger.LogWarning(method, DiagnosticId.COMInteropNotSupportedInFullAOT); } + if ((_compilationOptions & RyuJitCompilationOptions.UseResilience) != 0) + Logger.LogMessage($"Ignoring unresolved method {method}, because: {exception.Message}"); else - { - Logger.LogWarning($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis); - } + Logger.LogError($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis); } } @@ -242,5 +244,7 @@ public enum RyuJitCompilationOptions { MethodBodyFolding = 0x1, ControlFlowGuardAnnotations = 0x2, + UseDwarf5 = 0x4, + UseResilience = 0x8, } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs index 8b753c71039942..a1446f9d3ff274 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs @@ -110,6 +110,12 @@ public override ICompilation ToCompilation() if ((_mitigationOptions & SecurityMitigationOptions.ControlFlowGuardAnnotations) != 0) options |= RyuJitCompilationOptions.ControlFlowGuardAnnotations; + if (_useDwarf5) + options |= RyuJitCompilationOptions.UseDwarf5; + + if (_resilient) + options |= RyuJitCompilationOptions.UseResilience; + var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider, GetPreinitializationManager()); JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs index f6cd2e187d46c5..4bcf3432f522f3 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CastingTests.cs @@ -202,6 +202,21 @@ public void TestNullableCasting() Assert.True(intType.CanCastTo(nullableOfIntType)); } + [Fact] + public void TestGenericParameterArrayCasting() + { + TypeDesc baseArrayType = _testModule.GetType("Casting", "Base").MakeArrayType(); + TypeDesc iFooArrayType = _testModule.GetType("Casting", "IFoo").MakeArrayType(); + + TypeDesc paramArrayWithBaseClassConstraint = + _testModule.GetType("Casting", "ClassWithBaseClassConstraint`1").Instantiation[0].MakeArrayType(); + TypeDesc paramArrayWithInterfaceConstraint = + _testModule.GetType("Casting", "ClassWithInterfaceConstraint`1").Instantiation[0].MakeArrayType(); + + Assert.True(paramArrayWithBaseClassConstraint.CanCastTo(baseArrayType)); + Assert.False(paramArrayWithInterfaceConstraint.CanCastTo(iFooArrayType)); + } + [Fact] public void TestRecursiveCanCast() { diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs index a6ae700e942a1d..03ce4ae4332cdd 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Casting.cs @@ -3,6 +3,8 @@ namespace Casting { + class Base { } + interface IFoo { } interface IContravariant { } @@ -21,6 +23,8 @@ class ClassWithNoConstraint { } class ClassWithValueTypeConstraint where T : struct { } + class ClassWithBaseClassConstraint where T : Base { } + class ClassWithInterfaceConstraint where T : IFoo { } class ClassWithRecursiveImplementation : IContravariant> { } diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index 6c559924f405c6..6c5a4a6d377d85 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -1,4 +1,4 @@ - + ilc true @@ -121,10 +121,6 @@ On Linux renaming the library makes it difficult to debug it. --> - + diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index e973c05b08c2c6..51400a9e939be0 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -61,6 +61,7 @@ internal class Program private string _instructionSet; private string _guard; private int _maxGenericCycle = CompilerTypeSystemContext.DefaultGenericCycleCutoffPoint; + private bool _useDwarf5; private string _singleMethodTypeName; private string _singleMethodName; @@ -84,6 +85,8 @@ internal class Program private IReadOnlyList _directPInvokeLists = Array.Empty(); + private bool _resilient; + private IReadOnlyList _rootedAssemblies = Array.Empty(); private IReadOnlyList _conditionallyRootedAssemblies = Array.Empty(); private IReadOnlyList _trimmedAssemblies = Array.Empty(); @@ -178,6 +181,7 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("Ot", ref optimizeTime, "Enable optimizations, favor code speed"); syntax.DefineOptionList("m|mibc", ref _mibcFilePaths, "Mibc file(s) for profile guided optimization"); ; syntax.DefineOption("g", ref _enableDebugInfo, "Emit debugging information"); + syntax.DefineOption("gdwarf-5", ref _useDwarf5, "Generate source-level debug information with dwarf version 5"); syntax.DefineOption("nativelib", ref _nativeLib, "Compile as static or shared library"); syntax.DefineOption("exportsfile", ref _exportsFile, "File to write exported method definitions"); syntax.DefineOption("dgmllog", ref _dgmlLogFileName, "Save result of dependency analysis as DGML"); @@ -188,6 +192,7 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("systemmodule", ref _systemModuleName, "System module name (default: System.Private.CoreLib)"); syntax.DefineOption("multifile", ref _multiFile, "Compile only input files (do not compile referenced assemblies)"); syntax.DefineOption("waitfordebugger", ref waitForDebugger, "Pause to give opportunity to attach debugger"); + syntax.DefineOption("resilient", ref _resilient, "Ignore unresolved types, methods, and assemblies. Defaults to false"); syntax.DefineOptionList("codegenopt", ref _codegenOptions, "Define a codegen option"); syntax.DefineOptionList("rdxml", ref _rdXmlFilePaths, "RD.XML file(s) for compilation"); syntax.DefineOption("map", ref _mapFileName, "Generate a map file"); @@ -769,7 +774,8 @@ static string ILLinkify(string rootedAssembly) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode) .UseSecurityMitigationOptions(securityMitigationOptions) - .UseDebugInfoProvider(debugInfoProvider); + .UseDebugInfoProvider(debugInfoProvider) + .UseDwarf5(_useDwarf5); if (scanResults != null) { @@ -798,6 +804,8 @@ static string ILLinkify(string rootedAssembly) builder.UseMethodImportationErrorProvider(scanResults.GetMethodImportationErrorProvider()); } + builder.UseResilience(_resilient); + ICompilation compilation = builder.ToCompilation(); ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null; diff --git a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticId.cs b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticId.cs index 8bffef3ab0e5b5..5ec2e6ec7c5541 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticId.cs +++ b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticId.cs @@ -5,17 +5,123 @@ namespace ILLink.Shared { public enum DiagnosticId { + // Linker error ids. + XmlFeatureDoesNotSpecifyFeatureValue = 1001, + XmlUnsupportedNonBooleanValueForFeature = 1002, + XmlException = 1003, + _unused_FailedToProcessDescriptorFile = 1004, + CouldNotFindMethodInAssembly = 1005, + CannotStubConstructorWhenBaseTypeDoesNotHaveConstructor = 1006, + CouldNotFindType = 1007, + CouldNotFindConstructor = 1008, + CouldNotFindAssemblyReference = 1009, + CouldNotLoadAssembly = 1010, + FailedToWriteOutput = 1011, + LinkerUnexpectedError = 1012, + ErrorProcessingXmlLocation = 1013, + XmlDocumentLocationHasInvalidFeatureDefault = 1014, + UnrecognizedCommandLineOption = 1015, + InvalidWarningVersion = 1016, + InvalidGenerateWarningSuppressionsValue = 1017, + MissingArgumentForCommanLineOptionName = 1018, + CustomDataFormatIsInvalid = 1019, + NoFilesToLinkSpecified = 1020, + NewMvidAndDeterministicCannotBeUsedAtSameTime = 1021, + AssemblyInCustomStepOptionCouldNotBeFound = 1022, + AssemblyPathInCustomStepMustBeFullyQualified = 1023, + InvalidArgForCustomStep = 1024, + ExpectedSignToControlNewStepInsertion = 1025, + PipelineStepCouldNotBeFound = 1026, + CustomStepTypeCouldNotBeFound = 1027, + CustomStepTypeIsIncompatibleWithLinkerVersion = 1028, + InvalidOptimizationValue = 1029, + InvalidArgumentForTokenOption = 1030, + InvalidAssemblyAction = 1031, + RootAssemblyCouldNotBeFound = 1032, + XmlDescriptorCouldNotBeFound = 1033, + RootAssemblyDoesNotHaveEntryPoint = 1034, + RootAssemblyCannotUseAction = 1035, + InvalidAssemblyName = 1036, + InvalidAssemblyRootMode = 1037, + ExportedTypeCannotBeResolved = 1038, + ReferenceAssemblyCouldNotBeLoaded = 1039, + FailedToResolveMetadataElement = 1040, + TypeUsedWithAttributeValueCouldNotBeFound = 1041, + CannotConverValueToType = 1042, + CustomAttributeArgumentForTypeRequiresNestedNode = 1043, + CouldNotResolveCustomAttributeTypeValue = 1044, + UnexpectedAttributeArgumentType = 1045, + InvalidMetadataOption = 1046, + // Linker diagnostic ids. + TypeHasNoFieldsToPreserve = 2001, + TypeHasNoMethodsToPreserve = 2002, + CouldNotResolveDependencyAssembly = 2003, + CouldNotResolveDependencyType = 2004, + CouldNotResolveDependencyMember = 2005, + _unused_UnrecognizedReflectionPattern = 2006, + XmlCouldNotResolveAssembly = 2007, + XmlCouldNotResolveType = 2008, + XmlCouldNotFindMethodOnType = 2009, + XmlInvalidValueForStub = 2010, + XmlUnkownBodyModification = 2011, + XmlCouldNotFindFieldOnType = 2012, + XmlSubstitutedFieldNeedsToBeStatic = 2013, + XmlMissingSubstitutionValueForField = 2014, + XmlInvalidSubstitutionValueForField = 2015, + XmlCouldNotFindEventOnType = 2016, + XmlCouldNotFindPropertyOnType = 2017, + XmlCouldNotFindGetAccesorOfPropertyOnType = 2018, + XmlCouldNotFindSetAccesorOfPropertyOnType = 2019, + _unused_RearrangedXmlWarning1 = 2020, + _unused_RearrangedXmlWarning2 = 2021, + XmlCouldNotFindMatchingConstructorForCustomAttribute = 2022, + XmlMoreThanOneReturnElementForMethod = 2023, + XmlMoreThanOneValueForParameterOfMethod = 2024, + XmlDuplicatePreserveMember = 2025, RequiresUnreferencedCode = 2026, + AttributeShouldOnlyBeUsedOnceOnMember = 2027, + AttributeDoesntHaveTheRequiredNumberOfParameters = 2028, + XmlElementDoesNotContainRequiredAttributeFullname = 2029, + XmlCouldNotResolveAssemblyForAttribute = 2030, + XmlAttributeTypeCouldNotBeFound = 2031, + UnrecognizedParameterInMethodCreateInstance = 2032, + DeprecatedPreserveDependencyAttribute = 2033, + DynamicDependencyAttributeCouldNotBeAnalyzed = 2034, + UnresolvedAssemblyInDynamicDependencyAttribute = 2035, + UnresolvedTypeInDynamicDependencyAttribute = 2036, + NoMembersResolvedForMemberSignatureOrType = 2037, + XmlMissingNameAttributeInResource = 2038, + XmlInvalidValueForAttributeActionForResource = 2039, + XmlCouldNotFindResourceToRemoveInAssembly = 2040, + DynamicallyAccessedMembersIsNotAllowedOnMethods = 2041, + DynamicallyAccessedMembersCouldNotFindBackingField = 2042, + DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor = 2043, + XmlCouldNotFindAnyTypeInNamespace = 2044, + AttributeIsReferencedButTrimmerRemoveAllInstances = 2045, RequiresUnreferencedCodeAttributeMismatch = 2046, + _unused_DynamicallyAccessedMembersMismatchBetweenOverrides = 2047, + XmlRemoveAttributeInstancesCanOnlyBeUsedOnType = 2048, + _unused_UnrecognizedInternalAttribute = 2049, CorrectnessOfCOMCannotBeGuaranteed = 2050, + XmlPropertyDoesNotContainAttributeName = 2051, + XmlCouldNotFindProperty = 2052, + _unused_XmlInvalidPropertyValueForProperty = 2053, + _unused_XmlInvalidArgumentForParameterOfType = 2054, MakeGenericType = 2055, + DynamicallyAccessedMembersOnPropertyConflictsWithBackingField = 2056, + UnrecognizedTypeNameInTypeGetType = 2057, + ParametersOfAssemblyCreateInstanceCannotBeAnalyzed = 2058, + UnrecognizedTypeInRuntimeHelpersRunClassConstructor = 2059, MakeGenericMethod = 2060, - RequiresOnBaseClass = 2109, - RequiresUnreferencedCodeOnStaticConstructor = 2116, + UnresolvedAssemblyInCreateInstance = 2061, + MethodParameterCannotBeStaticallyDetermined = 2062, + MethodReturnValueCannotBeStaticallyDetermined = 2063, + FieldValueCannotBeStaticallyDetermined = 2064, + ImplicitThisCannotBeStaticallyDetermined = 2065, + TypePassedToGenericParameterCannotBeStaticallyDetermined = 2066, // Dynamically Accessed Members attribute mismatch. - MakeGenericMethodCannotBeStaticallyAnalyzed = 2060, DynamicallyAccessedMembersMismatchParameterTargetsParameter = 2067, DynamicallyAccessedMembersMismatchParameterTargetsMethodReturnType = 2068, DynamicallyAccessedMembersMismatchParameterTargetsField = 2069, @@ -41,7 +147,32 @@ public enum DiagnosticId DynamicallyAccessedMembersMismatchTypeArgumentTargetsField = 2089, DynamicallyAccessedMembersMismatchTypeArgumentTargetsThisParameter = 2090, DynamicallyAccessedMembersMismatchTypeArgumentTargetsGenericParameter = 2091, + DynamicallyAccessedMembersMismatchOnMethodParameterBetweenOverrides = 2092, + DynamicallyAccessedMembersMismatchOnMethodReturnValueBetweenOverrides = 2093, + DynamicallyAccessedMembersMismatchOnImplicitThisBetweenOverrides = 2094, + DynamicallyAccessedMembersMismatchOnGenericParameterBetweenOverrides = 2095, + + CaseInsensitiveTypeGetTypeCallIsNotSupported = 2096, + DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings = 2097, + DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings = 2098, + DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings = 2099, + XmlUnsuportedWildcard = 2100, + AssemblyWithEmbeddedXmlApplyToAnotherAssembly = 2101, + InvalidIsTrimmableValue = 2102, PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined = 2103, + AssemblyProducedTrimWarnings = 2104, + TypeWasNotFoundInAssemblyNorBaseLibrary = 2105, + DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings = 2106, + MethodsAreAssociatedWithStateMachine = 2107, + InvalidScopeInUnconditionalSuppressMessage = 2108, + RequiresUnreferencedCodeOnBaseClass = 2109, + DynamicallyAccessedMembersFieldAccessedViaReflection = 2110, + DynamicallyAccessedMembersMethodAccessedViaReflection = 2111, + DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode = 2112, + DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode = 2113, + DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers = 2114, + DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers = 2115, + RequiresUnreferencedCodeOnStaticConstructor = 2116, // Single-file diagnostic ids. AvoidAssemblyLocationInSingleFile = 3000, @@ -52,15 +183,35 @@ public enum DiagnosticId // Dynamic code diagnostic ids. RequiresDynamicCode = 3050, RequiresDynamicCodeAttributeMismatch = 3051, - // TODO: these are all unique to NativeAOT - mono/linker repo is not aware these error codes usage. - // IL3052 - COM - // IL3053 - AOT analysis warnings - // IL3054 - Generic cycle + COMInteropNotSupportedInFullAOT = 3052, + AssemblyProducedAOTWarnings = 3053, + GenericRecursionCycle = 3054, CorrectnessOfAbstractDelegatesCannotBeGuaranteed = 3055, } public static class DiagnosticIdExtensions { public static string AsString(this DiagnosticId diagnosticId) => $"IL{(int)diagnosticId}"; + + public static string GetDiagnosticSubcategory(this DiagnosticId diagnosticId) => + (int)diagnosticId switch + { + 2026 => MessageSubCategory.TrimAnalysis, + 2032 => MessageSubCategory.TrimAnalysis, + 2041 => MessageSubCategory.TrimAnalysis, + 2042 => MessageSubCategory.TrimAnalysis, + 2043 => MessageSubCategory.TrimAnalysis, + 2045 => MessageSubCategory.TrimAnalysis, + 2046 => MessageSubCategory.TrimAnalysis, + 2050 => MessageSubCategory.TrimAnalysis, + >= 2055 and <= 2099 => MessageSubCategory.TrimAnalysis, + 2103 => MessageSubCategory.TrimAnalysis, + 2106 => MessageSubCategory.TrimAnalysis, + 2107 => MessageSubCategory.TrimAnalysis, + >= 2109 and <= 2116 => MessageSubCategory.TrimAnalysis, + >= 3050 and <= 3052 => MessageSubCategory.AotAnalysis, + >= 3054 and <= 3055 => MessageSubCategory.AotAnalysis, + _ => MessageSubCategory.None, + }; } } diff --git a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs index 103b93ed28bb01..f14b58b0600830 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.cs +++ b/src/coreclr/tools/aot/ILLink.Shared/DiagnosticString.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; + namespace ILLink.Shared { public readonly struct DiagnosticString @@ -11,15 +13,15 @@ public readonly struct DiagnosticString public DiagnosticString(DiagnosticId diagnosticId) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString($"{diagnosticId}Title") ?? string.Empty; - _messageFormat = resourceManager.GetString($"{diagnosticId}Message") ?? string.Empty; + _titleFormat = resourceManager.GetString($"{diagnosticId}Title") ?? throw new InvalidOperationException($"{diagnosticId} does not have a matching resource called {diagnosticId}Title"); + _messageFormat = resourceManager.GetString($"{diagnosticId}Message") ?? throw new InvalidOperationException($"{diagnosticId} does not have a matching resource called {diagnosticId}Message"); } public DiagnosticString(string diagnosticResourceStringName) { var resourceManager = SharedStrings.ResourceManager; - _titleFormat = resourceManager.GetString($"{diagnosticResourceStringName}Title") ?? string.Empty; - _messageFormat = resourceManager.GetString($"{diagnosticResourceStringName}Message") ?? string.Empty; + _titleFormat = resourceManager.GetString($"{diagnosticResourceStringName}Title") ?? throw new InvalidOperationException($"{diagnosticResourceStringName} does not have a matching resource called {diagnosticResourceStringName}Title"); + _messageFormat = resourceManager.GetString($"{diagnosticResourceStringName}Message") ?? throw new InvalidOperationException($"{diagnosticResourceStringName} does not have a matching resource called {diagnosticResourceStringName}Message"); } public string GetMessage(params string[] args) => diff --git a/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd b/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd new file mode 100644 index 00000000000000..f1156b0a4d6902 --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/ILLink.LinkAttributes.xsd @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems b/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems index 0a61390d8d025e..ffbfab3b98417f 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems +++ b/src/coreclr/tools/aot/ILLink.Shared/ILLink.Shared.projitems @@ -13,6 +13,7 @@ + @@ -21,4 +22,9 @@ Designer - \ No newline at end of file + + + Designer + + + diff --git a/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs b/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs new file mode 100644 index 00000000000000..92c1077b14baf3 --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/MessageSubCategory.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ILLink.Shared +{ + public static class MessageSubCategory + { + public const string None = ""; + public const string TrimAnalysis = "Trim analysis"; + public const string UnresolvedAssembly = "Unresolved assembly"; + public const string AotAnalysis = "AOT analysis"; + } +} diff --git a/src/coreclr/tools/aot/ILLink.Shared/README.md b/src/coreclr/tools/aot/ILLink.Shared/README.md new file mode 100644 index 00000000000000..229b67e492bf0b --- /dev/null +++ b/src/coreclr/tools/aot/ILLink.Shared/README.md @@ -0,0 +1 @@ +Sources taken from https://github.com/dotnet/linker/tree/890591b13da936d2c38a52afdaeac0db69858d4f/src/ILLink.Shared. diff --git a/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx b/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx index 0d53dff7e254e0..fe39e38906517a 100644 --- a/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx +++ b/src/coreclr/tools/aot/ILLink.Shared/SharedStrings.resx @@ -53,7 +53,6 @@ value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. - mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter @@ -117,12 +116,954 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + An Xml Feature does not specify a 'featurevalue' attribute. + + + Failed to process '{0}'. Feature '{1}' does not specify a 'featurevalue' attribute. + + + Feature definition has to be a boolean. + + + Failed to process '{0}'. Unsupported non-boolean feature definition '{1}'. + + + An exception was thrown while processing the xml file. + + + Error processing '{0}': {1}. + + + An error ocurred while processing a method in assembly. + + + Error processing method '{0}' in assembly '{1}'. + + + Cannot stub constructor of a type when base type does not have default constructor. Constructors of derived types marked for substitution require to have a default constructor in its base type. + + + Cannot stub constructor on '{0}' when base type does not have default constructor. + + + Could not find predefined type". + + + Missing predefined '{0}' type". + + + Could not find constructor. + + + Could not find constructor on '{0}'. + + + Assembly reference could not be resolved. + + + Assembly reference '{0}' could not be resolved. + + + Assembly cannot be loaded due to failure in processing the reference assembly. + + + Assembly '{0}' cannot be loaded due to failure in processing '{1}' reference + + + There was an error writing the linked assembly 'output'. + + + Failed to write '{0}'. + + + There was an unexpected error while trimming. An exception with more details is printed to the MSBuild log. Please share this stack trace with the IL Linker team to further investigate the cause and possible solution. + + + IL Trimmer has encountered an unexpected error. Please report the issue at https://github.com/dotnet/linker/issues + + + There was an error processing 'XML document location' xml file. The most likely reason for this is that the XML file has syntactical errors. + + + Error processing '{0}'. + + + Element in XML document contains a 'featuredefault' attribute with an invalid value. + + + Failed to process '{0}'. Unsupported value for featuredefault attribute. + + + The string passed to the command-line does not correspond to a valid command-line option. + + + Unrecognized command-line option: '{0}'. + + + The value given for the --warn argument was not a valid warning version. + + + Invalid warning version '{0}'. + + + Invalid value 'value' was used for command-line option '--generate-warning-suppressions'; must be 'cs' or 'xml'. + + + Invalid value '{0}' for '--generate-warning-suppressions' option. + + + The command-line option 'optionName' was specified but no argument was given. + + + Missing argument for '{0}' option. + + + The command-line option --custom-data receives a key-value pair using the format KEY=VALUE. + + + Value used with '--custom-data' has to be in the KEY=VALUE format. + + + No input files were specified. Use one of the resolver options. + + + No input files were specified. Use one of '{0}' options. + + + Options '--new-mvid' and '--deterministic' cannot be used at the same time. + + + Options '--new-mvid' and '--deterministic' cannot be used at the same time. + + + The assembly argument specified for '--custom-step' option could not be found. + + + The assembly '{0}' specified for '--custom-step' option could not be found. + + + The path to the assembly specified for '--custom-step' must be fully qualified. + + + The path to the assembly '{0}' specified for '--custom-step' must be fully qualified. + + + An invalid value was specified for '--custom-step' option. + + + Invalid value '{0}' specified for '--custom-step' option. + + + A custom step that is inserted relative to an existing step in the pipeline must specify whether to be added before (-) or after (+) the step it's relative to. + + + Expected '+' or '-' to control new step insertion. + + + A custom step was specified for insertion relative to a non existent step. + + + Pipeline step '{0}' could not be found. + + + The custom step could not be found in the given assembly. + + + Custom step '{0}' could not be found. + + + Custom step is incompatible with this trimmer version. + + + Custom step '{0}' is incompatible with this trimmer version. + + + The optimization 'text' is invalid. Optimization values can either be 'beforefieldinit', 'overrideremoval', 'unreachablebodies', 'unusedinterfaces', 'ipconstprop', or 'sealer'. + + + Invalid optimization value '{0}'. + + + Invalid argument for 'token' option. + + + Invalid argument for '{0}' option. + + + Invalid assembly action. + + + Invalid assembly action '{0}'. + + + Root assembly could not be found. + + + Root assembly '{0}' could not be found. + + + XML descriptor file could not be found'. + + + XML descriptor file '{0}' could not be found'. + + + Root assembly does not have entry point. + + + Root assembly '{0}' does not have entry point. + + + Referenced root assembly cannot use the specified action. + + + Root assembly '{0}' cannot use action '{1}'. + + + Invalid assembly name. + + + Invalid assembly name '{0}'. + + + Invalid assembly root mode. + + + Invalid assembly root mode '{0}'. + + + Exported type cannot be resolved. + + + Exported type '{0}' cannot be resolved. + + + A reference assembly input passed via -reference could not be loaded. + + + Reference assembly '{0}' could not be loaded. + + + Metadata element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + {0}. + + + Field element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Field '{0}' reference could not be resolved. + + + Method element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Method '{0}' reference could not be resolved. + + + Type element cannot be resolved. This usually means there is a version mismatch between dependencies. + + + Type '{0}' reference could not be resolved. + + + The type name used to define custom attribute value could not be resolved. + + + The type '{0}' used with attribute value '{1}' could not be found. + + + The 'value' specified for the custom attribute value cannot be converted to specified argument type 'typeName'. + + + Cannot convert value '{0}' to type '{1}'. + + + The syntax for custom attribute value for 'type' requires to also specify the underlying attribute type. + + + Custom attribute argument for '{0}' requires nested '{1}' node. + + + The value specified for the custom attribute of System.Type type could not be resolved. + + + Could not resolve custom attribute type value '{0}'. + + + The type name used with attribute type is not one of the supported types. + + + Unexpected attribute argument type '{0}'. + + + Invalid metadata value. + + + Invalid metadata value '{0}'. + + + The XML descriptor preserves fields on type, but this type has no fields. + + + Type '{0}' has no fields to preserve. + + + The XML descriptor preserves methods on type, but this type has no methods. + + + Type '{0}' has no methods to preserve. + + + The assembly in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency assembly '{0}' specified in a 'PreserveDependency' attribute. + + + The type in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency type '{0}' specified in a 'PreserveDependency' attribute. + + + The member in PreserveDependency attribute could not be resolved. + + + Could not resolve dependency member '{0}' declared in type '{1}' specified in a 'PreserveDependency' attribute. + + + The assembly in the XML could not be resolved. + + + Could not resolve assembly '{0}'. + + + The type in the XML could not be resolved. + + + Could not resolve type '{0}'. + + + The XML defined a method on a type, but the method was not found. + + + Could not find method '{0}' on type '{1}'. + + + Invalid value for 'signature' stub in the substitution XML. + + + Invalid value for '{0}' stub. + + + The value of the body attribute used in the substitution XML is invalid (the only supported options are remove and stub). + + + Unknown body modification '{0}' for '{1}'. + + + The XML defined a field on a type, but the field was not found. + + + Could not find field '{0}' on type '{1}'. + + + The substituted field 'field' was non-static or constant. Only static non-constant fields are supported. + + + Substituted field '{0}' needs to be static field. + + + A field was specified for substitution but no value to be substituted was given. + + + Missing 'value' attribute for field '{0}'. + + + The value used in the substitution XML for field is not a built-in type, or does not match the type of the field. + + + Invalid value '{0}' for '{1}'. + + + The XML defined a event on a type, but the event was not found. + + + Could not find event '{0}' on type '{1}'. + + + The XML defined a property on a type, but the property was not found. + + + Could not find property '{0}' on type '{1}'. + + + The XML defined the get accessor of property on a type, but the accessor was not found. + + + Could not find the get accessor of property '{0}' on type '{1}'. + + + The XML defined the set accessor of property on a type, but the accessor was not found. + + + Could not find the set accessor of property '{0}' in type '{1}'. + + + The XML attribute arguments use values or types which don't match to any constructor + + + Could not find matching constructor for custom attribute '{0}' arguments. + + + Method 'method' has more than one return element specified. There can only be one return element. + + + There is more than one 'return' child element specified for method '{0}'. + + + Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter. + + + More than one value specified for parameter '{0}' of method '{1}'. + + + The XML descriptor marks for preservation the member more than once. + + + Duplicate preserve of '{0}'. + Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code Using member '{0}' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code.{1}{2} + + Using dynamic types might cause types or members to be removed by trimmer. + + + Invoking members on dynamic types is not trimming-compatible. Types or members might have been removed by the trimmer. + + + The linker found multiple instances of attribute on a member. This attribute is only allowed to have one instance. + + + Attribute '{0}' should only be used once on '{1} + + + Attribute doesn't have the required number of parameters specified. + + + Attribute '{0}' doesn't have the required number of parameters specified. + + + 'attribute' element does not contain attribute 'fullname' or it's empty. + + + 'attribute' element does not contain attribute 'fullname' or it's empty. + + + The assembly name specified for attribute could not be resolved. + + + Could not resolve assembly '{0}' for attribute '{1}'. + + + The described attribute type could not be found in the assemblies. + + + Attribute type '{0}' could not be found. + + + The value passed as the assembly name or type name to the CreateInstance method can't be statically analyzed. + + + Unrecognized value passed to the parameter '{0}' of method '{1}'. It's not possible to guarantee the availability of the target type. + + + 'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead. + + + 'PreserveDependencyAttribute' is deprecated. Use 'DynamicDependencyAttribute' instead. + + + The input contains an invalid use of DynamicDependencyAttribute. + + + The 'DynamicDependencyAttribute' could not be analyzed. + + + The assembly string given in a DynamicDependencyAttribute constructor could not be resolved. + + + Unresolved assembly '{0}' in 'DynamicDependencyAttribute'. + + + The type in a DynamicDependencyAttribute constructor could not be resolved. + + + Unresolved type '{0}' in 'DynamicDependencyAttribute'. + + + The member signature or DynamicallyAccessedMemberTypes in a DynamicDependencyAttribute constructor did not resolve to any members on the type. + + + No members were resolved for '{0}'. + + + The resource element in a substitution file did not have a 'name' attribute. + + + Missing 'name' attribute for resource. + + + The resource element in a substitution file did not have a valid 'action' attribute. + + + Invalid value '{0}' for attribute 'action' for resource '{1}'. + + + The resource name in a substitution file could not be found in the specified assembly. + + + Could not find embedded resource '{0}' to remove in assembly '{1}'. + + + The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters. + + + The 'DynamicallyAccessedMembersAttribute' is not allowed on methods. It is allowed on method return value or method parameters though. + + + Could not find a unique backing field for property to propagate 'DynamicallyAccessedMembersAttribute'. + + + Could not find a unique backing field for property '{0}' to propagate 'DynamicallyAccessedMembersAttribute'. + + + 'DynamicallyAccessedMembersAttribute' on property conflicts with the same attribute on its accessor. + + + 'DynamicallyAccessedMembersAttribute' on property '{0}' conflicts with the same attribute on its accessor '{1}'. + + + The XML descriptor specifies a namespace but there are no types found in such namespace. + + + Could not find any type in namespace '{0}'. + + + An attribute is being referenced in the code but the attribute instances have been removed using the 'RemoveAttributeInstances' internal attribute. + + + Attribute '{0}' is being referenced in code but the trimmer was instructed to remove all instances of this attribute. If the attribute instances are necessary make sure to either remove the trimmer attribute XML portion which removes the attribute instances, or override the removal by using the trimmer XML descriptor to keep the attribute type (which in turn keeps all of its instances). + + + 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + + {0}. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + + Internal attribute 'RemoveAttributeInstances' can only be used on attribute types. + + + Internal attribute '{0}' can only be used on attribute types. + + + Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. + + + P/invoke method '{0}' declares a parameter with COM marshalling. Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. + + + An attribute element has property but this could not be found. + + + Property element does not contain attribute 'name'. + + + An attribute element has property but this could not be found. + + + Property '{0}' could not be found. + + + Either the type on which the MakeGenericType is called can't be statically determined, or the type parameters to be used for generic arguments can't be statically determined. + + + Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. + + + 'DynamicallyAccessedMemberAttribute' on property conflicts with the same attribute on its backing field. + + + 'DynamicallyAccessedMemberAttribute' on property '{0}' conflicts with the same attribute on its backing field '{1}'. + + + Unrecognized value passed to the parameter of method. It's not possible to guarantee the availability of the target type. + + + Unrecognized value passed to the parameter 'typeName' of method '{0}'. It's not possible to guarantee the availability of the target type. + + + Parameters passed to method cannot be analyzed. Consider using methods 'System.Type.GetType' and `System.Activator.CreateInstance` instead. + + + Parameters passed to method '{0}' cannot be analyzed. Consider using methods 'System.Type.GetType' and `System.Activator.CreateInstance` instead. + + + The type passed to the RunClassConstructor is not statically known, Trimmer can't make sure that its static constructor is available. + + + Unrecognized value passed to the parameter 'type' of method '{0}'. It's not possible to guarantee the availability of the target static constructor. + + + Call to 'System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. + + + Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. + + + Calling CreateInstance with assembly name which can't be resolved. + + + The assembly name '{0}' passed to method '{1}' references assembly which is not available. + + + The parameter of method has a DynamicallyAccessedMembersAttribute, but the value passed to it can not be statically analyzed. + + + Value passed to parameter '{0}' of method '{1}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The return value of method has a DynamicallyAccessedMembersAttribute, but the value returned from the method can not be statically analyzed. + + + Value returned from method '{0}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The field has a DynamicallyAccessedMembersAttribute, but the value assigned to it can not be statically analyzed. + + + Value assigned to {0} can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The method has a DynamicallyAccessedMembersAttribute (which applies to the implicit 'this' parameter), but the value used for the 'this' parameter can not be statically analyzed. + + + Value passed to implicit 'this' parameter of method '{0}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + The generic parameter of type or method has a DynamicallyAccessedMembersAttribute, but the value used for it can not be statically analyzed. + + + Type passed to generic parameter '{0}' of '{1}' can not be statically determined and may not meet 'DynamicallyAccessedMembersAttribute' requirements. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations. + + + '{0}' argument does not satisfy {4} in call to '{1}'. The parameter '{2}' of method '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The parameter of method does not have matching annotations. + + + '{0}' method return value does not satisfy {3} requirements. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The parameter of method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {3} requirements. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations. + + + 'this' argument does not satisfy {3} in call to '{0}'. The parameter '{1}' of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The parameter of method does not have matching annotations. + + + '{0}' generic argument does not satisfy {4} in '{1}'. The parameter '{2}' of method '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The return value of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The return value of the source method does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The return value of the source method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The return value of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The return value of the source method does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The return value of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The field '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The source field does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The source field does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The field '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The source field does not have matching annotations. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The field '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' argument does not satisfy {3} in call to '{1}'. The implicit 'this' argument of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' method return value does not satisfy {2} requirements. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The implicit 'this' argument of source method does not have matching annotations. + + + value stored in field '{0}' does not satisfy {2} requirements. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The implicit 'this' argument of source method does not have matching annotations. + + + 'this' argument does not satisfy {2} in call to '{0}'. The implicit 'this' argument of method '{1}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The implicit 'this' argument of source method does not have matching annotations. + + + '{0}' generic argument does not satisfy {3} in '{1}'. The implicit 'this' argument of method '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' argument does not satisfy {4} in call to '{1}'. The generic parameter '{2}' of '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target method return value does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' method return value does not satisfy {3} requirements. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Value stored in target field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The generic parameter of the source method or type does not have matching annotations. + + + value stored in field '{0}' does not satisfy {3} requirements. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations. + + + 'this' argument does not satisfy {3} in call to '{0}'. The generic parameter '{1}' of '{2}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The generic parameter of the source method or type does not have matching annotations. + + + '{0}' generic argument does not satisfy {4} in '{1}'. The generic parameter '{2}' of '{3}' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. + + + 'DynamicallyAccessedMemberTypes' on the parameter of method don't match overridden parameter of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter '{0}' of method '{1}' don't match overridden parameter '{2}' of method '{3}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the return value of method don't match overridden return value of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method '{0}' don't match overridden return value of method '{1}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the implicit 'this' parameter of method don't match overridden implicit 'this' parameter of method. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the implicit 'this' parameter of method '{0}' don't match overridden implicit 'this' parameter of method '{1}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' on the generic parameter of method or type don't match overridden generic parameter method or type. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + 'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the generic parameter '{0}' of '{1}' don't match overridden generic parameter '{2}' of '{3}'. All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage. + + + Call to 'Type.GetType' method can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types. + + + Call to '{0}' can perform case insensitive lookup of the type, currently ILLink can not guarantee presence of all the matching types. + + + Field has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'. + + + Field '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to fields of type 'System.Type' or 'System.String'. + + + Parameter of method has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'. + + + Parameter '{0}' of method '{1}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to parameters of type 'System.Type' or 'System.String'. + + + Property has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Property '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + XML contains unsupported wildcard for assembly 'fullname' attribute. + + + XML contains unsupported wildcard for assembly 'fullname' attribute. + + + Embedded XML in assembly contains assembly "fullname" attribute for another assembly + + + Embedded XML in assembly '{0}' contains assembly "fullname" attribute for another assembly '{1}' + + + Invalid AssemblyMetadata 'IsTrimmable' attribute in assembly. Value must be "True". + + + Invalid AssemblyMetadata("IsTrimmable", "{0}") attribute in assembly '{1}'. Value must be "True". + + + Value passed to the parameter of method cannot be statically determined as a property accessor. + + + Value passed to the '{0}' parameter of method '{1}' cannot be statically determined as a property accessor. + + + Assembly produced trim warnings. + + + Assembly '{0}' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries + + + Type was not found in the caller assembly nor in the base library. Type name strings used for dynamically accessing a type should be assembly qualified. + + + Type '{0}' was not found in the caller assembly nor in the base library. Type name strings used for dynamically accessing a type should be assembly qualified. + + + Return type of method has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Return type of method '{0}' has 'DynamicallyAccessedMembersAttribute', but that attribute can only be applied to properties of type 'System.Type' or 'System.String'. + + + Trimmer currently can't correctly handle if the same compiler generated state machine type is associated (via the state machine attributes) with two different methods. + + + Methods '{0}' and '{1}' are both associated with state machine type '{2}'. This is currently unsupported and may lead to incorrectly reported warnings. + + + Invalid scope used in 'UnconditionalSuppressMessageAttribute'. The only scopes supported on global unconditional suppressions are 'module', 'type' and 'member'. + + + Invalid scope '{0}' used in 'UnconditionalSuppressMessageAttribute' on module '{1}' with target '{2}'. + + + Types that derive from a base class with 'RequiresUnreferencedCodeAttribute' need to explicitly use the 'RequiresUnreferencedCodeAttribute' or suppress this warning + + + Type '{0}' derives from '{1}' which has 'RequiresUnreferencedCodeAttribute'. {2}{3} + + + Field with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field. + + + Field '{0}' with 'DynamicallyAccessedMembersAttribute' is accessed via reflection. Trimmer can't guarantee availability of the requirements of the field. + + + Method with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. + + + Method '{0}' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which requires unreferenced code. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.{2}{3} + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which requires unreferenced code. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which requires unreferenced code.{2}{3} + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on a type or one of its base types references a member which has 'DynamicallyAccessedMembersAttribute' requirements. + + + 'DynamicallyAccessedMembersAttribute' on '{0}' or one of its base types references '{1}' which has 'DynamicallyAccessedMembersAttribute' requirements. + + + The use of 'RequiresUnreferencedCodeAttribute' on static constructors is disallowed since is a method not callable by the user, is only called by the runtime. Placing the attribute directly on the static constructor will have no effect, instead use 'RequiresUnreferencedCodeAttribute' on the type which will handle warning and silencing from the static constructor. + + + 'RequiresUnreferencedCodeAttribute' cannot be placed directly on static constructor '{0}', consider placing 'RequiresUnreferencedCodeAttribute' on the type declaration instead. + Avoid accessing Assembly file path when publishing as a single file @@ -141,29 +1082,47 @@ Using member '{0}' which has 'RequiresAssemblyFilesAttribute' can break functionality when embedded in a single-file app.{1}{2} + + 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + + {0}. 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling. Using member '{0}' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling.{1}{2} - - {0}. 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. - - - 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides. + + 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. {0}. 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. - - 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides. + + COM interop is not supported with full ahead of time compilation. - - {0}. 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + COM interop is not supported with full ahead of time compilation. - - 'RequiresAssemblyFilesAttribute' annotations must match across all interface implementations or overrides. + + Assembly produced AOT analysis warnings. + + + Assembly '{0}' produced AOT analysis warnings. + + + Generic expansion to was aborted due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. + + + Generic expansion to '{0}' was aborted due to generic recursion. An exception will be thrown at runtime if this codepath is ever reached. Generic recursion also negatively affects compilation speed and the size of the compilation output. It is advisable to remove the source of the generic recursion by restructuring the program around the source of recursion. The source of generic recursion might include: {1} + + + P/invoke method declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation. + + + P/invoke method '{0}' declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation: the marshalling code for the delegate might not be available. Use a non-abstract delegate type or ensure any delegate instance passed as parameter is marked with `UnmanagedFunctionPointerAttribute`. Base member '{2}' with '{0}' has a derived member '{1}' without '{0}' @@ -177,40 +1136,4 @@ Interface member '{2}' with '{0}' has an implementation member '{1}' without '{0}' - - Type '{0}' derives from '{1}' which has 'RequiresUnreferencedCodeAttribute'. {2}{3} - - - Types that derive from a base class with 'RequiresUnreferencedCodeAttribute' need to explicitly use the 'RequiresUnreferencedCodeAttribute' or suppress this warning - - - Invoking members on dynamic types is not trimming-compatible. Types or members might have been removed by the trimmer. - - - Using dynamic types might cause types or members to be removed by trimmer. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic type. - - - 'RequiresUnreferencedCodeAttribute' cannot be placed directly on static constructor '{0}', consider placing 'RequiresUnreferencedCodeAttribute' on the type declaration instead. - - - The use of 'RequiresUnreferencedCodeAttribute' on static constructors is disallowed since is a method not callable by the user, is only called by the runtime. Placing the attribute directly on the static constructor will have no effect, instead use 'RequiresUnreferencedCodeAttribute' on the type which will handle warning and silencing from the static constructor. - - - Call to '{0}' can not be statically analyzed. It's not possible to guarantee the availability of requirements of the generic method. - - - Value passed to the '{0}' parameter of method '{1}' cannot be statically determined as a property accessor. - - - P/invoke method '{0}' declares a parameter with COM marshalling. Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. - - - P/invoke method '{0}' declares a parameter with an abstract delegate. Correctness of interop for abstract delegates cannot be guaranteed after native compilation: the marshalling code for the delegate might not be available. Use a non-abstract delegate type or ensure any delegate instance passed as parameter is marked with `UnmanagedFunctionPointerAttribute`. - diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index ff538c05fd64c4..6eedd33da4a6d0 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -730,7 +730,6 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru builder .UseIbcTuning(_commandLineOptions.Tuning) - .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseMapCsvFile(_commandLineOptions.MapCsv) .UsePdbFile(_commandLineOptions.Pdb, _commandLineOptions.PdbPath) @@ -748,6 +747,7 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) .UseParallelism(_commandLineOptions.Parallelism) + .UseResilience(_commandLineOptions.Resilient) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(optimizationMode); diff --git a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs index 09e2f52ea053aa..afdb148089b266 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs @@ -260,7 +260,7 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou try { // Create stream because CreateFromFile(string, ...) uses FileShare.None which is too strict - fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); mappedFile = MemoryMappedFile.CreateFromFile( fileStream, null, fileStream.Length, MemoryMappedFileAccess.Read, HandleInheritability.None, true); accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); @@ -278,12 +278,9 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou } finally { - if (accessor != null) - accessor.Dispose(); - if (mappedFile != null) - mappedFile.Dispose(); - if (fileStream != null) - fileStream.Dispose(); + accessor?.Dispose(); + mappedFile?.Dispose(); + fileStream?.Dispose(); } } diff --git a/src/coreclr/utilcode/securitywrapper.cpp b/src/coreclr/utilcode/securitywrapper.cpp index 8f7ac38f444a0e..67b462bf00a267 100644 --- a/src/coreclr/utilcode/securitywrapper.cpp +++ b/src/coreclr/utilcode/securitywrapper.cpp @@ -206,117 +206,6 @@ HRESULT GetSidFromProcessWorker(DWORD dwProcessId, SidType sidType, PSID *ppSid) return hr; } -#ifndef FEATURE_CORESYSTEM -//----------------------------------------------------------------------------- -// get the sid of a given process id using WTSEnumerateProcesses -// @todo: Make this function fail when WTSEnumerateProcesses is not available -// Or is it always available on all of our platform? -// -// Caller remember to call delete on *ppSid -//----------------------------------------------------------------------------- -HRESULT GetSidFromProcessEXWorker(DWORD dwProcessId, PSID *ppSid) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - PRECONDITION(CheckPointer(ppSid)); - } - CONTRACTL_END; - - HRESULT hr = S_OK; - PWTS_PROCESS_INFOW rgProcessInfo = NULL; - DWORD dwNumProcesses; - DWORD iProc; - DWORD cbSid; - PSID pSid = NULL; - - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx: 0x%08x\n", - dwProcessId)); - - - *ppSid = NULL; - if (!WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, // use local server - 0, // Reserved must be zero - 1, // version must be 1 - &rgProcessInfo, // Receives pointer to process list - &dwNumProcesses)) - { - hr = HRESULT_FROM_GetLastError(); - goto exit; - } - - for (iProc = 0; iProc < dwNumProcesses; iProc++) - { - - if (rgProcessInfo[iProc].ProcessId == dwProcessId) - { - if (rgProcessInfo[iProc].pUserSid == NULL) - { - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx is not able to retrieve SID\n")); - - // if there is no Sid for the user, don't call GetLengthSid. - // It will crash! It is ok to return E_FAIL as caller will ignore it. - hr = E_FAIL; - goto exit; - } - cbSid = GetLengthSid(rgProcessInfo[iProc].pUserSid); - pSid = new (nothrow) BYTE[cbSid]; - if (pSid == NULL) - { - hr = E_OUTOFMEMORY; - } - else - { - if (!CopySid(cbSid, pSid, rgProcessInfo[iProc].pUserSid)) - { - hr = HRESULT_FROM_GetLastError(); - } - else - { - // We are done. Go to exit - hr = S_OK; - } - } - - // we already find a match. Even if we fail from memory allocation of CopySid, still - // goto exit. - goto exit; - } - } - - // Walk the whole list and cannot find the matching PID - // Find a better error code. - hr = E_FAIL; - -exit: - - if (rgProcessInfo) - { - WTSFreeMemory(rgProcessInfo); - } - - if (FAILED(hr) && pSid) - { - delete [] (reinterpret_cast(pSid)); - } - - if (SUCCEEDED(hr)) - { - _ASSERTE(pSid); - *ppSid = pSid; - } - LOG((LF_CORDB, LL_INFO10000, - "SecurityUtil::GetSidFromProcessEx return hr : 0x%08x\n", - hr)); - - - return hr; -} -#endif // !FEATURE_CORESYSTEM - //----------------------------------------------------------------------------- // The functions below initialize this SidBuffer instance with a Sid from // the token of the specified process. The first pair use the OWNER sid from @@ -361,12 +250,6 @@ HRESULT SidBuffer::InitFromProcessNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kOwnerSid, (PSID *) &m_pBuffer); -#ifndef FEATURE_CORESYSTEM - if (FAILED(hr)) - { - hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); - } -#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; @@ -526,12 +409,6 @@ HRESULT SidBuffer::InitFromProcessUserNoThrow(DWORD pid) _ASSERTE(m_pBuffer == NULL); HRESULT hr = GetSidFromProcessWorker(pid, kUserSid, (PSID *) &m_pBuffer); -#ifndef FEATURE_CORESYSTEM - if (FAILED(hr)) - { - hr = GetSidFromProcessEXWorker(pid, (PSID *) &m_pBuffer); - } -#endif // !FEATURE_CORESYSTEM if (FAILED(hr)) { return hr; diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index 6b5f7af901ac11..9ab6790efb3f60 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -2137,11 +2137,7 @@ void SString::PVPrintf(const WCHAR *format, va_list args) { // First, try to use the existing buffer va_copy(ap, args); -#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); -#else - int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); -#endif va_end(ap); if (result >= 0) { @@ -2171,11 +2167,7 @@ void SString::PVPrintf(const WCHAR *format, va_list args) errno = 0; va_copy(ap, args); -#if defined(FEATURE_CORESYSTEM) int result = _vsnwprintf_s(GetRawUnicode(), GetRawCount()+1, _TRUNCATE, format, ap); -#else - int result = _vswprintf_p(GetRawUnicode(), GetRawCount()+1, format, ap); -#endif va_end(ap); if (result >= 0) diff --git a/src/coreclr/utilcode/stresslog.cpp b/src/coreclr/utilcode/stresslog.cpp index a9e36516b6dcd2..5d13b2ec7695ca 100644 --- a/src/coreclr/utilcode/stresslog.cpp +++ b/src/coreclr/utilcode/stresslog.cpp @@ -345,6 +345,12 @@ void StressLog::AddModule(uint8_t* moduleBase) } #endif //MEMORY_MAPPED_STRESSLOG theLog.modules[moduleIndex].size = PAL_CopyModuleData(moduleBase, destination, destination_end); +#ifdef MEMORY_MAPPED_STRESSLOG + if (hdr != nullptr) + { + hdr->modules[moduleIndex].size = theLog.modules[moduleIndex].size; + } +#endif //MEMORY_MAPPED_STRESSLOG #endif //HOST_WINDOWS } @@ -884,7 +890,6 @@ void StressLog::LogMsg(unsigned level, unsigned facility, const StressLogMsg &ms if (InlinedStressLogOn(facility, level)) { -#ifdef HOST_WINDOWS // On Linux, this cast: (va_list)msg.m_args gives a compile error ThreadStressLog* msgs = t_pCurrentThreadLog; if (msgs == 0) @@ -894,7 +899,15 @@ void StressLog::LogMsg(unsigned level, unsigned facility, const StressLogMsg &ms if (msgs == 0) return; } +#ifdef HOST_WINDOWS + // On Linux, this cast: (va_list)msg.m_args gives a compile error msgs->LogMsg(facility, msg.m_cArgs, msg.m_format, (va_list)msg.m_args); +#else + msgs->LogMsg(facility, msg.m_cArgs, msg.m_format, + msg.m_args[0], msg.m_args[1], msg.m_args[2], msg.m_args[3], + msg.m_args[4], msg.m_args[5], msg.m_args[6], msg.m_args[7], + msg.m_args[8], msg.m_args[9], msg.m_args[10], msg.m_args[11], + msg.m_args[12], msg.m_args[13], msg.m_args[14], msg.m_args[15]); #endif //HOST_WINDOWS } diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 44b5250547689c..ee90f9db6c538a 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -25,61 +25,6 @@ UINT32 g_nClrInstanceId = 0; #endif //!DACCESS_COMPILE -//********** Code. ************************************************************ - -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -extern WinRTStatusEnum gWinRTStatus = WINRT_STATUS_UNINITED; -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM - -#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) -//------------------------------------------------------------------------------ -// -// Attempt to detect the presense of Windows Runtime support on the current OS. -// Our algorithm to do this is to ensure that: -// 1. combase.dll exists -// 2. combase.dll contains a RoInitialize export -// - -void InitWinRTStatus() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_CANNOT_TAKE_LOCK; - - WinRTStatusEnum winRTStatus = WINRT_STATUS_UNSUPPORTED; - - const WCHAR wszComBaseDll[] = W("\\combase.dll"); - const SIZE_T cchComBaseDll = ARRAY_SIZE(wszComBaseDll); - - WCHAR wszComBasePath[MAX_LONGPATH + 1]; - const SIZE_T cchComBasePath = ARRAY_SIZE(wszComBasePath); - - ZeroMemory(wszComBasePath, cchComBasePath * sizeof(wszComBasePath[0])); - - UINT cchSystemDirectory = WszGetSystemDirectory(wszComBasePath, MAX_LONGPATH); - - // Make sure that we're only probing in the system directory. If we can't find the system directory, or - // we find it but combase.dll doesn't fit into it, we'll fall back to a safe default of saying that WinRT - // is simply not present. - if (cchSystemDirectory > 0 && cchComBasePath - cchSystemDirectory >= cchComBaseDll) - { - if (wcscat_s(wszComBasePath, wszComBaseDll) == 0) - { - HModuleHolder hComBase(WszLoadLibrary(wszComBasePath)); - if (hComBase != NULL) - { - FARPROC activateInstace = GetProcAddress(hComBase, "RoInitialize"); - if (activateInstace != NULL) - { - winRTStatus = WINRT_STATUS_SUPPORTED; - } - } - } - } - - gWinRTStatus = winRTStatus; -} -#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM //***************************************************************************** // Convert a string of hex digits into a hex value of the specified # of bytes. //***************************************************************************** @@ -1806,9 +1751,7 @@ HRESULT validateOneArg( // Validate the referenced type. if(FAILED(hr = validateOneArg(tk, pSig, pulNSentinels, pImport, FALSE))) IfFailGo(hr); break; - case ELEMENT_TYPE_BYREF: //fallthru - if(TypeFromToken(tk)==mdtFieldDef) IfFailGo(VLDTR_E_SIG_BYREFINFIELD); - FALLTHROUGH; + case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_PINNED: case ELEMENT_TYPE_SZARRAY: // Validate the referenced type. diff --git a/src/coreclr/utilcode/utilmessagebox.cpp b/src/coreclr/utilcode/utilmessagebox.cpp index 5a8b1f5e2d69b8..8ae1d046169e78 100644 --- a/src/coreclr/utilcode/utilmessagebox.cpp +++ b/src/coreclr/utilcode/utilmessagebox.cpp @@ -17,12 +17,6 @@ #include "clrversion.h" #include "../dlls/mscorrc/resource.h" #include "ex.h" -#if !defined(FEATURE_CORESYSTEM) -#undef NTDDI_VERSION -#define NTDDI_VERSION NTDDI_WIN7 -#include "commctrl.h" -#endif - BOOL ShouldDisplayMsgBoxOnCriticalFailure() { @@ -193,48 +187,46 @@ int UtilMessageBoxNonLocalizedVA( } #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) - // If the current process isn't interactive (a service for example), then we report the message - // in the event log and via OutputDebugString. +#ifdef HOST_UNIX + // For non-interactive processes, we report the message in the event log and via OutputDebugString. // // We may still however attempt to display the message box if the MB_SERVICE_NOTIFICATION // message box style was specified. - if (!RunningInteractive()) + StackSString message; + + message.Printf(W(".NET Runtime version : %s - "), CLR_PRODUCT_VERSION_L); + if (lpTitle) + message.Append(lpTitle); + if (!formattedMessage.IsEmpty()) + message.Append(formattedMessage); + + ClrReportEvent(W(".NET Runtime"), + EVENTLOG_ERROR_TYPE, // event type + 0, // category zero + 1024, // event identifier + NULL, // no user security identifier + message.GetUnicode()); + + if(lpTitle != NULL) + WszOutputDebugString(lpTitle); + if(!formattedMessage.IsEmpty()) + WszOutputDebugString(formattedMessage); + + // If we are running as a service and displayForNonInteractive is FALSE then IDABORT is + // the best value to return as it will most likely cause callers of this API to abort the process. + // This is the right thing to do since attaching a debugger doesn't make much sense when the process isn't + // running in interactive mode. + if(!displayForNonInteractive) { - StackSString message; - - message.Printf(W(".NET Runtime version : %s - "), CLR_PRODUCT_VERSION_L); - if (lpTitle) - message.Append(lpTitle); - if (!formattedMessage.IsEmpty()) - message.Append(formattedMessage); - - ClrReportEvent(W(".NET Runtime"), - EVENTLOG_ERROR_TYPE, // event type - 0, // category zero - 1024, // event identifier - NULL, // no user security identifier - message.GetUnicode()); - - if(lpTitle != NULL) - WszOutputDebugString(lpTitle); - if(!formattedMessage.IsEmpty()) - WszOutputDebugString(formattedMessage); - - // If we are running as a service and displayForNonInteractive is FALSE then IDABORT is - // the best value to return as it will most likely cause callers of this API to abort the process. - // This is the right thing to do since attaching a debugger doesn't make much sense when the process isn't - // running in interactive mode. - if(!displayForNonInteractive) - { - fDisplayMsgBox = FALSE; - result = IDABORT; - } - else - { - // Include in the MB_DEFAULT_DESKTOP_ONLY style. - uType |= MB_DEFAULT_DESKTOP_ONLY; - } + fDisplayMsgBox = FALSE; + result = IDABORT; + } + else + { + // Include in the MB_DEFAULT_DESKTOP_ONLY style. + uType |= MB_DEFAULT_DESKTOP_ONLY; } +#endif // HOST_UNIX #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) if (fDisplayMsgBox) diff --git a/src/coreclr/utilcode/winfix.cpp b/src/coreclr/utilcode/winfix.cpp index d572c8edb26ef6..c6733767e77bf3 100644 --- a/src/coreclr/utilcode/winfix.cpp +++ b/src/coreclr/utilcode/winfix.cpp @@ -217,39 +217,6 @@ void EnsureCharSetInfoInitialized() return; } - -// Running with an interactive workstation. -BOOL RunningInteractive() -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_FORBID_FAULT; - - static int fInteractive = -1; - if (fInteractive != -1) - return fInteractive != 0; - -#if !defined(FEATURE_CORESYSTEM) - HWINSTA hwinsta = NULL; - - if ((hwinsta = GetProcessWindowStation() ) != NULL) - { - DWORD lengthNeeded; - USEROBJECTFLAGS flags; - - if (GetUserObjectInformationW (hwinsta, UOI_FLAGS, &flags, sizeof(flags), &lengthNeeded)) - { - if ((flags.dwFlags & WSF_VISIBLE) == 0) - fInteractive = 0; - } - } -#endif // !FEATURE_CORESYSTEM - - if (fInteractive != 0) - fInteractive = 1; - - return fInteractive != 0; -} - typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription); extern pfnSetThreadDescription g_pfnSetThreadDescription; diff --git a/src/coreclr/vm/.vscode/c_cpp_properties.json b/src/coreclr/vm/.vscode/c_cpp_properties.json index 3e0fa37196a654..16279d8db9e741 100644 --- a/src/coreclr/vm/.vscode/c_cpp_properties.json +++ b/src/coreclr/vm/.vscode/c_cpp_properties.json @@ -50,7 +50,6 @@ "FEATURE_COMINTEROP_UNMANAGED_ACTIVATION", "FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION", "FEATURE_CORECLR", - "FEATURE_CORESYSTEM", "FEATURE_DATABREAKPOINT", "FEATURE_DEFAULT_INTERFACES", "FEATURE_EVENT_TRACE=1", diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 2f34d2c0ceaa17..08a5bb92a66ed7 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -63,7 +63,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON debuginfostore.cpp decodemd.cpp disassembler.cpp - domainfile.cpp + domainassembly.cpp dynamicmethod.cpp ecall.cpp eedbginterfaceimpl.cpp @@ -161,8 +161,7 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON debuginfostore.h decodemd.h disassembler.h - domainfile.h - domainfile.inl + domainassembly.h dynamicmethod.h ecall.h eedbginterfaceimpl.h @@ -289,7 +288,6 @@ set(GC_HEADERS_DAC set(VM_SOURCES_WKS ${VM_SOURCES_DAC_AND_WKS_COMMON} appdomainnative.cpp - assemblyname.cpp assemblynative.cpp assemblyspec.cpp baseassemblyspec.cpp @@ -392,7 +390,6 @@ set(VM_HEADERS_WKS ${VM_HEADERS_DAC_AND_WKS_COMMON} ../inc/jithelpers.h appdomainnative.hpp - assemblyname.hpp assemblynative.hpp assemblyspec.hpp assemblyspecbase.h diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 0194f960809d92..80e22d4f7f209a 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -11,7 +11,6 @@ #include "eeconfig.h" #include "gcheaputilities.h" #include "eventtrace.h" -#include "assemblyname.hpp" #include "eeprofinterfaces.h" #include "dbginterface.h" #ifndef DACCESS_COMPILE @@ -1322,10 +1321,10 @@ void SystemDomain::LoadBaseSystemClasses() // 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_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetCurrentAssembly(); + m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetAssembly(); // Set up binder for CoreLib - CoreLibBinder::AttachModule(m_pSystemAssembly->GetManifestModule()); + CoreLibBinder::AttachModule(m_pSystemAssembly->GetModule()); // Load Object g_pObjectClass = CoreLibBinder::GetClass(CLASS__OBJECT); @@ -2174,7 +2173,7 @@ BOOL AppDomain::ContainsAssembly(Assembly * assem) while (i.Next(pDomainAssembly.This())) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly == assem) return TRUE; } @@ -2239,7 +2238,7 @@ DispIDCache* AppDomain::SetupRefDispIDCache() #endif // FEATURE_COMINTEROP -FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) +FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainAssembly *pDomainAssembly) { CONTRACTL { @@ -2252,7 +2251,7 @@ FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssemb } CONTRACTL_END; - NewHolder result(new FileLoadLock(pLock, pPEAssembly, pDomainFile)); + NewHolder result(new FileLoadLock(pLock, pPEAssembly, pDomainAssembly)); pLock->AddElement(result); result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel. @@ -2272,10 +2271,10 @@ FileLoadLock::~FileLoadLock() ((PEAssembly *) m_data)->Release(); } -DomainFile *FileLoadLock::GetDomainFile() +DomainAssembly *FileLoadLock::GetDomainAssembly() { LIMITED_METHOD_CONTRACT; - return m_pDomainFile; + return m_pDomainAssembly; } FileLoadLevel FileLoadLock::GetLoadLevel() @@ -2357,7 +2356,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) if (level > m_level) { // Must complete each level in turn, unless we have an error - CONSISTENCY_CHECK(m_pDomainFile->IsError() || (level == (m_level+1))); + CONSISTENCY_CHECK(m_pDomainAssembly->IsError() || (level == (m_level+1))); // Remove the lock from the list if the load is completed if (level >= FILE_ACTIVE) { @@ -2371,18 +2370,18 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) m_pList->Unlink(this); _ASSERTE(fDbgOnly_SuccessfulUnlink); - m_pDomainFile->ClearLoading(); + m_pDomainAssembly->ClearLoading(); - CONSISTENCY_CHECK(m_dwRefCount >= 2); // Caller (LoadDomainFile) should have 1 refcount and m_pList should have another which was acquired in FileLoadLock::Create. + CONSISTENCY_CHECK(m_dwRefCount >= 2); // Caller (LoadDomainAssembly) should have 1 refcount and m_pList should have another which was acquired in FileLoadLock::Create. m_level = (FileLoadLevel)level; // Dev11 bug 236344 // In AppDomain::IsLoading, if the lock is taken on m_pList and then FindFileLock returns NULL, - // we depend on the DomainFile's load level being up to date. Hence we must update the load + // we depend on the DomainAssembly's load level being up to date. Hence we must update the load // level while the m_pList lock is held. if (success) - m_pDomainFile->SetLoadLevel(level); + m_pDomainAssembly->SetLoadLevel(level); } @@ -2394,7 +2393,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) m_level = (FileLoadLevel)level; if (success) - m_pDomainFile->SetLoadLevel(level); + m_pDomainAssembly->SetLoadLevel(level); } #ifndef DACCESS_COMPILE @@ -2405,7 +2404,7 @@ BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success) case FILE_LOAD_DELIVER_EVENTS: case FILE_LOADED: case FILE_ACTIVE: // The timing of stress logs is not critical, so even for the FILE_ACTIVE stage we need not do it while the m_pList lock is held. - STRESS_LOG3(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainFile %p - success = %i\n", fileLoadLevelName[level], m_pDomainFile, success); + STRESS_LOG3(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainAssembly %p - success = %i\n", fileLoadLevelName[level], m_pDomainAssembly, success); break; default: break; @@ -2434,9 +2433,9 @@ void FileLoadLock::SetError(Exception *ex) m_cachedHR = ex->GetHR(); LOG((LF_LOADER, LL_WARNING, "LOADER: %x:***%s*\t!!!Non-transient error 0x%x\n", - m_pDomainFile->GetAppDomain(), m_pDomainFile->GetSimpleName(), m_cachedHR)); + m_pDomainAssembly->GetAppDomain(), m_pDomainAssembly->GetSimpleName(), m_cachedHR)); - m_pDomainFile->SetError(ex); + m_pDomainAssembly->SetError(ex); CompleteLoadLevel(FILE_ACTIVE, FALSE); } @@ -2464,10 +2463,10 @@ UINT32 FileLoadLock::Release() return count; } -FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) +FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainAssembly *pDomainAssembly) : ListLockEntry(pLock, pPEAssembly, "File load lock"), m_level((FileLoadLevel) (FILE_LOAD_CREATE)), - m_pDomainFile(pDomainFile), + m_pDomainAssembly(pDomainAssembly), m_cachedHR(S_OK) { WRAPPER_NO_CONTRACT; @@ -2522,26 +2521,6 @@ void AppDomain::LoadSystemAssemblies() LoadAssembly(NULL, SystemDomain::System()->SystemPEAssembly(), FILE_ACTIVE); } -FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END - - LoadLockHolder lock(this); - - FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); - - if (pLockEntry == NULL) - return pFile->GetLoadLevel(); - else - return pLockEntry->GetLoadLevel(); -} - // This checks if the thread has initiated (or completed) loading at the given level. A false guarantees that // (a) The current thread (or a thread blocking on the current thread) has not started loading the file // at the given level, and @@ -2555,7 +2534,7 @@ FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) // thread has completed the load step. // -BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level) +BOOL AppDomain::IsLoading(DomainAssembly *pFile, FileLoadLevel level) { // Cheap out if (pFile->GetLoadLevel() < level) @@ -2592,7 +2571,7 @@ BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level) // CheckLoading is a weaker form of IsLoading, which will not block on // other threads waiting for their status. This is appropriate for asserts. -CHECK AppDomain::CheckLoading(DomainFile *pFile, FileLoadLevel level) +CHECK AppDomain::CheckLoading(DomainAssembly *pFile, FileLoadLevel level) { // Cheap out if (pFile->GetLoadLevel() < level) @@ -2626,7 +2605,7 @@ CHECK AppDomain::CheckCanLoadTypes(Assembly *pAssembly) MODE_ANY; } CONTRACTL_END; - CHECK_MSG(CheckValidModule(pAssembly->GetManifestModule()), + CHECK_MSG(CheckValidModule(pAssembly->GetModule()), "Type loading can occur only when executing in the assembly's app domain"); CHECK_OK; } @@ -2658,7 +2637,7 @@ CHECK AppDomain::CheckCanExecuteManagedCode(MethodDesc* pMD) #endif // !DACCESS_COMPILE -void AppDomain::LoadDomainFile(DomainFile *pFile, +void AppDomain::LoadDomainAssembly(DomainAssembly *pFile, FileLoadLevel targetLevel) { CONTRACTL @@ -2698,7 +2677,7 @@ void AppDomain::LoadDomainFile(DomainFile *pFile, lock.Release(); - LoadDomainFile(pLockEntry, targetLevel); + LoadDomainAssembly(pLockEntry, targetLevel); } #else // DACCESS_COMPILE @@ -2875,12 +2854,12 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (result == NULL) { - // We pass our ref on fileLock to LoadDomainFile to release. + // We pass our ref on fileLock to LoadDomainAssembly to release. // Note that if we throw here, we will poison fileLock with an error condition, // so it will not be removed until app domain unload. So there is no need // to release our ref count. - result = (DomainAssembly *)LoadDomainFile(fileLock, targetLevel); + result = (DomainAssembly *)LoadDomainAssembly(fileLock, targetLevel); } else { @@ -2889,20 +2868,12 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (registerNewAssembly) { - pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetCurrentAssembly()); + pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetAssembly()); } } else result->EnsureLoadLevel(targetLevel); - // Malformed metadata may contain a Module reference to what is actually - // an Assembly. In this case we need to throw an exception, since returning - // a DomainModule as a DomainAssembly is a type safety violation. - if (!result->IsAssembly()) - { - ThrowHR(COR_E_ASSEMBLYEXPECTED); - } - // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity if (pIdentity == NULL) { @@ -2918,28 +2889,20 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, RETURN result; } // AppDomain::LoadDomainAssembly - -struct LoadFileArgs +DomainAssembly *AppDomain::LoadDomainAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel) { - FileLoadLock *pLock; - FileLoadLevel targetLevel; - DomainFile *result; -}; - -DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetLevel) -{ - CONTRACT(DomainFile *) + CONTRACT(DomainAssembly *) { STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pLock)); - PRECONDITION(pLock->GetDomainFile()->GetAppDomain() == this); + PRECONDITION(pLock->GetDomainAssembly()->GetAppDomain() == this); POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel() || RETVAL->GetLoadLevel() >= targetLevel); POSTCONDITION(RETVAL->CheckNoError(targetLevel)); } CONTRACT_END; - DomainFile *pFile = pLock->GetDomainFile(); + DomainAssembly *pFile = pLock->GetDomainAssembly(); // Make sure we release the lock on exit FileLoadLockRefHolder lockRef(pLock); @@ -3034,7 +2997,7 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL // lower level. In such a case, we throw an exception which transiently fails the current // load, since it is likely we have not satisfied the caller. // (An alternate, and possibly preferable, strategy here would be for all callers to explicitly - // identify the minimum load level acceptable via CheckLoadDomainFile and throw from there.) + // specify the minimum load level acceptable and throw if not reached.) pFile->RequireLoadLevel((FileLoadLevel)(immediateTargetLevel-1)); @@ -3042,7 +3005,7 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL RETURN pFile; } -void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder) +void AppDomain::TryIncrementalLoad(DomainAssembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder) { STANDARD_VM_CONTRACT; @@ -3056,7 +3019,7 @@ void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, F // Special case: for LoadLibrary, we cannot hold the lock during the // actual LoadLibrary call, because we might get a callback from _CorDllMain on any - // other thread. (Note that this requires DomainFile's LoadLibrary to be independently threadsafe.) + // other thread. (Note that this requires DomainAssembly's LoadLibrary to be independently threadsafe.) if (workLevel == FILE_LOAD_LOADLIBRARY) { @@ -3140,7 +3103,7 @@ CHECK AppDomain::CheckValidModule(Module * pModule) } CONTRACTL_END; - if (pModule->GetDomainFile() != NULL) + if (pModule->GetDomainAssembly() != NULL) CHECK_OK; CHECK_OK; @@ -3827,7 +3790,7 @@ PEAssembly *AppDomain::TryResolveAssemblyUsingEvent(AssemblySpec *pSpec) Assembly *pAssembly = RaiseAssemblyResolveEvent(pSpec); if (pAssembly != nullptr) { - PEAssembly* pPEAssembly = pAssembly->GetManifestFile(); + PEAssembly* pPEAssembly = pAssembly->GetPEAssembly(); pPEAssembly->AddRef(); result = pPEAssembly; } @@ -4215,7 +4178,7 @@ DWORD DomainLocalModule::GetClassFlags(MethodTable* pMT, DWORD iClassIndex /*=(D } CONTRACTL_END; { - CONSISTENCY_CHECK(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + CONSISTENCY_CHECK(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); } if (pMT->IsDynamicStatics()) @@ -4246,7 +4209,7 @@ void DomainLocalModule::SetClassInitialized(MethodTable* pMT) } CONTRACTL_END; - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); _ASSERTE(!IsClassInitialized(pMT)); _ASSERTE(!IsClassInitError(pMT)); @@ -4258,7 +4221,7 @@ void DomainLocalModule::SetClassInitError(MethodTable* pMT) { WRAPPER_NO_CONTRACT; - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); SetClassFlags(pMT, ClassInitFlags::ERROR_FLAG); } @@ -4268,9 +4231,9 @@ void DomainLocalModule::SetClassFlags(MethodTable* pMT, DWORD dwFlags) CONTRACTL { THROWS; GC_TRIGGERS; - PRECONDITION(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + PRECONDITION(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; if (pMT->IsDynamicStatics()) @@ -4295,7 +4258,7 @@ void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID) MODE_ANY; INJECT_FAULT(COMPlusThrowOM();); // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; @@ -4313,7 +4276,7 @@ void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID) DynamicClassInfo* pNewDynamicClassTable; pNewDynamicClassTable = (DynamicClassInfo*) - (void*)GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem( + (void*)GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem( S_SIZE_T(sizeof(DynamicClassInfo)) * S_SIZE_T(aDynamicEntries)); memcpy(pNewDynamicClassTable, m_pDynamicClassTable, sizeof(DynamicClassInfo) * m_aDynamicEntries); @@ -4337,13 +4300,13 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) THROWS; GC_TRIGGERS; // Assumes BaseDomain::DomainLocalBlockLockHolder is taken - PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock()); + PRECONDITION(GetDomainAssembly()->GetAppDomain()->OwnDomainLocalBlockLock()); } CONTRACTL_END; _ASSERTE(!pMT->ContainsGenericVariables()); _ASSERTE(!pMT->IsSharedByGenericInstantiations()); - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); _ASSERTE(pMT->IsDynamicStatics()); DWORD dynamicEntryIDIndex = pMT->GetModuleDynamicEntryID(); @@ -4368,7 +4331,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) { if (pDynamicStatics == NULL) { - LoaderHeap * pLoaderAllocator = GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap(); + LoaderHeap * pLoaderAllocator = GetDomainAssembly()->GetLoaderAllocator()->GetHighFrequencyHeap(); if (pMT->Collectible()) { @@ -4407,7 +4370,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) else #endif nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwStaticBytes); - ((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray); + ((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray); GCPROTECT_END(); } if (dwNumHandleStatics > 0) @@ -4423,7 +4386,7 @@ void DomainLocalModule::AllocateDynamicClass(MethodTable *pMT) OBJECTREF gcStaticsArray = NULL; GCPROTECT_BEGIN(gcStaticsArray); gcStaticsArray = AllocateObjectArray(dwNumHandleStatics, g_pObjectClass); - ((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray); + ((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainAssembly()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray); GCPROTECT_END(); } } @@ -4448,7 +4411,7 @@ void DomainLocalModule::PopulateClass(MethodTable *pMT) if (!IsClassAllocated(pMT, iClassIndex)) { - BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain()); + BaseDomain::DomainLocalBlockLockHolder lh(GetDomainAssembly()->GetAppDomain()); if (!IsClassAllocated(pMT, iClassIndex)) { @@ -4903,7 +4866,7 @@ AppDomain::AssemblyIterator::Next_Unlocked( // Un-tenured collectible assemblies should not be returned. (This can only happen in a brief // window during collectible assembly creation. No thread should need to have a pointer // to the just allocated DomainAssembly at this stage.) - if (!pDomainAssembly->GetAssembly()->GetManifestModule()->IsTenured()) + if (!pDomainAssembly->GetAssembly()->GetModule()->IsTenured()) { continue; // reject } @@ -5186,9 +5149,9 @@ DomainLocalModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // sizeof(DomainLocalModule) == 0x28 DAC_ENUM_DTHIS(); - if (m_pDomainFile.IsValid()) + if (m_pDomainAssembly.IsValid()) { - m_pDomainFile->EnumMemoryRegions(flags); + m_pDomainAssembly->EnumMemoryRegions(flags); } if (m_pDynamicClassTable.Load().IsValid()) diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index a369823a53937c..fbe728ff7e1c08 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -21,7 +21,7 @@ #include "arraylist.h" #include "comreflectioncache.hpp" #include "comutilnative.h" -#include "domainfile.h" +#include "domainassembly.h" #include "fptrstubs.h" #include "gcheaputilities.h" #include "gchandleutilities.h" @@ -201,18 +201,18 @@ struct DomainLocalModule static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); } static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); } - inline DomainFile* GetDomainFile() + inline DomainAssembly* GetDomainAssembly() { LIMITED_METHOD_CONTRACT SUPPORTS_DAC; - return m_pDomainFile; + return m_pDomainAssembly; } #ifndef DACCESS_COMPILE - inline void SetDomainFile(DomainFile* pDomainFile) + inline void SetDomainAssembly(DomainAssembly* pDomainAssembly) { LIMITED_METHOD_CONTRACT - m_pDomainFile = pDomainFile; + m_pDomainAssembly = pDomainAssembly; } #endif @@ -236,7 +236,7 @@ struct DomainLocalModule if (pMT->IsDynamicStatics()) { - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator()); } else @@ -252,7 +252,7 @@ struct DomainLocalModule if (pMT->IsDynamicStatics()) { - _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics()); + _ASSERTE(GetDomainAssembly()->GetModule() == pMT->GetModuleForStatics()); return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator()); } else @@ -403,7 +403,7 @@ struct DomainLocalModule FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID) { DWORD rid = (DWORD)(dwClassDomainID) + 1; - TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef)); + TypeHandle th = GetDomainAssembly()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef)); _ASSERTE(!th.IsNull()); MethodTable * pMT = th.AsMethodTable(); PREFIX_ASSUME(pMT != NULL); @@ -416,7 +416,7 @@ struct DomainLocalModule void SetClassFlags(MethodTable* pMT, DWORD dwFlags); DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex); - PTR_DomainFile m_pDomainFile; + PTR_DomainAssembly m_pDomainAssembly; VolatilePtr m_pDynamicClassTable; // used for generics and reflection.emit in memory Volatile m_aDynamicEntries; // number of entries in dynamic table VolatilePtr m_pADThunkTable; @@ -747,7 +747,7 @@ typedef PEFileListLock::Holder PEFileListLockHolder; // Loading infrastructure: // -// a DomainFile is a file being loaded. Files are loaded in layers to enable loading in the +// a DomainAssembly is a file being loaded. Files are loaded in layers to enable loading in the // presence of dependency loops. // // FileLoadLevel describes the various levels available. These are implemented slightly @@ -773,14 +773,14 @@ class FileLoadLock : public ListLockEntry { private: FileLoadLevel m_level; - DomainFile *m_pDomainFile; + DomainAssembly *m_pDomainAssembly; HRESULT m_cachedHR; public: - static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); + static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainAssembly *pDomainAssembly); ~FileLoadLock(); - DomainFile *GetDomainFile(); + DomainAssembly *GetDomainAssembly(); FileLoadLevel GetLoadLevel(); // CanAcquire will return FALSE if Acquire will definitely not take the lock due @@ -807,7 +807,7 @@ class FileLoadLock : public ListLockEntry private: - FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); + FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainAssembly *pDomainAssembly); static void HolderLeave(FileLoadLock *pThis); @@ -1307,7 +1307,7 @@ enum AssemblyIterationFlags // (all m_level values) kIncludeAvailableToProfilers = 0x00000020, // include assemblies available to profilers - // See comment at code:DomainFile::IsAvailableToProfilers + // See comment at code:DomainAssembly::IsAvailableToProfilers // Execution / introspection flags kIncludeExecution = 0x00000004, // include assemblies that are loaded for execution only @@ -1797,13 +1797,12 @@ class AppDomain : public BaseDomain CHECK CheckCanLoadTypes(Assembly *pAssembly); CHECK CheckCanExecuteManagedCode(MethodDesc* pMD); - CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level); + CHECK CheckLoading(DomainAssembly *pFile, FileLoadLevel level); - FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile); - BOOL IsLoading(DomainFile *pFile, FileLoadLevel level); + BOOL IsLoading(DomainAssembly *pFile, FileLoadLevel level); static FileLoadLevel GetThreadFileLoadLevel(); - void LoadDomainFile(DomainFile *pFile, + void LoadDomainAssembly(DomainAssembly *pFile, FileLoadLevel targetLevel); enum FindAssemblyOptions @@ -1839,10 +1838,10 @@ class AppDomain : public BaseDomain // private: void LoadSystemAssemblies(); - DomainFile *LoadDomainFile(FileLoadLock *pLock, + DomainAssembly *LoadDomainAssembly(FileLoadLock *pLock, FileLoadLevel targetLevel); - void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder); + void TryIncrementalLoad(DomainAssembly *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder); #ifndef DACCESS_COMPILE // needs AssemblySpec @@ -2453,7 +2452,7 @@ class SystemDomain : public BaseDomain { WRAPPER_NO_CONTRACT; - return SystemAssembly()->GetManifestModule(); + return SystemAssembly()->GetModule(); } static BOOL IsSystemLoaded() @@ -2580,7 +2579,7 @@ class SystemDomain : public BaseDomain // Or, it might be the location of CoreLib if (System()->SystemAssembly() != NULL - && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath())) + && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetPEAssembly()->GetPath())) return TRUE; return FALSE; diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 09c6ff22c2f838..83840af5b51387 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -17,9 +17,6 @@ #include "assembly.hpp" #include "appdomain.hpp" -#include "assemblyname.hpp" - - #include "eeprofinterfaces.h" #include "reflectclasswriter.h" @@ -126,14 +123,13 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pPEAssembly, DebuggerAssembl m_pDomain(pDomain), m_pClassLoader(NULL), m_pEntryPoint(NULL), - m_pManifest(NULL), - m_pManifestFile(clr::SafeAddRef(pPEAssembly)), + m_pModule(NULL), + m_pPEAssembly(clr::SafeAddRef(pPEAssembly)), m_pFriendAssemblyDescriptor(NULL), m_isDynamic(false), #ifdef FEATURE_COLLECTIBLE_TYPES m_isCollectible(fIsCollectible), #endif - m_nextAvailableModuleIndex(1), m_pLoaderAllocator(NULL), #ifdef FEATURE_COMINTEROP m_pITypeLib(NULL), @@ -189,7 +185,7 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat m_pClassLoader = new ClassLoader(this); m_pClassLoader->Init(pamTracker); - PEAssembly* pPEAssembly = GetManifestFile(); + PEAssembly* pPEAssembly = GetPEAssembly(); // "Module::Create" will initialize R2R support, if there is an R2R header. // make sure the PE is loaded or R2R will be disabled. @@ -197,17 +193,15 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat if (pPEAssembly->IsDynamic()) // manifest modules of dynamic assemblies are always transient - m_pManifest = ReflectionModule::Create(this, pPEAssembly, pamTracker, REFEMIT_MANIFEST_MODULE_NAME); + m_pModule = ReflectionModule::Create(this, pPEAssembly, pamTracker, REFEMIT_MANIFEST_MODULE_NAME); else - m_pManifest = Module::Create(this, mdFileNil, pPEAssembly, pamTracker); + m_pModule = Module::Create(this, mdFileNil, pPEAssembly, pamTracker); FastInterlockIncrement((LONG*)&g_cAssemblies); - PrepareModuleForAssembly(m_pManifest, pamTracker); - - CacheManifestFiles(); + PrepareModuleForAssembly(m_pModule, pamTracker); - if (!m_pManifest->IsReadyToRun()) + if (!m_pModule->IsReadyToRun()) CacheManifestExportedTypes(pamTracker); // We'll load the friend assembly information lazily. For the ngen case we should avoid @@ -231,7 +225,7 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat FAULT_FORBID(); //Cannot fail after this point. - PublishModuleIntoAssembly(m_pManifest); + PublishModuleIntoAssembly(m_pModule); return; // Explicit return to let you know you are NOT welcome to add code after the CANNOTTHROW/FAULT_FORBID expires } @@ -252,9 +246,9 @@ Assembly::~Assembly() if (m_pFriendAssemblyDescriptor != NULL) m_pFriendAssemblyDescriptor->Release(); - if (m_pManifestFile) + if (m_pPEAssembly) { - m_pManifestFile->Release(); + m_pPEAssembly->Release(); } #ifdef FEATURE_COMINTEROP @@ -334,7 +328,7 @@ void Assembly::Terminate( BOOL signalProfiler ) Assembly * Assembly::Create( BaseDomain * pDomain, - PEAssembly * pFile, + PEAssembly * pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker * pamTracker, @@ -342,7 +336,7 @@ Assembly * Assembly::Create( { STANDARD_VM_CONTRACT; - NewHolder pAssembly (new Assembly(pDomain, pFile, debuggerFlags, fIsCollectible)); + NewHolder pAssembly (new Assembly(pDomain, pPEAssembly, debuggerFlags, fIsCollectible)); #ifdef PROFILING_SUPPORTED { @@ -429,7 +423,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C || name.Find(i, ':') || name.Find(i, '/')) { - COMPlusThrow(kArgumentException, W("Argument_InvalidAssemblyName")); + COMPlusThrow(kArgumentException, W("InvalidAssemblyName")); } // Set up the assembly manifest metadata @@ -516,7 +510,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C IfFailThrow(pAssemblyEmit->DefineAssembly(publicKey, publicKey.GetSize(), ulHashAlgId, name, &assemData, dwFlags, &ma)); - pPEAssembly = PEAssembly::Create(pCallerAssembly->GetManifestFile(), pAssemblyEmit); + pPEAssembly = PEAssembly::Create(pCallerAssembly->GetPEAssembly(), pAssemblyEmit); AssemblyBinder* pFallbackBinder = pBinder; @@ -531,7 +525,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. - PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetManifestFile(); + PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetPEAssembly(); _ASSERTE(pCallerAssemblyManifestFile != NULL); if (!pCallerAssemblyManifestFile->IsDynamic()) @@ -625,7 +619,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C // Assembly::Create will call SuppressRelease on the NewHolder that holds the LoaderAllocator when it transfers ownership pAssem = Assembly::Create(pDomain, pPEAssembly, pDomainAssembly->GetDebuggerInfoBits(), pLoaderAllocator->IsCollectible(), pamTracker, pLoaderAllocator); - ReflectionModule* pModule = (ReflectionModule*) pAssem->GetManifestModule(); + ReflectionModule* pModule = (ReflectionModule*) pAssem->GetModule(); pModule->SetCreatingAssembly( pCallerAssembly ); @@ -696,7 +690,7 @@ void Assembly::SetDomainAssembly(DomainAssembly *pDomainAssembly) } CONTRACTL_END; - GetManifestModule()->SetDomainFile(pDomainAssembly); + GetModule()->SetDomainAssembly(pDomainAssembly); } // Assembly::SetDomainAssembly @@ -705,7 +699,7 @@ void Assembly::SetDomainAssembly(DomainAssembly *pDomainAssembly) DomainAssembly *Assembly::GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return GetManifestModule()->GetDomainAssembly(); + return GetModule()->GetDomainAssembly(); } PTR_LoaderHeap Assembly::GetLowFrequencyHeap() @@ -798,9 +792,9 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, mdToken mdLinkRef; mdToken mdBinding; - IMDInternalImport *pManifestImport = GetManifestImport(); + IMDInternalImport *pMDImport = GetMDImport(); - IfFailThrow(pManifestImport->GetExportedTypeProps( + IfFailThrow(pMDImport->GetExportedTypeProps( mdType, NULL, NULL, @@ -809,7 +803,7 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, NULL)); // dwflags // Don't trust the returned tokens. - if (!pManifestImport->IsValidToken(mdLinkRef)) + if (!pMDImport->IsValidToken(mdLinkRef)) { if (loadFlag != Loader::Load) { @@ -834,27 +828,27 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, #ifndef DACCESS_COMPILE // LoadAssembly never returns NULL DomainAssembly * pDomainAssembly = - GetManifestModule()->LoadAssembly(mdLinkRef); + GetModule()->LoadAssembly(mdLinkRef); PREFIX_ASSUME(pDomainAssembly != NULL); - RETURN pDomainAssembly->GetCurrentModule(); + RETURN pDomainAssembly->GetModule(); #else _ASSERTE(!"DAC shouldn't attempt to trigger loading"); return NULL; #endif // !DACCESS_COMPILE }; case Loader::DontLoad: - pAssembly = GetManifestModule()->GetAssemblyIfLoaded(mdLinkRef); + pAssembly = GetModule()->GetAssemblyIfLoaded(mdLinkRef); break; case Loader::SafeLookup: - pAssembly = GetManifestModule()->LookupAssemblyRef(mdLinkRef); + pAssembly = GetModule()->LookupAssemblyRef(mdLinkRef); break; default: _ASSERTE(FALSE); } if (pAssembly) - RETURN pAssembly->GetManifestModule(); + RETURN pAssembly->GetModule(); else RETURN NULL; @@ -871,7 +865,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); + Module *pModule = GetModule()->GetModuleIfLoaded(mdLinkRef); #ifdef DACCESS_COMPILE return pModule; #else @@ -884,17 +878,17 @@ 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 = NULL; + DomainAssembly* pDomainModule = NULL; if (loadFlag == Loader::Load) { - pDomainModule = GetManifestModule()->LoadModule(::GetAppDomain(), mdLinkRef); + pDomainModule = GetModule()->LoadModule(::GetAppDomain(), mdLinkRef); } if (pDomainModule == NULL) RETURN NULL; else { - pModule = pDomainModule->GetCurrentModule(); + pModule = pDomainModule->GetModule(); if (pModule == NULL) { _ASSERTE(loadFlag!=Loader::Load); @@ -1017,8 +1011,8 @@ Module * Assembly::FindModuleByTypeRef( #ifndef DACCESS_COMPILE if (loadFlag == Loader::Load) { - DomainFile* pActualDomainFile = pModule->LoadModule(::GetAppDomain(), tkType); - RETURN(pActualDomainFile->GetModule()); + DomainAssembly* pActualDomainAssembly = pModule->LoadModule(::GetAppDomain(), tkType); + RETURN(pActualDomainAssembly->GetModule()); } else { @@ -1054,7 +1048,7 @@ Module * Assembly::FindModuleByTypeRef( if (pAssembly != NULL) { - RETURN pAssembly->m_pManifest; + RETURN pAssembly->m_pModule; } #ifdef DACCESS_COMPILE @@ -1072,14 +1066,14 @@ Module * Assembly::FindModuleByTypeRef( if (pDomainAssembly == NULL) RETURN NULL; - pAssembly = pDomainAssembly->GetCurrentAssembly(); + pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly == NULL) { RETURN NULL; } else { - RETURN pAssembly->m_pManifest; + RETURN pAssembly->m_pModule; } #endif //!DACCESS_COMPILE } @@ -1114,9 +1108,9 @@ Module *Assembly::FindModuleByName(LPCSTR pszModuleName) ThrowHR(COR_E_UNAUTHORIZEDACCESS); if (this == SystemDomain::SystemAssembly()) - RETURN m_pManifest->GetModuleIfLoaded(kFile); + RETURN m_pModule->GetModuleIfLoaded(kFile); else - RETURN m_pManifest->LoadModule(::GetAppDomain(), kFile)->GetModule(); + RETURN m_pModule->LoadModule(::GetAppDomain(), kFile)->GetModule(); } void Assembly::CacheManifestExportedTypes(AllocMemTracker *pamTracker) @@ -1132,28 +1126,24 @@ void Assembly::CacheManifestExportedTypes(AllocMemTracker *pamTracker) // Prejitted assemblies are expected to have their table prebuilt. // If not, we do it here at load time (as if we would jit the assembly). - if (m_pManifest->IsPersistedObject(m_pManifest->m_pAvailableClasses)) + if (m_pModule->IsPersistedObject(m_pModule->m_pAvailableClasses)) RETURN; mdToken mdExportedType; - HENUMInternalHolder phEnum(GetManifestImport()); + HENUMInternalHolder phEnum(GetMDImport()); phEnum.EnumInit(mdtExportedType, mdTokenNil); ClassLoader::AvailableClasses_LockHolder lh(m_pClassLoader); - for(int i = 0; GetManifestImport()->EnumNext(&phEnum, &mdExportedType); i++) - m_pClassLoader->AddExportedTypeHaveLock(GetManifestModule(), + for(int i = 0; GetMDImport()->EnumNext(&phEnum, &mdExportedType); i++) + m_pClassLoader->AddExportedTypeHaveLock(GetModule(), mdExportedType, pamTracker); RETURN; } -void Assembly::CacheManifestFiles() -{ -} - //@TODO: if module is not signed it needs to acquire the //permissions from the assembly. @@ -1186,7 +1176,7 @@ void Assembly::PrepareModuleForAssembly(Module* module, AllocMemTracker *pamTrac module->GetDebuggerInfoBits())); #endif // DEBUGGING_SUPPORTED - m_pManifest->EnsureFileCanBeStored(module->GetModuleRef()); + m_pModule->EnsureFileCanBeStored(module->GetModuleRef()); } // This is the final step of publishing a Module into an Assembly. This step cannot fail. @@ -1200,7 +1190,7 @@ void Assembly::PublishModuleIntoAssembly(Module *module) } CONTRACTL_END - GetManifestModule()->EnsuredStoreFile(module->GetModuleRef(), module); + GetModule()->EnsuredStoreFile(module->GetModuleRef(), module); FastInterlockIncrement((LONG*)&m_pClassLoader->m_cUnhashedModules); } @@ -1222,7 +1212,7 @@ void Assembly::CacheFriendAssemblyInfo() if (m_pFriendAssemblyDescriptor == NULL) { - ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetManifestFile()); + ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetPEAssembly()); _ASSERTE(pFriendAssemblies != NULL); CrstHolder friendDescriptorLock(&g_friendAssembliesCrst); @@ -1257,7 +1247,7 @@ void Assembly::UpdateCachedFriendAssemblyInfo() while (true) { - ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetManifestFile()); + ReleaseHolder pFriendAssemblies = FriendAssemblyDescriptor::CreateFriendAssemblyDescriptor(this->GetPEAssembly()); FriendAssemblyDescriptor* pFriendAssemblyDescriptorNextLoop = NULL; { @@ -1699,14 +1689,14 @@ MethodDesc* Assembly::GetEntryPoint() if (m_pEntryPoint) RETURN m_pEntryPoint; - mdToken mdEntry = m_pManifestFile->GetEntryPointToken(); + mdToken mdEntry = m_pPEAssembly->GetEntryPointToken(); if (IsNilToken(mdEntry)) RETURN NULL; Module *pModule = NULL; switch(TypeFromToken(mdEntry)) { case mdtFile: - pModule = m_pManifest->LoadModule(::GetAppDomain(), mdEntry)->GetModule(); + pModule = m_pModule->LoadModule(::GetAppDomain(), mdEntry)->GetModule(); mdEntry = pModule->GetEntryPointToken(); if ( (TypeFromToken(mdEntry) != mdtMethodDef) || @@ -1715,8 +1705,8 @@ MethodDesc* Assembly::GetEntryPoint() break; case mdtMethodDef: - if (m_pManifestFile->GetMDImport()->IsValidToken(mdEntry)) - pModule = m_pManifest; + if (m_pPEAssembly->GetMDImport()->IsValidToken(mdEntry)) + pModule = m_pModule; break; } @@ -1874,7 +1864,7 @@ BOOL Assembly::IsInstrumentedHelper() return false; // We must have a native image in order to perform IBC instrumentation - if (!GetManifestFile()->IsReadyToRun()) + if (!GetPEAssembly()->IsReadyToRun()) return false; // @Consider using the full name instead of the short form @@ -2001,7 +1991,7 @@ mdAssemblyRef Assembly::AddAssemblyRef(Assembly *refedAssembly, IMetaDataAssembl SafeComHolder emitHolder; AssemblySpec spec; - spec.InitializeSpec(refedAssembly->GetManifestFile()); + spec.InitializeSpec(refedAssembly->GetPEAssembly()); if (refedAssembly->IsCollectible()) { @@ -2059,7 +2049,7 @@ void Assembly::AddExportedType(mdExportedType cl) CONTRACTL_END AllocMemTracker amTracker; - m_pClassLoader->AddExportedTypeDontHaveLock(GetManifestModule(), + m_pClassLoader->AddExportedTypeDontHaveLock(GetModule(), cl, &amTracker); amTracker.SuppressRelease(); @@ -2238,13 +2228,13 @@ Assembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { m_pClassLoader->EnumMemoryRegions(flags); } - if (m_pManifest.IsValid()) + if (m_pModule.IsValid()) { - m_pManifest->EnumMemoryRegions(flags, true); + m_pModule->EnumMemoryRegions(flags, true); } - if (m_pManifestFile.IsValid()) + if (m_pPEAssembly.IsValid()) { - m_pManifestFile->EnumMemoryRegions(flags); + m_pPEAssembly->EnumMemoryRegions(flags); } } diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index f8de5c162e7524..8c72128f3e4f6c 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -56,16 +56,8 @@ struct CreateDynamicAssemblyArgs : CreateDynamicAssemblyArgsGC StackCrawlMark* stackMark; }; -// An assembly is the unit of deployment for managed code. Typically Assemblies are one to one with files -// (Modules), however this is not necessary, as an assembly can contain serveral files (typically you only -// do this so that you can resource-only modules that are national language specific) -// -// Conceptually Assemblies are loaded into code:AppDomain -// -// So in general an assemly is a list of code:Module, where a code:Module is 1-1 with a DLL or EXE file. -// -// One of the modules the code:Assembly.m_pManifest is special in that it knows about all the other -// modules in an assembly (often it is the only one). +// An assembly is the unit of deployment for managed code. +// Assemblies are one to one with files since coreclr does not support multimodule assemblies. // class Assembly { @@ -88,7 +80,7 @@ class Assembly 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(); } + BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->IsSystem(); } static Assembly *CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, CreateDynamicAssemblyArgs *args); @@ -108,15 +100,7 @@ class Assembly void SetIsTenured() { WRAPPER_NO_CONTRACT; - m_pManifest->SetIsTenured(); - } - - // CAUTION: This should only be used as backout code if an assembly is unsuccessfully - // added to the shared domain assembly map. - void UnsetIsTenured() - { - WRAPPER_NO_CONTRACT; - m_pManifest->UnsetIsTenured(); + m_pModule->SetIsTenured(); } #endif // DACCESS_COMPILE @@ -130,72 +114,6 @@ class Assembly return m_pClassLoader; } - // ------------------------------------------------------------ - // Modules - // ------------------------------------------------------------ - - class ModuleIterator - { - Module* m_pManifest; - DWORD m_i; - - public: - // The preferred constructor. If you use this, you don't have to - // call Start() yourself - ModuleIterator(Assembly *pAssembly) - { - WRAPPER_NO_CONTRACT; - Start(pAssembly); - } - - // When you don't have the Assembly at contruction time, use this - // constructor, and explicitly call Start() to begin the iteration. - ModuleIterator() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - m_pManifest = NULL; - m_i = (DWORD) -1; - } - - void Start(Assembly * pAssembly) - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - m_pManifest = pAssembly->GetManifestModule(); - m_i = (DWORD) -1; - } - - BOOL Next() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - while (++m_i <= m_pManifest->GetFileMax()) - { - if (GetModule() != NULL) - return TRUE; - } - return FALSE; - } - - Module *GetModule() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - return m_pManifest->LookupFile(TokenFromRid(m_i, mdtFile)); - } - }; - - ModuleIterator IterateModules() - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - return ModuleIterator(this); - } - - //**************************************************************************************** // // Get the domain the assembly lives in. @@ -231,75 +149,75 @@ class Assembly LPCWSTR GetDebugName() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetDebugName(); + return GetPEAssembly()->GetDebugName(); } #endif LPCUTF8 GetSimpleName() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetSimpleName(); + return GetPEAssembly()->GetSimpleName(); } BOOL IsStrongNamed() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->IsStrongNamed(); + return GetPEAssembly()->IsStrongNamed(); } const void *GetPublicKey(DWORD *pcbPK) { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetPublicKey(pcbPK); + return GetPEAssembly()->GetPublicKey(pcbPK); } ULONG GetHashAlgId() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetHashAlgId(); + return GetPEAssembly()->GetHashAlgId(); } HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision) { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetVersion(pMajor, pMinor, pBuild, pRevision); + return GetPEAssembly()->GetVersion(pMajor, pMinor, pBuild, pRevision); } LPCUTF8 GetLocale() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetLocale(); + return GetPEAssembly()->GetLocale(); } DWORD GetFlags() { WRAPPER_NO_CONTRACT; - return GetManifestFile()->GetFlags(); + return GetPEAssembly()->GetFlags(); } PTR_LoaderHeap GetLowFrequencyHeap(); PTR_LoaderHeap GetHighFrequencyHeap(); PTR_LoaderHeap GetStubHeap(); - PTR_Module GetManifestModule() + PTR_Module GetModule() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return m_pManifest; + return m_pModule; } - PTR_PEAssembly GetManifestFile() + PTR_PEAssembly GetPEAssembly() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return m_pManifestFile; + return m_pPEAssembly; } - IMDInternalImport* GetManifestImport() + IMDInternalImport* GetMDImport() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return m_pManifestFile->GetMDImport(); + return m_pPEAssembly->GetMDImport(); } HRESULT GetCustomAttribute(mdToken parentToken, @@ -309,7 +227,7 @@ class Assembly { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return GetManifestModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData); + return GetModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData); } mdAssembly GetManifestToken() @@ -324,7 +242,7 @@ class Assembly { WRAPPER_NO_CONTRACT; - return m_pManifestFile->GetDisplayName(result, flags); + return m_pPEAssembly->GetDisplayName(result, flags); } #endif // DACCESS_COMPILE @@ -332,7 +250,7 @@ class Assembly { WRAPPER_NO_CONTRACT; - return m_pManifestFile->GetCodeBase(result); + return m_pPEAssembly->GetCodeBase(result); } OBJECTREF GetExposedObject(); @@ -360,7 +278,7 @@ class Assembly ULONG HashIdentity() { - return GetManifestFile()->HashIdentity(); + return GetPEAssembly()->HashIdentity(); } //**************************************************************************************** @@ -408,8 +326,6 @@ class Assembly FORCEINLINE BOOL IsDynamic() { LIMITED_METHOD_CONTRACT; return m_isDynamic; } FORCEINLINE BOOL IsCollectible() { LIMITED_METHOD_DAC_CONTRACT; return m_isCollectible; } - DWORD GetNextModuleIndex() { LIMITED_METHOD_CONTRACT; return m_nextAvailableModuleIndex++; } - void AddType(Module* pModule, mdTypeDef cl); void AddExportedType(mdExportedType cl); @@ -520,9 +436,9 @@ class Assembly int mask = INTEROP_ATTRIBUTE_UNSET; - if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::ImportedFromTypeLib, NULL, 0) == S_OK) + if (GetModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::ImportedFromTypeLib, NULL, 0) == S_OK) mask |= INTEROP_ATTRIBUTE_IMPORTED_FROM_TYPELIB; - if (GetManifestModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::PrimaryInteropAssembly, NULL, 0) == S_OK) + if (GetModule()->GetCustomAttribute(TokenFromRid(1, mdtAssembly), WellKnownAttribute::PrimaryInteropAssembly, NULL, 0) == S_OK) mask |= INTEROP_ATTRIBUTE_PRIMARY_INTEROP_ASSEMBLY; if (!IsDynamic()) @@ -540,7 +456,6 @@ class Assembly //**************************************************************************************** void CacheManifestExportedTypes(AllocMemTracker *pamTracker); - void CacheManifestFiles(); void CacheFriendAssemblyInfo(); #ifndef DACCESS_COMPILE @@ -554,11 +469,9 @@ class Assembly PTR_BaseDomain m_pDomain; // Parent Domain PTR_ClassLoader m_pClassLoader; // Single Loader - - PTR_MethodDesc m_pEntryPoint; // Method containing the entry point - PTR_Module m_pManifest; - PTR_PEAssembly m_pManifestFile; + PTR_Module m_pModule; + PTR_PEAssembly m_pPEAssembly; FriendAssemblyDescriptor *m_pFriendAssemblyDescriptor; @@ -566,7 +479,6 @@ class Assembly #ifdef FEATURE_COLLECTIBLE_TYPES BOOL m_isCollectible; #endif // FEATURE_COLLECTIBLE_TYPES - DWORD m_nextAvailableModuleIndex; PTR_LoaderAllocator m_pLoaderAllocator; #ifdef FEATURE_COMINTEROP @@ -590,8 +502,6 @@ class Assembly }; -typedef Assembly::ModuleIterator ModuleIterator; - #ifndef DACCESS_COMPILE //--------------------------------------------------------------------------------------- @@ -673,7 +583,7 @@ class FriendAssemblyDescriptor static bool IsAssemblyOnList(Assembly *pAssembly, const ArrayList &alAssemblyNames) { - return IsAssemblyOnList(pAssembly->GetManifestFile(), alAssemblyNames); + return IsAssemblyOnList(pAssembly->GetPEAssembly(), alAssemblyNames); } static diff --git a/src/coreclr/vm/assemblyname.cpp b/src/coreclr/vm/assemblyname.cpp deleted file mode 100644 index bd6e41e52611b3..00000000000000 --- a/src/coreclr/vm/assemblyname.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Header: AssemblyName.cpp -** -** Purpose: Implements AssemblyName (loader domain) architecture -** -** - - -** -===========================================================*/ - -#include "common.h" - -#include -#include - -#include "assemblyname.hpp" -#include "field.h" -#include "strongnameholders.h" -#include "strongnameinternal.h" -#include "eeconfig.h" - -FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE) -{ - FCALL_CONTRACT; - - struct _gc - { - ASSEMBLYNAMEREF result; - STRINGREF filename; - } gc; - - gc.result = NULL; - gc.filename = (STRINGREF) filenameUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - - if (gc.filename == NULL) - COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName")); - - if (gc.filename->GetStringLength() == 0) - COMPlusThrow(kArgumentException, W("Argument_EmptyFileName")); - - gc.result = (ASSEMBLYNAMEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__ASSEMBLY_NAME)); - - - /////////////////////////////////////////////// - SString sFileName(gc.filename->GetBuffer()); - PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache); - - // Ask for FLAT. We will only look at metadata and release the image shortly. - // Besides we may be getting the assembly name for images that contain native code for a - // non-native platform and would end up using flat anyways. - PEImageLayout* pLayout = pImage->GetOrCreateLayout(PEImageLayout::LAYOUT_FLAT); - - pImage->VerifyIsAssembly(); - - AssemblySpec spec; - spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL); - spec.AssemblyNameInit(&gc.result, pImage); - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(gc.result); -} -FCIMPLEND - -FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE) -{ - FCALL_CONTRACT; - - U1ARRAYREF orOutputArray = NULL; - OBJECTREF refThis = (OBJECTREF) refThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_1(refThis); - - if (refThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - - ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis; - U1ARRAYREF orPublicKey = orThis->GetPublicKey(); - - if (orPublicKey != NULL) { - DWORD cb = orPublicKey->GetNumComponents(); - StrongNameBufferHolder pbToken; - - if (cb) { - CQuickBytes qb; - BYTE *pbKey = (BYTE*) qb.AllocThrows(cb); - memcpy(pbKey, orPublicKey->GetDataPtr(), cb); - - { - GCX_PREEMP(); - IfFailThrow(StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb)); - } - } - - orOutputArray = (U1ARRAYREF)AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb); - memcpyNoGCRefs(orOutputArray->m_Array, pbToken, cb); - } - - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(orOutputArray); -} -FCIMPLEND - - -FCIMPL1(void, AssemblyNameNative::Init, Object * refThisUNSAFE) -{ - FCALL_CONTRACT; - - ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE; - HRESULT hr = S_OK; - - HELPER_METHOD_FRAME_BEGIN_1(pThis); - - if (pThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); - - ACQUIRE_STACKING_ALLOCATOR(pStackingAllocator); - - AssemblySpec spec; - hr = spec.InitializeSpec(pStackingAllocator, (ASSEMBLYNAMEREF *) &pThis, TRUE); - - if (SUCCEEDED(hr)) - { - spec.AssemblyNameInit(&pThis,NULL); - } - else - { - ThrowHR(hr); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - diff --git a/src/coreclr/vm/assemblyname.hpp b/src/coreclr/vm/assemblyname.hpp deleted file mode 100644 index 9e818fc1a9f7cc..00000000000000 --- a/src/coreclr/vm/assemblyname.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Header: AssemblyName.hpp -** -** Purpose: Implements AssemblyName (loader domain) architecture -** -** - - -** -===========================================================*/ -#ifndef _AssemblyName_H -#define _AssemblyName_H - -class AssemblyNameNative -{ -public: - static FCDECL1(Object*, GetFileInformation, StringObject* filenameUNSAFE); - static FCDECL1(Object*, GetPublicKeyToken, Object* refThisUNSAFE); - static FCDECL1(void, Init, Object * refThisUNSAFE); -}; - -#endif // _AssemblyName_H - diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index a51280e21e4a34..dba5110590717c 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -20,7 +20,6 @@ #include "assemblynative.hpp" #include "dllimport.h" #include "field.h" -#include "assemblyname.hpp" #include "eeconfig.h" #include "interoputil.h" #include "frames.h" @@ -86,9 +85,8 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(QCall::ObjectHandleOnStack } // Initialize spec - spec.InitializeSpec(pStackingAllocator, - &assemblyNameRef, - FALSE); + spec.InitializeSpec(pStackingAllocator, &assemblyNameRef); + GCPROTECT_END(); spec.SetCodeBase(NULL); @@ -107,7 +105,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(QCall::ObjectHandleOnStack { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEAssembly *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile(); + PEAssembly *pRefAssemblyManifestFile = pRefAssembly->GetPEAssembly(); spec.SetFallbackBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackBinder()); } @@ -271,7 +269,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl // 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()->GetPEImage() == pILImage); + BOOL fIsSameAssembly = (pLoadedAssembly->GetPEAssembly()->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. @@ -282,7 +280,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl if (ptrSymbolArray != NULL) { PBYTE pSymbolArray = reinterpret_cast(ptrSymbolArray); - pLoadedAssembly->GetManifestModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); + pLoadedAssembly->GetModule()->SetSymbolBytes(pSymbolArray, (DWORD)cbSymbolArrayLength); } #endif // DEBUGGING_SUPPORTED } @@ -404,7 +402,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedType(QCall::AssemblyHandle mdToken mdImpl; Assembly * pAsm = pAssembly->GetAssembly(); - Module *pManifestModule = pAsm->GetManifestModule(); + Module *pManifestModule = pAsm->GetModule(); IfFailThrow(pManifestModule->GetMDImport()->GetExportedTypeProps(mdtExternalType, &pszNameSpace, &pszClassName, &mdImpl, NULL, NULL)); if (TypeFromToken(mdImpl) == mdtAssemblyRef) { @@ -614,7 +612,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem HENUMInternalHolder phEnum(pAssembly->GetMDImport()); phEnum.EnumInit(mdtFile, mdTokenNil); - InlineSArray modules; + InlineSArray modules; modules.Append(pAssembly); @@ -623,7 +621,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem { if (fLoadIfNotFound) { - DomainFile* pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile); + DomainAssembly* pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile); modules.Append(pModule); } } @@ -640,7 +638,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem for(COUNT_T i = 0; i < modules.GetCount(); i++) { - DomainFile * pModule = modules[i]; + DomainAssembly * pModule = modules[i]; OBJECTREF o = pModule->GetExposedModuleObject(); orModules->SetAt(i, o); @@ -699,10 +697,10 @@ extern "C" void QCALLTYPE AssemblyNative_GetModule(QCall::AssemblyHandle pAssemb LPCUTF8 pModuleName = NULL; - if SUCCEEDED(pAssembly->GetDomainAssembly()->GetModule()->GetScopeName(&pModuleName)) + if SUCCEEDED(pAssembly->GetModule()->GetScopeName(&pModuleName)) { if (::SString::_stricmp(pModuleName, szModuleName) == 0) - pModule = pAssembly->GetDomainAssembly()->GetModule(); + pModule = pAssembly->GetModule(); } @@ -727,7 +725,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle Assembly * pAsm = pAssembly->GetAssembly(); - IMDInternalImport *pImport = pAsm->GetManifestImport(); + IMDInternalImport *pImport = pAsm->GetMDImport(); { HENUMTypeDefInternalHolder phTDEnum(pImport); @@ -755,7 +753,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle if (IsTdPublic(dwFlags)) { - TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetManifestModule(), mdTD, + TypeHandle typeHnd = ClassLoader::LoadTypeDefThrowing(pAsm->GetModule(), mdTD, ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef); types.Append(typeHnd); @@ -803,7 +801,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetExportedTypes(QCall::AssemblyHandle IsTdPublic(dwFlags)) { NameHandle typeName(pszNameSpace, pszClassName); - typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); + typeName.SetTypeToken(pAsm->GetModule(), mdCT); TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); types.Append(typeHnd); @@ -847,7 +845,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedTypes(QCall::AssemblyHandle Assembly * pAsm = pAssembly->GetAssembly(); - IMDInternalImport *pImport = pAsm->GetManifestImport(); + IMDInternalImport *pImport = pAsm->GetMDImport(); // enumerate the ExportedTypes table { @@ -873,7 +871,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetForwardedTypes(QCall::AssemblyHandle if ((TypeFromToken(mdImpl) == mdtAssemblyRef) && (mdImpl != mdAssemblyRefNil)) { NameHandle typeName(pszNameSpace, pszClassName); - typeName.SetTypeToken(pAsm->GetManifestModule(), mdCT); + typeName.SetTypeToken(pAsm->GetModule(), mdCT); TypeHandle typeHnd = pAsm->GetLoader()->LoadTypeHandleThrowIfFailed(&typeName); types.Append(typeHnd); @@ -979,7 +977,7 @@ FCIMPL1(Object*, AssemblyNative::GetReferencedAssemblies, AssemblyBaseObject * p HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - IMDInternalImport *pImport = pAssembly->GetAssembly()->GetManifestImport(); + IMDInternalImport *pImport = pAssembly->GetAssembly()->GetMDImport(); MethodTable* pAsmNameClass = CoreLibBinder::GetClass(CLASS__ASSEMBLY_NAME); @@ -1106,7 +1104,7 @@ FCIMPL1(ReflectModuleBaseObject *, AssemblyNative::GetInMemoryAssemblyModule, As DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); - FC_RETURN_MODULE_OBJECT(pAssembly->GetCurrentModule(), refAssembly); + FC_RETURN_MODULE_OBJECT(pAssembly->GetModule(), refAssembly); } FCIMPLEND @@ -1358,7 +1356,7 @@ extern "C" void QCALLTYPE AssemblyNative_ApplyUpdate( { COMPlusThrow(kNotSupportedException, W("NotSupported_DebuggerAttached")); } - Module* pModule = assembly->GetDomainAssembly()->GetModule(); + Module* pModule = assembly->GetModule(); if (!pModule->IsEditAndContinueEnabled()) { COMPlusThrow(kInvalidOperationException, W("InvalidOperation_AssemblyNotEditable")); diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index dfbee7152df19a..cce0b240105d37 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -250,8 +250,7 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) // This uses thread storage to allocate space. Please use Checkpoint and release it. -HRESULT AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName, - BOOL fParse /*=TRUE*/) +void AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName) { CONTRACTL { @@ -290,107 +289,86 @@ HRESULT AssemblySpec::InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* SetName(lpName); } - if (fParse) { - HRESULT hr = ParseName(); - // Sometimes Fusion flags invalid characters in the name, sometimes it doesn't - // depending on where the invalid characters are - // We want to Raise the assembly resolve event on all invalid characters - // but calling ParseName before checking for invalid characters gives Fusion a chance to - // parse the rest of the name (to get a public key token, etc.) - if ((hr == FUSION_E_INVALID_NAME) || (!IsValidAssemblyName())) { - // This is the only case where we do not throw on an error - // We don't want to throw so as to give the caller a chance to call RaiseAssemblyResolveEvent - // The only caller that cares is System.Reflection.Assembly.InternalLoad which calls us through - // AssemblyNameNative::Init - return FUSION_E_INVALID_NAME; - } - else - IfFailThrow(hr); + AssemblyMetaDataInternal asmInfo; + // Flags + DWORD dwFlags = (*pName)->GetFlags(); + + // Version + VERSIONREF version = (VERSIONREF) (*pName)->GetVersion(); + if(version == NULL) { + asmInfo.usMajorVersion = (USHORT)-1; + asmInfo.usMinorVersion = (USHORT)-1; + asmInfo.usBuildNumber = (USHORT)-1; + asmInfo.usRevisionNumber = (USHORT)-1; } else { - AssemblyMetaDataInternal asmInfo; - // Flags - DWORD dwFlags = (*pName)->GetFlags(); - - // Version - VERSIONREF version = (VERSIONREF) (*pName)->GetVersion(); - if(version == NULL) { - asmInfo.usMajorVersion = (USHORT)-1; - asmInfo.usMinorVersion = (USHORT)-1; - asmInfo.usBuildNumber = (USHORT)-1; - asmInfo.usRevisionNumber = (USHORT)-1; - } - else { - asmInfo.usMajorVersion = (USHORT)version->GetMajor(); - asmInfo.usMinorVersion = (USHORT)version->GetMinor(); - asmInfo.usBuildNumber = (USHORT)version->GetBuild(); - asmInfo.usRevisionNumber = (USHORT)version->GetRevision(); - } + asmInfo.usMajorVersion = (USHORT)version->GetMajor(); + asmInfo.usMinorVersion = (USHORT)version->GetMinor(); + asmInfo.usBuildNumber = (USHORT)version->GetBuild(); + asmInfo.usRevisionNumber = (USHORT)version->GetRevision(); + } - asmInfo.szLocale = 0; + asmInfo.szLocale = 0; - if ((*pName)->GetCultureInfo() != NULL) - { - struct _gc { - OBJECTREF cultureinfo; - STRINGREF pString; - } gc; - - gc.cultureinfo = (*pName)->GetCultureInfo(); - gc.pString = NULL; - - GCPROTECT_BEGIN(gc); - - MethodDescCallSite getName(METHOD__CULTURE_INFO__GET_NAME, &gc.cultureinfo); - - ARG_SLOT args[] = { - ObjToArgSlot(gc.cultureinfo) - }; - gc.pString = getName.Call_RetSTRINGREF(args); - if (gc.pString != NULL) { - WCHAR* pString; - int iString; - gc.pString->RefInterpretGetStringValuesDangerousForGC(&pString, &iString); - DWORD lgth = WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, NULL, 0, NULL, NULL); - S_UINT32 lengthWillNull = S_UINT32(lgth) + S_UINT32(1); - LPSTR lpLocale = (LPSTR) alloc->Alloc(lengthWillNull); - if (lengthWillNull.IsOverflow()) - { - COMPlusThrowHR(COR_E_OVERFLOW); - } - WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, - lpLocale, lengthWillNull.Value(), NULL, NULL); - lpLocale[lgth] = '\0'; - asmInfo.szLocale = lpLocale; - } - GCPROTECT_END(); - } + if ((*pName)->GetCultureInfo() != NULL) + { + struct _gc { + OBJECTREF cultureinfo; + STRINGREF pString; + } gc; - // Strong name - DWORD cbPublicKeyOrToken=0; - BYTE* pbPublicKeyOrToken=NULL; - // Note that we prefer to take a public key token if present, - // even if flags indicate a full public key - if ((*pName)->GetPublicKeyToken() != NULL) { - dwFlags &= ~afPublicKey; - PBYTE pArray = NULL; - pArray = (*pName)->GetPublicKeyToken()->GetDirectPointerToNonObjectElements(); - cbPublicKeyOrToken = (*pName)->GetPublicKeyToken()->GetNumComponents(); - pbPublicKeyOrToken = pArray; - } - else if ((*pName)->GetPublicKey() != NULL) { - dwFlags |= afPublicKey; - PBYTE pArray = NULL; - pArray = (*pName)->GetPublicKey()->GetDirectPointerToNonObjectElements(); - cbPublicKeyOrToken = (*pName)->GetPublicKey()->GetNumComponents(); - pbPublicKeyOrToken = pArray; + gc.cultureinfo = (*pName)->GetCultureInfo(); + gc.pString = NULL; + + GCPROTECT_BEGIN(gc); + + MethodDescCallSite getName(METHOD__CULTURE_INFO__GET_NAME, &gc.cultureinfo); + + ARG_SLOT args[] = { + ObjToArgSlot(gc.cultureinfo) + }; + gc.pString = getName.Call_RetSTRINGREF(args); + if (gc.pString != NULL) { + WCHAR* pString; + int iString; + gc.pString->RefInterpretGetStringValuesDangerousForGC(&pString, &iString); + DWORD lgth = WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, NULL, 0, NULL, NULL); + S_UINT32 lengthWillNull = S_UINT32(lgth) + S_UINT32(1); + LPSTR lpLocale = (LPSTR) alloc->Alloc(lengthWillNull); + if (lengthWillNull.IsOverflow()) + { + COMPlusThrowHR(COR_E_OVERFLOW); + } + WszWideCharToMultiByte(CP_UTF8, 0, pString, iString, + lpLocale, lengthWillNull.Value(), NULL, NULL); + lpLocale[lgth] = '\0'; + asmInfo.szLocale = lpLocale; } - BaseAssemblySpec::Init(GetName(),&asmInfo,pbPublicKeyOrToken,cbPublicKeyOrToken,dwFlags); - } + GCPROTECT_END(); + } + + // Strong name + DWORD cbPublicKeyOrToken=0; + BYTE* pbPublicKeyOrToken=NULL; + // Note that we prefer to take a public key token if present, + // even if flags indicate a full public key + if ((*pName)->GetPublicKeyToken() != NULL) { + dwFlags &= ~afPublicKey; + PBYTE pArray = NULL; + pArray = (*pName)->GetPublicKeyToken()->GetDirectPointerToNonObjectElements(); + cbPublicKeyOrToken = (*pName)->GetPublicKeyToken()->GetNumComponents(); + pbPublicKeyOrToken = pArray; + } + else if ((*pName)->GetPublicKey() != NULL) { + dwFlags |= afPublicKey; + PBYTE pArray = NULL; + pArray = (*pName)->GetPublicKey()->GetDirectPointerToNonObjectElements(); + cbPublicKeyOrToken = (*pName)->GetPublicKey()->GetNumComponents(); + pbPublicKeyOrToken = pArray; + } + BaseAssemblySpec::Init(GetName(),&asmInfo,pbPublicKeyOrToken,cbPublicKeyOrToken,dwFlags); CloneFieldsToStackingAllocator(alloc); - - return S_OK; } void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName, PEImage* pImageInfo) @@ -756,7 +734,7 @@ DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, BinderTracing::AssemblyBindOperation bindOperation(this); bindOperation.SetResult(pAssembly->GetPEAssembly(), true /*cached*/); - pDomain->LoadDomainFile(pAssembly, targetLevel); + pDomain->LoadDomainAssembly(pAssembly, targetLevel); RETURN pAssembly; } diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 5d09b5b75a664e..8d2bd8045593d2 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -16,7 +16,7 @@ #define _ASSEMBLYSPEC_H #include "hash.h" #include "assemblyspecbase.h" -#include "domainfile.h" +#include "domainassembly.h" #include "holder.h" class AppDomain; @@ -103,9 +103,7 @@ class AssemblySpec : public BaseAssemblySpec void InitializeSpec(PEAssembly* pPEAssembly); - HRESULT InitializeSpec(StackingAllocator* alloc, - ASSEMBLYNAMEREF* pName, - BOOL fParse = TRUE); + void InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName); void AssemblyNameInit(ASSEMBLYNAMEREF* pName, PEImage* pImageInfo); //[in,out], [in] diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 87876cded4d57f..c25b7aa19cc9d1 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -443,7 +443,6 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb // // szName is only used by dynamic modules, see ReflectionModule::Initialize // -// void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) { CONTRACTL @@ -464,14 +463,6 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) m_DictionaryCrst.Init(CrstDomainLocalBlock); AllocateMaps(); - - if (IsSystem() || - (strcmp(m_pSimpleName, "System") == 0) || - (strcmp(m_pSimpleName, "System.Core") == 0)) - { - FastInterlockOr(&m_dwPersistedFlags, LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME); - } - m_dwTransientFlags &= ~((DWORD)CLASSES_FREED); // Set flag indicating LookupMaps are now in a consistent and destructable state #ifdef FEATURE_COLLECTIBLE_TYPES @@ -1041,7 +1032,7 @@ BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEAssembly *pPEAssemb BOOL Module::IsManifest() { WRAPPER_NO_CONTRACT; - return dac_cast(GetAssembly()->GetManifestModule()) == + return dac_cast(GetAssembly()->GetModule()) == dac_cast(this); } @@ -1049,14 +1040,7 @@ DomainAssembly* Module::GetDomainAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return dac_cast(m_ModuleID->GetDomainFile()); -} - -DomainFile *Module::GetDomainFile() -{ - LIMITED_METHOD_DAC_CONTRACT; - - return dac_cast(m_ModuleID->GetDomainFile()); + return dac_cast(m_ModuleID->GetDomainAssembly()); } #ifndef DACCESS_COMPILE @@ -1629,9 +1613,7 @@ BOOL Module::IsNoStringInterning() HRESULT hr; - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); _ASSERTE(mdImport); mdToken token; @@ -1736,9 +1718,7 @@ BOOL Module::IsRuntimeWrapExceptions() HRESULT hr; BOOL fRuntimeWrapExceptions = FALSE; - // This flag applies to assembly, but it is stored on module so it can be cached in ngen image - // Thus, we should ever need it for manifest module only. - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); mdToken token; IfFailGo(mdImport->GetAssemblyFromScope(&token)); @@ -1792,7 +1772,7 @@ BOOL Module::IsRuntimeMarshallingEnabled() HRESULT hr; - IMDInternalImport *mdImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = GetAssembly()->GetMDImport(); mdToken token; if (SUCCEEDED(hr = mdImport->GetAssemblyFromScope(&token))) @@ -1822,7 +1802,7 @@ BOOL Module::IsPreV4Assembly() if (!(m_dwPersistedFlags & COMPUTED_IS_PRE_V4_ASSEMBLY)) { - IMDInternalImport *pImport = GetAssembly()->GetManifestImport(); + IMDInternalImport *pImport = GetAssembly()->GetMDImport(); _ASSERTE(pImport); BOOL fIsPreV4Assembly = FALSE; @@ -2004,13 +1984,13 @@ void Module::AllocateStatics(AllocMemTracker *pamTracker) BuildStaticsOffsets(pamTracker); } -void Module::SetDomainFile(DomainFile *pDomainFile) +void Module::SetDomainAssembly(DomainAssembly *pDomainAssembly) { CONTRACTL { INSTANCE_CHECK; - PRECONDITION(CheckPointer(pDomainFile)); - PRECONDITION(IsManifest() == pDomainFile->IsAssembly()); + PRECONDITION(CheckPointer(pDomainAssembly)); + PRECONDITION(IsManifest()); THROWS; GC_TRIGGERS; MODE_ANY; @@ -2030,7 +2010,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) } else { - pLoaderAllocator = pDomainFile->GetAppDomain()->GetLoaderAllocator(); + pLoaderAllocator = pDomainAssembly->GetAppDomain()->GetLoaderAllocator(); } SIZE_T size = GetDomainLocalModuleSize(); @@ -2070,7 +2050,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) m_ModuleID = pModuleData; } - m_ModuleID->SetDomainFile(pDomainFile); + m_ModuleID->SetDomainAssembly(pDomainAssembly); // Allocate static handles now. // NOTE: Bootstrapping issue with CoreLib - we will manually allocate later @@ -2078,7 +2058,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile) // as it is currently initialized through the DomainLocalModule::PopulateClass in MethodTable::CheckRunClassInitThrowing // (If we don't do this, it would allocate here unused regular static handles that will be overridden later) if (g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] != NULL && !GetAssembly()->IsCollectible()) - AllocateRegularStaticHandles(pDomainFile->GetAppDomain()); + AllocateRegularStaticHandles(pDomainAssembly->GetAppDomain()); } OBJECTREF Module::GetExposedObject() @@ -2093,7 +2073,7 @@ OBJECTREF Module::GetExposedObject() } CONTRACT_END; - RETURN GetDomainFile()->GetExposedModuleObject(); + RETURN GetDomainAssembly()->GetExposedModuleObject(); } // @@ -3320,7 +3300,7 @@ Module::GetAssemblyIfLoaded( } if (pDomainAssembly && pDomainAssembly->IsLoaded()) - pAssembly = pDomainAssembly->GetCurrentAssembly(); // Do not use GetAssembly - that may force the completion of a load + pAssembly = pDomainAssembly->GetAssembly(); // Only store in the rid map if working with the current AppDomain. if (fCanUseRidMap && pAssembly) @@ -3404,7 +3384,7 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) if (pAssembly != NULL) { pDomainAssembly = pAssembly->GetDomainAssembly(); - ::GetAppDomain()->LoadDomainFile(pDomainAssembly, FILE_LOADED); + ::GetAppDomain()->LoadDomainAssembly(pDomainAssembly, FILE_LOADED); RETURN pDomainAssembly; } @@ -3431,9 +3411,9 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases - if (pDomainAssembly->GetCurrentAssembly() != NULL) + if (pDomainAssembly->GetAssembly() != NULL) { - StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetCurrentAssembly()); + StoreAssemblyRef(kAssemblyRef, pDomainAssembly->GetAssembly()); } } @@ -3474,7 +3454,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) if (kFile == mdTokenNil) RETURN NULL; - RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile); + RETURN GetAssembly()->GetModule()->GetModuleIfLoaded(kFile); } Module *pModule = LookupFile(kFile); @@ -3483,7 +3463,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) if (IsManifest()) { if (kFile == mdFileNil) - pModule = GetAssembly()->GetManifestModule(); + pModule = GetAssembly()->GetModule(); } else { @@ -3497,7 +3477,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) { if (kMatch == mdFileNil) { - pModule = pAssembly->GetManifestModule(); + pModule = pAssembly->GetModule(); } else { @@ -3505,7 +3485,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) } } else - pModule = pAssembly->GetManifestModule()->LookupFile(kMatch); + pModule = pAssembly->GetModule()->LookupFile(kMatch); } #ifndef DACCESS_COMPILE @@ -3521,9 +3501,9 @@ Module *Module::GetModuleIfLoaded(mdFile kFile) #ifndef DACCESS_COMPILE -DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile) +DomainAssembly *Module::LoadModule(AppDomain *pDomain, mdFile kFile) { - CONTRACT(DomainFile *) + CONTRACT(DomainAssembly *) { INSTANCE_CHECK; THROWS; @@ -3543,7 +3523,7 @@ DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile) else { // This is mdtFile - IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile, + IfFailThrow(GetAssembly()->GetMDImport()->GetFileProps(kFile, &psModuleName, NULL, NULL, @@ -3582,7 +3562,7 @@ PTR_Module Module::LookupModule(mdToken kFile) if (kFileLocal == mdTokenNil) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); - RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal); + RETURN GetAssembly()->GetModule()->LookupModule(kFileLocal); } PTR_Module pModule = LookupFile(kFile); @@ -3593,12 +3573,12 @@ PTR_Module Module::LookupModule(mdToken kFile) mdFile kMatch = pAssembly->GetManifestFileToken(GetMDImport(), kFile); if (IsNilToken(kMatch)) { if (kMatch == mdFileNil) - pModule = pAssembly->GetManifestModule(); + pModule = pAssembly->GetModule(); else COMPlusThrowHR(COR_E_BADIMAGEFORMAT); } else - pModule = pAssembly->GetManifestModule()->LookupFile(kMatch); + pModule = pAssembly->GetModule()->LookupFile(kMatch); } RETURN pModule; } @@ -4067,7 +4047,7 @@ void Module::UpdateDynamicMetadataIfNeeded() #endif // DEBUGGING_SUPPORTED -BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int flags, BOOL attaching) +BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainAssembly * pDomainAssembly, int flags, BOOL attaching) { WRAPPER_NO_CONTRACT; @@ -4078,7 +4058,7 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in // Always capture metadata, even if no debugger is attached. If a debugger later attaches, it will use // this data. { - Module * pModule = pDomainFile->GetModule(); + Module * pModule = pDomainAssembly->GetModule(); pModule->UpdateDynamicMetadataIfNeeded(); } @@ -4099,7 +4079,7 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in m_pPEAssembly->GetPath().GetCount(), GetAssembly(), pDomain, - pDomainFile, + pDomainAssembly, attaching); result = TRUE; @@ -4595,7 +4575,7 @@ Module *Module::GetModuleFromIndex(DWORD ix) Assembly *pAssembly = this->LookupAssemblyRef(mdAssemblyRefToken); if (pAssembly) { - RETURN pAssembly->GetManifestModule(); + RETURN pAssembly->GetModule(); } else { @@ -6478,11 +6458,7 @@ void Module::WriteAllModuleProfileData(bool cleanup) while (assemblyIterator.Next(pDomainAssembly.This())) { - DomainModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (i.Next()) - { - /*hr=*/i.GetModule()->WriteMethodProfileDataLogFile(cleanup); - } + pDomainAssembly->GetModule()->WriteMethodProfileDataLogFile(cleanup); } } } @@ -7473,7 +7449,7 @@ VOID Module::EnsureActive() MODE_ANY; } CONTRACTL_END; - GetDomainFile()->EnsureActive(); + GetDomainAssembly()->EnsureActive(); } #endif // DACCESS_COMPILE @@ -7492,13 +7468,13 @@ VOID Module::EnsureAllocated() } CONTRACTL_END; - GetDomainFile()->EnsureAllocated(); + GetDomainAssembly()->EnsureAllocated(); } VOID Module::EnsureLibraryLoaded() { STANDARD_VM_CONTRACT; - GetDomainFile()->EnsureLibraryLoaded(); + GetDomainAssembly()->EnsureLibraryLoaded(); } #endif // !DACCESS_COMPILE @@ -7513,10 +7489,10 @@ CHECK Module::CheckActivated() CONTRACTL_END; #ifndef DACCESS_COMPILE - DomainFile *pDomainFile = GetDomainFile(); - CHECK(pDomainFile != NULL); - PREFIX_ASSUME(pDomainFile != NULL); - CHECK(pDomainFile->CheckActivated()); + DomainAssembly *pDomainAssembly = GetDomainAssembly(); + CHECK(pDomainAssembly != NULL); + PREFIX_ASSUME(pDomainAssembly != NULL); + CHECK(pDomainAssembly->CheckActivated()); #endif CHECK_OK; } diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 2b9198b811732f..d9cd6742cb6c0e 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -832,8 +832,7 @@ class Module //If m_MethodDefToPropertyInfoMap has been generated COMPUTED_METHODDEF_TO_PROPERTYINFO_MAP = 0x00002000, - // Low level system assembly. Used by preferred zap module computation. - LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME = 0x00004000, + // unused = 0x00004000, //If setting has been cached RUNTIME_MARSHALLING_ENABLED_IS_CACHED = 0x00008000, @@ -1132,13 +1131,9 @@ class Module MethodTable *GetGlobalMethodTable(); bool NeedsGlobalMethodTable(); - // This works for manifest modules too - DomainFile *GetDomainFile(); - - // Operates on assembly of module DomainAssembly *GetDomainAssembly(); - void SetDomainFile(DomainFile *pDomainFile); + void SetDomainAssembly(DomainAssembly *pDomainAssembly); OBJECTREF GetExposedObject(); @@ -1195,14 +1190,6 @@ class Module LIMITED_METHOD_CONTRACT; FastInterlockOr(&m_dwTransientFlags, MODULE_IS_TENURED); } - - // CAUTION: This should only be used as backout code if an assembly is unsuccessfully - // added to the shared domain assembly map. - VOID UnsetIsTenured() - { - LIMITED_METHOD_CONTRACT; - FastInterlockAnd(&m_dwTransientFlags, ~MODULE_IS_TENURED); - } #endif // !DACCESS_COMPILE @@ -1223,13 +1210,6 @@ class Module } #endif - BOOL IsLowLevelSystemAssemblyByName() - { - LIMITED_METHOD_CONTRACT; - // The flag is set during initialization, so we can skip the memory barrier - return m_dwPersistedFlags.LoadWithoutBarrier() & LOW_LEVEL_SYSTEM_ASSEMBLY_BY_NAME; - } - #ifndef DACCESS_COMPILE VOID EnsureActive(); VOID EnsureAllocated(); @@ -1436,7 +1416,7 @@ class Module DomainAssembly * LoadAssembly(mdAssemblyRef kAssemblyRef); Module *GetModuleIfLoaded(mdFile kFile); - DomainFile *LoadModule(AppDomain *pDomain, mdFile kFile); + DomainAssembly *LoadModule(AppDomain *pDomain, mdFile kFile); PTR_Module LookupModule(mdToken kFile); //wrapper over GetModuleIfLoaded, takes modulerefs as well DWORD GetAssemblyRefFlags(mdAssemblyRef tkAssemblyRef); @@ -1719,7 +1699,7 @@ class Module public: // Debugger stuff - BOOL NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, int level, BOOL attaching); + BOOL NotifyDebuggerLoad(AppDomain *pDomain, DomainAssembly * pDomainAssembly, int level, BOOL attaching); void NotifyDebuggerUnload(AppDomain *pDomain); void SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits); diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl index ca770297a4bc9c..fee8a8f4fcc33a 100644 --- a/src/coreclr/vm/ceeload.inl +++ b/src/coreclr/vm/ceeload.inl @@ -297,25 +297,25 @@ inline Assembly *Module::LookupAssemblyRef(mdAssemblyRef token) inline void Module::ForceStoreAssemblyRef(mdAssemblyRef token, Assembly *value) { WRAPPER_NO_CONTRACT; // THROWS/GC_NOTRIGGER/INJECT_FAULT()/MODE_ANY - _ASSERTE(value->GetManifestModule()); + _ASSERTE(value->GetModule()); _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); - m_ManifestModuleReferencesMap.AddElement(this, RidFromToken(token), value->GetManifestModule()); + m_ManifestModuleReferencesMap.AddElement(this, RidFromToken(token), value->GetModule()); } inline void Module::StoreAssemblyRef(mdAssemblyRef token, Assembly *value) { WRAPPER_NO_CONTRACT; - _ASSERTE(value->GetManifestModule()); + _ASSERTE(value->GetModule()); _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); - m_ManifestModuleReferencesMap.TrySetElement(RidFromToken(token), value->GetManifestModule()); + m_ManifestModuleReferencesMap.TrySetElement(RidFromToken(token), value->GetModule()); } inline mdAssemblyRef Module::FindAssemblyRef(Assembly *targetAssembly) { WRAPPER_NO_CONTRACT; - return m_ManifestModuleReferencesMap.Find(targetAssembly->GetManifestModule()) | mdtAssemblyRef; + return m_ManifestModuleReferencesMap.Find(targetAssembly->GetModule()) | mdtAssemblyRef; } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/classhash.cpp b/src/coreclr/vm/classhash.cpp index 28c636f7c9aadd..7320f7bae72a75 100644 --- a/src/coreclr/vm/classhash.cpp +++ b/src/coreclr/vm/classhash.cpp @@ -267,7 +267,7 @@ VOID EEClassHashTable::ConstructKeyFromData(PTR_EEClassHashEntry pEntry, // IN mdToken mdtUncompressed = UncompressModuleAndClassDef(Data); if (TypeFromToken(mdtUncompressed) == mdtExportedType) { - IfFailThrow(GetModule()->GetClassLoader()->GetAssembly()->GetManifestImport()->GetExportedTypeProps( + IfFailThrow(GetModule()->GetClassLoader()->GetAssembly()->GetMDImport()->GetExportedTypeProps( mdtUncompressed, (LPCSTR *)&pszNameSpace, (LPCSTR *)&pszName, diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index a2b0129e2dd71f..c1a5ffb86ecd90 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -563,7 +563,7 @@ BOOL ClassLoader::IsNested(Module *pModule, mdToken token, mdToken *mdEncloser) (*mdEncloser != mdTypeRefNil)); case mdtExportedType: - IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetExportedTypeProps( + IfFailThrow(pModule->GetAssembly()->GetMDImport()->GetExportedTypeProps( token, NULL, // namespace NULL, // name @@ -643,17 +643,11 @@ void ClassLoader::GetClassValue(NameHandleTable nhTable, #endif PTR_Assembly assembly = GetAssembly(); - PREFIX_ASSUME(assembly != NULL); - ModuleIterator i = assembly->IterateModules(); + Module * pCurrentClsModule = assembly->GetModule(); + _ASSERTE(pCurrentClsModule != NULL); - while (i.Next()) + if (!pLookInThisModuleOnly || (pCurrentClsModule == pLookInThisModuleOnly)) { - Module * pCurrentClsModule = i.GetModule(); - PREFIX_ASSUME(pCurrentClsModule != NULL); - - if (pLookInThisModuleOnly && (pCurrentClsModule != pLookInThisModuleOnly)) - continue; - #ifdef FEATURE_READYTORUN if (nhTable == nhCaseSensitive && pCurrentClsModule->IsReadyToRun() && pCurrentClsModule->GetReadyToRunInfo()->HasHashtableOfTypes() && pCurrentClsModule->GetAvailableClassHash() == NULL) @@ -744,7 +738,7 @@ void ClassLoader::GetClassValue(NameHandleTable nhTable, (pBucket = pTable->FindNextNestedClass(pName, pData, &sContext)) != NULL); break; case mdtExportedType: - while ((!CompareNestedEntryWithExportedType(pNameModule->GetAssembly()->GetManifestImport(), + while ((!CompareNestedEntryWithExportedType(pNameModule->GetAssembly()->GetMDImport(), mdEncloser, pCurrentClsModule->GetAvailableClassHash(), pBucket->GetEncloser())) && @@ -838,16 +832,11 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() _ASSERT(m_cUnhashedModules > 0); AllocMemTracker amTracker; - ModuleIterator i = GetAssembly()->IterateModules(); - // Create a case-sensitive hashtable for each module, and fill it with the module's typedef entries - while (i.Next()) + // Create a case-sensitive hashtable for the module, and fill it with the module's typedef entries + Module *pModule = GetAssembly()->GetModule(); + if (pModule->GetAvailableClassHash() == NULL) { - Module *pModule = i.GetModule(); - PREFIX_ASSUME(pModule != NULL); - if (pModule->GetAvailableClassHash() != NULL) - continue; - // Lazy construction of the case-sensitive hashtable of types is *only* a scenario for ReadyToRun images // (either images compiled with an old version of crossgen, or for case-insensitive type lookups in R2R modules) _ASSERT(pModule->IsReadyToRun()); @@ -858,14 +847,14 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() PopulateAvailableClassHashTable(pModule, &amTracker); } - // Add exported types of the manifest module to the hashtable - IMDInternalImport * pManifestImport = GetAssembly()->GetManifestImport(); + // Add exported types to the hashtable + IMDInternalImport * pManifestImport = GetAssembly()->GetMDImport(); HENUMInternalHolder phEnum(pManifestImport); phEnum.EnumInit(mdtExportedType, mdTokenNil); mdToken mdExportedType; while (pManifestImport->EnumNext(&phEnum, &mdExportedType)) - AddExportedTypeHaveLock(GetAssembly()->GetManifestModule(), mdExportedType, &amTracker); + AddExportedTypeHaveLock(GetAssembly()->GetModule(), mdExportedType, &amTracker); amTracker.SuppressRelease(); } @@ -882,7 +871,7 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() } CONTRACTL_END; - if (GetAssembly()->GetManifestModule()->GetAvailableClassHash() == NULL) + if (GetAssembly()->GetModule()->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 @@ -893,28 +882,23 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() // Add any unhashed modules into our hash tables, and try again. AllocMemTracker amTracker; - ModuleIterator i = GetAssembly()->IterateModules(); - - while (i.Next()) + Module *pModule = GetAssembly()->GetModule(); + if (pModule->GetAvailableClassCaseInsHash() == NULL) { - Module *pModule = i.GetModule(); - if (pModule->GetAvailableClassCaseInsHash() == NULL) - { - EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker); + EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker); - LOG((LF_CLASSLOADER, LL_INFO10, "%s's classes being added to case insensitive hash table\n", - pModule->GetSimpleName())); + LOG((LF_CLASSLOADER, LL_INFO10, "%s's classes being added to case insensitive hash table\n", + pModule->GetSimpleName())); - { - CANNOTTHROWCOMPLUSEXCEPTION(); - FAULT_FORBID(); + { + CANNOTTHROWCOMPLUSEXCEPTION(); + FAULT_FORBID(); - amTracker.SuppressRelease(); - pModule->SetAvailableClassCaseInsHash(pNewClassCaseInsHash); - FastInterlockDecrement((LONG*)&m_cUnhashedModules); + amTracker.SuppressRelease(); + pModule->SetAvailableClassCaseInsHash(pNewClassCaseInsHash); + FastInterlockDecrement((LONG*)&m_cUnhashedModules); - _ASSERT(m_cUnhashedModules >= 0); - } + _ASSERT(m_cUnhashedModules >= 0); } } } @@ -1498,7 +1482,7 @@ ClassLoader::LoadTypeHandleThrowing( if (typeHnd.IsNull() || !CompareNameHandleWithTypeHandleNoThrow(pName, typeHnd)) { if (SUCCEEDED(pClsLdr->FindTypeDefByExportedType( - pClsLdr->GetAssembly()->GetManifestImport(), + pClsLdr->GetAssembly()->GetMDImport(), FoundExportedType, pFoundModule->GetMDImport(), &FoundCl))) @@ -1860,16 +1844,8 @@ void ClassLoader::FreeModules() CONTRACTL_END; Module *pManifest = NULL; - if (GetAssembly() && (NULL != (pManifest = GetAssembly()->GetManifestModule()))) { - // Unload the manifest last, since it contains the module list in its rid map - ModuleIterator i = GetAssembly()->IterateModules(); - while (i.Next()) { - // Have the module free its various tables and some of the EEClass links - if (i.GetModule() != pManifest) - i.GetModule()->Destruct(); - } - - // Now do the manifest module. + if (GetAssembly() && (NULL != (pManifest = GetAssembly()->GetModule()))) + { pManifest->Destruct(); } @@ -3267,15 +3243,6 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey, UINT32 typeLoad = ETW::TypeSystemLog::TypeLoadBegin(); #endif - // When using domain neutral assemblies (and not eagerly propagating dependency loads), - // it's possible to get here without having injected the module into the current app domain. - // GetDomainFile will accomplish that. - - if (!pTypeKey->IsConstructed()) - { - pTypeKey->GetModule()->GetDomainFile(); - } - ClassLoadLevel currentLevel = typeHnd.IsNull() ? CLASS_LOAD_BEGIN : typeHnd.GetLoadLevel(); ClassLoadLevel targetLevelUnderLock = targetLevel < CLASS_DEPENDENCIES_LOADED ? targetLevel : (ClassLoadLevel) (CLASS_DEPENDENCIES_LOADED-1); if (currentLevel < targetLevelUnderLock) @@ -5159,12 +5126,7 @@ ClassLoader::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) if (m_pAssembly.IsValid()) { - ModuleIterator modIter = GetAssembly()->IterateModules(); - - while (modIter.Next()) - { - modIter.GetModule()->EnumMemoryRegions(flags, true); - } + m_pAssembly->GetModule()->EnumMemoryRegions(flags, true); } } diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index 8fa82da46db6e2..d59e13d45d45d4 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -2036,18 +2036,15 @@ HRESULT CodeVersionManager::EnumerateDomainClosedMethodDescs( // these are the default flags which won't actually be used in shared mode other than // asserting they were specified with their default values AssemblyIterationFlags assemFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution); - ModuleIterationOption moduleFlags = (ModuleIterationOption)kModIterIncludeLoaded; if (pAppDomainToSearch != NULL) { assemFlags = (AssemblyIterationFlags)(kIncludeAvailableToProfilers | kIncludeExecution); - moduleFlags = (ModuleIterationOption)kModIterIncludeAvailableToProfilers; } LoadedMethodDescIterator it( pAppDomainToSearch, pModuleContainingMethodDef, methodDef, - assemFlags, - moduleFlags); + assemFlags); CollectibleAssemblyHolder pDomainAssembly; while (it.Next(pDomainAssembly.This())) { diff --git a/src/coreclr/vm/comdynamic.cpp b/src/coreclr/vm/comdynamic.cpp index 4996b53e2e48c8..99a6c788b1e4f4 100644 --- a/src/coreclr/vm/comdynamic.cpp +++ b/src/coreclr/vm/comdynamic.cpp @@ -900,12 +900,8 @@ void UpdateRuntimeStateForAssemblyCustomAttribute(Module* pModule, mdToken tkCus actualFlags = ((DWORD)pAssembly->GetDebuggerInfoBits() & mask) | flags; pAssembly->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); - ModuleIterator i = pAssembly->IterateModules(); - while (i.Next()) - { - actualFlags = ((DWORD)(i.GetModule()->GetDebuggerInfoBits()) & mask) | flags; - i.GetModule()->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); - } + actualFlags = ((DWORD)(pAssembly->GetModule()->GetDebuggerInfoBits()) & mask) | flags; + pAssembly->GetModule()->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)actualFlags); } // InternalsVisibleTo and IgnoresAccessChecksTo attribute processing diff --git a/src/coreclr/vm/commodule.cpp b/src/coreclr/vm/commodule.cpp index f19482c2a59f38..cd2b5ab843456b 100644 --- a/src/coreclr/vm/commodule.cpp +++ b/src/coreclr/vm/commodule.cpp @@ -256,13 +256,13 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRef(QCall::ModuleHandle pModul } SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); CQuickBytes qbNewSig; ULONG cbNewSig; IfFailThrow( pRefedModule->GetMDImport()->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash value pvComSig, cbComSig, @@ -335,7 +335,7 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRefOfMethodInfo(QCall::ModuleH Assembly * pRefingAssembly = pModule->GetAssembly(); SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); CQuickBytes qbNewSig; ULONG cbNewSig; @@ -349,7 +349,7 @@ extern "C" INT32 QCALLTYPE ModuleBuilder_GetMemberRefOfMethodInfo(QCall::ModuleH } IfFailThrow( pMeth->GetMDImport()->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash blob value pvComSig, cbComSig, @@ -421,14 +421,14 @@ extern "C" mdMemberRef QCALLTYPE ModuleBuilder_GetMemberRefOfFieldInfo(QCall::Mo COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible")); } SafeComHolderPreemp pAssemblyEmit; - IfFailThrow( pRefingAssembly->GetManifestModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); + IfFailThrow( pRefingAssembly->GetModule()->GetEmitter()->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); // Translate the field signature this scope CQuickBytes qbNewSig; ULONG cbNewSig; IfFailThrow( pRefedMDImport->TranslateSigWithScope( - pRefedAssembly->GetManifestImport(), + pRefedAssembly->GetMDImport(), NULL, 0, // hash value pvComSig, cbComSig, @@ -499,14 +499,20 @@ extern "C" void QCALLTYPE ModuleBuilder_SetFieldRVAContent(QCall::ModuleHandle p if (pReflectionModule->m_sdataSection == 0) IfFailThrow( pGen->GetSectionCreate (".sdata", sdReadWrite, &pReflectionModule->m_sdataSection) ); + // Define the alignment that the rva will be set to. Since the CoreCLR runtime only has hard alignment requirements + // up to 8 bytes, the highest alignment we may need is 8 byte alignment. This hard alignment requirement is only needed + // by Runtime.Helpers.CreateSpan. Since the previous alignment was 4 bytes before CreateSpan was implemented, if the + // data isn't itself of size divisible by 8, just align to 4 to the memory cost of excess alignment. + DWORD alignment = (length % 8 == 0) ? 8 : 4; + // Get the size of current .sdata section. This will be the RVA for this field within the section DWORD dwRVA = 0; IfFailThrow( pGen->GetSectionDataLen(pReflectionModule->m_sdataSection, &dwRVA) ); - dwRVA = (dwRVA + sizeof(DWORD)-1) & ~(sizeof(DWORD)-1); + dwRVA = (dwRVA + alignment-1) & ~(alignment-1); // allocate the space in .sdata section void * pvBlob; - IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, sizeof(DWORD), (void**) &pvBlob) ); + IfFailThrow( pGen->GetSectionBlock(pReflectionModule->m_sdataSection, length, alignment, (void**) &pvBlob) ); // copy over the initialized data if specified if (pContent != NULL) diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index bcd9af84555c68..c2fff3f9c9a961 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -120,8 +120,6 @@ typedef DPTR(class ComPlusCallMethodDesc) PTR_ComPlusCallMethodDesc; typedef VPTR(class DebugInterface) PTR_DebugInterface; typedef DPTR(class Dictionary) PTR_Dictionary; typedef VPTR(class DomainAssembly) PTR_DomainAssembly; -typedef VPTR(class DomainFile) PTR_DomainFile; -typedef VPTR(class DomainModule) PTR_DomainModule; typedef DPTR(struct FailedAssembly) PTR_FailedAssembly; typedef VPTR(class EditAndContinueModule) PTR_EditAndContinueModule; typedef DPTR(class EEClass) PTR_EEClass; @@ -429,7 +427,6 @@ extern DummyGlobalContract ___contract; #include "typehandle.inl" #include "object.inl" #include "clsload.inl" -#include "domainfile.inl" #include "method.inl" #include "syncblk.inl" #include "threads.inl" diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index eaaddafdbe9c6b..2da6e14750d713 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -15,7 +15,7 @@ #include "appdomain.inl" #include #include "peimagelayout.inl" -#include "domainfile.h" +#include "domainassembly.h" #include "holder.h" #include "bundle.h" #include "strongnameinternal.h" diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp index 707cd24274148b..54bb5177cae530 100644 --- a/src/coreclr/vm/corelib.cpp +++ b/src/coreclr/vm/corelib.cpp @@ -32,7 +32,6 @@ #include "comdatetime.h" #include "compatibilityswitch.h" #include "debugdebugger.h" -#include "assemblyname.hpp" #include "assemblynative.hpp" #include "comthreadpool.h" #include "comwaithandle.h" diff --git a/src/coreclr/vm/dbginterface.h b/src/coreclr/vm/dbginterface.h index 51b2c3bf36358f..c9bc65c33fd287 100644 --- a/src/coreclr/vm/dbginterface.h +++ b/src/coreclr/vm/dbginterface.h @@ -68,7 +68,7 @@ class DebugInterface DWORD dwModuleName, // number of characters in file name excludign null Assembly * pAssembly, // the assembly the module belongs to AppDomain * pAppDomain, // the AppDomain the module is being loaded into - DomainFile * pDomainFile, + DomainAssembly * pDomainAssembly, BOOL fAttaching) = 0; // true if this notification is due to a debugger // being attached to the process @@ -242,7 +242,7 @@ class DebugInterface // send a custom notification from the target to the RS. This will become an ICorDebugThread and // ICorDebugAppDomain on the RS. - virtual void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomainFile, mdTypeDef classToken) = 0; + virtual void SendCustomDebuggerNotification(Thread * pThread, DomainAssembly * pDomainAssembly, mdTypeDef classToken) = 0; // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side. virtual void SendMDANotification( diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index 2ade537044abbe..566bb74d6d3eb9 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -827,11 +827,11 @@ FCIMPL1(void, DebugDebugger::CustomNotification, Object * dataUNSAFE) StrongHandleHolder objHandle = pAppDomain->CreateStrongHandle(pData); MethodTable * pMT = pData->GetGCSafeMethodTable(); Module * pModule = pMT->GetModule(); - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); mdTypeDef classToken = pMT->GetCl(); pThread->SetThreadCurrNotification(objHandle); - g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainFile, classToken); + g_pDebugInterface->SendCustomDebuggerNotification(pThread, pDomainAssembly, classToken); pThread->ClearThreadCurrNotification(); if (pThread->IsAbortRequested()) diff --git a/src/coreclr/vm/domainfile.cpp b/src/coreclr/vm/domainassembly.cpp similarity index 80% rename from src/coreclr/vm/domainfile.cpp rename to src/coreclr/vm/domainassembly.cpp index 22796801543b31..458f988280b02d 100644 --- a/src/coreclr/vm/domainfile.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -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. // -------------------------------------------------------------------------------- -// DomainFile.cpp +// DomainAssembly.cpp // // -------------------------------------------------------------------------------- @@ -30,33 +30,42 @@ #endif // FEATURE_PERFMAP #ifndef DACCESS_COMPILE -DomainFile::DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly) - : m_pDomain(pDomain), +DomainAssembly::DomainAssembly(AppDomain* pDomain, PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator) : + m_pAssembly(NULL), + m_pDomain(pDomain), m_pPEAssembly(pPEAssembly), m_pModule(NULL), + m_fCollectible(pLoaderAllocator->IsCollectible()), + m_NextDomainAssemblyInSameALC(NULL), + m_pLoaderAllocator(pLoaderAllocator), m_level(FILE_LOAD_CREATE), - m_pError(NULL), - m_notifyflags(NOT_NOTIFIED), m_loading(TRUE), + m_hExposedModuleObject(NULL), + m_hExposedAssemblyObject(NULL), + m_pError(NULL), + m_bDisableActivationCheck(FALSE), + m_fHostAssemblyPublished(FALSE), m_pDynamicMethodTable(NULL), - m_pUMThunkHash(NULL), - m_bDisableActivationCheck(FALSE) + m_debuggerFlags(DACF_NONE), + m_notifyflags(NOT_NOTIFIED), + m_fDebuggerUnloadStarted(FALSE) { CONTRACTL { CONSTRUCTOR_CHECK; - THROWS; // From CreateHandle - GC_NOTRIGGER; + THROWS; // ValidateForExecution + GC_TRIGGERS; // ValidateForExecution MODE_ANY; - FORBID_FAULT; } CONTRACTL_END; - m_hExposedModuleObject = NULL; pPEAssembly->AddRef(); + pPEAssembly->ValidateForExecution(); + + SetupDebuggingConfig(); } -DomainFile::~DomainFile() +DomainAssembly::~DomainAssembly() { CONTRACTL { @@ -70,36 +79,24 @@ DomainFile::~DomainFile() m_pPEAssembly->Release(); if (m_pDynamicMethodTable) m_pDynamicMethodTable->Destroy(); - delete m_pError; -} -#endif //!DACCESS_COMPILE + delete m_pError; -LoaderAllocator * DomainFile::GetLoaderAllocator() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - Assembly *pAssembly = GetDomainAssembly()->GetAssembly(); - if ((pAssembly != NULL) && (pAssembly->IsCollectible())) + if (m_fHostAssemblyPublished) { - return pAssembly->GetLoaderAllocator(); + // Remove association first. + UnregisterFromHostAssembly(); } - else + + if (m_pAssembly != NULL) { - return this->GetAppDomain()->GetLoaderAllocator(); + delete m_pAssembly; } } -#ifndef DACCESS_COMPILE - // Optimization intended for EnsureLoadLevel only #include -void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) +void DomainAssembly::EnsureLoadLevel(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -112,7 +109,7 @@ void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) TRIGGERSGC (); if (IsLoading()) { - this->GetAppDomain()->LoadDomainFile(this, targetLevel); + this->GetAppDomain()->LoadDomainAssembly(this, targetLevel); // Enforce the loading requirement. Note that we may have a deadlock in which case we // may be off by one which is OK. (At this point if we are short of targetLevel we know @@ -127,26 +124,7 @@ void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel) } #include -void DomainFile::AttemptLoadLevel(FileLoadLevel targetLevel) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - THROWS; - GC_TRIGGERS; - } - CONTRACT_END; - - if (IsLoading()) - this->GetAppDomain()->LoadDomainFile(this, targetLevel); - else - ThrowIfError(targetLevel); - - RETURN; -} - - -CHECK DomainFile::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) +CHECK DomainAssembly::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) { CONTRACTL { @@ -176,7 +154,7 @@ CHECK DomainFile::CheckLoadLevel(FileLoadLevel requiredLevel, BOOL deadlockOK) -void DomainFile::RequireLoadLevel(FileLoadLevel targetLevel) +void DomainAssembly::RequireLoadLevel(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -196,7 +174,7 @@ void DomainFile::RequireLoadLevel(FileLoadLevel targetLevel) } -void DomainFile::SetError(Exception *ex) +void DomainAssembly::SetError(Exception *ex) { CONTRACT_VOID { @@ -211,26 +189,26 @@ void DomainFile::SetError(Exception *ex) m_pError = new ExInfo(ex->DomainBoundClone()); - GetCurrentModule()->NotifyEtwLoadFinished(ex->GetHR()); - - if (!IsProfilerNotified()) + if (m_pModule) { - SetProfilerNotified(); + m_pModule->NotifyEtwLoadFinished(ex->GetHR()); -#ifdef PROFILING_SUPPORTED - if (GetCurrentModule() != NULL) + if (!IsProfilerNotified()) { + SetProfilerNotified(); + +#ifdef PROFILING_SUPPORTED // Only send errors for non-shared assemblies; other assemblies might be successfully completed // in another app domain later. - GetCurrentModule()->NotifyProfilerLoadFinished(ex->GetHR()); - } + m_pModule->NotifyProfilerLoadFinished(ex->GetHR()); #endif + } } RETURN; } -void DomainFile::ThrowIfError(FileLoadLevel targetLevel) +void DomainAssembly::ThrowIfError(FileLoadLevel targetLevel) { CONTRACT_VOID { @@ -250,7 +228,7 @@ void DomainFile::ThrowIfError(FileLoadLevel targetLevel) RETURN; } -CHECK DomainFile::CheckNoError(FileLoadLevel targetLevel) +CHECK DomainAssembly::CheckNoError(FileLoadLevel targetLevel) { LIMITED_METHOD_CONTRACT; CHECK(m_level >= targetLevel @@ -259,7 +237,7 @@ CHECK DomainFile::CheckNoError(FileLoadLevel targetLevel) CHECK_OK; } -CHECK DomainFile::CheckLoaded() +CHECK DomainAssembly::CheckLoaded() { CONTRACTL { @@ -270,7 +248,7 @@ CHECK DomainFile::CheckLoaded() } CONTRACTL_END; - CHECK_MSG(CheckNoError(FILE_LOADED), "DomainFile load resulted in an error"); + CHECK_MSG(CheckNoError(FILE_LOADED), "DomainAssembly load resulted in an error"); if (IsLoaded()) CHECK_OK; @@ -287,7 +265,7 @@ CHECK DomainFile::CheckLoaded() CHECK_OK; } -CHECK DomainFile::CheckActivated() +CHECK DomainAssembly::CheckActivated() { CONTRACTL { @@ -298,7 +276,7 @@ CHECK DomainFile::CheckActivated() } CONTRACTL_END; - CHECK_MSG(CheckNoError(FILE_ACTIVE), "DomainFile load resulted in an error"); + CHECK_MSG(CheckNoError(FILE_ACTIVE), "DomainAssembly load resulted in an error"); if (IsActive()) CHECK_OK; @@ -311,7 +289,7 @@ CHECK DomainFile::CheckActivated() CHECK_OK; CHECK_MSG(GetPEAssembly()->IsLoaded(), "PEAssembly has not been loaded"); - CHECK_MSG(IsLoaded(), "DomainFile has not been fully loaded"); + CHECK_MSG(IsLoaded(), "DomainAssembly has not been fully loaded"); CHECK_MSG(m_bDisableActivationCheck || CheckLoadLevel(FILE_ACTIVE), "File has not had execution verified"); CHECK_OK; @@ -319,20 +297,6 @@ CHECK DomainFile::CheckActivated() #endif //!DACCESS_COMPILE -DomainAssembly *DomainFile::GetDomainAssembly() -{ - CONTRACTL - { - SUPPORTS_DAC; - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - _ASSERTE(IsAssembly()); - return (DomainAssembly *) this; -} - // Return true iff the debugger should get notifications about this assembly. // // Notes: @@ -358,7 +322,7 @@ BOOL DomainAssembly::IsVisibleToDebugger() // Returns managed representation of the module (Module or ModuleBuilder). // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). // -OBJECTREF DomainFile::GetExposedModuleObject() +OBJECTREF DomainAssembly::GetExposedModuleObject() { CONTRACTL { @@ -423,9 +387,9 @@ OBJECTREF DomainFile::GetExposedModuleObject() } return pLoaderAllocator->GetHandleValue(m_hExposedModuleObject); -} // DomainFile::GetExposedModuleObject +} -BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) +BOOL DomainAssembly::DoIncrementalLoad(FileLoadLevel level) { STANDARD_VM_CONTRACT; @@ -491,7 +455,7 @@ BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) #ifdef FEATURE_MULTICOREJIT { - Module * pModule = GetModule(); + Module * pModule = m_pModule; if (pModule != NULL) // Should not triggle assert when module is NULL { @@ -503,7 +467,7 @@ BOOL DomainFile::DoIncrementalLoad(FileLoadLevel level) return TRUE; } -void DomainFile::PreLoadLibrary() +void DomainAssembly::PreLoadLibrary() { CONTRACTL { @@ -512,11 +476,9 @@ void DomainFile::PreLoadLibrary() } CONTRACTL_END; -} // DomainFile::PreLoadLibrary +} // DomainAssembly::PreLoadLibrary -// Note that this is the sole loading function which must be called OUTSIDE THE LOCK, since -// it will potentially involve the OS loader lock. -void DomainFile::LoadLibrary() +void DomainAssembly::LoadLibrary() { CONTRACTL { @@ -527,7 +489,7 @@ void DomainFile::LoadLibrary() } -void DomainFile::PostLoadLibrary() +void DomainAssembly::PostLoadLibrary() { CONTRACTL { @@ -557,46 +519,46 @@ void DomainFile::PostLoadLibrary() if (!IsProfilerNotified()) { SetProfilerNotified(); - GetCurrentModule()->NotifyProfilerLoadFinished(S_OK); + GetModule()->NotifyProfilerLoadFinished(S_OK); } #endif } -void DomainFile::AddDependencies() +void DomainAssembly::AddDependencies() { STANDARD_VM_CONTRACT; } -void DomainFile::EagerFixups() +void DomainAssembly::EagerFixups() { WRAPPER_NO_CONTRACT; #ifdef FEATURE_READYTORUN - if (GetCurrentModule()->IsReadyToRun()) + if (GetModule()->IsReadyToRun()) { - GetCurrentModule()->RunEagerFixups(); + GetModule()->RunEagerFixups(); - PEImageLayout * pLayout = GetCurrentModule()->GetReadyToRunInfo()->GetImage(); + PEImageLayout * pLayout = GetModule()->GetReadyToRunInfo()->GetImage(); TADDR base = dac_cast(pLayout->GetBase()); ExecutionManager::AddCodeRange(base, base + (TADDR)pLayout->GetVirtualSize(), ExecutionManager::GetReadyToRunJitManager(), RangeSection::RANGE_SECTION_READYTORUN, - GetCurrentModule() /* (void *)pLayout */); + GetModule() /* (void *)pLayout */); } #endif // FEATURE_READYTORUN } -void DomainFile::VtableFixups() +void DomainAssembly::VtableFixups() { WRAPPER_NO_CONTRACT; - GetCurrentModule()->FixupVTables(); + GetModule()->FixupVTables(); } -void DomainFile::FinishLoad() +void DomainAssembly::FinishLoad() { CONTRACTL { @@ -621,7 +583,7 @@ void DomainFile::FinishLoad() #endif } -void DomainFile::Activate() +void DomainAssembly::Activate() { CONTRACT_VOID { @@ -631,24 +593,11 @@ void DomainFile::Activate() } CONTRACT_END; - // If we are a module, ensure we've activated the assembly first. - - if (!IsAssembly()) - { - GetDomainAssembly()->EnsureActive(); - } - else - { - // We cannot execute any code in this assembly until we know what exception plan it is on. - // At the point of an exception's stack-crawl it is too late because we cannot tolerate a GC. - // See PossiblyUnwrapThrowable and its callers. - _ASSERTE(GetLoadedModule() == GetDomainAssembly()->GetLoadedAssembly()->GetManifestModule()); - GetLoadedModule()->IsRuntimeWrapExceptions(); - } - - // Now activate any dependencies. - // This will typically cause reentrancy of course. - + // We cannot execute any code in this assembly until we know what exception plan it is on. + // At the point of an exception's stack-crawl it is too late because we cannot tolerate a GC. + // See PossiblyUnwrapThrowable and its callers. + _ASSERTE(GetModule() == GetAssembly()->GetModule()); + GetModule()->IsRuntimeWrapExceptions(); // // Now call the module constructor. Note that this might cause reentrancy; @@ -669,84 +618,18 @@ void DomainFile::Activate() } #endif //_DEBUG - RETURN; } -//-------------------------------------------------------------------------------- -// DomainAssembly -//-------------------------------------------------------------------------------- - -DomainAssembly::DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator) - : DomainFile(pDomain, pPEAssembly), - m_pAssembly(NULL), - m_debuggerFlags(DACF_NONE), - m_fDebuggerUnloadStarted(FALSE), - m_fCollectible(pLoaderAllocator->IsCollectible()), - m_fHostAssemblyPublished(false), - m_pLoaderAllocator(pLoaderAllocator), - m_NextDomainAssemblyInSameALC(NULL) -{ - CONTRACTL - { - CONSTRUCTOR_CHECK; - STANDARD_VM_CHECK; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - pPEAssembly->ValidateForExecution(); - - // !!! backout - - m_hExposedAssemblyObject = NULL; - - SetupDebuggingConfig(); - - // Add a Module iterator entry for this assembly. - IfFailThrow(m_Modules.Append(this)); -} - -DomainAssembly::~DomainAssembly() -{ - CONTRACTL - { - DESTRUCTOR_CHECK; - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - if (m_fHostAssemblyPublished) - { - // Remove association first. - UnregisterFromHostAssembly(); - } - - ModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) - { - if (i.GetDomainFile() != this) - delete i.GetDomainFile(); - } - - if (m_pAssembly != NULL) - { - delete m_pAssembly; - } -} - void DomainAssembly::SetAssembly(Assembly* pAssembly) { STANDARD_VM_CONTRACT; - _ASSERTE(pAssembly->GetManifestModule()->GetPEAssembly()==m_pPEAssembly); + _ASSERTE(pAssembly->GetModule()->GetPEAssembly()==m_pPEAssembly); _ASSERTE(m_pAssembly == NULL); m_pAssembly = pAssembly; - m_pModule = pAssembly->GetManifestModule(); + m_pModule = pAssembly->GetModule(); pAssembly->SetDomainAssembly(this); } @@ -841,7 +724,7 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject() } return pLoaderAllocator->GetHandleValue(m_hExposedAssemblyObject); -} // DomainAssembly::GetExposedAssemblyObject +} void DomainAssembly::Begin() { @@ -917,8 +800,7 @@ void DomainAssembly::Allocate() } SetAssembly(pAssembly); - -} // DomainAssembly::Allocate +} void DomainAssembly::DeliverAsyncEvents() { @@ -933,10 +815,8 @@ void DomainAssembly::DeliverAsyncEvents() OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE); m_pDomain->RaiseLoadingAssemblyEvent(this); - } - void DomainAssembly::DeliverSyncEvents() { CONTRACTL @@ -946,17 +826,8 @@ void DomainAssembly::DeliverSyncEvents() } CONTRACTL_END; - GetCurrentModule()->NotifyEtwLoadFinished(S_OK); + GetModule()->NotifyEtwLoadFinished(S_OK); - // We may be notified from inside the loader lock if we are delivering IJW events, so keep track. -#ifdef PROFILING_SUPPORTED - if (!IsProfilerNotified()) - { - SetProfilerNotified(); - GetCurrentModule()->NotifyProfilerLoadFinished(S_OK); - } - -#endif #ifdef DEBUGGING_SUPPORTED GCX_COOP(); if (!IsDebuggerNotified()) @@ -968,7 +839,7 @@ void DomainAssembly::DeliverSyncEvents() } #endif // DEBUGGING_SUPPORTED -} // DomainAssembly::DeliverSyncEvents +} /* // The enum for dwLocation from managed code: @@ -1152,7 +1023,6 @@ BOOL DomainAssembly::NotifyDebuggerLoad(int flags, BOOL attaching) } // There is still work we need to do even when no debugger is attached. - if (flags & ATTACH_ASSEMBLY_LOAD) { if (ShouldNotifyDebugger()) @@ -1162,24 +1032,18 @@ BOOL DomainAssembly::NotifyDebuggerLoad(int flags, BOOL attaching) result = TRUE; } - DomainModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) + if(this->ShouldNotifyDebugger()) { - DomainFile * pDomainFile = i.GetDomainFile(); - if(pDomainFile->ShouldNotifyDebugger()) - { - result = result || - pDomainFile->GetModule()->NotifyDebuggerLoad(this->GetAppDomain(), pDomainFile, flags, attaching); - } + result = result || + this->GetModule()->NotifyDebuggerLoad(this->GetAppDomain(), this, flags, attaching); } + if( ShouldNotifyDebugger()) { result|=m_pModule->NotifyDebuggerLoad(m_pDomain, this, ATTACH_MODULE_LOAD, attaching); SetDebuggerNotified(); } - - return result; } @@ -1195,29 +1059,22 @@ void DomainAssembly::NotifyDebuggerUnload() m_fDebuggerUnloadStarted = TRUE; - // Dispatch module unloads for all modules. Debugger is resilient in case we haven't dispatched + // Dispatch module unload for the module. Debugger is resilient in case we haven't dispatched // a previous load event (such as if debugger attached after the modules was loaded). - DomainModuleIterator i = IterateModules(kModIterIncludeLoading); - while (i.Next()) - { - i.GetDomainFile()->GetModule()->NotifyDebuggerUnload(this->GetAppDomain()); - } + this->GetModule()->NotifyDebuggerUnload(this->GetAppDomain()); g_pDebugInterface->UnloadAssembly(this); - } #endif // #ifndef DACCESS_COMPILE #ifdef DACCESS_COMPILE -void -DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) +void DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { SUPPORTS_DAC; - //sizeof(DomainFile) == 0x60 - DAC_ENUM_VTHIS(); + DAC_ENUM_DTHIS(); // Modules are needed for all minidumps, but they are enumerated elsewhere // so we don't need to duplicate effort; thus we do noting with m_pModule. @@ -1233,19 +1090,6 @@ DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { m_pDomain->EnumMemoryRegions(flags, true); } -} - -void -DomainAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) -{ - SUPPORTS_DAC; - - //sizeof(DomainAssembly) == 0xe0 - DAC_ENUM_VTHIS(); - DomainFile::EnumMemoryRegions(flags); - - // For minidumps without full memory, we need to always be able to iterate over m_Modules. - m_Modules.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/domainassembly.h similarity index 59% rename from src/coreclr/vm/domainfile.h rename to src/coreclr/vm/domainassembly.h index 917af193ceadea..268c49654253cd 100644 --- a/src/coreclr/vm/domainfile.h +++ b/src/coreclr/vm/domainassembly.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. // -------------------------------------------------------------------------------- -// DomainFile.h +// DomainAssembly.h // // -------------------------------------------------------------------------------- -#ifndef _DOMAINFILE_H_ -#define _DOMAINFILE_H_ +#ifndef _DOMAINASSEMBLY_H_ +#define _DOMAINASSEMBLY_H_ // -------------------------------------------------------------------------------- // Required headers @@ -59,27 +59,23 @@ enum NotificationStatus }; // -------------------------------------------------------------------------------- -// DomainFile represents a file loaded (or being loaded) into an app domain. It +// DomainAssembly represents an assembly loaded (or being loaded) into an app domain. It // is guranteed to be unique per file per app domain. // -------------------------------------------------------------------------------- -class DomainFile +class DomainAssembly final { - VPTR_BASE_VTABLE_CLASS(DomainFile); - - public: +public: // ------------------------------------------------------------ // Public API // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - virtual ~DomainFile(); - DomainFile() {LIMITED_METHOD_CONTRACT;}; + ~DomainAssembly(); + DomainAssembly() {LIMITED_METHOD_CONTRACT;}; #endif - virtual LoaderAllocator *GetLoaderAllocator(); - PTR_AppDomain GetAppDomain() { LIMITED_METHOD_CONTRACT; @@ -93,12 +89,41 @@ class DomainFile return PTR_PEAssembly(m_pPEAssembly); } + Assembly* GetAssembly() + { + LIMITED_METHOD_DAC_CONTRACT; + CONSISTENCY_CHECK(CheckLoaded()); + + return m_pAssembly; + } + + Module* GetModule() + { + LIMITED_METHOD_CONTRACT; + CONSISTENCY_CHECK(CheckLoaded()); + + return m_pModule; + } + IMDInternalImport *GetMDImport() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetMDImport(); } + OBJECTREF GetExposedAssemblyObjectIfExists() + { + LIMITED_METHOD_CONTRACT; + + OBJECTREF objRet = NULL; + GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedAssemblyObject, &objRet); + return objRet; + } + + // Returns managed representation of the assembly (Assembly or AssemblyBuilder). + // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). + OBJECTREF GetExposedAssemblyObject(); + OBJECTREF GetExposedModuleObjectIfExists() { LIMITED_METHOD_CONTRACT; @@ -130,9 +155,17 @@ class DomainFile } #endif - virtual BOOL IsAssembly() = 0; + BOOL IsCollectible() + { + LIMITED_METHOD_CONTRACT; + return m_fCollectible; + } - DomainAssembly *GetDomainAssembly(); + ULONG HashIdentity() + { + WRAPPER_NO_CONTRACT; + return GetPEAssembly()->HashIdentity(); + } // ------------------------------------------------------------ // Loading state checks @@ -202,7 +235,6 @@ class DomainFile return EnsureLoadLevel(FILE_LOAD_ALLOCATE); } - void EnsureLibraryLoaded() { WRAPPER_NO_CONTRACT; @@ -214,10 +246,6 @@ class DomainFile // is required for an operation. Note that deadlocks are tolerated so the level may be one void EnsureLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); - // AttemptLoadLevel is a generic routine used to try to further load the file to a given level. - // No guarantee is made about the load level resulting however. - void AttemptLoadLevel(FileLoadLevel targetLevel) DAC_EMPTY(); - // CheckLoadLevel is an assert predicate used to verify the load level of an assembly. // deadlockOK indicates that the level is allowed to be one short if we are restricted // by loader reentrancy. @@ -245,16 +273,12 @@ class DomainFile // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - BOOL Equals(DomainFile *pFile) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pFile->GetPEAssembly()); } + BOOL Equals(DomainAssembly *pAssembly) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pAssembly->GetPEAssembly()); } BOOL Equals(PEAssembly *pPEAssembly) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pPEAssembly); } #endif // DACCESS_COMPILE - Module* GetCurrentModule(); - Module* GetLoadedModule(); - Module* GetModule(); - #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif #ifndef DACCESS_COMPILE @@ -262,7 +286,33 @@ class DomainFile DynamicMethodTable* GetDynamicMethodTable(); #endif - protected: + DomainAssembly* GetNextDomainAssemblyInSameALC() + { + return m_NextDomainAssemblyInSameALC; + } + + void SetNextDomainAssemblyInSameALC(DomainAssembly* domainAssembly) + { + _ASSERTE(m_NextDomainAssemblyInSameALC == NULL); + m_NextDomainAssemblyInSameALC = domainAssembly; + } + + LoaderAllocator* GetLoaderAllocator() + { + LIMITED_METHOD_CONTRACT; + return m_pLoaderAllocator; + } + +// ------------------------------------------------------------ +// Resource access +// ------------------------------------------------------------ + + BOOL GetResource(LPCSTR szName, DWORD* cbResource, + PBYTE* pbInMemoryResource, DomainAssembly** pAssemblyRef, + LPCSTR* szFileName, DWORD* dwLocation, + BOOL fSkipRaiseResolveEvent); + + private: // ------------------------------------------------------------ // Loader API // ------------------------------------------------------------ @@ -272,59 +322,53 @@ class DomainFile friend class Module; friend class FileLoadLock; - DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly); + DomainAssembly(AppDomain* pDomain, PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator); BOOL DoIncrementalLoad(FileLoadLevel targetLevel); void ClearLoading() { LIMITED_METHOD_CONTRACT; m_loading = FALSE; } void SetLoadLevel(FileLoadLevel level) { LIMITED_METHOD_CONTRACT; m_level = level; } #ifndef DACCESS_COMPILE - virtual void Begin() = 0; - virtual void Allocate() = 0; + void Begin(); + void Allocate(); void AddDependencies(); void PreLoadLibrary(); void LoadLibrary(); - void PostLoadLibrary(); + void PostLoadLibrary(); void EagerFixups(); void VtableFixups(); - virtual void DeliverSyncEvents() = 0; - virtual void DeliverAsyncEvents() = 0; + void DeliverSyncEvents(); + void DeliverAsyncEvents(); void FinishLoad(); void Activate(); + + void RegisterWithHostAssembly(); + void UnregisterFromHostAssembly(); #endif // This should be used to permanently set the load to fail. Do not use with transient conditions void SetError(Exception *ex); + void SetAssembly(Assembly* pAssembly); 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; } - // ------------------------------------------------------------ - // Instance data - // ------------------------------------------------------------ - - PTR_AppDomain m_pDomain; - PTR_PEAssembly m_pPEAssembly; - PTR_Module m_pModule; - FileLoadLevel m_level; - LOADERHANDLE m_hExposedModuleObject; - class ExInfo { enum { - ExType_ClrEx, - ExType_HR + ExType_ClrEx, + ExType_HR } m_type; union { - Exception *m_pEx; - HRESULT m_hr; + Exception* m_pEx; + HRESULT m_hr; }; - public: + public: void Throw() { CONTRACTL @@ -334,209 +378,35 @@ class DomainFile MODE_ANY; } CONTRACTL_END; - if (m_type==ExType_ClrEx) + if (m_type == ExType_ClrEx) { - PAL_CPP_THROW(Exception *, m_pEx->DomainBoundClone()); + PAL_CPP_THROW(Exception*, m_pEx->DomainBoundClone()); } - if (m_type==ExType_HR) + if (m_type == ExType_HR) ThrowHR(m_hr); _ASSERTE(!"Bad exception type"); ThrowHR(E_UNEXPECTED); }; + ExInfo(Exception* pEx) { LIMITED_METHOD_CONTRACT; - m_type=ExType_ClrEx; - m_pEx=pEx; + m_type = ExType_ClrEx; + m_pEx = pEx; }; - void ConvertToHResult() - { - LIMITED_METHOD_CONTRACT; - if(m_type==ExType_HR) - return; - _ASSERTE(m_type==ExType_ClrEx); - HRESULT hr=m_pEx->GetHR(); - delete m_pEx; - m_hr=hr; - m_type=ExType_HR; - }; ~ExInfo() { LIMITED_METHOD_CONTRACT; - if (m_type==ExType_ClrEx) + if (m_type == ExType_ClrEx) delete m_pEx; } - }* m_pError; - - void ReleaseManagedData() - { - if (m_pError) - m_pError->ConvertToHResult(); }; - DWORD m_notifyflags; - BOOL m_loading; - // m_pDynamicMethodTable is used by the light code generation to allow method - // generation on the fly. They are lazily created when/if a dynamic method is requested - // for this specific module - DynamicMethodTable *m_pDynamicMethodTable; - class UMThunkHash *m_pUMThunkHash; - BOOL m_bDisableActivationCheck; -}; - -//--------------------------------------------------------------------------------------- -// One of these values is specified when requesting a module iterator to customize which -// modules should appear in the enumeration -enum ModuleIterationOption -{ - // include only modules that are already loaded (m_level >= FILE_LOAD_DELIVER_EVENTS) - kModIterIncludeLoaded = 1, - - // include all modules, even those that are still in the process of loading (all m_level values) - kModIterIncludeLoading = 2, - - // include only modules loaded just enough that profilers are notified of them. - // (m_level >= FILE_LOAD_LOADLIBRARY). See comment at code:DomainFile::IsAvailableToProfilers - kModIterIncludeAvailableToProfilers = 3, -}; - -// -------------------------------------------------------------------------------- -// DomainAssembly is a subclass of DomainFile which specifically represents a assembly. -// -------------------------------------------------------------------------------- - -class DomainAssembly : public DomainFile -{ - VPTR_VTABLE_CLASS(DomainAssembly, DomainFile); - public: - // ------------------------------------------------------------ - // Public API - // ------------------------------------------------------------ - - LoaderAllocator *GetLoaderAllocator() - { - LIMITED_METHOD_CONTRACT; - return m_pLoaderAllocator; - } - - void SetAssembly(Assembly* pAssembly); - - BOOL IsAssembly() - { - LIMITED_METHOD_DAC_CONTRACT; - return TRUE; - } - - OBJECTREF GetExposedAssemblyObjectIfExists() - { - LIMITED_METHOD_CONTRACT; - - OBJECTREF objRet = NULL; - GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedAssemblyObject, &objRet); - return objRet; - } - - // Returns managed representation of the assembly (Assembly or AssemblyBuilder). - // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases). - OBJECTREF GetExposedAssemblyObject(); - - Assembly* GetCurrentAssembly(); - Assembly* GetLoadedAssembly(); - Assembly* GetAssembly(); - -#ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); -#endif - - // ------------------------------------------------------------ - // Modules - // ------------------------------------------------------------ - class ModuleIterator - { - ArrayList::Iterator m_i; - ModuleIterationOption m_moduleIterationOption; - - public: - BOOL Next() - { - WRAPPER_NO_CONTRACT; - while (m_i.Next()) - { - if (m_i.GetElement() == NULL) - { - continue; - } - if (GetDomainFile()->IsError()) - { - continue; - } - if (m_moduleIterationOption == kModIterIncludeLoading) - return TRUE; - if ((m_moduleIterationOption == kModIterIncludeLoaded) && - GetDomainFile()->IsLoaded()) - return TRUE; - if ((m_moduleIterationOption == kModIterIncludeAvailableToProfilers) && - GetDomainFile()->IsAvailableToProfilers()) - return TRUE; - } - return FALSE; - } - Module *GetModule() - { - WRAPPER_NO_CONTRACT; - return GetDomainFile()->GetModule(); - } - Module *GetLoadedModule() - { - WRAPPER_NO_CONTRACT; - return GetDomainFile()->GetLoadedModule(); - } - DomainFile *GetDomainFile() - { - WRAPPER_NO_CONTRACT; - return dac_cast(m_i.GetElement()); - } - SIZE_T GetIndex() - { - WRAPPER_NO_CONTRACT; - return m_i.GetIndex(); - } - - private: - friend class DomainAssembly; - // Cannot have constructor so this iterator can be used inside a union - static ModuleIterator Create(DomainAssembly * pDomainAssembly, ModuleIterationOption moduleIterationOption) - { - WRAPPER_NO_CONTRACT; - ModuleIterator i; - - i.m_i = pDomainAssembly->m_Modules.Iterate(); - i.m_moduleIterationOption = moduleIterationOption; - - return i; - } - }; - friend class ModuleIterator; - - ModuleIterator IterateModules(ModuleIterationOption moduleIterationOption) - { - WRAPPER_NO_CONTRACT; - return ModuleIterator::Create(this, moduleIterationOption); - } - - // ------------------------------------------------------------ - // Resource access - // ------------------------------------------------------------ - - BOOL GetResource(LPCSTR szName, DWORD *cbResource, - PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef, - LPCSTR *szFileName, DWORD *dwLocation, - BOOL fSkipRaiseResolveEvent); - - // ------------------------------------------------------------ - // Debugger control API - // ------------------------------------------------------------ +// ------------------------------------------------------------ +// Debugger control API +// ------------------------------------------------------------ DebuggerAssemblyControlFlags GetDebuggerInfoBits(void) { @@ -553,75 +423,46 @@ class DomainAssembly : public DomainFile void SetupDebuggingConfig(void); DWORD ComputeDebuggingConfig(void); - HRESULT GetDebuggingCustomAttributes(DWORD *pdwFlags); + HRESULT GetDebuggingCustomAttributes(DWORD* pdwFlags); BOOL IsVisibleToDebugger(); BOOL NotifyDebuggerLoad(int flags, BOOL attaching); void NotifyDebuggerUnload(); - inline BOOL IsCollectible(); - - - private: - +private: // ------------------------------------------------------------ - // Loader API + // Instance data // ------------------------------------------------------------ - friend class AppDomain; - friend class Assembly; + PTR_Assembly m_pAssembly; + PTR_AppDomain m_pDomain; + PTR_PEAssembly m_pPEAssembly; + PTR_Module m_pModule; -#ifndef DACCESS_COMPILE -public: - ~DomainAssembly(); -private: - DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator); -#endif + BOOL m_fCollectible; + DomainAssembly* m_NextDomainAssemblyInSameALC; + PTR_LoaderAllocator m_pLoaderAllocator; - // ------------------------------------------------------------ - // Internal routines - // ------------------------------------------------------------ + FileLoadLevel m_level; + BOOL m_loading; -#ifndef DACCESS_COMPILE - void Begin(); - void Allocate(); - void DeliverSyncEvents(); - void DeliverAsyncEvents(); - void RegisterWithHostAssembly(); - void UnregisterFromHostAssembly(); -#endif + LOADERHANDLE m_hExposedModuleObject; + LOADERHANDLE m_hExposedAssemblyObject; - public: - ULONG HashIdentity(); + ExInfo* m_pError; - // ------------------------------------------------------------ - // Instance data - // ------------------------------------------------------------ + BOOL m_bDisableActivationCheck; + BOOL m_fHostAssemblyPublished; + + // m_pDynamicMethodTable is used by the light code generation to allow method + // generation on the fly. They are lazily created when/if a dynamic method is requested + // for this specific module + DynamicMethodTable* m_pDynamicMethodTable; - private: - LOADERHANDLE m_hExposedAssemblyObject; - PTR_Assembly m_pAssembly; - DebuggerAssemblyControlFlags m_debuggerFlags; - ArrayList m_Modules; - BOOL m_fDebuggerUnloadStarted; - BOOL m_fCollectible; - Volatile m_fHostAssemblyPublished; - PTR_LoaderAllocator m_pLoaderAllocator; - DomainAssembly* m_NextDomainAssemblyInSameALC; - - public: - DomainAssembly* GetNextDomainAssemblyInSameALC() - { - return m_NextDomainAssemblyInSameALC; - } - - void SetNextDomainAssemblyInSameALC(DomainAssembly* domainAssembly) - { - _ASSERTE(m_NextDomainAssemblyInSameALC == NULL); - m_NextDomainAssemblyInSameALC = domainAssembly; - } -}; -typedef DomainAssembly::ModuleIterator DomainModuleIterator; + DebuggerAssemblyControlFlags m_debuggerFlags; + DWORD m_notifyflags; + BOOL m_fDebuggerUnloadStarted; +}; -#endif // _DOMAINFILE_H_ +#endif // _DOMAINASSEMBLY_H_ diff --git a/src/coreclr/vm/domainfile.inl b/src/coreclr/vm/domainfile.inl deleted file mode 100644 index a87d9aaef13096..00000000000000 --- a/src/coreclr/vm/domainfile.inl +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// - -inline Module* DomainFile::GetCurrentModule() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return m_pModule; -} - -inline Module* DomainFile::GetLoadedModule() -{ - LIMITED_METHOD_CONTRACT; - CONSISTENCY_CHECK(CheckLoaded()); - - return m_pModule; -} - -inline Module* DomainFile::GetModule() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - { - // While executing the consistency check, we will take a lock. - // But since this is debug-only, we'll allow the lock violation so that - // CANNOT_TAKE_LOCK callers aren't penalized - CONTRACT_VIOLATION(TakesLockViolation); - CONSISTENCY_CHECK(CheckLoadLevel(FILE_LOAD_ALLOCATE)); - } - - return m_pModule; -} - -inline Assembly* DomainAssembly::GetCurrentAssembly() -{ - LIMITED_METHOD_CONTRACT; - - return m_pAssembly; -} - -inline Assembly* DomainAssembly::GetLoadedAssembly() -{ - LIMITED_METHOD_DAC_CONTRACT; - CONSISTENCY_CHECK(CheckLoaded()); - - return m_pAssembly; -} - -inline Assembly* DomainAssembly::GetAssembly() -{ - LIMITED_METHOD_CONTRACT; - - CONSISTENCY_CHECK(CheckLoadLevel(FILE_LOAD_ALLOCATE)); - return m_pAssembly; -} - -inline ULONG DomainAssembly::HashIdentity() -{ - WRAPPER_NO_CONTRACT; - return GetPEAssembly()->HashIdentity(); -} - -inline BOOL DomainAssembly::IsCollectible() -{ - LIMITED_METHOD_CONTRACT; - return m_fCollectible; -} - diff --git a/src/coreclr/vm/dwbucketmanager.hpp b/src/coreclr/vm/dwbucketmanager.hpp index 2524f706c7ef3f..6eb0e9438b5f32 100644 --- a/src/coreclr/vm/dwbucketmanager.hpp +++ b/src/coreclr/vm/dwbucketmanager.hpp @@ -650,7 +650,7 @@ void BaseBucketParamsManager::GetModuleVersion(_Out_writes_(maxLength) WCHAR* ta // if we failed to get a version and this isn't the manifest module then try that if (!gotFileVersion && !pModule->IsManifest()) { - pModule = pModule->GetAssembly()->GetManifestModule(); + pModule = pModule->GetAssembly()->GetModule(); if (pModule) gotFileVersion = GetFileVersionInfoForModule(pModule, major, minor, build, revision); } @@ -701,7 +701,7 @@ void BaseBucketParamsManager::GetModuleTimeStamp(_Out_writes_(maxLength) WCHAR* { // We only store the IL timestamp in the native image for the // manifest module. We should consider fixing this for Orcas. - PTR_PEAssembly pFile = pModule->GetAssembly()->GetManifestModule()->GetPEAssembly(); + PTR_PEAssembly pFile = pModule->GetAssembly()->GetModule()->GetPEAssembly(); // for dynamic modules use 0 as the time stamp ULONG ulTimeStamp = 0; diff --git a/src/coreclr/vm/dwreport.cpp b/src/coreclr/vm/dwreport.cpp index 1032725eb854b3..47defdeedb5d0d 100644 --- a/src/coreclr/vm/dwreport.cpp +++ b/src/coreclr/vm/dwreport.cpp @@ -17,6 +17,7 @@ #include "field.h" #include #include +#include #include "dbginterface.h" #include #include "dlwrap.h" @@ -57,14 +58,6 @@ class SimpleModuleHolder operator HMODULE() { return hModule; } }; -#ifndef FEATURE_CORESYSTEM -#define WER_MODULE_NAME_W WINDOWS_KERNEL32_DLLNAME_W -typedef SimpleModuleHolder WerModuleHolder; -#else -#define WER_MODULE_NAME_W W("api-ms-win-core-windowserrorreporting-l1-1-0.dll") -typedef SimpleModuleHolder WerModuleHolder; -#endif - //------------------------------------------------------------------------------ // Description // Indicate if Watson is enabled @@ -107,47 +100,17 @@ BOOL RegisterOutOfProcessWatsonCallbacks() CONTRACTL_END; WCHAR wszDACName[] = MAIN_DAC_MODULE_NAME_W W(".dll"); - WerModuleHolder hWerModule(WER_MODULE_NAME_W); - -#ifdef FEATURE_CORESYSTEM - if ((hWerModule == NULL) && !RunningOnWin8()) - { - // If we are built for CoreSystemServer, but are running on Windows 7, we need to look elsewhere - hWerModule = WerModuleHolder(W("Kernel32.dll")); - } -#endif - - if (hWerModule == NULL) - { - _ASSERTE(!"failed to get WER module handle"); - return FALSE; - } - - typedef HRESULT (WINAPI * WerRegisterRuntimeExceptionModuleFnPtr)(PCWSTR, PDWORD); - WerRegisterRuntimeExceptionModuleFnPtr pFnWerRegisterRuntimeExceptionModule; - - pFnWerRegisterRuntimeExceptionModule = (WerRegisterRuntimeExceptionModuleFnPtr) - GetProcAddress(hWerModule, "WerRegisterRuntimeExceptionModule"); - - _ASSERTE(pFnWerRegisterRuntimeExceptionModule != NULL); - if (pFnWerRegisterRuntimeExceptionModule == NULL) - { - return FALSE; - } HRESULT hr = S_OK; EX_TRY { PathString wszDACPath; - if (SUCCEEDED(::GetClrModuleDirectory(wszDACPath))) + hr = ::GetClrModuleDirectory(wszDACPath); + if (SUCCEEDED(hr)) { wszDACPath.Append(wszDACName); - hr = (*pFnWerRegisterRuntimeExceptionModule)(wszDACPath, (PDWORD)GetClrModuleBase()); - } - else { - hr = E_FAIL; + hr = WerRegisterRuntimeExceptionModule(wszDACPath, (PDWORD)GetClrModuleBase()); } - } EX_CATCH_HRESULT(hr); @@ -156,16 +119,7 @@ BOOL RegisterOutOfProcessWatsonCallbacks() STRESS_LOG0(LF_STARTUP, LL_ERROR, "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); - -#ifdef FEATURE_CORESYSTEM - // For CoreSys we *could* be running on a platform that doesn't have Watson proper - // (the APIs might exist but they just fail). - // WerRegisterRuntimeExceptionModule may return E_NOIMPL. return TRUE; -#else // FEATURE_CORESYSTEM - _ASSERTE(! "WATSON support: failed to register DAC dll with WerRegisterRuntimeExceptionModule"); - return FALSE; -#endif // FEATURE_CORESYSTEM } STRESS_LOG0(LF_STARTUP, diff --git a/src/coreclr/vm/dynamicmethod.cpp b/src/coreclr/vm/dynamicmethod.cpp index 35137855229e5a..a5a9ee44ba8ebd 100644 --- a/src/coreclr/vm/dynamicmethod.cpp +++ b/src/coreclr/vm/dynamicmethod.cpp @@ -20,7 +20,7 @@ #ifndef DACCESS_COMPILE // get the method table for dynamic methods -DynamicMethodTable* DomainFile::GetDynamicMethodTable() +DynamicMethodTable* DomainAssembly::GetDynamicMethodTable() { CONTRACT (DynamicMethodTable*) { diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index f3ada145b68395..08ab8e71c868a4 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -291,12 +291,6 @@ FCFuncStart(gAssemblyLoadContextFuncs) FCFuncElement("IsTracingEnabled", AssemblyNative::IsTracingEnabled) FCFuncEnd() -FCFuncStart(gAssemblyNameFuncs) - FCFuncElement("nInit", AssemblyNameNative::Init) - FCFuncElement("ComputePublicKeyToken", AssemblyNameNative::GetPublicKeyToken) - FCFuncElement("nGetFileInformation", AssemblyNameNative::GetFileInformation) -FCFuncEnd() - FCFuncStart(gAssemblyBuilderFuncs) FCFuncElement("GetInMemoryAssemblyModule", AssemblyNative::GetInMemoryAssemblyModule) FCFuncEnd() @@ -770,7 +764,6 @@ FCClassElement("ArgIterator", "System", gVarArgFuncs) FCClassElement("Array", "System", gArrayFuncs) FCClassElement("AssemblyBuilder", "System.Reflection.Emit", gAssemblyBuilderFuncs) FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadContextFuncs) -FCClassElement("AssemblyName", "System.Reflection", gAssemblyNameFuncs) FCClassElement("Buffer", "System", gBufferFuncs) FCClassElement("CastHelpers", "System.Runtime.CompilerServices", gCastHelpers) FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilitySwitchFuncs) diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index e5473b11041775..3c5d8ded8c574e 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -1380,7 +1380,7 @@ void BulkComLogger::AddCcwHandle(Object **handle) -#include "domainfile.h" +#include "domainassembly.h" BulkStaticsLogger::BulkStaticsLogger(BulkTypeEventLogger *typeLogger) : m_buffer(0), m_used(0), m_count(0), m_domain(0), m_typeLogger(typeLogger) @@ -1524,69 +1524,64 @@ void BulkStaticsLogger::LogAllStatics() continue; CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); - DomainModuleIterator modIter = pDomainAssembly->IterateModules(kModIterIncludeLoaded); + // Get the domain module from the module/appdomain pair. + Module *module = pDomainAssembly->GetModule(); + if (module == NULL) + continue; - while (modIter.Next()) - { - // Get the domain module from the module/appdomain pair. - Module *module = modIter.GetModule(); - if (module == NULL) - continue; + DomainAssembly *domainAssembly = module->GetDomainAssembly(); + if (domainAssembly == NULL) + continue; - DomainFile *domainFile = module->GetDomainFile(); - if (domainFile == NULL) - continue; + // Ensure the module has fully loaded. + if (!domainAssembly->IsActive()) + continue; - // Ensure the module has fully loaded. - if (!domainFile->IsActive()) + DomainLocalModule *domainModule = module->GetDomainLocalModule(); + if (domainModule == NULL) + continue; + + // Now iterate all types with + LookupMap::Iterator mtIter = module->EnumerateTypeDefs(); + while (mtIter.Next()) + { + // I don't think mt can be null here, but the dac does a null check... + // IsFullyLoaded should be equivalent to 'GetLoadLevel() == CLASS_LOADED' + MethodTable *mt = mtIter.GetElement(); + if (mt == NULL || !mt->IsFullyLoaded()) continue; - DomainLocalModule *domainModule = module->GetDomainLocalModule(); - if (domainModule == NULL) + EEClass *cls = mt->GetClass(); + _ASSERTE(cls != NULL); + + if (cls->GetNumStaticFields() <= 0) continue; - // Now iterate all types with - LookupMap::Iterator mtIter = module->EnumerateTypeDefs(); - while (mtIter.Next()) + ApproxFieldDescIterator fieldIter(mt, ApproxFieldDescIterator::STATIC_FIELDS); + for (FieldDesc *field = fieldIter.Next(); field != NULL; field = fieldIter.Next()) { - // I don't think mt can be null here, but the dac does a null check... - // IsFullyLoaded should be equivalent to 'GetLoadLevel() == CLASS_LOADED' - MethodTable *mt = mtIter.GetElement(); - if (mt == NULL || !mt->IsFullyLoaded()) + // Don't want thread local + _ASSERTE(field->IsStatic()); + if (field->IsSpecialStatic() || field->IsEnCNew()) continue; - EEClass *cls = mt->GetClass(); - _ASSERTE(cls != NULL); + // Static valuetype values are boxed. + CorElementType fieldType = field->GetFieldType(); + if (fieldType != ELEMENT_TYPE_CLASS && fieldType != ELEMENT_TYPE_VALUETYPE) + continue; - if (cls->GetNumStaticFields() <= 0) + BYTE *base = field->GetBaseInDomainLocalModule(domainModule); + if (base == NULL) continue; - ApproxFieldDescIterator fieldIter(mt, ApproxFieldDescIterator::STATIC_FIELDS); - for (FieldDesc *field = fieldIter.Next(); field != NULL; field = fieldIter.Next()) - { - // Don't want thread local - _ASSERTE(field->IsStatic()); - if (field->IsSpecialStatic() || field->IsEnCNew()) - continue; - - // Static valuetype values are boxed. - CorElementType fieldType = field->GetFieldType(); - if (fieldType != ELEMENT_TYPE_CLASS && fieldType != ELEMENT_TYPE_VALUETYPE) - continue; - - BYTE *base = field->GetBaseInDomainLocalModule(domainModule); - if (base == NULL) - continue; - - Object **address = (Object**)field->GetStaticAddressHandle(base); - Object *obj = NULL; - if (address == NULL || ((obj = *address) == NULL)) - continue; - - WriteEntry(domain, address, *address, field); - } // foreach static field - } - } // foreach domain module + Object **address = (Object**)field->GetStaticAddressHandle(base); + Object *obj = NULL; + if (address == NULL || ((obj = *address) == NULL)) + continue; + + WriteEntry(domain, address, *address, field); + } // foreach static field + } } // foreach domain assembly } // foreach AppDomain } // BulkStaticsLogger::LogAllStatics @@ -6047,7 +6042,7 @@ VOID ETW::LoaderLog::SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions PCWSTR szDtraceOutput1=W(""); BOOL bIsDynamicAssembly = pAssembly->IsDynamic(); BOOL bIsCollectibleAssembly = pAssembly->IsCollectible(); - BOOL bIsReadyToRun = pAssembly->GetManifestFile()->IsReadyToRun(); + BOOL bIsReadyToRun = pAssembly->GetPEAssembly()->IsReadyToRun(); ULONGLONG ullAssemblyId = (ULONGLONG)pAssembly; ULONGLONG ullDomainId = (ULONGLONG)pAssembly->GetDomain(); @@ -6338,7 +6333,7 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL if(!bIsDynamicAssembly) { - ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetPEImage()->GetPath().GetUnicode(); + ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetPEAssembly()->GetPEImage()->GetPath().GetUnicode(); ModuleNativePath = (PWCHAR)pEmptyString; } @@ -7246,18 +7241,14 @@ VOID ETW::EnumerationLog::IterateDomain(BaseDomain *pDomain, DWORD enumerationOp CollectibleAssemblyHolder pDomainAssembly; while (assemblyIterator.Next(pDomainAssembly.This())) { - CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetLoadedAssembly(); + CollectibleAssemblyHolder pAssembly = pDomainAssembly->GetAssembly(); if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCStart) { ETW::EnumerationLog::IterateAssembly(pAssembly, enumerationOptions); } - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module * pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + Module * pModule = pDomainAssembly->GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); if((enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleDCEnd) || (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload)) @@ -7313,12 +7304,8 @@ VOID ETW::EnumerationLog::IterateCollectibleLoaderAllocator(AssemblyLoaderAlloca { Assembly *pAssembly = domainAssemblyIt->GetAssembly(); // TODO: handle iterator - DomainModuleIterator domainModuleIterator = domainAssemblyIt->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) - { - Module *pModule = domainModuleIterator.GetModule(); - ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); - } + Module* pModule = domainAssemblyIt->GetModule(); + ETW::EnumerationLog::IterateModule(pModule, enumerationOptions); if (enumerationOptions & ETW::EnumerationLog::EnumerationStructs::DomainAssemblyModuleUnload) { @@ -7362,11 +7349,8 @@ VOID ETW::EnumerationLog::IterateAssembly(Assembly *pAssembly, DWORD enumeration { if(pAssembly->GetDomain()->IsAppDomain()) { - DomainModuleIterator dmIterator = pAssembly->GetDomainAssembly()->IterateModules(kModIterIncludeLoaded); - while (dmIterator.Next()) - { - ETW::LoaderLog::SendModuleEvent(dmIterator.GetModule(), enumerationOptions, TRUE); - } + Module* pModule = pAssembly->GetDomainAssembly()->GetModule(); + ETW::LoaderLog::SendModuleEvent(pModule, enumerationOptions, TRUE); } } diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index fa2b8ffc7dfe38..dd80bf37ec6792 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -500,7 +500,7 @@ OBJECTREF PossiblyUnwrapThrowable(OBJECTREF throwable, Assembly *pAssembly) // Check if we are required to compute the RuntimeWrapExceptions status. BOOL fIsRuntimeWrappedException = ((throwable != NULL) && (throwable->GetMethodTable() == pMT_RuntimeWrappedException)); BOOL fRequiresComputingRuntimeWrapExceptionsStatus = (fIsRuntimeWrappedException && - (!(pAssembly->GetManifestModule()->IsRuntimeWrapExceptionsStatusComputed()))); + (!(pAssembly->GetModule()->IsRuntimeWrapExceptionsStatusComputed()))); CONTRACTL { @@ -513,7 +513,7 @@ OBJECTREF PossiblyUnwrapThrowable(OBJECTREF throwable, Assembly *pAssembly) } CONTRACTL_END; - if (fIsRuntimeWrappedException && (!pAssembly->GetManifestModule()->IsRuntimeWrapExceptions())) + if (fIsRuntimeWrappedException && (!pAssembly->GetModule()->IsRuntimeWrapExceptions())) { // We already created the instance, fetched the field. We know it is // not marshal by ref, or any of the other cases that might trigger GC. @@ -12136,8 +12136,8 @@ VOID CheckAndThrowSameTypeAndAssemblyInvalidCastException(TypeHandle thCastFrom, _ASSERTE(pAssemblyTypeFrom != NULL); _ASSERTE(pAssemblyTypeTo != NULL); - PEAssembly *pPEAssemblyTypeFrom = pAssemblyTypeFrom->GetManifestFile(); - PEAssembly *pPEAssemblyTypeTo = pAssemblyTypeTo->GetManifestFile(); + PEAssembly *pPEAssemblyTypeFrom = pAssemblyTypeFrom->GetPEAssembly(); + PEAssembly *pPEAssemblyTypeTo = pAssemblyTypeTo->GetPEAssembly(); _ASSERTE(pPEAssemblyTypeFrom != NULL); _ASSERTE(pPEAssemblyTypeTo != NULL); diff --git a/src/coreclr/vm/field.cpp b/src/coreclr/vm/field.cpp index a0e1260976dee8..3855f4a22c0df7 100644 --- a/src/coreclr/vm/field.cpp +++ b/src/coreclr/vm/field.cpp @@ -61,6 +61,8 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr FieldType == ELEMENT_TYPE_R8 || FieldType == ELEMENT_TYPE_CLASS || FieldType == ELEMENT_TYPE_VALUETYPE || + FieldType == ELEMENT_TYPE_BYREF || + FieldType == ELEMENT_TYPE_TYPEDBYREF || FieldType == ELEMENT_TYPE_PTR || FieldType == ELEMENT_TYPE_FNPTR ); @@ -70,7 +72,8 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr m_requiresFullMbValue = 0; SetMemberDef(mb); - m_type = FieldType; + // A TypedByRef should be treated like a regular value type. + m_type = FieldType != ELEMENT_TYPE_TYPEDBYREF ? FieldType : ELEMENT_TYPE_VALUETYPE; m_prot = fdFieldAccessMask & dwMemberAttrs; m_isStatic = fIsStatic != 0; m_isRVA = fIsRVA != 0; @@ -81,7 +84,7 @@ VOID FieldDesc::Init(mdFieldDef mb, CorElementType FieldType, DWORD dwMemberAttr #endif _ASSERTE(GetMemberDef() == mb); // no truncation - _ASSERTE(GetFieldType() == FieldType); + _ASSERTE(GetFieldType() == FieldType || (FieldType == ELEMENT_TYPE_TYPEDBYREF && m_type == ELEMENT_TYPE_VALUETYPE)); _ASSERTE(GetFieldProtection() == (fdFieldAccessMask & dwMemberAttrs)); _ASSERTE((BOOL) IsStatic() == (fIsStatic != 0)); } @@ -152,6 +155,7 @@ TypeHandle FieldDesc::LookupFieldTypeHandle(ClassLoadLevel level, BOOL dropGener _ASSERTE(type == ELEMENT_TYPE_CLASS || type == ELEMENT_TYPE_VALUETYPE || type == ELEMENT_TYPE_STRING || + type == ELEMENT_TYPE_TYPEDBYREF || type == ELEMENT_TYPE_SZARRAY || type == ELEMENT_TYPE_VAR ); diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 3bf1abcfcfbee9..b509a5c221ed18 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -1063,7 +1063,7 @@ CorClassIfaceAttr ReadClassInterfaceTypeCustomAttribute(TypeHandle type) { // Check the class interface attribute at the assembly level. Assembly *pAssembly = type.GetAssembly(); - hr = TryParseClassInterfaceAttribute(pAssembly->GetManifestModule(), pAssembly->GetManifestToken(), &attrValueMaybe); + hr = TryParseClassInterfaceAttribute(pAssembly->GetModule(), pAssembly->GetManifestToken(), &attrValueMaybe); if (FAILED(hr)) ThrowHR(hr, BFA_BAD_CLASS_INT_CA_FORMAT); } @@ -2501,8 +2501,8 @@ HRESULT GetTypeLibGuidForAssembly(Assembly *pAssembly, GUID *pGuid) CQuickArray rName; // String for guid. ULONG cbData; // Size of the string in bytes. - // Get GUID from Assembly, else from Manifest Module, else Generate from name. - hr = pAssembly->GetManifestImport()->GetItemGuid(TokenFromRid(1, mdtAssembly), pGuid); + // Get GUID from Assembly, else Generate from name. + hr = pAssembly->GetMDImport()->GetItemGuid(TokenFromRid(1, mdtAssembly), pGuid); if (*pGuid == GUID_NULL) { @@ -2548,7 +2548,7 @@ HRESULT GetTypeLibVersionForAssembly( ULONG cbData = 0; // Check to see if the TypeLibVersionAttribute is set. - IfFailRet(pAssembly->GetManifestImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_TYPELIBVERSION_TYPE, (const void**)&pbData, &cbData)); + IfFailRet(pAssembly->GetMDImport()->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), INTEROP_TYPELIBVERSION_TYPE, (const void**)&pbData, &cbData)); // For attribute contents, see https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.typelibversionattribute if (cbData >= (2 + 2 * sizeof(UINT32))) diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 109f98ceecfe13..27d2452491e2a1 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -529,16 +529,8 @@ ftype BankersRound(ftype value) if ((value -(integerPart +0.5)) == 0.0) { // round to even -#if defined(TARGET_ARM) && defined(FEATURE_CORESYSTEM) - // @ARMTODO: On ARM when building on CoreSystem (where we link against the system CRT) an attempt to - // use fmod(float, float) fails to link (apparently this is converted to a reference to fmodf, which - // is not included in the system CRT). Use the double version instead. - if (fmod(double(integerPart), double(2.0)) == 0.0) - return integerPart; -#else if (fmod(ftype(integerPart), ftype(2.0)) == 0.0) return integerPart; -#endif // Else return the nearest even integer return (ftype)_copysign(ceil(fabs(value+0.5)), @@ -1442,7 +1434,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass_Helper, DomainLocalModul HELPER_METHOD_FRAME_BEGIN_RET_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1464,7 +1456,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCStaticBaseDynamicClass, DomainLocalModule *pLoc if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1486,7 +1478,7 @@ HCIMPL2(void, JIT_ClassInitDynamicClass_Helper, DomainLocalModule *pLocalModule, HELPER_METHOD_FRAME_BEGIN_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1525,7 +1517,7 @@ HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass_Helper, DomainLocalModule * HELPER_METHOD_FRAME_BEGIN_RET_0(); - MethodTable *pMT = pLocalModule->GetDomainFile()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); + MethodTable *pMT = pLocalModule->GetDomainAssembly()->GetModule()->GetDynamicClassMT(dwDynamicClassDomainID); _ASSERTE(pMT); pMT->CheckRunClassInitThrowing(); @@ -1547,7 +1539,7 @@ HCIMPL2(void*, JIT_GetSharedGCStaticBaseDynamicClass, DomainLocalModule *pLocalM if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1861,7 +1853,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, DomainLocalModule if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_NONGCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_NONGCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); return retval; @@ -1872,7 +1864,7 @@ HCIMPL2(void*, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, DomainLocalModule // then we have to go through the slow path // Obtain the Module - Module * pModule = pDomainLocalModule->GetDomainFile()->GetModule(); + Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule(); // Obtain the MethodTable MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID); @@ -1909,7 +1901,7 @@ HCIMPL2(void*, JIT_GetSharedGCThreadStaticBaseDynamicClass, DomainLocalModule *p if (pLocalInfo != NULL) { PTR_BYTE retval; - GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainFile()->GetModule()->GetLoaderAllocator(), + GET_DYNAMICENTRY_GCTHREADSTATICS_BASEPOINTER(pDomainLocalModule->GetDomainAssembly()->GetModule()->GetLoaderAllocator(), pLocalInfo, &retval); @@ -1921,7 +1913,7 @@ HCIMPL2(void*, JIT_GetSharedGCThreadStaticBaseDynamicClass, DomainLocalModule *p // then we have to go through the slow path // Obtain the Module - Module * pModule = pDomainLocalModule->GetDomainFile()->GetModule(); + Module * pModule = pDomainLocalModule->GetDomainAssembly()->GetModule(); // Obtain the MethodTable MethodTable * pMT = pModule->GetDynamicClassMT(dwDynamicClassDomainID); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e28434acabe56e..3a9f5c0207a6bb 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -953,7 +953,7 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken ThrowBadTokenException(pResolvedToken); { - DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK); + DomainAssembly *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK); if (pTargetModule == NULL) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); th = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable()); @@ -9002,9 +9002,6 @@ CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, FieldDesc* field = (FieldDesc*) fieldHnd; CorElementType type = field->GetFieldType(); - // TODO should not burn the time to do this for anything but Value Classes - _ASSERTE(type != ELEMENT_TYPE_BYREF); - if (type == ELEMENT_TYPE_I) { PTR_MethodTable enclosingMethodTable = field->GetApproxEnclosingMethodTable(); @@ -12736,7 +12733,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, LARGE_INTEGER methodJitTimeStop; QueryPerformanceCounter(&methodJitTimeStop); SString codeBase; - ftn->GetModule()->GetDomainFile()->GetPEAssembly()->GetPathOrCodeBase(codeBase); + ftn->GetModule()->GetDomainAssembly()->GetPEAssembly()->GetPathOrCodeBase(codeBase); codeBase.AppendPrintf(W(",0x%x,%d,%d\n"), //(const WCHAR *)codeBase, //module name ftn->GetMemberDef(), //method token @@ -12818,13 +12815,11 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, "Jitted Entry at" FMT_ADDR "method %s::%s %s\n", DBG_ADDR(nativeEntry), ftn->m_pszDebugClassName, ftn->m_pszDebugMethodName, ftn->m_pszDebugMethodSignature)); -#if defined(FEATURE_CORESYSTEM) - #ifdef _DEBUG LPCUTF8 pszDebugClassName = ftn->m_pszDebugClassName; LPCUTF8 pszDebugMethodName = ftn->m_pszDebugMethodName; LPCUTF8 pszDebugMethodSignature = ftn->m_pszDebugMethodSignature; -#else +#elif 0 LPCUTF8 pszNamespace; LPCUTF8 pszDebugClassName = ftn->GetMethodTable()->GetFullyQualifiedNameInfo(&pszNamespace); LPCUTF8 pszDebugMethodName = ftn->GetName(); @@ -12833,7 +12828,6 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry), // pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode); -#endif ClrFlushInstructionCache(nativeEntry, sizeOfCode); ret = (PCODE)nativeEntry; diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 5b5c9d142c89db..657ff7b2b40cec 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -360,7 +360,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (iData.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -393,7 +393,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (i.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -420,7 +420,7 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain while (i.Next_Unlocked(pDomainAssembly.This())) { // The assembly could be collected (ref-count = 0), do not use holder which calls add-ref - Assembly * pAssembly = pDomainAssembly->GetLoadedAssembly(); + Assembly * pAssembly = pDomainAssembly->GetAssembly(); if (pAssembly != NULL) { @@ -672,7 +672,7 @@ BOOL LoaderAllocator::Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator) DomainAssembly* pDomainAssembly = (DomainAssembly*)(pID->GetDomainAssemblyIterator()); if (pDomainAssembly != NULL) { - Assembly *pAssembly = pDomainAssembly->GetCurrentAssembly(); + Assembly *pAssembly = pDomainAssembly->GetAssembly(); pLoaderAllocator->m_pFirstDomainAssemblyFromSameALCToDelete = pAssembly->GetDomainAssembly(); } diff --git a/src/coreclr/vm/memberload.cpp b/src/coreclr/vm/memberload.cpp index 78fdb518a1618e..4c8e7dc7e2a925 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); + DomainAssembly *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 841b3214d2e2d5..da24a53d064a17 100644 --- a/src/coreclr/vm/methoditer.cpp +++ b/src/coreclr/vm/methoditer.cpp @@ -77,11 +77,7 @@ BOOL LoadedMethodDescIterator::Next( dbg_m_pDomainAssembly = *pDomainAssemblyHolder; #endif //_DEBUG - m_moduleIterator = (*pDomainAssemblyHolder)->IterateModules(m_moduleIterationFlags); - -ADVANCE_MODULE: - if (!m_moduleIterator.Next()) - goto ADVANCE_ASSEMBLY; + m_currentModule = (*pDomainAssemblyHolder)->GetModule(); if (m_mainMD->HasClassInstantiation()) { @@ -96,7 +92,7 @@ BOOL LoadedMethodDescIterator::Next( if (m_mainMD->HasClassInstantiation()) { if (!GetCurrentModule()->GetAvailableParamTypes()->FindNext(&m_typeIterator, &m_typeIteratorEntry)) - goto ADVANCE_MODULE; + goto ADVANCE_ASSEMBLY; if (CORCOMPILE_IS_POINTER_TAGGED(m_typeIteratorEntry->GetTypeHandle().AsTAddr())) goto ADVANCE_TYPE; @@ -130,7 +126,7 @@ BOOL LoadedMethodDescIterator::Next( } else if (m_startedNonGenericType) { - goto ADVANCE_MODULE; + goto ADVANCE_ASSEMBLY; } else { @@ -188,7 +184,7 @@ Module * LoadedMethodDescIterator::GetCurrentModule() } CONTRACTL_END - return m_moduleIterator.GetLoadedModule(); + return m_currentModule; } MethodDesc *LoadedMethodDescIterator::Current() @@ -228,8 +224,7 @@ LoadedMethodDescIterator::Start( AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemblyIterationFlags, - ModuleIterationOption moduleIterationFlags) + AssemblyIterationFlags assemblyIterationFlags) { CONTRACTL { @@ -241,7 +236,6 @@ LoadedMethodDescIterator::Start( CONTRACTL_END; m_assemIterationFlags = assemblyIterationFlags; - m_moduleIterationFlags = moduleIterationFlags; m_mainMD = NULL; m_module = pModule; m_md = md; diff --git a/src/coreclr/vm/methoditer.h b/src/coreclr/vm/methoditer.h index 71192be2e0c01a..fdc49e2ce59710 100644 --- a/src/coreclr/vm/methoditer.h +++ b/src/coreclr/vm/methoditer.h @@ -9,7 +9,7 @@ #include "instmethhash.h" #include "method.hpp" #include "appdomain.hpp" -#include "domainfile.h" +#include "domainassembly.h" #include "typehash.h" @@ -44,9 +44,8 @@ class LoadedMethodDescIterator // These are used when iterating over an AppDomain AppDomain::AssemblyIterator m_assemIterator; - DomainModuleIterator m_moduleIterator; + Module* m_currentModule; AssemblyIterationFlags m_assemIterationFlags; - ModuleIterationOption m_moduleIterationFlags; EETypeHashTable::Iterator m_typeIterator; EETypeHashEntry * m_typeIteratorEntry; @@ -69,19 +68,17 @@ class LoadedMethodDescIterator void Start(AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution), - ModuleIterationOption moduleIterationFlags = kModIterIncludeLoaded); + AssemblyIterationFlags assemIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); void Start(AppDomain * pAppDomain, Module *pModule, mdMethodDef md, MethodDesc *pDesc); LoadedMethodDescIterator( AppDomain * pAppDomain, Module *pModule, mdMethodDef md, - AssemblyIterationFlags assemblyIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution), - ModuleIterationOption moduleIterationFlags = kModIterIncludeLoaded) + AssemblyIterationFlags assemblyIterationFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)) { LIMITED_METHOD_CONTRACT; - Start(pAppDomain, pModule, md, assemblyIterationFlags, moduleIterationFlags); + Start(pAppDomain, pModule, md, assemblyIterationFlags); } LoadedMethodDescIterator(void); diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 68d11affa4351f..59566e2e717179 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -3935,6 +3935,27 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, break; } + case ELEMENT_TYPE_BYREF: + { + dwLog2FieldSize = LOG2_PTRSIZE; + if (fIsStatic) + { + // Byref-like types cannot be used for static fields + BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_STATICFIELD); + } + if (!bmtFP->fIsByRefLikeType) + { + // Non-byref-like types cannot contain byref-like instance fields + BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_INSTANCEFIELD); + } + break; + } + + case ELEMENT_TYPE_TYPEDBYREF: + { + goto IS_VALUETYPE; + } + // Class type variable (method type variables aren't allowed in fields) // These only occur in open types used for verification/reflection. case ELEMENT_TYPE_VAR: @@ -4042,7 +4063,10 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, pByValueClass = (MethodTable *)-1; } } // If 'this' is a value class - + } + // TypedReference shares the rest of the code here +IS_VALUETYPE: + { // It's not self-referential so try to load it if (pByValueClass == NULL) { diff --git a/src/coreclr/vm/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index b747608a184783..18a0a141a8228b 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -234,11 +234,11 @@ FileLoadLevel MulticoreJitManager::GetModuleFileLoadLevel(Module * pModule) if (pModule != NULL) { - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); - if (pDomainFile != NULL) + if (pDomainAssembly != NULL) { - level = pDomainFile->GetLoadLevel(); + level = pDomainAssembly->GetLoadLevel(); } } @@ -310,7 +310,7 @@ bool RecorderModuleInfo::SetModule(Module * pMod) SString sAssemblyName; StackScratchBuffer scratch; - pMod->GetAssembly()->GetManifestFile()->GetDisplayName(sAssemblyName); + pMod->GetAssembly()->GetPEAssembly()->GetDisplayName(sAssemblyName); LPCUTF8 pAssemblyName = sAssemblyName.GetUTF8(scratch); unsigned lenAssemblyName = sAssemblyName.GetCount(); @@ -770,21 +770,8 @@ HRESULT MulticoreJitModuleEnumerator::HandleAssembly(DomainAssembly * pAssembly) { STANDARD_VM_CONTRACT; - DomainAssembly::ModuleIterator modIt = pAssembly->IterateModules(kModIterIncludeLoaded); - - HRESULT hr = S_OK; - - while (modIt.Next() && SUCCEEDED(hr)) - { - Module * pModule = modIt.GetModule(); - - if (pModule != NULL) - { - hr = OnModule(pModule); - } - } - - return hr; + Module * pModule = pAssembly->GetModule(); + return OnModule(pModule); } diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index 3bb47cff1acb31..2664a44ad2d18b 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -289,7 +289,7 @@ void NativeImage::CheckAssemblyMvid(Assembly *assembly) const } GUID assemblyMvid; - assembly->GetManifestImport()->GetScopeProps(NULL, &assemblyMvid); + assembly->GetMDImport()->GetScopeProps(NULL, &assemblyMvid); const byte *pImageBase = (const BYTE *)m_pImageLayout->GetBase(); const GUID *componentMvid = (const GUID *)&pImageBase[m_pComponentAssemblyMvids->VirtualAddress] + assemblyNameIndex->Index; diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index d5a91b4863c2fc..e050e0b1719ff8 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -318,7 +318,7 @@ namespace #endif // !TARGET_UNIX NATIVE_LIBRARY_HANDLE hmod = NULL; - PEAssembly *pManifestFile = pAssembly->GetManifestFile(); + PEAssembly *pManifestFile = pAssembly->GetPEAssembly(); PTR_AssemblyBinder pBinder = pManifestFile->GetAssemblyBinder(); //Step 0: Check if the assembly was bound using TPA. @@ -363,7 +363,7 @@ namespace { STANDARD_VM_CONTRACT; - PTR_AssemblyBinder pBinder = pAssembly->GetManifestFile()->GetAssemblyBinder(); + PTR_AssemblyBinder pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); return pBinder->GetManagedAssemblyLoadContext(); } @@ -461,7 +461,7 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; - SString path = pAssembly->GetManifestFile()->GetPath(); + SString path = pAssembly->GetPEAssembly()->GetPath(); SString::Iterator lastPathSeparatorIter = path.End(); if (PEAssembly::FindLastPathSeparator(path, lastPathSeparatorIter)) @@ -610,7 +610,7 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; -#if defined(FEATURE_CORESYSTEM) && !defined(TARGET_UNIX) +#if !defined(TARGET_UNIX) // Try to go straight to System32 for Windows API sets. This is replicating quick check from // the OS implementation of api sets. if (IsWindowsAPISet(wszLibName)) @@ -621,7 +621,7 @@ namespace return hmod; } } -#endif // FEATURE_CORESYSTEM && !TARGET_UNIX +#endif // !TARGET_UNIX if (g_hostpolicy_embedded) { @@ -771,7 +771,7 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryByName(LPCWSTR libraryName, Asse } else { - GetDllImportSearchPathFlags(callingAssembly->GetManifestModule(), + GetDllImportSearchPathFlags(callingAssembly->GetModule(), &dllImportSearchPathFlags, &searchAssemblyDirectory); } diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 9f228fdb5af825..7926fa8b85bf8c 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -552,7 +552,7 @@ BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, pDomainAssembly = pAssembly->GetDomainAssembly(); pPEAssembly = pDomainAssembly->GetPEAssembly(); - if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName( + if (FAILED(pAssembly->GetMDImport()->FindManifestResourceByName( szName, &mdResource))) { @@ -1080,7 +1080,7 @@ void PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - DAC_ENUM_VTHIS(); + DAC_ENUM_DTHIS(); EMEM_OUT(("MEM: %p PEAssembly\n", dac_cast(this))); #ifdef _DEBUG diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index 3342e835f265a3..8cb12f986c8bb3 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -83,11 +83,6 @@ typedef VPTR(PEAssembly) PTR_PEAssembly; class PEAssembly final { - // ------------------------------------------------------------ - // SOS support - // ------------------------------------------------------------ - VPTR_BASE_CONCRETE_VTABLE_CLASS(PEAssembly) - public: // ------------------------------------------------------------ @@ -98,7 +93,7 @@ class PEAssembly final STDMETHOD_(ULONG, Release)(); #ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif #if CHECK_INVARIANTS @@ -381,7 +376,7 @@ class PEAssembly final #ifdef DACCESS_COMPILE // just to make the DAC and GCC happy. - virtual ~PEAssembly() {}; + ~PEAssembly() {}; PEAssembly() = default; #else PEAssembly( @@ -393,7 +388,7 @@ class PEAssembly final BINDER_SPACE::Assembly* pHostAssembly = NULL ); - virtual ~PEAssembly(); + ~PEAssembly(); #endif void OpenMDImport(); diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 1b72b89106df65..946943cc3cd612 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -456,34 +456,6 @@ void PEImage::GetMVID(GUID *pMvid) #endif // _DEBUG } -void PEImage::VerifyIsAssembly() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // buch of legacy stuff here wrt the error codes... - - if (!HasNTHeaders()) - ThrowFormat(COR_E_BADIMAGEFORMAT); - - if(!HasCorHeader()) - ThrowFormat(COR_E_ASSEMBLYEXPECTED); - - CHECK checkGoodFormat; - checkGoodFormat = CheckILFormat(); - if (!checkGoodFormat) - ThrowFormat(COR_E_BADIMAGEFORMAT); - - mdAssembly a; - if (FAILED(GetMDImport()->GetAssemblyFromScope(&a))) - ThrowFormat(COR_E_ASSEMBLYEXPECTED); -} - void DECLSPEC_NORETURN PEImage::ThrowFormat(HRESULT hrError) { CONTRACTL diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index 6451283d007ce4..f353cebe978d14 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -182,8 +182,6 @@ class PEImage final CHECK CheckILFormat(); CHECK CheckUniqueInstance(); - void VerifyIsAssembly(); - void SetModuleFileNameHintForDAC(); #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 30708584c3f72e..5e004f6ed0c1fc 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -393,7 +393,7 @@ NativeImagePerfMap::NativeImagePerfMap(Assembly * pAssembly, BSTR pDestPath) // Get the native image signature (GUID). // Used to ensure that we match symbols to the correct NGEN image. WCHAR wszSignature[39]; - GetNativeImageSignature(pAssembly->GetManifestFile(), wszSignature, ARRAY_SIZE(wszSignature)); + GetNativeImageSignature(pAssembly->GetPEAssembly(), wszSignature, ARRAY_SIZE(wszSignature)); // Build the path to the perfmap file, which consists of .ni..map. // Example: /tmp/System.Private.CoreLib.ni.{GUID}.map diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index a4fdb065285ddf..681301621f72ff 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -520,7 +520,7 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) // Lookup in the entry point assembly for a R2R entrypoint (generics with large version bubble enabled) if (pCode == NULL && HasClassOrMethodInstantiation() && SystemDomain::System()->DefaultDomain()->GetRootAssembly() != NULL) { - pModule = SystemDomain::System()->DefaultDomain()->GetRootAssembly()->GetManifestModule(); + pModule = SystemDomain::System()->DefaultDomain()->GetRootAssembly()->GetModule(); _ASSERT(pModule != NULL); if (pModule->IsReadyToRun() && pModule->IsInSameVersionBubble(GetModule())) diff --git a/src/coreclr/vm/profilingenumerators.cpp b/src/coreclr/vm/profilingenumerators.cpp index 609b57cf4ee3ab..7d537924df8919 100644 --- a/src/coreclr/vm/profilingenumerators.cpp +++ b/src/coreclr/vm/profilingenumerators.cpp @@ -250,7 +250,7 @@ HRESULT IterateUnsharedModules(AppDomain * pAppDomain, // enumerable. // // Note: To determine what happens in a given load stage of a module or assembly, - // look at the switch statement in code:DomainFile::DoIncrementalLoad, and keep in + // look at the switch statement in code:DomainAssembly::DoIncrementalLoad, and keep in // mind that it takes cases on the *next* load stage; in other words, the actions // that appear in a case for a given load stage are actually executed as we attempt // to transition TO that load stage, and thus they actually execute while the module @@ -282,21 +282,14 @@ HRESULT IterateUnsharedModules(AppDomain * pAppDomain, // < Module NOT available from catch-up enumeration // < ModuleUnloadStarted issued // - // The IterateModules parameter below ensures only modules at level >= - // code:FILE_LOAD_LOADLIBRARY will be included in the iteration. - // // Details for module callbacks are the same as those for assemblies, so see // code:#ProfilerEnumAssemblies for info on how the timing works. - DomainModuleIterator domainModuleIterator = - pDomainAssembly->IterateModules(kModIterIncludeAvailableToProfilers); - while (domainModuleIterator.Next()) + + // Call user-supplied callback, and cancel iteration if requested + HRESULT hr = (callbackObj->*callbackMethod)(pDomainAssembly->GetModule()); + if (hr != S_OK) { - // Call user-supplied callback, and cancel iteration if requested - HRESULT hr = (callbackObj->*callbackMethod)(domainModuleIterator.GetModule()); - if (hr != S_OK) - { - return hr; - } + return hr; } } @@ -402,9 +395,9 @@ HRESULT ProfilerModuleEnum::Init() HRESULT hr = S_OK; - // When an assembly or module is loaded into an AppDomain, a separate DomainFile is - // created (one per pairing of the AppDomain with the module or assembly). This means - // that we'll create multiple DomainFiles for the same module if it is loaded + // When an assembly is loaded into an AppDomain, a DomainAssembly is + // created (one per pairing of the AppDomain with the assembly). This means + // that we'll create multiple DomainAssemblys for the same module if it is loaded // domain-neutral (i.e., "shared"). The profiling API callbacks shield the profiler // from this, and only report a given module the first time it's loaded. So a // profiler sees only one ModuleLoadFinished for a module loaded domain-neutral, even @@ -457,8 +450,8 @@ HRESULT IterateAppDomainContainingModule::AddAppDomainContainingModule(AppDomain } CONTRACTL_END; - DomainFile * pDomainFile = m_pModule->GetDomainFile(); - if ((pDomainFile != NULL) && (pDomainFile->IsAvailableToProfilers())) + DomainAssembly * pDomainAssembly = m_pModule->GetDomainAssembly(); + if ((pDomainAssembly != NULL) && (pDomainAssembly->IsAvailableToProfilers())) { if (m_index < m_cAppDomainIds) { diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 50e57f8144eef3..5162ac38a3bb4c 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -5710,7 +5710,7 @@ HRESULT ProfToEEInterfaceImpl::GetAssemblyInfo(AssemblyID assemblyId, // Find the module the manifest lives in. if (pModuleId) { - *pModuleId = (ModuleID) pAssembly->GetManifestModule(); + *pModuleId = (ModuleID) pAssembly->GetModule(); // This is the case where the profiler has called GetAssemblyInfo // on an assembly that has been completely created yet. diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 96971b81801951..2d5d1cfc92b37c 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -27,7 +27,6 @@ #include "comdatetime.h" #include "compatibilityswitch.h" #include "debugdebugger.h" -#include "assemblyname.hpp" #include "assemblynative.hpp" #include "comthreadpool.h" #include "comwaithandle.h" diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 495e10e4f4a365..e49ad881f5fe54 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -1579,19 +1579,17 @@ extern "C" void QCALLTYPE ReflectionInvocation_RunClassConstructor(QCall::TypeHa END_QCALL; } -// This method triggers the module constructor for a give module +// This method triggers the module constructor for a given module extern "C" void QCALLTYPE ReflectionInvocation_RunModuleConstructor(QCall::ModuleHandle pModule) { QCALL_CONTRACT; - DomainFile *pDomainFile = pModule->GetDomainFile(); - if (pDomainFile != NULL && pDomainFile->IsActive()) + DomainAssembly *pDomainAssembly = pModule->GetDomainAssembly(); + if (pDomainAssembly != NULL && pDomainAssembly->IsActive()) return; BEGIN_QCALL; - if(pDomainFile == NULL) - pDomainFile = pModule->GetDomainFile(); - pDomainFile->EnsureActive(); + pDomainAssembly->EnsureActive(); END_QCALL; } diff --git a/src/coreclr/vm/rejit.cpp b/src/coreclr/vm/rejit.cpp index aaf335390764cb..80f05489ad3b2f 100644 --- a/src/coreclr/vm/rejit.cpp +++ b/src/coreclr/vm/rejit.cpp @@ -811,35 +811,31 @@ HRESULT ReJitManager::UpdateNativeInlinerActiveILVersions( _ASSERTE(pDomainAssembly != NULL); _ASSERTE(pDomainAssembly->GetAssembly() != NULL); - DomainModuleIterator domainModuleIterator = pDomainAssembly->IterateModules(kModIterIncludeLoaded); - while (domainModuleIterator.Next()) + Module * pModule = pDomainAssembly->GetModule(); + if (pModule->HasReadyToRunInlineTrackingMap()) { - Module * pCurModule = domainModuleIterator.GetModule(); - if (pCurModule->HasReadyToRunInlineTrackingMap()) - { - inlinerIter.Reset(pCurModule, pInlinee); + inlinerIter.Reset(pModule, pInlinee); - MethodDesc *pInliner = NULL; - while (inlinerIter.Next()) + MethodDesc *pInliner = NULL; + while (inlinerIter.Next()) + { + pInliner = inlinerIter.GetMethodDesc(); { - pInliner = inlinerIter.GetMethodDesc(); + CodeVersionManager *pCodeVersionManager = pModule->GetCodeVersionManager(); + CodeVersionManager::LockHolder codeVersioningLockHolder; + ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(pInliner); + if (!ilVersion.HasDefaultIL()) { - CodeVersionManager *pCodeVersionManager = pCurModule->GetCodeVersionManager(); - CodeVersionManager::LockHolder codeVersioningLockHolder; - ILCodeVersion ilVersion = pCodeVersionManager->GetActiveILCodeVersion(pInliner); - if (!ilVersion.HasDefaultIL()) - { - // This method has already been ReJITted, no need to request another ReJIT at this point. - // The ReJITted method will be in the JIT inliner check below. - continue; - } + // This method has already been ReJITted, no need to request another ReJIT at this point. + // The ReJITted method will be in the JIT inliner check below. + continue; } + } - hr = UpdateActiveILVersion(pMgrToCodeActivationBatch, pInliner->GetModule(), pInliner->GetMemberDef(), fIsRevert, flags); - if (FAILED(hr)) - { - ReportReJITError(pInliner->GetModule(), pInliner->GetMemberDef(), NULL, hr); - } + hr = UpdateActiveILVersion(pMgrToCodeActivationBatch, pInliner->GetModule(), pInliner->GetMemberDef(), fIsRevert, flags); + if (FAILED(hr)) + { + ReportReJITError(pInliner->GetModule(), pInliner->GetMemberDef(), NULL, hr); } } } diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 41057e01620d38..362ea14986498e 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -186,9 +186,9 @@ NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pM if (pModule == NULL) return NULL; - DomainFile * pDomainFile = pModule->GetDomainFile(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); - OBJECTREF refModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + OBJECTREF refModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if(refModule != NULL) return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule); @@ -354,7 +354,7 @@ FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObj if (refType == NULL) FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - Module *pModule = refType->GetType().GetAssembly()->GetManifestModule(); + Module *pModule = refType->GetType().GetAssembly()->GetModule(); DomainAssembly *pDomainAssembly = pModule->GetDomainAssembly(); FC_RETURN_ASSEMBLY_OBJECT(pDomainAssembly, refType); @@ -2667,20 +2667,20 @@ FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBas FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); - Assembly* currentAssembly = pAssembly->GetCurrentAssembly(); + Assembly* currentAssembly = pAssembly->GetAssembly(); - Module *pModule = currentAssembly->GetManifestModule(); - DomainFile * pDomainFile = pModule->GetDomainFile(); + Module *pModule = currentAssembly->GetModule(); + DomainAssembly * pDomainAssembly = pModule->GetDomainAssembly(); #ifdef _DEBUG OBJECTREF orModule; HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly); - orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + orModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if (orModule == NULL) orModule = pModule->GetExposedObject(); #else - OBJECTREF orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL; + OBJECTREF orModule = (pDomainAssembly != NULL) ? pDomainAssembly->GetExposedModuleObjectIfExists() : NULL; if (orModule != NULL) return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule); @@ -2705,7 +2705,7 @@ FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) { DomainAssembly *pAssembly = refAssembly->GetDomainAssembly(); mdAssembly token = mdAssemblyNil; - IMDInternalImport *mdImport = pAssembly->GetCurrentAssembly()->GetManifestImport(); + IMDInternalImport *mdImport = pAssembly->GetAssembly()->GetMDImport(); if (mdImport != 0) { @@ -2905,7 +2905,7 @@ FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObjec HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - DomainFile *pDomainModule = pModule->GetDomainFile(); + DomainAssembly *pDomainModule = pModule->GetDomainAssembly(); U1ARRAYREF dataArray = (U1ARRAYREF)sig; DWORD sigSize = dataArray->GetNumComponents(); diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index 200d36586ef52a..20bdfcc6fcc6eb 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1124,8 +1124,12 @@ extern "C" void *JIT_WriteBarrier_Loc; #ifdef TARGET_ARM64 extern "C" void (*JIT_WriteBarrier_Table)(); -extern "C" void *JIT_WriteBarrier_Loc = 0; -extern "C" void *JIT_WriteBarrier_Table_Loc = 0; + +extern "C" void *JIT_WriteBarrier_Loc; +void *JIT_WriteBarrier_Loc = 0; + +extern "C" void *JIT_WriteBarrier_Table_Loc; +void *JIT_WriteBarrier_Table_Loc = 0; #endif // TARGET_ARM64 #ifdef TARGET_ARM @@ -8526,8 +8530,8 @@ Thread::EnumMemoryRegionsWorker(CLRDataEnumMemoryFlags flags) DacEnumCodeForStackwalk(callEnd); // To stackwalk through funceval frames, we need to be sure to preserve the - // DebuggerModule's m_pRuntimeDomainFile. This is the only case that doesn't use the current - // vmDomainFile in code:DacDbiInterfaceImpl::EnumerateInternalFrames. The following + // DebuggerModule's m_pRuntimeDomainAssembly. This is the only case that doesn't use the current + // vmDomainAssembly in code:DacDbiInterfaceImpl::EnumerateInternalFrames. The following // code mimics that function. // Allow failure, since we want to continue attempting to walk the stack regardless of the outcome. EX_TRY diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index 1bfccb85e10d6f..f51f75445b3995 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -132,7 +132,7 @@ class Frame; class ThreadBaseObject; class AppDomainStack; class LoadLevelLimiter; -class DomainFile; +class DomainAssembly; class DeadlockAwareLock; struct HelperMethodFrameCallerList; class ThreadLocalIBCInfo; diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp index 524a9e595bc245..dab28d4703f175 100644 --- a/src/coreclr/vm/typeparse.cpp +++ b/src/coreclr/vm/typeparse.cpp @@ -1273,7 +1273,7 @@ TypeName::GetTypeHaveAssemblyHelper( TypeHandle th = TypeHandle(); SArray & names = GetNames(); - Module * pManifestModule = pAssembly->GetManifestModule(); + Module * pManifestModule = pAssembly->GetModule(); Module * pLookOnlyInModule = NULL; ClassLoader * pClassLoader = pAssembly->GetLoader(); @@ -1427,7 +1427,7 @@ DomainAssembly * LoadDomainAssembly( { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEAssembly *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); + PEAssembly *pRequestingAssemblyManifestFile = pRequestingAssembly->GetPEAssembly(); spec.SetFallbackBinderForRequestingAssembly(pRequestingAssemblyManifestFile->GetFallbackBinder()); } diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 026ba5da743a56..12a4ed3225739a 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -329,22 +329,6 @@ void NPrintToHandleA(HANDLE Handle, const char *pszString, size_t BytesToWrite) while (BytesToWrite > 0) { DWORD dwChunkToWrite = (DWORD) min(BytesToWrite, maxWriteFileSize); - // No CharNextExA on CoreSystem, we just assume no multi-byte characters (this code path shouldn't be - // used in the production codepath for currently supported CoreSystem based products anyway). -#ifndef FEATURE_CORESYSTEM - if (dwChunkToWrite < BytesToWrite) { - break; - // must go by char to find biggest string that will fit, taking DBCS chars into account - //dwChunkToWrite = 0; - //const char *charNext = pszString; - //while (dwChunkToWrite < maxWriteFileSize-2 && charNext) { - // charNext = CharNextExA(0, pszString+dwChunkToWrite, 0); - // dwChunkToWrite = (DWORD)(charNext - pszString); - //} - //if (dwChunkToWrite == 0) - // break; - } -#endif // !FEATURE_CORESYSTEM // Try to write to handle. If this is not a CUI app, then this is probably // not going to work unless the dev took special pains to set their own console diff --git a/src/coreclr/vm/win32threadpool.cpp b/src/coreclr/vm/win32threadpool.cpp index 7ffbc34948a471..3e16f18a2d83b9 100644 --- a/src/coreclr/vm/win32threadpool.cpp +++ b/src/coreclr/vm/win32threadpool.cpp @@ -494,11 +494,7 @@ void ThreadpoolMgr::InitPlatformVariables() _ASSERTE(hNtDll); if (!UsePortableThreadPool()) { -#ifdef FEATURE_CORESYSTEM hCoreSynch = CLRLoadLibrary(W("api-ms-win-core-synch-l1-1-0.dll")); -#else - hCoreSynch = CLRLoadLibrary(W("kernel32.dll")); -#endif _ASSERTE(hCoreSynch); } } @@ -3999,7 +3995,7 @@ DWORD WINAPI ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) * 2. GCCpuGroups=1, CLR creates GC threads for all processors in all CPU groups * thus, the threadpool thread would use a whole CPU group (if Thread_UseAllCpuGroups is not set). * ==> use g_SystemInfo.dwNumberOfProcessors. - * 3. !defined(TARGET_UNIX) but defined(FEATURE_CORESYSTEM), GetCurrentProcessCpuCount() + * 3. !defined(TARGET_UNIX), GetCurrentProcessCpuCount() * returns g_SystemInfo.dwNumberOfProcessors ==> use g_SystemInfo.dwNumberOfProcessors; * Other cases: * 1. Normal case: the mask is all or a subset of all processors in a CPU group; diff --git a/src/coreclr/vm/zapsig.cpp b/src/coreclr/vm/zapsig.cpp index dbdff7a98c8f5b..b66c7b10571384 100644 --- a/src/coreclr/vm/zapsig.cpp +++ b/src/coreclr/vm/zapsig.cpp @@ -620,7 +620,7 @@ Module *ZapSig::DecodeModuleFromIndex(Module *fromModule, } } - return pAssembly->GetManifestModule(); + return pAssembly->GetModule(); } Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, @@ -686,7 +686,7 @@ Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, if (pAssembly == NULL) return NULL; - return pAssembly->GetManifestModule(); + return pAssembly->GetModule(); } diff --git a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs index f17bbbe6378ccc..e1e81da93ff4d5 100644 --- a/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs +++ b/src/installer/managed/Microsoft.NET.HostModel/AppHost/HostWriter.cs @@ -94,7 +94,7 @@ void UpdateResources() try { // Open the source host file. - appHostSourceStream = new FileStream(appHostSourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + appHostSourceStream = new FileStream(appHostSourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1); memoryMappedFile = MemoryMappedFile.CreateFromFile(appHostSourceStream, null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, true); memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.CopyOnWrite); diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props new file mode 100644 index 00000000000000..1f343d09fe1053 --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + $(MSBuildThisFileDirectory)ILCompilerRIDs.props + + + + + diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props new file mode 100644 index 00000000000000..70e13f311b74a7 --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj new file mode 100644 index 00000000000000..65fd54d7bf3fb6 --- /dev/null +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/Microsoft.DotNet.ILCompiler.pkgproj @@ -0,0 +1,26 @@ + + + + true + true + Provides a native AOT compiler and runtime for .NET + + + + + + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/nativeaot-packages.proj b/src/installer/pkg/projects/nativeaot-packages.proj new file mode 100644 index 00000000000000..10ab1d60c56fa5 --- /dev/null +++ b/src/installer/pkg/projects/nativeaot-packages.proj @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/installer/pkg/projects/netcoreappRIDs.props b/src/installer/pkg/projects/netcoreappRIDs.props index 37fa250ded667b..6282d87b88a92b 100644 --- a/src/installer/pkg/projects/netcoreappRIDs.props +++ b/src/installer/pkg/projects/netcoreappRIDs.props @@ -26,6 +26,9 @@ arm + + armv6 + arm64 diff --git a/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Hash.cs b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Hash.cs index dc3e3426596e99..a4c41cfbcac620 100644 --- a/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Hash.cs +++ b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Hash.cs @@ -34,16 +34,21 @@ public static byte[] HashData(byte[] data, int offset, int count, HashAlgorithmN throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")] public static byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) { // The classes that call us are sealed and their base class has checked this already. Debug.Assert(data != null); Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name)); - using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithm)) - { - return hasher.ComputeHash(data); - } + return + hashAlgorithm == HashAlgorithmName.SHA256 ? SHA256.HashData(data) : + hashAlgorithm == HashAlgorithmName.SHA1 ? SHA1.HashData(data) : + hashAlgorithm == HashAlgorithmName.SHA512 ? SHA512.HashData(data) : + hashAlgorithm == HashAlgorithmName.SHA384 ? SHA384.HashData(data) : + hashAlgorithm == HashAlgorithmName.MD5 ? MD5.HashData(data) : + throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] @@ -61,15 +66,5 @@ public static bool TryHashData(ReadOnlySpan source, Span destination hashAlgorithm == HashAlgorithmName.MD5 ? MD5.TryHashData(source, destination, out bytesWritten) : throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name); } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")] - private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmName) => - hashAlgorithmName == HashAlgorithmName.SHA256 ? SHA256.Create() : - hashAlgorithmName == HashAlgorithmName.SHA1 ? SHA1.Create() : - hashAlgorithmName == HashAlgorithmName.SHA512 ? SHA512.Create() : - hashAlgorithmName == HashAlgorithmName.SHA384 ? SHA384.Create() : - hashAlgorithmName == HashAlgorithmName.MD5 ? MD5.Create() : - throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName.Name); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs index 6cf3766ad8ed53..993d6d42ae7517 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs @@ -16,7 +16,15 @@ internal static partial class AppleCrypto internal static partial SafeHmacHandle HmacCreate(PAL_HashAlgorithm algorithm, ref int cbDigest); [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacInit")] - internal static partial int HmacInit(SafeHmacHandle ctx, byte[] pbKey, int cbKey); + private static unsafe partial int HmacInit(SafeHmacHandle ctx, byte* pbKey, int cbKey); + + internal static unsafe int HmacInit(SafeHmacHandle ctx, ReadOnlySpan key) + { + fixed (byte* pKey = &MemoryMarshal.GetReference(key)) + { + return HmacInit(ctx, pKey, key.Length); + } + } internal static int HmacUpdate(SafeHmacHandle ctx, ReadOnlySpan data) => HmacUpdate(ctx, ref MemoryMarshal.GetReference(data), data.Length); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs index 567f97df901ce7..4bbd79987510bd 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Text; internal static partial class Interop { @@ -33,6 +32,19 @@ public bool IsIPv6 private uint _isIPv6; // Non-zero if this is an IPv6 address; zero for IPv4. internal uint ScopeId; // Scope ID (IPv6 only) + public override unsafe int GetHashCode() + { + HashCode h = default; + fixed (byte* ptr = Address) + { + h.AddBytes(new ReadOnlySpan(ptr, IsIPv6 ? IPv6AddressBytes : IPv4AddressBytes)); + } + return h.ToHashCode(); + } + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IPAddress other && Equals(other); + public bool Equals(IPAddress other) { int addressByteCount; diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index d403daac342ad1..12b75443f74723 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -327,12 +327,9 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia Crypto.ErrClearError(); } - if (sslAuthenticationOptions.CertSelectionDelegate != null && sslAuthenticationOptions.CertificateContext == null) - { - // We don't have certificate but we have callback. We should wait for remote certificate and - // possible trusted issuer list. - Interop.Ssl.SslSetClientCertCallback(sslHandle, 1); - } + // Set client cert callback, this will interrupt the handshake with SecurityStatusPalErrorCode.CredentialsNeeded + // if server actually requests a certificate. + Ssl.SslSetClientCertCallback(sslHandle, 1); } if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired) diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs index 7a1574155a7d9a..e1a9bc4cce2ac3 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.Constants.cs @@ -198,6 +198,7 @@ internal static partial class User32 public const int WAIT_TIMEOUT = 0x00000102; + public const int WM_DESTROY = 0x0002; public const int WM_CLOSE = 0x0010; public const int WM_QUERYENDSESSION = 0x0011; public const int WM_QUIT = 0x0012; diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs similarity index 77% rename from src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs rename to src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs index 6bcfa1488d6848..5f9af4ffc2aa79 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.PeekMessage.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetMessage.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class User32 { [GeneratedDllImport(Libraries.User32, CharSet = CharSet.Unicode, ExactSpelling = true)] - public static partial bool PeekMessageW(ref MSG msg, IntPtr hwnd, int msgMin, int msgMax, int remove); + public static partial int GetMessageW(ref MSG msg, IntPtr hwnd, int msgMin, int msgMax); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs new file mode 100644 index 00000000000000..511e68c0f883ba --- /dev/null +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.PostQuitMessage.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class User32 + { + [GeneratedDllImport(Libraries.User32, CharSet = CharSet.Unicode, ExactSpelling = true)] + public static partial void PostQuitMessage(int exitCode); + } +} diff --git a/src/libraries/Common/src/System/Net/CookieComparer.cs b/src/libraries/Common/src/System/Net/CookieComparer.cs index 7d511ace0a9acc..529ec06a51a1fe 100644 --- a/src/libraries/Common/src/System/Net/CookieComparer.cs +++ b/src/libraries/Common/src/System/Net/CookieComparer.cs @@ -5,23 +5,29 @@ namespace System.Net { internal static class CookieComparer { - internal static int Compare(Cookie left, Cookie right) + internal static bool Equals(Cookie left, Cookie right) { - int result; - - if ((result = string.Compare(left.Name, right.Name, StringComparison.OrdinalIgnoreCase)) != 0) + if (!string.Equals(left.Name, right.Name, StringComparison.OrdinalIgnoreCase)) { - return result; + return false; } - if ((result = string.Compare(left.Domain, right.Domain, StringComparison.OrdinalIgnoreCase)) != 0) + if (!EqualDomains(left.Domain, right.Domain)) { - return result; + return false; } // NB: Only the path is case sensitive as per spec. However, many Windows applications assume // case-insensitivity. - return string.Compare(left.Path, right.Path, StringComparison.Ordinal); + return string.Equals(left.Path, right.Path, StringComparison.Ordinal); + } + + internal static bool EqualDomains(ReadOnlySpan left, ReadOnlySpan right) + { + if (left.Length != 0 && left[0] == '.') left = left.Slice(1); + if (right.Length != 0 && right[0] == '.') right = right.Slice(1); + + return left.Equals(right, StringComparison.OrdinalIgnoreCase); } } } diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs index 579e69a153f045..c2fcca169d21dc 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/UnixCommandLinePing.cs @@ -90,7 +90,8 @@ public static string ConstructCommandLine(int packetSize, int timeout, string ad // OSX: ping requires -W flag which accepts timeout in MILLISECONDS; ping6 doesn't support timeout if (OperatingSystem.IsFreeBSD()) { - if (ipv4) + // Syntax changed in FreeBSD 13.0 and options are not common for both address families + if (ipv4 || Environment.OSVersion.Version.Major > 12) { sb.Append(" -W "); } @@ -135,7 +136,8 @@ public static string ConstructCommandLine(int packetSize, int timeout, string ad if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsMacOS()) { // OSX and FreeBSD use -h to set hop limit for IPv6 and -m ttl for IPv4 - if (ipv4) + // Syntax changed in FreeBSD 13.0 and options are not common for both address families + if (ipv4 || (OperatingSystem.IsFreeBSD() && Environment.OSVersion.Version.Major > 12)) { sb.Append(" -m "); } diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs index a0b8af82113da7..dc902e555081bc 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanAndroid.Derive.cs @@ -23,10 +23,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); @@ -45,10 +43,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs index 90d2e4f01145c0..ad955d55ce8eed 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs @@ -76,10 +76,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) { @@ -99,10 +97,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey)) { diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs index 11638ed44be8a7..9d32a702bf07fa 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs @@ -24,10 +24,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); @@ -46,10 +44,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs index 214bc96f8b0e95..df1a7fae8e39a0 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanSecurityTransforms.cs @@ -121,10 +121,8 @@ public override byte[] DeriveKeyFromHash( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); @@ -143,10 +141,8 @@ public override byte[] DeriveKeyFromHmac( byte[]? secretPrepend, byte[]? secretAppend) { - if (otherPartyPublicKey == null) - throw new ArgumentNullException(nameof(otherPartyPublicKey)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(otherPartyPublicKey); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ThrowIfDisposed(); diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs index c78de735480356..86d98f5014f6cc 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAAndroid.cs @@ -678,12 +678,9 @@ protected override bool TryHashData(ReadOnlySpan data, Span destinat public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (!TrySignHash( hash, @@ -708,14 +705,8 @@ public override bool TrySignHash( RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); bool ret = TrySignHash( hash, @@ -817,14 +808,8 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (padding != RSASignaturePadding.Pkcs1 && padding != RSASignaturePadding.Pss) { throw PaddingModeNotSupported(); @@ -894,9 +879,6 @@ public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan sign private static Exception PaddingModeNotSupported() => new CryptographicException(SR.Cryptography_InvalidPaddingMode); - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs b/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs index 82709832cd88de..27fc35493783f6 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSACng.SignVerify.cs @@ -52,14 +52,9 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS } string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + + ArgumentNullException.ThrowIfNull(padding); if (hash.Length != GetHashSizeInBytes(hashAlgorithm)) { @@ -99,14 +94,8 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS public override unsafe bool TrySignHash(ReadOnlySpan hash, Span destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { @@ -159,14 +148,8 @@ public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName public override unsafe bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { string? hashAlgorithmName = hashAlgorithm.Name; - if (string.IsNullOrEmpty(hashAlgorithmName)) - { - throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm)); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle()) { diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs index 149e240893039b..def40a8d5685a9 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs @@ -750,12 +750,9 @@ protected override bool TryHashData(ReadOnlySpan data, Span destinat public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); if (!TrySignHash( hash, @@ -780,14 +777,8 @@ public override bool TrySignHash( RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); bool ret = TrySignHash( hash, @@ -860,11 +851,7 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); ValidatePadding(padding); IntPtr digestAlgorithm = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithm.Name); @@ -951,9 +938,6 @@ private static void ValidatePadding(RSASignaturePadding padding) private static Exception PaddingModeNotSupported() => new CryptographicException(SR.Cryptography_InvalidPaddingMode); - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } #if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS } diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs index 7bce2648d443a9..190c7e4d53c9e2 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSASecurityTransforms.cs @@ -386,12 +386,9 @@ private bool TryDecrypt( public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (hash == null) - throw new ArgumentNullException(nameof(hash)); - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - throw HashAlgorithmNameNullOrEmpty(); - if (padding == null) - throw new ArgumentNullException(nameof(padding)); + ArgumentNullException.ThrowIfNull(hash); + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -443,14 +440,8 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS public override bool TrySignHash(ReadOnlySpan hash, Span destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, out int bytesWritten) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -550,14 +541,8 @@ public override bool VerifyHash( public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { - if (string.IsNullOrEmpty(hashAlgorithm.Name)) - { - throw HashAlgorithmNameNullOrEmpty(); - } - if (padding == null) - { - throw new ArgumentNullException(nameof(padding)); - } + ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + ArgumentNullException.ThrowIfNull(padding); ThrowIfDisposed(); @@ -795,8 +780,5 @@ private static bool HasConsistentPrivateKey(in RSAParameters parameters) return true; } } - - private static Exception HashAlgorithmNameNullOrEmpty() => - new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, "hashAlgorithm"); } } diff --git a/src/libraries/Common/tests/Resources/Strings.resx b/src/libraries/Common/tests/Resources/Strings.resx index 1673683936a79a..7d48d2b4fe49d5 100644 --- a/src/libraries/Common/tests/Resources/Strings.resx +++ b/src/libraries/Common/tests/Resources/Strings.resx @@ -156,9 +156,6 @@ IO_PathTooLong_Path {0} - - Arg_InvalidSearchPattern {0} - The argv[0] argument cannot include a double quote. @@ -168,9 +165,6 @@ HPACK integer exceeds limits or has an overlong encoding. - - Failed to HPACK encode the headers. - Huffman-coded literal string failed to decode. @@ -201,9 +195,6 @@ Connection aborted by peer ({0}). - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. diff --git a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs index 7dc9519665c588..792e5387fd04aa 100644 --- a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs +++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs @@ -711,7 +711,6 @@ public abstract class StandaloneStreamConformanceTests : StreamConformanceTests } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ArgumentValidation_ThrowsExpectedException() { await foreach (Stream? stream in GetStreamsForValidation()) @@ -725,7 +724,6 @@ public virtual async Task ArgumentValidation_ThrowsExpectedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Disposed_ThrowsObjectDisposedException() { await foreach (Stream? stream in GetStreamsForValidation()) @@ -815,7 +813,6 @@ public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Write_DataReadFromDesiredOffset(ReadWriteMode mode) { using Stream? stream = await CreateReadWriteStream(); @@ -1599,7 +1596,6 @@ protected static bool Bidirectional(StreamPair streams) => streams.Stream2.CanRead && streams.Stream2.CanWrite; [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ArgumentValidation_ThrowsExpectedException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1611,7 +1607,6 @@ public virtual async Task ArgumentValidation_ThrowsExpectedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Disposed_ThrowsObjectDisposedException() { StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1624,7 +1619,6 @@ public virtual async Task Disposed_ThrowsObjectDisposedException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWriteAsync_PrecanceledOperations_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1636,7 +1630,6 @@ public virtual async Task ReadWriteAsync_PrecanceledOperations_ThrowsCancellatio } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_CancelPendingTask_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1646,7 +1639,6 @@ public virtual async Task ReadAsync_CancelPendingTask_ThrowsCancellationExceptio } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_CancelPendingValueTask_ThrowsCancellationException() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1656,7 +1648,6 @@ public virtual async Task ReadAsync_CancelPendingValueTask_ThrowsCancellationExc } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWriteByte_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1729,7 +1720,6 @@ public virtual async Task ReadWrite_Success_Large(ReadWriteMode mode, int writeS [Theory] [MemberData(nameof(ReadWrite_Success_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_Success(ReadWriteMode mode, int writeSize, bool startWithFlush) { foreach (CancellationToken nonCanceledToken in new[] { CancellationToken.None, new CancellationTokenSource().Token }) @@ -1786,7 +1776,6 @@ public virtual async Task ReadWrite_Success(ReadWriteMode mode, int writeSize, b [Theory] [MemberData(nameof(ReadWrite_Modes))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_MessagesSmallerThanReadBuffer_Success(ReadWriteMode mode) { if (!FlushGuaranteesAllDataWritten) @@ -1835,7 +1824,6 @@ public virtual async Task ReadWrite_MessagesSmallerThanReadBuffer_Success(ReadWr [Theory] [MemberData(nameof(AllReadWriteModesAndValue), false)] [MemberData(nameof(AllReadWriteModesAndValue), true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Read_Eof_Returns0(ReadWriteMode mode, bool dataAvailableFirst) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1874,7 +1862,6 @@ public virtual async Task Read_Eof_Returns0(ReadWriteMode mode, bool dataAvailab [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -1904,7 +1891,6 @@ public virtual async Task Read_DataStoredAtDesiredOffset(ReadWriteMode mode) [InlineData(ReadWriteMode.SyncArray)] [InlineData(ReadWriteMode.AsyncArray)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Write_DataReadFromDesiredOffset(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2003,7 +1989,6 @@ public static IEnumerable ReadAsync_ContinuesOnCurrentContextIfDesired [Theory] [MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx @@ -2086,7 +2071,6 @@ public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDe [Theory] [MemberData(nameof(ReadAsync_ContinuesOnCurrentContextIfDesired_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadAsync_ContinuesOnCurrentTaskSchedulerIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx @@ -2176,7 +2160,6 @@ await Task.Factory.StartNew(() => [InlineData(ReadWriteMode.AsyncMemory)] [InlineData(ReadWriteMode.SyncAPM)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ZeroByteRead_BlocksUntilDataAvailableOrNops(ReadWriteMode mode) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2243,7 +2226,6 @@ public virtual async Task ZeroByteRead_BlocksUntilDataAvailableOrNops(ReadWriteM [InlineData(ReadWriteMode.AsyncMemory)] [InlineData(ReadWriteMode.SyncAPM)] [InlineData(ReadWriteMode.AsyncAPM)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ZeroByteWrite_OtherDataReceivedSuccessfully(ReadWriteMode mode) { byte[][] buffers = new[] { Array.Empty(), Encoding.UTF8.GetBytes("hello"), Array.Empty(), Encoding.UTF8.GetBytes("world") }; @@ -2297,7 +2279,6 @@ public virtual async Task ZeroByteWrite_OtherDataReceivedSuccessfully(ReadWriteM [Theory] [InlineData(false)] [InlineData(true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadWrite_CustomMemoryManager_Success(bool useAsync) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2418,7 +2399,6 @@ public virtual async Task CopyToAsync_AllDataCopied_Large(bool useAsync) => [Theory] [MemberData(nameof(CopyToAsync_AllDataCopied_MemberData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task CopyToAsync_AllDataCopied(int byteCount, bool useAsync) { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2456,7 +2436,6 @@ await Task.WhenAll(Enumerable.Range(0, 20).Select(_ => Task.Run(async () => } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Timeout_Roundtrips() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2491,7 +2470,6 @@ public virtual async Task Timeout_Roundtrips() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task ReadTimeout_Expires_Throws() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2626,7 +2604,6 @@ public virtual async Task ReadAsync_DuringReadAsync_ThrowsIfUnsupported() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Flush_ValidOnWriteableStreamWithNoData_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2641,7 +2618,6 @@ public virtual async Task Flush_ValidOnWriteableStreamWithNoData_Success() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Flush_ValidOnReadableStream_Success() { using StreamPair streams = await CreateConnectedStreamsAsync(); @@ -2659,7 +2635,6 @@ public virtual async Task Flush_ValidOnReadableStream_Success() [InlineData(0)] [InlineData(1)] [InlineData(2)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51371", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public virtual async Task Dispose_ClosesStream(int disposeMode) { if (!CansReturnFalseAfterDispose) diff --git a/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs b/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs new file mode 100644 index 00000000000000..a37fb304bb9a15 --- /dev/null +++ b/src/libraries/Common/tests/System/Net/ManualChunkingStream.cs @@ -0,0 +1,103 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Test.Common +{ + // Wrapper stream to manually chop writes. This can be useful for simulating partial network transfers + public class ManualChunkingStream : Stream + { + private readonly Stream _innerStream; + private readonly StreamBuffer _writeBuffer = new StreamBuffer(); + private bool _chunkWrite; + + public ManualChunkingStream(Stream stream, bool chunkWrite) + { + _innerStream = stream; + _chunkWrite = chunkWrite; + } + + public int PendingWriteLength => _writeBuffer.ReadBytesAvailable; + + public async ValueTask CommitWriteAsync(int length) + { + Debug.Assert(length <= PendingWriteLength && length > 0, "length <= PendingWriteLength && length > 0"); + byte[] buffer = ArrayPool.Shared.Rent(length); + + int read = await _writeBuffer.ReadAsync(buffer.AsMemory(0, length)); + Debug.Assert(read == length, "read == length"); + await _innerStream.WriteAsync(buffer, 0, read); + await _innerStream.FlushAsync(); + + ArrayPool.Shared.Return(buffer); + } + + public void SetWriteChunking(bool chunking) + { + _chunkWrite = chunking; + if (!_chunkWrite && PendingWriteLength > 0) + { + // flush pending writes + byte[] buffer = ArrayPool.Shared.Rent(PendingWriteLength); + + int read = _writeBuffer.Read(buffer.AsSpan(0, PendingWriteLength)); + Debug.Assert(PendingWriteLength == 0, "PendingWriteLength == 0"); + _innerStream.Write(buffer, 0, read); + _innerStream.Flush(); + + ArrayPool.Shared.Return(buffer); + } + } + + public override bool CanSeek => _innerStream.CanSeek; + + public override bool CanRead => _innerStream.CanRead; + + public override bool CanTimeout => _innerStream.CanTimeout; + + public override bool CanWrite => _innerStream.CanWrite; + + public override long Position + { + get => _innerStream.Position; + set => _innerStream.Position = value; + } + + public override void SetLength(long value) => _innerStream.SetLength(value); + + public override long Length => _innerStream.Length; + + public override void Flush() => _innerStream.Flush(); + + public override Task FlushAsync(CancellationToken cancellationToken) => _innerStream.FlushAsync(cancellationToken); + + public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin); + + public override int Read(byte[] buffer, int offset, int count) => Read(new Span(buffer, offset, count)); + + public override int Read(Span buffer) => _innerStream.Read(buffer); + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => ReadAsync(new Memory(buffer, offset, count)).AsTask(); + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) => _innerStream.ReadAsync(buffer, cancellationToken); + + public override void Write(byte[] buffer, int offset, int count) => Write(new ReadOnlySpan(buffer, offset, count)); + + public override void Write(ReadOnlySpan buffer) + { + if (_chunkWrite) + _writeBuffer.Write(buffer); + else + _innerStream.Write(buffer); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => WriteAsync(new ReadOnlyMemory(buffer, offset, count)).AsTask(); + + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => _chunkWrite ? _writeBuffer.WriteAsync(buffer, cancellationToken) : _innerStream.WriteAsync(buffer, cancellationToken); + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs index b311193948a3a7..e214765dd47139 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs @@ -337,13 +337,21 @@ public void EmptyHashAlgorithm() foreach (DSASignatureFormat format in Enum.GetValues(typeof(DSASignatureFormat))) { - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", () => SignData(key, empty, default, format)); - AssertExtensions.Throws( + AssertExtensions.Throws( "hashAlgorithm", () => VerifyData(key, empty, empty, default, format)); + + AssertExtensions.Throws( + "hashAlgorithm", + () => SignData(key, empty, new HashAlgorithmName(""), format)); + + AssertExtensions.Throws( + "hashAlgorithm", + () => VerifyData(key, empty, empty, new HashAlgorithmName(""), format)); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs index af64f2fc031eb1..ff6f0c99d193ce 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDhKeyFileTests : ECKeyFileTests { protected override ECDiffieHellman CreateKey() => ECDiffieHellmanFactory.Create(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs index 35bed6e7247855..51bb3d34182aa4 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDsa.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDsaKeyFileTests : ECKeyFileTests { protected override ECDsa CreateKey() => ECDsaFactory.Create(); diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs index d747aec14e5517..187c76ad351a9f 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs @@ -40,9 +40,9 @@ public void SignData_InvalidArguments_Throws(ECDsa ecdsa) AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[0], 0, -1, default(HashAlgorithmName))); AssertExtensions.Throws("count", () => ecdsa.SignData(new byte[0], 0, 1, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[0], 0, 0, default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new byte[10], 0, 10, new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.SignData(new byte[0], new HashAlgorithmName(Guid.NewGuid().ToString("N")))); @@ -64,8 +64,8 @@ public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[0], 0, -1, null, default(HashAlgorithmName))); AssertExtensions.Throws("count", () => ecdsa.VerifyData(new byte[0], 0, 1, null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], new byte[0], default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], 0, 0, new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[0], 0, 0, new byte[0], default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[10], new byte[0], new HashAlgorithmName(""))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new byte[10], 0, 10, new byte[0], new HashAlgorithmName(""))); @@ -110,7 +110,8 @@ protected override byte[] SignData(ECDsa ecdsa, byte[] data, int offset, int cou public void SignData_InvalidArguments_Throws(ECDsa ecdsa) { AssertExtensions.Throws("data", () => ecdsa.SignData((Stream)null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.SignData(new MemoryStream(), new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.SignData(new MemoryStream(), new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } @@ -119,7 +120,7 @@ public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) { AssertExtensions.Throws("data", () => ecdsa.VerifyData((Stream)null, null, default(HashAlgorithmName))); AssertExtensions.Throws("signature", () => ecdsa.VerifyData(new MemoryStream(), null, default(HashAlgorithmName))); - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], default(HashAlgorithmName))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], default(HashAlgorithmName))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(new MemoryStream(), new byte[0], new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.VerifyData(new MemoryStream(), new byte[0], new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs index eb12b87acba738..0f6a191e31dd0a 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs @@ -28,7 +28,7 @@ protected override void UseAfterDispose(ECDsa ecdsa, byte[] data, byte[] sig) [Theory, MemberData(nameof(RealImplementations))] public void SignData_InvalidArguments_Throws(ECDsa ecdsa) { - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(null), out int bytesWritten)); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(null), out int bytesWritten)); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(""), out int bytesWritten)); Assert.ThrowsAny(() => ecdsa.TrySignData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(Guid.NewGuid().ToString("N")), out int bytesWritten)); } @@ -36,7 +36,7 @@ public void SignData_InvalidArguments_Throws(ECDsa ecdsa) [Theory, MemberData(nameof(RealImplementations))] public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa) { - AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(null))); + AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(null))); AssertExtensions.Throws("hashAlgorithm", () => ecdsa.VerifyData(ReadOnlySpan.Empty, ReadOnlySpan.Empty, new HashAlgorithmName(""))); Assert.ThrowsAny(() => ecdsa.VerifyData(ReadOnlySpan.Empty, Span.Empty, new HashAlgorithmName(Guid.NewGuid().ToString("N")))); } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs index 4a7dace2695205..e78cea374bac53 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs @@ -48,14 +48,18 @@ public abstract class SignVerify protected abstract bool VerifyData(RSA rsa, byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding); protected abstract bool VerifyHash(RSA rsa, byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding); - [Theory] - [InlineData(null)] - [InlineData("")] - public void InvalidHashAlgorithmName_Throws(string name) + [Fact] + public void InvalidHashAlgorithmName_Throws() { using (RSA rsa = RSAFactory.Create()) { - var invalidName = new HashAlgorithmName(name); + var invalidName = new HashAlgorithmName(null); + AssertExtensions.Throws("hashAlgorithm", () => SignData(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => SignHash(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => VerifyData(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + AssertExtensions.Throws("hashAlgorithm", () => VerifyHash(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); + + invalidName = new HashAlgorithmName(""); AssertExtensions.Throws("hashAlgorithm", () => SignData(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hashAlgorithm", () => SignHash(rsa, new byte[1], invalidName, RSASignaturePadding.Pkcs1)); AssertExtensions.Throws("hashAlgorithm", () => VerifyData(rsa, new byte[1], new byte[1], invalidName, RSASignaturePadding.Pkcs1)); diff --git a/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs b/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs index bc53138d8be13a..8f14f24f97f933 100644 --- a/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs +++ b/src/libraries/Common/tests/TestUtilities/System/IO/FileCleanupTestBase.cs @@ -147,6 +147,11 @@ protected static string GetNamedPipeServerStreamName() return Guid.NewGuid().ToString("N"); } + if (!PlatformDetection.IsCaseSensitiveOS) + { + return $"/tmp/{Guid.NewGuid().ToString("N")}"; + } + const int MinUdsPathLength = 104; // required min is 92, but every platform we currently target is at least 104 const int MinAvailableForSufficientRandomness = 5; // we want enough randomness in the name to avoid conflicts between concurrent tests string prefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_"); diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 1cbd9c19f69155..db1af4f4fba6d9 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -60,8 +60,14 @@ public static partial class PlatformDetection public static bool IsNotWindows => !IsWindows; public static bool IsCaseInsensitiveOS => IsWindows || IsOSX || IsMacCatalyst; - public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; +#if NETCOREAPP + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS && !RuntimeInformation.RuntimeIdentifier.StartsWith("iossimulator") + && !RuntimeInformation.RuntimeIdentifier.StartsWith("tvossimulator"); +#else + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; +#endif + public static bool IsThreadingSupported => !IsBrowser; public static bool IsBinaryFormatterSupported => IsNotMobile && !IsNativeAot; public static bool IsSymLinkSupported => !IsiOS && !IstvOS; @@ -176,6 +182,7 @@ public static bool IsMetadataTokenSupported // Changed to `true` when linking public static bool IsBuiltWithAggressiveTrimming => false; + public static bool IsNotBuiltWithAggressiveTrimming => !IsBuiltWithAggressiveTrimming; // Windows - Schannel supports alpn from win8.1/2012 R2 and higher. // Linux - OpenSsl supports alpn from openssl 1.0.2 and higher. diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 49c6d278ee1d2f..a5cc7f68250084 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -87,8 +87,6 @@ - - false true false diff --git a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx index bf2f61e56bdc21..0e3913b9ba776f 100644 --- a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Resources/Strings.resx @@ -272,9 +272,6 @@ Recursive type definition is not supported. - - Bit position in AllKeywords ({0}) must equal the command argument named "EtwSessionKeyword" ({1}). - An event with stop suffix must follow a corresponding event with a start suffix. diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx index 9f74883c8e8ec6..f6d5587b1d7231 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx @@ -121,10 +121,6 @@ Multiple constructors accepting all given argument types have been found in type '{0}'. There should only be one applicable constructor. {0} = service type - - Unable to locate implementation '{0}' for service '{1}'. - {0} = implementation type, {1} = service type - Unable to resolve service for type '{0}' while attempting to activate '{1}'. {0} = service which cannot be resolved, {1} = service being activated diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs index 8f812ae45e6a86..737c23d7f4445a 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { @@ -33,10 +34,14 @@ public ServiceCacheKey(Type? type, int slot) Slot = slot; } - public bool Equals(ServiceCacheKey other) - { - return Type == other.Type && Slot == other.Slot; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(ServiceCacheKey other) => + Type == other.Type && Slot == other.Slot; + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is ServiceCacheKey other && Equals(other); public override int GetHashCode() { diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs index 55902bd8a3a9bd..5c8159051c66c5 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/ConsoleLifetimeExitTests.cs @@ -105,11 +105,7 @@ await Host.CreateDefaultBuilder() services.AddHostedService(); }) .RunConsoleAsync(); - }); - - remoteHandle.Process.WaitForExit(); - - Assert.Equal(124, remoteHandle.Process.ExitCode); + }, new RemoteInvokeOptions() { ExpectedExitCode = 124 }); } private class EnsureEnvironmentExitCodeWorker : BackgroundService @@ -130,6 +126,9 @@ await Task.Run(() => [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] public void EnsureEnvironmentExitDoesntHang() { + // SIGTERM is only handled on net6.0+, so the workaround to "clobber" the exit code is still in place on .NET Framework + int expectedExitCode = PlatformDetection.IsNetFramework ? 0 : 125; + using var remoteHandle = RemoteExecutor.Invoke(async () => { await Host.CreateDefaultBuilder() @@ -139,13 +138,7 @@ await Host.CreateDefaultBuilder() services.AddHostedService(); }) .RunConsoleAsync(); - }, new RemoteInvokeOptions() { TimeOut = 30_000 }); // give a 30 second time out, so if this does hang, it doesn't hang for the full timeout - - Assert.True(remoteHandle.Process.WaitForExit(30_000), "The hosted process should have exited within 30 seconds"); - - // SIGTERM is only handled on net6.0+, so the workaround to "clobber" the exit code is still in place on NetFramework - int expectedExitCode = PlatformDetection.IsNetFramework ? 0 : 125; - Assert.Equal(expectedExitCode, remoteHandle.Process.ExitCode); + }, new RemoteInvokeOptions() { TimeOut = 30_000, ExpectedExitCode = expectedExitCode }); // give a 30 second time out, so if this does hang, it doesn't hang for the full timeout } private class EnsureEnvironmentExitDoesntHangWorker : BackgroundService diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln index bf9829d652330d..6f3c58066d303b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln @@ -1,9 +1,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32111.311 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{79CE8C7E-A4AF-413C-A54D-86F17073559C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{1491B9C9-955D-4DB0-B1D5-70137A78EAAE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn3.11", "gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{1491B9C9-955D-4DB0-B1D5-70137A78EAAE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{A5439E79-96D6-4F02-8DD0-23DFF979851D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.0", "gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{A5439E79-96D6-4F02-8DD0-23DFF979851D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{7F536552-0E2A-4642-B7CF-863727C2F9CD}" EndProject @@ -23,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{548DF5F7-790 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{7631380A-FB73-4241-9987-0891A21E9769}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{03F31CEE-D63E-4E7F-949F-139B33DC3385}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,14 +76,14 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {79CE8C7E-A4AF-413C-A54D-86F17073559C} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE} = {03F31CEE-D63E-4E7F-949F-139B33DC3385} + {A5439E79-96D6-4F02-8DD0-23DFF979851D} = {03F31CEE-D63E-4E7F-949F-139B33DC3385} + {7F536552-0E2A-4642-B7CF-863727C2F9CD} = {7631380A-FB73-4241-9987-0891A21E9769} + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} {C333EC5A-F386-4A01-AE20-12D499551304} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} - {1491B9C9-955D-4DB0-B1D5-70137A78EAAE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {A5439E79-96D6-4F02-8DD0-23DFF979851D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {F8CF3192-B902-4631-972A-C405FDECC48D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {7F536552-0E2A-4642-B7CF-863727C2F9CD} = {7631380A-FB73-4241-9987-0891A21E9769} {DAA1349E-960E-49EB-81F3-FF4F99D8A325} = {7631380A-FB73-4241-9987-0891A21E9769} + {F8CF3192-B902-4631-972A-C405FDECC48D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {450DA749-CBDC-4BDC-950F-8A491CF59D49} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index ad8a524b0fc8cc..2f624f6cec974e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -339,17 +339,21 @@ public IReadOnlyList GetLogClasses(IEnumerable GetLogClasses(IEnumerable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs index 972fb1ec0488ce..1cb4775b275b97 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.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; using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.Logging @@ -8,7 +9,7 @@ namespace Microsoft.Extensions.Logging /// /// Identifies a logging event. The primary identifier is the "Id" property, with the "Name" property providing a short description of this type of event. /// - public readonly struct EventId + public readonly struct EventId : IEquatable { /// /// Implicitly creates an EventId from the given . diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 8ca2bab854730e..eb95f66e4f5a36 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -18,6 +18,7 @@ Microsoft.Extensions.Logging.LogLevel Microsoft.Extensions.Logging.Logger<T> Microsoft.Extensions.Logging.LoggerMessage Microsoft.Extensions.Logging.Abstractions.NullLogger + DisableMicrosoftExtensionsLoggingSourceGenerator diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index d55bf4a8028d52..eda529fade4ef1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -8,7 +8,6 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] public class LoggerMessageGeneratedCodeTests { [Fact] @@ -341,6 +340,20 @@ public void LevelTests() Assert.Equal(LogLevel.Warning, logger.LastLogLevel); Assert.Equal(1, logger.CallCount); Assert.Equal(11, logger.LastEventId.Id); + + logger.Reset(); + LevelTestExtensions.M12(logger, LogLevel.Trace); + Assert.Null(logger.LastException); + Assert.Equal("M12 Trace", logger.LastFormattedString); + Assert.Equal(LogLevel.Trace, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + LevelTestExtensions.M13(logger, LogLevel.Trace); + Assert.Null(logger.LastException); + Assert.Equal("M13 Microsoft.Extensions.Logging.Generators.Tests.MockLogger", logger.LastFormattedString); + Assert.Equal(LogLevel.Trace, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); } [Fact] @@ -361,6 +374,13 @@ public void ExceptionTests() Assert.Equal("M1 System.ArgumentException: Bar", logger.LastFormattedString); Assert.Equal(LogLevel.Debug, logger.LastLogLevel); Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ExceptionTestExtensions.M2(logger, "One", new ArgumentException("Foo")); + Assert.Equal("Foo", logger.LastException!.Message); + Assert.Equal("M2 One: System.ArgumentException: Foo", logger.LastFormattedString); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Equal(1, logger.CallCount); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs index cc0b8ba1adfe36..8ebb2ab8c0aa21 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs @@ -10,7 +10,8 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", typeof(PlatformDetection), nameof(PlatformDetection.IsWindows), nameof(PlatformDetection.IsMonoRuntime))] public class LoggerMessageGeneratorEmitterTests { [Fact] @@ -27,7 +28,7 @@ public async Task TestEmitter() new[] { typeof(ILogger).Assembly, typeof(LoggerMessageAttribute).Assembly }, new[] { testSourceCode }).ConfigureAwait(false); - Assert.Empty(d); + Assert.True(src.Contains("WithDiagnostics") ? !d.IsEmpty : d.IsEmpty); Assert.Single(r); } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index 3c3ce17ef0b181..4697e5603cd0f5 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] public class LoggerMessageGeneratorParserTests { [Fact] @@ -204,11 +204,15 @@ partial class C { [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {ex} {ex2}"")] static partial void M1(ILogger logger, System.Exception ex, System.Exception ex2); + + [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = ""M2 {arg1}: {ex}"")] + static partial void M2(ILogger logger, string arg1, System.Exception ex); } "); - Assert.Single(diagnostics); + Assert.Equal(2, diagnostics.Count); Assert.Equal(DiagnosticDescriptors.ShouldntMentionExceptionInMessage.Id, diagnostics[0].Id); + Assert.Equal(DiagnosticDescriptors.ShouldntMentionExceptionInMessage.Id, diagnostics[1].Id); } [Fact] @@ -234,11 +238,15 @@ partial class C { [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1 {logger}"")] static partial void M1(ILogger logger); + + [LoggerMessage(EventId = 2, Message = ""M2 {logger}"")] + static partial void M2(ILogger logger, LogLevel level); } "); - Assert.Single(diagnostics); + Assert.Equal(2, diagnostics.Count); Assert.Equal(DiagnosticDescriptors.ShouldntMentionLoggerInMessage.Id, diagnostics[0].Id); + Assert.Equal(DiagnosticDescriptors.ShouldntMentionLoggerInMessage.Id, diagnostics[1].Id); } [Fact] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs new file mode 100644 index 00000000000000..8a2299cf864cd4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ExceptionTestExtensions.WithDiagnostics.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class ExceptionTestExtensions + { +#pragma warning disable SYSLIB1013 + [LoggerMessage(EventId = 2, Level = LogLevel.Debug, Message = "M2 {arg1}: {ex}")] + public static partial void M2(ILogger logger, string arg1, Exception ex); +#pragma warning disable SYSLIB1013 + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.cs new file mode 100644 index 00000000000000..aabcb67ae4bd07 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/LevelTestExtensions.WithDiagnostics.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. + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class LevelTestExtensions + { +#pragma warning disable SYSLIB1002 + [LoggerMessage(EventId = 12, Message = "M12 {level}")] + public static partial void M12(ILogger logger, LogLevel level); +#pragma warning restore SYSLIB1002 + +#pragma warning disable SYSLIB1018 + [LoggerMessage(EventId = 13, Message = "M13 {logger}")] + public static partial void M13(ILogger logger, LogLevel level); +#pragma warning restore SYSLIB1018 + } +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 25a77800588447..fc0fb68ac6e7e4 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -3760,6 +3760,14 @@ "any", "base" ], + "linux-armv6": [ + "linux-armv6", + "linux", + "unix-armv6", + "unix", + "any", + "base" + ], "linux-mips64": [ "linux-mips64", "linux", @@ -8248,6 +8256,12 @@ "any", "base" ], + "unix-armv6": [ + "unix-armv6", + "unix", + "any", + "base" + ], "unix-mips64": [ "unix-mips64", "unix", @@ -8902,4 +8916,4 @@ "any", "base" ] -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index f8c398707e0bb6..0b71f880e893d5 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -1504,6 +1504,12 @@ "unix-loongarch64" ] }, + "linux-armv6": { + "#import": [ + "linux", + "unix-armv6" + ] + }, "linux-mips64": { "#import": [ "linux", @@ -3444,6 +3450,11 @@ "unix" ] }, + "unix-armv6": { + "#import": [ + "unix" + ] + }, "unix-mips64": { "#import": [ "unix" @@ -3788,4 +3799,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index d1613c4345b314..da7960a1f57856 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -3,11 +3,11 @@ any - x64;x86;arm;armel;arm64;loongarch64;mips64;s390x + x64;x86;arm;armv6;armel;arm64;loongarch64;mips64;s390x unix - x64;x86;arm;armel;arm64;loongarch64;mips64;s390x + x64;x86;arm;armv6;armel;arm64;loongarch64;mips64;s390x linux diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb index 77219110807c4b..d97358dcd5a5b3 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb @@ -375,7 +375,7 @@ Namespace Microsoft.VisualBasic.FileIO Public Function PeekChars(ByVal numberOfChars As Integer) As String If numberOfChars <= 0 Then - Throw GetArgumentExceptionWithArgName("numberOfChars", SR.TextFieldParser_NumberOfCharsMustBePositive, "numberOfChars") + Throw GetArgumentExceptionWithArgName("numberOfChars", SR.TextFieldParser_NumberOfCharsMustBePositive) End If If m_Reader Is Nothing Or m_Buffer Is Nothing Then @@ -1151,7 +1151,7 @@ Namespace Microsoft.VisualBasic.FileIO Dim Bound As Integer = Widths.Length - 1 For i As Integer = 0 To Bound - 1 If Widths(i) < 1 Then - Throw GetArgumentExceptionWithArgName("FieldWidths", SR.TextFieldParser_FieldWidthsMustPositive, "FieldWidths") + Throw GetArgumentExceptionWithArgName("FieldWidths", SR.TextFieldParser_FieldWidthsMustPositive) End If Next End Sub @@ -1163,11 +1163,11 @@ Namespace Microsoft.VisualBasic.FileIO ''' Private Sub ValidateAndEscapeDelimiters() If m_Delimiters Is Nothing Then - Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing, "Delimiters") + Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing) End If If m_Delimiters.Length = 0 Then - Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing, "Delimiters") + Throw GetArgumentExceptionWithArgName("Delimiters", SR.TextFieldParser_DelimitersNothing) End If Dim Length As Integer = m_Delimiters.Length diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs b/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs index d9f981b2425982..a2a8e28e8d17b7 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/FileSystemTests.cs @@ -620,8 +620,7 @@ static void remoteWrite(string fileName, string text) } }, fileName, - text, - new RemoteInvokeOptions() { ExpectedExitCode = 0 }).Dispose(); + text).Dispose(); } } diff --git a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs index 56cbc26afe977c..49eeecff31ab0c 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/Microsoft/Win32/Registry.cs @@ -64,7 +64,7 @@ private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subK return baseKey; } - throw new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(keyName)), nameof(keyName)); + throw new ArgumentException(SR.Arg_RegInvalidKeyName, nameof(keyName)); } public static object? GetValue(string keyName, string? valueName, object? defaultValue) diff --git a/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs index f5ff293848ffa7..f16e03965ed186 100644 --- a/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs +++ b/src/libraries/Microsoft.Win32.Registry/src/System/Security/AccessControl/RegistrySecurity.Windows.cs @@ -19,7 +19,7 @@ public sealed partial class RegistrySecurity : NativeObjectSecurity break; case Interop.Errors.ERROR_INVALID_NAME: - exception = new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(name))); + exception = new ArgumentException(SR.Arg_RegInvalidKeyName, nameof(name)); break; case Interop.Errors.ERROR_INVALID_HANDLE: diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj index 007fd6f60fa58b..0ccd62c3f8c3a0 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/src/Microsoft.Win32.SystemEvents.csproj @@ -35,6 +35,8 @@ Microsoft.Win32.SystemEvents Link="Common\Interop\Windows\User32\Interop.DispatchMessage.cs" /> + Link="Common\Interop\Windows\User32\Interop.MSG.cs" /> - + ? s_threadCallbackList; // list of Delegates private static volatile int s_threadCallbackMessage; - private static volatile ManualResetEvent? s_eventThreadTerminated; // Per-instance data that is isolated to the window thread. private volatile IntPtr _windowHandle; @@ -1071,7 +1070,7 @@ private static void RemoveEventHandler(object key, Delegate? value) private static void Shutdown() { - if (s_systemEvents != null && s_systemEvents._windowHandle != IntPtr.Zero) + if (s_systemEvents != null) { lock (s_procLockObject) { @@ -1080,17 +1079,22 @@ private static void Shutdown() // If we are using system events from another thread, request that it terminate if (s_windowThread != null) { - s_eventThreadTerminated = new ManualResetEvent(false); - #if DEBUG int pid; int thread = Interop.User32.GetWindowThreadProcessId(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), out pid); Debug.Assert(thread != Interop.Kernel32.GetCurrentThreadId(), "Don't call Shutdown on the system events thread"); #endif - Interop.User32.PostMessageW(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), Interop.User32.WM_QUIT, IntPtr.Zero, IntPtr.Zero); - s_eventThreadTerminated.WaitOne(); - s_windowThread.Join(); // avoids an AppDomainUnloaded exception on our background thread. + // The handle could be valid, Zero or invalid depending on the state of the thread + // that is processing the messages. We optimistically expect it to be valid to + // notify the thread to shutdown. The Zero or invalid values should be present + // only when the thread is already shutting down due to external factors. + if (s_systemEvents._windowHandle != IntPtr.Zero) + { + Interop.User32.PostMessageW(new HandleRef(s_systemEvents, s_systemEvents._windowHandle), Interop.User32.WM_QUIT, IntPtr.Zero, IntPtr.Zero); + } + + s_windowThread.Join(); } else { @@ -1218,6 +1222,11 @@ private IntPtr WindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) OnTimerElapsed(wParam); break; + case Interop.User32.WM_DESTROY: + Interop.User32.PostQuitMessage(0); + _windowHandle = IntPtr.Zero; + break; + default: // If we received a thread execute message, then execute it. if (msg == s_threadCallbackMessage && msg != 0) @@ -1248,33 +1257,10 @@ private void WindowThreadProc() { Interop.User32.MSG msg = default(Interop.User32.MSG); - bool keepRunning = true; - - // Blocking on a GetMessage() call prevents the EE from being able to unwind - // this thread properly (e.g. during AppDomainUnload). So, we use PeekMessage() - // and sleep so we always block in managed code instead. - while (keepRunning) + while (Interop.User32.GetMessageW(ref msg, _windowHandle, 0, 0) > 0) { - int ret = Interop.User32.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, Interop.User32.QS_ALLINPUT, Interop.User32.MWMO_INPUTAVAILABLE); - - if (ret == Interop.User32.WAIT_TIMEOUT) - { - Thread.Sleep(1); - } - else - { - while (Interop.User32.PeekMessageW(ref msg, IntPtr.Zero, 0, 0, Interop.User32.PM_REMOVE)) - { - if (msg.message == Interop.User32.WM_QUIT) - { - keepRunning = false; - break; - } - - Interop.User32.TranslateMessage(ref msg); - Interop.User32.DispatchMessageW(ref msg); - } - } + Interop.User32.TranslateMessage(ref msg); + Interop.User32.DispatchMessageW(ref msg); } } @@ -1293,10 +1279,6 @@ private void WindowThreadProc() } Dispose(); - if (s_eventThreadTerminated != null) - { - s_eventThreadTerminated.Set(); - } } // A class that helps fire events on the right thread. diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx b/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx index 96464aac30db8c..bb14b9a2d94d6c 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Win32.SystemEvents/src/Resources/Strings.resx @@ -122,15 +122,9 @@ Cannot create timer. - - Cannot get temporary file name - Cannot end timer. - - System event notifications are not supported under the current context. Server processes, for example, may not support global system event notifications. - '{1}' is not a valid value for '{0}'. '{0}' must be greater than {2}. diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj index b74ffd4352b8bf..79b0db6d25a9a5 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj @@ -25,6 +25,7 @@ + diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs b/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs new file mode 100644 index 00000000000000..d8012da78db70b --- /dev/null +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/ShutdownTest.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Threading; +using Microsoft.DotNet.RemoteExecutor; +using Xunit; +using static Interop; + +namespace Microsoft.Win32.SystemEventsTests +{ + public abstract class ShutdownTest : SystemEventsTest + { + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore))] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] + public void ShutdownThroughRestartManager() + { + RemoteExecutor.Invoke(() => + { + // Register any event to ensure that SystemEvents get initialized + SystemEvents.TimeChanged += (o, e) => { }; + + // Fake Restart Manager behavior by sending external WM_CLOSE message + SendMessage(Interop.User32.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + + // Emulate calling the Shutdown event + var shutdownMethod = typeof(SystemEvents).GetMethod("Shutdown", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic, null, new Type[0], null); + Assert.NotNull(shutdownMethod); + shutdownMethod.Invoke(null, null); + }).Dispose(); + } + } +} diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets index 6a402a0cfeb096..74fd8ebb92b2cd 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateNupkgProps.targets @@ -10,7 +10,9 @@ Pack="true" /> - + <Project> @@ -25,4 +27,4 @@ Lines="$(PropsFileContents)" Overwrite="true" /> - \ No newline at end of file + diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets index 31fe16ae8c6f1a..aa5b94b12c7a6c 100644 --- a/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets +++ b/src/libraries/Microsoft.XmlSerializer.Generator/src/GenerateThisAssemblyCs.targets @@ -4,6 +4,8 @@ @@ -44,6 +46,6 @@ namespace Microsoft.XmlSerializer.Generator File="$(IntermediateOutputPath)ThisAssembly.cs" Lines="$(ThisAssemblyCsContents)" Overwrite="true" - Encoding="Unicode"/> + Encoding="Unicode" /> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs index aa8d7636cfbca0..2562372c666b4a 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs @@ -15,7 +15,9 @@ public partial class ImmutableDictionary /// /// Contains all the key/values in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket : IEnumerable> +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs index 82fd48fbc62e5f..04ca794da7808e 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs @@ -30,7 +30,9 @@ internal enum OperationResult /// /// Contains all the keys in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs index 1864717141ca47..00fc77efe910c2 100644 --- a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs +++ b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs @@ -6,7 +6,7 @@ namespace System.Collections.Specialized { - public partial struct BitVector32 + public partial struct BitVector32 : System.IEquatable { private int _dummyPrimitive; public BitVector32(System.Collections.Specialized.BitVector32 value) { throw null; } @@ -18,11 +18,12 @@ public partial struct BitVector32 public static int CreateMask(int previous) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue, System.Collections.Specialized.BitVector32.Section previous) { throw null; } + public bool Equals(System.Collections.Specialized.BitVector32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } public static string ToString(System.Collections.Specialized.BitVector32 value) { throw null; } - public readonly partial struct Section + public readonly partial struct Section : System.IEquatable { private readonly int _dummyPrimitive; public short Mask { get { throw null; } } diff --git a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs index ce4ba761ab7aff..60a2580cfb6fd0 100644 --- a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs +++ b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs @@ -10,7 +10,7 @@ namespace System.Collections.Specialized /// Provides a simple light bit vector with easy integer or Boolean access to /// a 32 bit storage. /// - public struct BitVector32 + public struct BitVector32 : IEquatable { private uint _data; @@ -151,7 +151,12 @@ private static Section CreateSectionHelper(short maxValue, short priorMask, shor return new Section(mask, offset); } - public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && _data == other._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(BitVector32 other) => _data == other._data; public override int GetHashCode() => _data.GetHashCode(); @@ -182,7 +187,7 @@ public override string ToString() /// /// Represents an section of the vector that can contain a integer number. /// - public readonly struct Section + public readonly struct Section : IEquatable
{ private readonly short _mask; private readonly short _offset; diff --git a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs index 61734a09b741f1..69453b6c574d5a 100644 --- a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs +++ b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs @@ -518,17 +518,32 @@ public static void EqualsTest() Assert.True(new BitVector32(0).Equals(original)); Assert.True(original.Equals(new BitVector32(0))); + Assert.True(original.Equals((object)original)); + Assert.True(new BitVector32().Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32())); + Assert.True(new BitVector32(0).Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32(0))); + BitVector32 other = new BitVector32(int.MaxValue / 2 - 1); Assert.True(other.Equals(other)); Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals(other)); Assert.True(other.Equals(new BitVector32(int.MaxValue / 2 - 1))); + Assert.True(other.Equals((object)other)); + Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals((object)other)); + Assert.True(other.Equals((object)new BitVector32(int.MaxValue / 2 - 1))); + Assert.False(other.Equals(original)); Assert.False(original.Equals(other)); Assert.False(other.Equals(null)); Assert.False(original.Equals(null)); Assert.False(other.Equals(int.MaxValue / 2 - 1)); Assert.False(original.Equals(0)); + + Assert.False(other.Equals((object)original)); + Assert.False(original.Equals((object)other)); + Assert.False(other.Equals(int.MaxValue / 2 - 1)); + Assert.False(original.Equals(0)); } [Fact] diff --git a/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs b/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs index f095d38c045462..ab5b9a5ac00760 100644 --- a/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs +++ b/src/libraries/System.ComponentModel.Composition.Registration/tests/System/ComponentModel/Composition/Registration/RegistrationBuilderTests.cs @@ -44,8 +44,7 @@ public DiscoveredCatalog() : base("") { } } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ShouldSucceed() { var rb = new RegistrationBuilder(); @@ -174,8 +173,7 @@ private interface IGenericInterface { } [Export(typeof(IGenericInterface<>))] private class ClassExportingInterface : IGenericInterface { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void GenericInterfaceExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ClassExportingInterface<>)); @@ -188,8 +186,7 @@ private class GenericBaseClass { } [Export(typeof(GenericBaseClass<>))] private class ClassExportingBaseClass : GenericBaseClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void GenericBaseClassExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ClassExportingBaseClass<>)); @@ -211,8 +208,7 @@ public void GenericExportInRegistrationBuilder() [Export(typeof(ExplicitGenericClass<>))] private class ExplicitGenericClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ExplicitGenericExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ExplicitGenericClass<>)); @@ -223,8 +219,7 @@ public void ExplicitGenericExportInRegistrationBuilder() [Export(typeof(ExplicitGenericClass<,>))] private class ExplicitGenericClass { } - [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/32743", TestRuntimes.Mono)] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] public void ExplicitGenericArity2ExportInRegistrationBuilder() { CompositionContainer container = CreateRegistrationBuilderContainer(typeof(ExplicitGenericClass<,>)); diff --git a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs index f55f6b216d37f9..60accaee91e879 100644 --- a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs +++ b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs @@ -608,7 +608,7 @@ public ImportDefinition(System.Linq.Expressions.Expression { private object _dummy; private int _dummyPrimitive; @@ -616,6 +616,7 @@ public partial struct LazyMemberInfo public LazyMemberInfo(System.Reflection.MemberTypes memberType, System.Func accessorsCreator) { throw null; } public LazyMemberInfo(System.Reflection.MemberTypes memberType, params System.Reflection.MemberInfo[] accessors) { throw null; } public System.Reflection.MemberTypes MemberType { get { throw null; } } + public bool Equals(System.ComponentModel.Composition.ReflectionModel.LazyMemberInfo other) { throw null; } public override bool Equals(object? obj) { throw null; } public System.Reflection.MemberInfo[] GetAccessors() { throw null; } public override int GetHashCode() { throw null; } diff --git a/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx index 8899ffb3aab230..683d709992edbe 100644 --- a/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.Composition/src/Resources/Strings.resx @@ -72,9 +72,6 @@ '{0}' cannot contain a null (Nothing in Visual Basic) element. - - Assembly file {0} is either not found or not a dll or exe file. - No exports were found that match the constraint: {0} @@ -129,12 +126,6 @@ The Type '{0}' supplied is not a valid Metadata View. - - A call to Compose occurred during a call to Compose on the same CompositionContainer object. Use the IsComposing property on CompositionContainer to ensure a composition is not already in progress before calling Compose. - - - This export does not support the metadata item '{0}'. - Interface '{0}' is not a valid MetadataView; MetadataViews do not support non-public interfaces, and interfaces that contain members that are not properties. @@ -144,9 +135,6 @@ The {0} member must be overridden by a derived class. - - The underlying dictionary is read-only. - This property cannot be set after the object's public surface has been accessed. @@ -357,9 +345,6 @@ The composable part definition '{0}' was ignored because the export '{1}' has different generic parameters than the part type. - - 'reflectionContext' must be a type that is assignable from System.Reflection.ReflectionContext. - '{0}' returns a mapped type that is a reflection-only type which is not supported. @@ -369,15 +354,9 @@ The implementation type for the MetadataView '{0} can not be null. - - A CreationPolicy of '(0)' can not be applied to an Import that is not an ExportFactory. - ExportFactory subclass '{0}' can not have more than two generic parameters. - - ScopingPolicyCatalog does not support catalog mutation. - This CompositionService does not support catalog changes. diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs index 480e339c4080f5..02d1f811e71b71 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs @@ -8,7 +8,7 @@ namespace System.ComponentModel.Composition.ReflectionModel { - public struct LazyMemberInfo + public struct LazyMemberInfo : IEquatable { private readonly MemberTypes _memberType; private MemberInfo?[]? _accessors; @@ -106,31 +106,32 @@ public override int GetHashCode() throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - public override bool Equals(object? obj) - { - if (obj is not LazyMemberInfo that) - { - return false; - } + public override bool Equals(object? obj) => + obj is LazyMemberInfo other && Equals(other); + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(LazyMemberInfo other) + { // Different member types mean different members - if (_memberType != that._memberType) + if (_memberType != other._memberType) { return false; } // if any of the lazy memebers create accessors in a delay-loaded fashion, we simply compare the creators - if ((_accessorsCreator != null) || (that._accessorsCreator != null)) + if ((_accessorsCreator != null) || (other._accessorsCreator != null)) { - return object.Equals(_accessorsCreator, that._accessorsCreator); + return object.Equals(_accessorsCreator, other._accessorsCreator); } // we are dealing with explicitly passed accessors in both cases - if (_accessors == null || that._accessors == null) + if (_accessors == null || other._accessors == null) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - return _accessors.SequenceEqual(that._accessors); + return _accessors.SequenceEqual(other._accessors); } public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right) diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs index 333dd8e473bb6d..712637375d096e 100644 --- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs +++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/AssemblyCatalogTests.cs @@ -84,19 +84,12 @@ internal static void Constructor_ValueAsCodebaseArgument_ShouldSetAssemblyProper } } - internal static void Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad(Func catalogCreator) + internal static void Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException(Func catalogCreator) { string filename = Path.GetTempFileName(); using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None)) { - if (PlatformDetection.IsWindows) // File locking is Windows specific. - { - Assert.Throws(() => catalogCreator(filename)); - } - else - { - Assert.Throws(() => catalogCreator(filename)); - } + Assert.Throws(() => catalogCreator(filename)); } } @@ -184,7 +177,7 @@ public void Constructor1_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor1_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s); }); @@ -294,7 +287,7 @@ public void Constructor2_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor2_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, new AssemblyCatalogTestsReflectionContext()); }); @@ -403,7 +396,7 @@ public void Constructor3_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor3_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, (ICompositionElement)new AssemblyCatalog(s)); }); @@ -511,7 +504,7 @@ public void Constructor4_ValueAsCodebaseArgument_ShouldSetAssemblyProperty() [Fact] public void Constructor4_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad() { - AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowFileLoad((s) => + AssemblyCatalogConstructorTests.Constructor_LockedFileAsCodeBaseArgument_ShouldThrowIOException((s) => { return new AssemblyCatalog(s, new AssemblyCatalogTestsReflectionContext(), (ICompositionElement)new AssemblyCatalog(s)); }); diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index 510fffca714069..8fe3c9a37f8217 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -2164,7 +2164,7 @@ public InstanceDescriptor(System.Reflection.MemberInfo? member, System.Collectio public object? Invoke() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct MemberRelationship + public readonly partial struct MemberRelationship : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -2173,6 +2173,7 @@ public readonly partial struct MemberRelationship public bool IsEmpty { get { throw null; } } public System.ComponentModel.MemberDescriptor Member { get { throw null; } } public object? Owner { get { throw null; } } + public bool Equals(System.ComponentModel.Design.Serialization.MemberRelationship other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.ComponentModel.Design.Serialization.MemberRelationship left, System.ComponentModel.Design.Serialization.MemberRelationship right) { throw null; } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx index e9dd12b50616dd..f607a8a2fe91cd 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx +++ b/src/libraries/System.ComponentModel.TypeConverter/src/Resources/Strings.resx @@ -193,9 +193,6 @@ The specified character value is not allowed for this property. - - The Mask value cannot be null or empty. - The specified mask contains invalid characters. @@ -253,4 +250,4 @@ BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information. - \ No newline at end of file + diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs index 6691792d7fcfe3..090fa91accbf7c 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs @@ -153,7 +153,7 @@ private static void ThrowRelationshipNotSupported(MemberRelationship source, Mem /// /// Used as storage in our relationship table /// - private struct RelationshipEntry + private struct RelationshipEntry : IEquatable { internal WeakReference _owner; internal MemberDescriptor _member; @@ -169,20 +169,19 @@ internal RelationshipEntry(MemberRelationship rel) public override bool Equals([NotNullWhen(true)] object? o) { Debug.Assert(o is RelationshipEntry, "This is only called indirectly from a dictionary only containing RelationshipEntry structs."); - return this == (RelationshipEntry)o; + return Equals((RelationshipEntry)o); } - public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) + public bool Equals(RelationshipEntry other) { - object? owner1 = (re1._owner.IsAlive ? re1._owner.Target : null); - object? owner2 = (re2._owner.IsAlive ? re2._owner.Target : null); - return owner1 == owner2 && re1._member.Equals(re2._member); + object? owner1 = (_owner.IsAlive ? _owner.Target : null); + object? owner2 = (other._owner.IsAlive ? other._owner.Target : null); + return owner1 == owner2 && _member.Equals(other._member); } - public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) - { - return !(re1 == re2); - } + public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) => re1.Equals(re2); + + public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) => !re1.Equals(re2); public override int GetHashCode() => _hashCode; } @@ -191,7 +190,7 @@ public override bool Equals([NotNullWhen(true)] object? o) /// /// This class represents a single relationship between an object and a member. /// - public readonly struct MemberRelationship + public readonly struct MemberRelationship : IEquatable { public static readonly MemberRelationship Empty; @@ -222,37 +221,26 @@ public MemberRelationship(object owner, MemberDescriptor member) /// /// Infrastructure support to make this a first class struct /// - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is MemberRelationship rel && rel.Owner == Owner && rel.Member == Member; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is MemberRelationship rel && Equals(rel); /// /// Infrastructure support to make this a first class struct /// - public override int GetHashCode() - { - if (Owner == null) - { - return base.GetHashCode(); - } + public bool Equals(MemberRelationship other) => other.Owner == Owner && other.Member == Member; - return Owner.GetHashCode() ^ Member.GetHashCode(); - } /// /// Infrastructure support to make this a first class struct /// - public static bool operator ==(MemberRelationship left, MemberRelationship right) - { - return left.Owner == right.Owner && left.Member == right.Member; - } + public override int GetHashCode() => Owner is null ? base.GetHashCode() : Owner.GetHashCode() ^ Member.GetHashCode(); /// /// Infrastructure support to make this a first class struct /// - public static bool operator !=(MemberRelationship left, MemberRelationship right) - { - return !(left == right); - } + public static bool operator ==(MemberRelationship left, MemberRelationship right) => left.Equals(right); + + /// + /// Infrastructure support to make this a first class struct + /// + public static bool operator !=(MemberRelationship left, MemberRelationship right) => !left.Equals(right); } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs index 2190f32299fbb4..7aa25ce5bdf631 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs @@ -11,7 +11,7 @@ namespace System.ComponentModel /// Provides a subset of the surface area, using volatile /// operations for reads and interlocked operations for writes. ///
- internal struct InterlockedBitVector32 + internal struct InterlockedBitVector32 : IEquatable { private int _data; @@ -44,7 +44,9 @@ public static int CreateMask(int previous) return previous == 0 ? 1 : previous << 1; } - public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 vector && _data == vector._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 other && Equals(other); + + public bool Equals(InterlockedBitVector32 other) => _data == other._data; public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs index 16ebdaf6ab3008..5810df7258e5fc 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/MaskedTextProvider.cs @@ -227,10 +227,7 @@ public MaskedTextProvider(string mask, CultureInfo? culture, char passwordChar, ///
public MaskedTextProvider(string mask, CultureInfo? culture, bool allowPromptAsInput, char promptChar, char passwordChar, bool restrictToAscii) { - if (string.IsNullOrEmpty(mask)) - { - throw new ArgumentException(SR.MaskedTextProviderMaskNullOrEmpty, nameof(mask)); - } + ArgumentException.ThrowIfNullOrEmpty(mask); foreach (char c in mask) { diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs index 9037db51752749..9c0393da53ab33 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Drawing/RectangleConverter.cs @@ -50,7 +50,7 @@ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destina if (values.Length != 4) { - throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, "text", text, "x, y, width, height")); + throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, text, "x, y, width, height")); } return new Rectangle(values[0], values[1], values[2], values[3]); diff --git a/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx b/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx index 31887609b0acf0..168e714ca191ea 100644 --- a/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx +++ b/src/libraries/System.Composition.Hosting/src/Resources/Strings.resx @@ -57,9 +57,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Sharing lock is required - No export was found for the contract '{0}' @@ -73,9 +70,6 @@ '{0}' on contract '{1}' supplied by {2} - - Export descriptor fulfillment function returned null. - {0} supplied by {1} @@ -103,9 +97,6 @@ The component (unknown) cannot be created outside the {0} sharing boundary. - - Metadata View Provider - The type '{0}' cannot be used as a metadata view. A metadata view must be a concrete class with a parameterless or dictionary constructor. diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx index 2dd95efcdbe2fe..29f880277d1335 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx +++ b/src/libraries/System.Configuration.ConfigurationManager/src/Resources/Strings.resx @@ -93,7 +93,7 @@ + --> Cannot add a ConfigurationSection that already belongs to the Configuration. @@ -364,9 +364,6 @@ The configSource attribute must be a relative physical path. - - The configSource attribute must be a relative physical path, so the '/' character is not allowed. - The 'configSource' property may not be set in a configuration that has no associated file. diff --git a/src/libraries/System.Console/src/System/IO/SyncTextReader.cs b/src/libraries/System.Console/src/System/IO/SyncTextReader.cs index 7a2661691e6247..33ef898edb688c 100644 --- a/src/libraries/System.Console/src/System/IO/SyncTextReader.cs +++ b/src/libraries/System.Console/src/System/IO/SyncTextReader.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; namespace System.IO @@ -95,11 +96,25 @@ public override string ReadToEnd() return Task.FromResult(ReadLine()); } + public override ValueTask ReadLineAsync(CancellationToken cancellationToken) + { + return cancellationToken.IsCancellationRequested ? + ValueTask.FromCanceled(cancellationToken) : + new ValueTask(ReadLine()); + } + public override Task ReadToEndAsync() { return Task.FromResult(ReadToEnd()); } + public override Task ReadToEndAsync(CancellationToken cancellationToken) + { + return cancellationToken.IsCancellationRequested ? + Task.FromCanceled(cancellationToken) : + Task.FromResult(ReadToEnd()); + } + public override Task ReadBlockAsync(char[] buffer, int index, int count) { if (buffer == null) diff --git a/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs b/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs index e72522bafc58b8..2a8bc01fcf2b45 100644 --- a/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs +++ b/src/libraries/System.Console/tests/CancelKeyPress.Unix.cs @@ -76,9 +76,10 @@ public void ExitDetectionNotBlockedByHandler() Assert.Equal(RemoteExecutor.SuccessExitCode, handle.ExitCode); } - // Release CancelKeyPress + // Release CancelKeyPress, and give it time to return and tear down the app mre.Set(); - }).Dispose(); + Thread.Sleep(WaitFailTestTimeoutSeconds * 1000); + }, new RemoteInvokeOptions() { ExpectedExitCode = 130 }).Dispose(); } private void HandlerInvokedForSignal(int signalOuter, bool redirectStandardInput) diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs index 569f83d8ac7776..5e664573d5ea6c 100644 --- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs +++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs @@ -2737,7 +2737,7 @@ public SqlAlreadyFilledException(string? message) { } public SqlAlreadyFilledException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -2752,6 +2752,7 @@ public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBinary Concat(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBinary other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2777,7 +2778,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlBoolean False; @@ -2796,6 +2797,7 @@ public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.ICompa public int CompareTo(System.Data.SqlTypes.SqlBoolean value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBoolean other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2847,7 +2849,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlBoolean Xor(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlByte MaxValue; @@ -2864,6 +2866,7 @@ public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlByte Divide(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlByte other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2987,7 +2990,7 @@ public enum SqlCompareOptions BinarySort = 32768, } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDateTime MaxValue; @@ -3010,6 +3013,7 @@ public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComp public int CompareTo(System.Data.SqlTypes.SqlDateTime value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDateTime x, System.Data.SqlTypes.SqlDateTime y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDateTime other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3038,7 +3042,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly byte MaxPrecision; @@ -3068,6 +3072,7 @@ public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.ICompa public static System.Data.SqlTypes.SqlDecimal ConvertToPrecScale(System.Data.SqlTypes.SqlDecimal n, int precision, int scale) { throw null; } public static System.Data.SqlTypes.SqlDecimal Divide(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDecimal other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public static System.Data.SqlTypes.SqlDecimal Floor(System.Data.SqlTypes.SqlDecimal n) { throw null; } public override int GetHashCode() { throw null; } @@ -3124,7 +3129,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlDecimal Truncate(System.Data.SqlTypes.SqlDecimal n, int position) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDouble MaxValue; @@ -3139,6 +3144,7 @@ public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlDouble Divide(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDouble other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3187,7 +3193,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3201,6 +3207,7 @@ public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(System.Data.SqlTypes.SqlGuid value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlGuid other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3229,7 +3236,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt16 MaxValue; @@ -3246,6 +3253,7 @@ public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt16 Divide(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt16 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3303,7 +3311,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt16 Xor(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt32 MaxValue; @@ -3320,6 +3328,7 @@ public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt32 Divide(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3377,7 +3386,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt32 Xor(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt64 MaxValue; @@ -3394,6 +3403,7 @@ public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt64 Divide(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt64 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3451,7 +3461,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public static System.Data.SqlTypes.SqlInt64 Xor(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlMoney MaxValue; @@ -3469,6 +3479,7 @@ public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlMoney Divide(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlMoney other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3535,7 +3546,7 @@ public SqlNullValueException(string? message) { } public SqlNullValueException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlSingle MaxValue; @@ -3551,6 +3562,7 @@ public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlSingle Divide(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlSingle other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3599,7 +3611,7 @@ void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter wri public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3630,6 +3642,7 @@ public partial struct SqlString : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlString Concat(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlString other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public byte[]? GetNonUnicodeBytes() { throw null; } diff --git a/src/libraries/System.Data.Common/src/Resources/Strings.resx b/src/libraries/System.Data.Common/src/Resources/Strings.resx index 671bf490bc1351..c1a4dee0c36b05 100644 --- a/src/libraries/System.Data.Common/src/Resources/Strings.resx +++ b/src/libraries/System.Data.Common/src/Resources/Strings.resx @@ -97,7 +97,6 @@ An error occurred with the multiple target converter while writing an Xml Schema. See the inner exception for details. An error occurred with the multiple target converter while writing an Xml Schema. A null or empty string was returned. Duplicated declaration '{0}'. - Cannot load diffGram. Table '{0}' is missing in the destination dataset. Cannot load diffGram. The 'sql' node is missing. Column name '{0}' is defined for different mapping types. Prefix '{0}' is not valid, because it contains special characters. diff --git a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs index 379035bb75d6b3..7f1a15f75f51b7 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs @@ -5,7 +5,7 @@ namespace System.Data { - internal readonly struct DataKey + internal readonly struct DataKey : IEquatable { private const int maxColumns = 32; @@ -154,7 +154,7 @@ public override bool Equals(object? value) return Equals((DataKey)value); } - internal bool Equals(DataKey value) + public bool Equals(DataKey value) { //check to see if this.columns && key2's columns are equal... DataColumn[] column1 = _columns; diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs index a757be446e73a7..f6a45dbba5f2cb 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs @@ -12,7 +12,7 @@ namespace System.Data.SqlTypes { [XmlSchemaProvider("GetXsdType")] - public struct SqlBinary : INullable, IComparable, IXmlSerializable + public struct SqlBinary : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private byte[]? _value; @@ -362,20 +362,15 @@ public int CompareTo(SqlBinary value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBinary)) - { - return false; - } - - SqlBinary i = (SqlBinary)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBinary other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBinary other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // Hash a byte array. // Trailing zeroes/spaces would affect the hash value, so caller needs to diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs index 1efff18021e52b..d7b723f9f05f01 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlBoolean : INullable, IComparable, IXmlSerializable + public struct SqlBoolean : INullable, IComparable, IXmlSerializable, IEquatable { // m_value: 2 (true), 1 (false), 0 (unknown/Null) private byte m_value; // Do not rename (binary serialization) @@ -465,26 +465,18 @@ public int CompareTo(SqlBoolean value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBoolean)) - { - return false; - } - - SqlBoolean i = (SqlBoolean)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBoolean other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBoolean other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs index f7c1cdde432260..3dc5548ffed7a3 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlByte : INullable, IComparable, IXmlSerializable + public struct SqlByte : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private byte m_value; // Do not rename (binary serialization) @@ -474,26 +474,18 @@ public int CompareTo(SqlByte value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlByte)) - { - return false; - } - - SqlByte i = (SqlByte)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlByte other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlByte other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs index 195ca26628ea40..1edd44bedf3388 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDateTime : INullable, IComparable, IXmlSerializable + public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private int m_day; // Day from 1900/1/1, could be negative. Range: Jan 1 1753 - Dec 31 9999. Do not rename (binary serialization) @@ -621,26 +621,18 @@ public int CompareTo(SqlDateTime value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDateTime)) - { - return false; - } - - SqlDateTime i = (SqlDateTime)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDateTime other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDateTime other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs index 784d50d2bb1cfc..336639fbf0e5b4 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes ///
[StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlDecimal : INullable, IComparable, IXmlSerializable + public struct SqlDecimal : INullable, IComparable, IXmlSerializable, IEquatable { // data in CSsNumeric in SQL Server // BYTE m_cbLen; // # of DWORDs + 1 (1 is for sign) @@ -3278,20 +3278,15 @@ public int CompareTo(SqlDecimal value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDecimal)) - { - return false; - } - - SqlDecimal i = (SqlDecimal)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDecimal other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDecimal other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs index 3f10f943124002..4cc9ac4e321e0e 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs @@ -19,7 +19,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDouble : INullable, IComparable, IXmlSerializable + public struct SqlDouble : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private double m_value; // Do not rename (binary serialization) @@ -390,26 +390,18 @@ public int CompareTo(SqlDouble value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDouble)) - { - return false; - } - - SqlDouble i = (SqlDouble)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDouble other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDouble other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs index 8e3c58dff3dadf..2742c25d53b53a 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs @@ -16,7 +16,7 @@ namespace System.Data.SqlTypes [Serializable] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlGuid : INullable, IComparable, IXmlSerializable + public struct SqlGuid : INullable, IComparable, IXmlSerializable, IEquatable { private const int SizeOfGuid = 16; @@ -281,26 +281,18 @@ public int CompareTo(SqlGuid value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlGuid)) - { - return false; - } - - SqlGuid i = (SqlGuid)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlGuid other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlGuid other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs index 5833a009385612..d3879a06cf91b2 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt16 : INullable, IComparable, IXmlSerializable + public struct SqlInt16 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private short m_value; // Do not rename (binary serialization) @@ -475,26 +475,18 @@ public int CompareTo(SqlInt16 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt16)) - { - return false; - } - - SqlInt16 i = (SqlInt16)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt16 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt16 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs index 271d6509e71f58..8ce08e74e4403e 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt32 : INullable, IComparable, IXmlSerializable + public struct SqlInt32 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null, the default ctor (plain 0) will make it Null. Do not rename (binary serialization) private int m_value; // Do not rename (binary serialization) @@ -490,26 +490,18 @@ public int CompareTo(SqlInt32 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt32)) - { - return false; - } - - SqlInt32 i = (SqlInt32)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt32 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt32 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs index b7f33674ce03a8..393945b0303957 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt64 : INullable, IComparable, IXmlSerializable + public struct SqlInt64 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private long m_value; // Do not rename (binary serialization) @@ -549,26 +549,18 @@ public int CompareTo(SqlInt64 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt64)) - { - return false; - } - - SqlInt64 i = (SqlInt64)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt64 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt64 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs index 5431c8737d4aff..64c0d168631c86 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes ///
[StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlMoney : INullable, IComparable, IXmlSerializable + public struct SqlMoney : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private bool _fNotNull; // false if null @@ -539,27 +539,20 @@ public int CompareTo(SqlMoney value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlMoney)) - { - return false; - } - - SqlMoney i = (SqlMoney)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlMoney other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlMoney other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { + public override int GetHashCode() => // Don't use Value property, because Value will convert to Decimal, which is not necessary. - return IsNull ? 0 : _value.GetHashCode(); - } + IsNull ? 0 : _value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs index 59f29dcc89cbca..5fa7562824e13d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes /// [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlSingle : INullable, IComparable, IXmlSerializable + public struct SqlSingle : INullable, IComparable, IXmlSerializable, IEquatable { private bool _fNotNull; // false if null private float _value; @@ -400,26 +400,18 @@ public int CompareTo(SqlSingle value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlSingle)) - { - return false; - } - - SqlSingle i = (SqlSingle)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlSingle other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlSingle other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs index cac4122feba684..0c22570d2462d2 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs @@ -34,7 +34,7 @@ public enum SqlCompareOptions [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlString : INullable, IComparable, IXmlSerializable + public struct SqlString : INullable, IComparable, IXmlSerializable, IEquatable { private string? m_value; // Do not rename (binary serialization) private CompareInfo? m_cmpInfo; // Do not rename (binary serialization) @@ -871,20 +871,15 @@ public int CompareTo(SqlString value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlString)) - { - return false; - } - - SqlString i = (SqlString)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlString other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlString other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/Selection.cs b/src/libraries/System.Data.Common/src/System/Data/Selection.cs index 21a6d951393c19..fd76acfda7c36f 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Selection.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Selection.cs @@ -9,7 +9,7 @@ namespace System.Data { - internal readonly struct IndexField + internal readonly struct IndexField : IEquatable { public readonly DataColumn Column; public readonly bool IsDescending; // false = Asc; true = Desc what is default value for this? @@ -22,15 +22,15 @@ internal IndexField(DataColumn column, bool isDescending) IsDescending = isDescending; } - public static bool operator ==(IndexField if1, IndexField if2) => - if1.Column == if2.Column && if1.IsDescending == if2.IsDescending; + public static bool operator ==(IndexField if1, IndexField if2) => if1.Equals(if2); - public static bool operator !=(IndexField if1, IndexField if2) => !(if1 == if2); + public static bool operator !=(IndexField if1, IndexField if2) => !if1.Equals(if2); // must override Equals if == operator is defined - public override bool Equals([NotNullWhen(true)] object? obj) => obj is IndexField ? - this == (IndexField)obj : - false; + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IndexField other && Equals(other); + + public bool Equals(IndexField other) => Column == other.Column && IsDescending == other.IsDescending; // must override GetHashCode if Equals is redefined public override int GetHashCode() => diff --git a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs index 54644b678a5bc2..d42609fed6b5cf 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.SqlTypes; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Numerics; @@ -433,7 +434,7 @@ public void ReadXml(XmlReader reader) string tempPath = Path.GetTempFileName(); File.WriteAllText(tempPath, "This better not be written..."); File.Delete(tempPath); - throw new XunitException("Unreachable code (SerializationGuard should have kicked in)"); + throw new UnreachableException("Unreachable code (SerializationGuard should have kicked in)"); } public void WriteXml(XmlWriter writer) diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs index 6a631b392bea90..8655d3feea0030 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs @@ -122,8 +122,11 @@ public void ComparisonMethods() // Equals Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test2)); + Assert.False(_test3.Equals((object)_test2)); Assert.True(_test3.Equals(_test1)); + Assert.True(_test3.Equals((object)_test1)); // NotEquals Assert.True(SqlBinary.NotEquals(_test1, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs index 4da63a4bcdcf83..b52f671dad2d4b 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs @@ -242,10 +242,14 @@ public void EqualsTest() SqlBoolean sqlFalse2 = new SqlBoolean(false); Assert.True(_sqlTrue.Equals(sqlTrue2)); + Assert.True(_sqlTrue.Equals((object)sqlTrue2)); Assert.True(_sqlFalse.Equals(sqlFalse2)); + Assert.True(_sqlFalse.Equals((object)sqlFalse2)); Assert.False(_sqlTrue.Equals(_sqlFalse)); + Assert.False(_sqlTrue.Equals((object)_sqlFalse)); Assert.False(_sqlFalse.Equals(_sqlTrue)); + Assert.False(_sqlFalse.Equals((object)_sqlTrue)); Assert.False(_sqlTrue.Equals(SqlBoolean.Null)); Assert.False(_sqlFalse.Equals(SqlBoolean.Null)); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs index 2ae5976e9f1a9e..9af75f4f46997b 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs @@ -155,9 +155,12 @@ public void EqualsMethod() SqlByte testByte180II = new SqlByte(180); Assert.False(testByte0.Equals(testByte158)); + Assert.False(testByte0.Equals((object)testByte158)); Assert.False(testByte158.Equals(testByte180)); + Assert.False(testByte158.Equals((object)testByte180)); Assert.False(testByte180.Equals(new SqlString("TEST"))); Assert.True(testByte180.Equals(testByte180II)); + Assert.True(testByte180.Equals((object)testByte180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs index 6d3287ed49b0fd..0c835ff00c5405 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs @@ -175,8 +175,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDateTime.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs index 6fd72ba4157aaf..b9807ebcc102e2 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs @@ -225,8 +225,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDecimal.Equals(_test2, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs index 4f0856e2ba2269..db913271dc0209 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs @@ -134,9 +134,12 @@ public void EqualsMethods() SqlDouble test22 = new SqlDouble(1.8e180); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlDouble.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs index 84dcb3a3f53730..4c21e38d07ef2a 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs @@ -126,9 +126,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(_test4)); + Assert.False(_test2.Equals((object)_test4)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlGuid.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs index 3c240d6d9ed0f1..7c00f4845884de 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs @@ -157,9 +157,12 @@ public void EqualsMethod() SqlInt16 test180II = new SqlInt16(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs index 601b6a8bdb1bcc..ed466fb50b277f 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs @@ -159,9 +159,12 @@ public void EqualsMethod() SqlInt64 test180II = new SqlInt64(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs index 726302190b3884..db99ba4de6691c 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs @@ -131,7 +131,9 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); Assert.False(SqlMoney.Equals(_test1, _test2).Value); Assert.True(SqlMoney.Equals(_test3, _test2).Value); } diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs index 2c92e08226e490..3ff6c803aaef60 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs @@ -132,9 +132,12 @@ public void EqualsMethods() SqlSingle test22 = new SqlSingle(1.8e32); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlSingle.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs index 86a4b1683c4c92..56f8fa51b06ca2 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs @@ -262,9 +262,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test1)); + Assert.False(_test3.Equals((object)_test1)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlString.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Odbc/src/Resources/Strings.resx b/src/libraries/System.Data.Odbc/src/Resources/Strings.resx index b6860f2dd50aa8..2c6f3249f08040 100644 --- a/src/libraries/System.Data.Odbc/src/Resources/Strings.resx +++ b/src/libraries/System.Data.Odbc/src/Resources/Strings.resx @@ -128,9 +128,6 @@ The {0} is already contained by another {1}. - - The {0} with is already contained by this {1}. - The {0} only accepts non-null {1} type objects. @@ -377,9 +374,6 @@ This {0} has completed; it is no longer usable. - - '{0}' cannot be called when the record is read only. - Invalid {2} attempt at dataIndex '{0}'. With CommandBehavior.SequentialAccess, you may only read from dataIndex '{1}' or greater. diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 9cc4d09bf298b6..2005ee7715654e 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -176,7 +176,6 @@ System.Data.Odbc.OdbcTransaction -
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index a94fb9e380da8e..3ab7c480affb74 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -307,15 +307,27 @@ namespace System.Diagnostics.Metrics { public sealed class Counter : Instrument where T : struct { - public void Add(T delta) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } - public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } - public void Add(T delta, ReadOnlySpan> tags) { throw null; } - public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } + public void Add(T delta) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } + public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } public void Add(T delta, in TagList tagList) { throw null; } internal Counter(Meter meter, string name, string? unit, string? description) : - base(meter, name, unit, description) { throw null; } + base(meter, name, unit, description) { throw null; } + } + public sealed class UpDownCounter : Instrument where T : struct + { + public void Add(T delta) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) { throw null; } + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) { throw null; } + public void Add(T delta, ReadOnlySpan> tags) { throw null; } + public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) { throw null; } + public void Add(T delta, in TagList tagList) { throw null; } + internal UpDownCounter(Meter meter, string name, string? unit, string? description) : + base(meter, name, unit, description) { throw null; } } public sealed class Histogram : Instrument where T : struct { @@ -362,6 +374,7 @@ public abstract class Instrument : Instrument where T : struct public class Meter : IDisposable { public Counter CreateCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } + public UpDownCounter CreateUpDownCounter(string name, string? unit = null, string? description = null) where T : struct { throw null; } public Histogram CreateHistogram(string name, string? unit = null, string? description = null) where T : struct { throw null; } public ObservableCounter CreateObservableCounter( string name, @@ -378,6 +391,21 @@ public ObservableCounter CreateObservableCounter( Func>> observeValues, string? unit = null, string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func observeValue, + string? unit = null, + string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func> observeValue, + string? unit = null, + string? description = null) where T : struct { throw null; } + public ObservableUpDownCounter CreateObservableUpDownCounter( + string name, + Func>> observeValues, + string? unit = null, + string? description = null) where T : struct { throw null; } public ObservableGauge CreateObservableGauge( string name, Func observeValue, @@ -416,6 +444,11 @@ public sealed class ObservableCounter : ObservableInstrument where T : str internal ObservableCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } protected override System.Collections.Generic.IEnumerable> Observe() { throw null;} } + public sealed class ObservableUpDownCounter : ObservableInstrument where T : struct + { + internal ObservableUpDownCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } + protected override System.Collections.Generic.IEnumerable> Observe() { throw null;} + } public sealed class ObservableGauge : ObservableInstrument where T : struct { internal ObservableGauge(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) { throw null; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx index 0d9ad07a07e401..f57c9d3a7b8723 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/Resources/Strings.resx @@ -144,9 +144,6 @@ "Can not change format for an activity that was already started" - - "Can not add link to activity after it has been started" - "Can not set ParentId on activity which has parent" diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index 510487abedfd3b..b2be804bdfbf19 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -72,11 +72,13 @@ System.Diagnostics.DiagnosticSource + + diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs index 7aa624c68bed28..b16bbf08835afa 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs @@ -82,6 +82,59 @@ public Meter(string name, string? version) /// public Histogram CreateHistogram(string name, string? unit = null, string? description = null) where T : struct => new Histogram(this, name, unit, description); + /// + /// Create a metrics UpDownCounter object. + /// + /// The instrument name. Cannot be null. + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// UpDownCounter is an Instrument which supports reporting positive or negative metric values. + /// Example uses for UpDownCounter: reporting the change in active requests or queue size. + /// + public UpDownCounter CreateUpDownCounter(string name, string? unit = null, string? description = null) where T : struct => new UpDownCounter(this, name, unit, description); + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by . + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func observeValue, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValue, unit, description); + + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func> observeValue, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValue, unit, description); + + /// + /// Create an ObservableUpDownCounter object. ObservableUpDownCounter is an Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// + /// The instrument name. Cannot be null. + /// The callback to call to get the measurements when the is called by . + /// Optional instrument unit of measurements. + /// Optional instrument description. + /// + /// Example uses for ObservableUpDownCounter: the process heap size or the approximate number of items in a lock-free circular buffer. + /// + public ObservableUpDownCounter CreateObservableUpDownCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct => + new ObservableUpDownCounter(this, name, observeValues, unit, description); + + /// /// ObservableCounter is an Instrument which reports monotonically increasing value(s) when the instrument is being observed. /// @@ -122,6 +175,7 @@ public ObservableCounter CreateObservableCounter(string name, Func CreateObservableCounter(string name, Func>> observeValues, string? unit = null, string? description = null) where T : struct => new ObservableCounter(this, name, observeValues, unit, description); + /// /// ObservableGauge is an asynchronous Instrument which reports non-additive value(s) (e.g. the room temperature - it makes no sense to report the temperature value from multiple rooms and sum them up) when the instrument is being observed. /// diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.cs new file mode 100644 index 00000000000000..7751067ac55a32 --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/ObservableUpDownCounter.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. + +using System.Collections.Generic; + +namespace System.Diagnostics.Metrics +{ + /// + /// ObservableUpDownCounter is a metrics observable Instrument which reports increasing or decreasing value(s) when the instrument is being observed. + /// e.g. the process heap size or the approximate number of items in a lock-free circular buffer. + /// Use Meter.CreateObservableUpDownCounter methods to create an ObservableUpDownCounter object. + /// + /// + /// This class supports only the following generic parameter types: , , , , , , and + /// +#if ALLOW_PARTIALLY_TRUSTED_CALLERS + [System.Security.SecuritySafeCriticalAttribute] +#endif + public sealed class ObservableUpDownCounter : ObservableInstrument where T : struct + { + private object _callback; + + internal ObservableUpDownCounter(Meter meter, string name, Func observeValue, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValue is null) + { + throw new ArgumentNullException(nameof(observeValue)); + } + + _callback = observeValue; + Publish(); + } + + internal ObservableUpDownCounter(Meter meter, string name, Func> observeValue, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValue is null) + { + throw new ArgumentNullException(nameof(observeValue)); + } + + _callback = observeValue; + Publish(); + } + + internal ObservableUpDownCounter(Meter meter, string name, Func>> observeValues, string? unit, string? description) : base(meter, name, unit, description) + { + if (observeValues is null) + { + throw new ArgumentNullException(nameof(observeValues)); + } + + _callback = observeValues; + Publish(); + } + + /// + /// Observe() fetches the current measurements being tracked by this observable counter. + /// + protected override IEnumerable> Observe() => Observe(_callback); + } +} \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs new file mode 100644 index 00000000000000..cad80c52c57ee5 --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/UpDownCounter.cs @@ -0,0 +1,76 @@ +// 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; + +namespace System.Diagnostics.Metrics +{ + /// + /// The UpDownCounter is an instrument that supports reporting positive or negative metric values. + /// UpDownCounter may be used in scenarios like reporting the change in active requests or queue size. + /// + /// + /// This class supports only the following generic parameter types: , , , , , , and + /// +#if ALLOW_PARTIALLY_TRUSTED_CALLERS + [System.Security.SecuritySafeCriticalAttribute] +#endif + public sealed class UpDownCounter : Instrument where T : struct + { + internal UpDownCounter(Meter meter, string name, string? unit, string? description) : base(meter, name, unit, description) + { + Publish(); + } + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + public void Add(T delta) => RecordMeasurement(delta); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag) => RecordMeasurement(delta, tag); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A first key-value pair tag associated with the measurement. + /// A second key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2) => RecordMeasurement(delta, tag1, tag2); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A first key-value pair tag associated with the measurement. + /// A second key-value pair tag associated with the measurement. + /// A third key-value pair tag associated with the measurement. + public void Add(T delta, KeyValuePair tag1, KeyValuePair tag2, KeyValuePair tag3) => RecordMeasurement(delta, tag1, tag2, tag3); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A span of key-value pair tags associated with the measurement. + public void Add(T delta, ReadOnlySpan> tags) => RecordMeasurement(delta, tags); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A list of key-value pair tags associated with the measurement. + public void Add(T delta, params KeyValuePair[] tags) => RecordMeasurement(delta, tags.AsSpan()); + + /// + /// Record the delta value of the measurement. The delta can be positive, negative or zero. + /// + /// The amount to be added which can be positive, negative or zero. + /// A of tags associated with the measurement. + public void Add(T delta, in TagList tagList) => RecordMeasurement(delta, in tagList); + } +} \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs index c0da50f20431db..929a378dd7f78a 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs @@ -37,12 +37,18 @@ public void InstrumentCreationTest() Counter counter = meter.CreateCounter("Counter", "seconds", "Seconds Counter"); ValidateInstrumentInfo(counter, "Counter", "seconds", "Seconds Counter", false, false); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter", "seconds", "Seconds UpDownCounter"); + ValidateInstrumentInfo(upDownCounter, "UpDownCounter", "seconds", "Seconds UpDownCounter", false, false); + Histogram histogram = meter.CreateHistogram("Histogram", "centimeters", "centimeters Histogram"); ValidateInstrumentInfo(histogram, "Histogram", "centimeters", "centimeters Histogram", false, false); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => 10, "millisecond", "millisecond ObservableCounter"); ValidateInstrumentInfo(observableCounter, "ObservableCounter", "millisecond", "millisecond ObservableCounter", false, true); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => -1, "request", "request ObservableUpDownCounter"); + ValidateInstrumentInfo(observableUpDownCounter, "ObservableUpDownCounter", "request", "request ObservableUpDownCounter", false, true); + ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => 10, "Fahrenheit", "Fahrenheit ObservableGauge"); ValidateInstrumentInfo(observableGauge, "ObservableGauge", "Fahrenheit", "Fahrenheit ObservableGauge", false, true); }).Dispose(); @@ -55,8 +61,10 @@ public void CreateInstrumentParametersTest() Meter meter = new Meter("CreateInstrumentParametersTest"); Assert.Throws(() => meter.CreateCounter(null, "seconds", "Seconds Counter")); + Assert.Throws(() => meter.CreateUpDownCounter(null, "items", "Items UpDownCounter")); Assert.Throws(() => meter.CreateHistogram(null, "seconds", "Seconds Counter")); Assert.Throws(() => meter.CreateObservableCounter(null, () => 0, "seconds", "Seconds ObservableCounter")); + Assert.Throws(() => meter.CreateObservableUpDownCounter(null, () => 0, "items", "Items ObservableUpDownCounter")); Assert.Throws(() => meter.CreateObservableGauge(null, () => 0, "seconds", "Seconds ObservableGauge")); }).Dispose(); @@ -76,6 +84,14 @@ public void SupportedGenericParameterTypesTest() Counter counter6 = meter.CreateCounter("Counter6", "seconds", "Seconds Counter"); Counter counter7 = meter.CreateCounter("Counter7", "seconds", "Seconds Counter"); + UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("UpDownCounter1", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("UpDownCounter2", "seconds", "Seconds Counter"); + UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("UpDownCounter3", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("UpDownCounter4", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("UpDownCounter5", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("UpDownCounter6", "seconds", "Seconds UpDownCounter"); + UpDownCounter upDownCounter7 = meter.CreateUpDownCounter("UpDownCounter7", "seconds", "Seconds UpDownCounter"); + Histogram histogram1 = meter.CreateHistogram("histogram1", "seconds", "Seconds histogram"); Histogram histogram2 = meter.CreateHistogram("histogram2", "seconds", "Seconds histogram"); Histogram histogram3 = meter.CreateHistogram("histogram3", "seconds", "Seconds histogram"); @@ -92,6 +108,14 @@ public void SupportedGenericParameterTypesTest() ObservableCounter observableCounter6 = meter.CreateObservableCounter("observableCounter6", () => 0, "seconds", "Seconds ObservableCounter"); ObservableCounter observableCounter7 = meter.CreateObservableCounter("observableCounter7", () => 0, "seconds", "Seconds ObservableCounter"); + ObservableUpDownCounter observableUpDownCounter1 = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter2 = meter.CreateObservableUpDownCounter("observableUpDownCounter2", () => 0, "items", "Items ObservableCounter"); + ObservableUpDownCounter observableUpDownCounter3 = meter.CreateObservableUpDownCounter("observableUpDownCounter3", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter4 = meter.CreateObservableUpDownCounter("observableUpDownCounter4", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter5 = meter.CreateObservableUpDownCounter("observableUpDownCounter5", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter6 = meter.CreateObservableUpDownCounter("observableUpDownCounter6", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableUpDownCounter observableUpDownCounter7 = meter.CreateObservableUpDownCounter("observableUpDownCounter7", () => 0, "items", "Items ObservableUpDownCounter"); + ObservableGauge observableGauge1 = meter.CreateObservableGauge("observableGauge1", () => 0, "seconds", "Seconds ObservableGauge"); ObservableGauge observableGauge2 = meter.CreateObservableGauge("observableGauge2", () => 0, "seconds", "Seconds ObservableGauge"); ObservableGauge observableGauge3 = meter.CreateObservableGauge("observableGauge3", () => 0, "seconds", "Seconds ObservableGauge"); @@ -101,6 +125,7 @@ public void SupportedGenericParameterTypesTest() ObservableGauge observableGauge7 = meter.CreateObservableGauge("observableGauge7", () => 0, "seconds", "Seconds ObservableGauge"); Assert.Throws(() => meter.CreateCounter("Counter", "seconds", "Seconds Counter")); + Assert.Throws(() => meter.CreateUpDownCounter("UpDownCounter", "items", "Items Counter")); Assert.Throws(() => meter.CreateHistogram("histogram1", "seconds", "Seconds histogram")); Assert.Throws(() => meter.CreateObservableCounter("observableCounter3", () => 0, "seconds", "Seconds ObservableCounter")); Assert.Throws(() => meter.CreateObservableGauge("observableGauge7", () => 0, "seconds", "Seconds ObservableGauge")); @@ -134,8 +159,10 @@ public void ListeningToInstrumentsPublishingTest() Histogram histogram = meter.CreateHistogram("histogram1", "seconds", "Seconds histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("observableCounter1", () => 0, "seconds", "Seconds ObservableCounter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter4", "request", "Requests UpDownCounter"); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => 0, "items", "Items ObservableCounter"); - Assert.Equal(4, instrumentsEncountered); + Assert.Equal(6, instrumentsEncountered); // Enable listening to the 4 instruments @@ -143,6 +170,8 @@ public void ListeningToInstrumentsPublishingTest() listener.EnableMeasurementEvents(observableGauge, observableGauge); listener.EnableMeasurementEvents(histogram, histogram); listener.EnableMeasurementEvents(observableCounter, observableCounter); + listener.EnableMeasurementEvents(upDownCounter, upDownCounter); + listener.EnableMeasurementEvents(observableUpDownCounter, observableUpDownCounter); // Enable listening to instruments unpublished event listener.MeasurementsCompleted = (instruments, state) => { instrumentsEncountered--; Assert.Same(state, instruments); }; @@ -169,15 +198,21 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() ObservableGauge gauge1 = meter.CreateObservableGauge("observableGauge1", (Func)(() => throw new ArgumentException())); ObservableCounter counter2 = meter.CreateObservableCounter("observableCounter2", (Func)(() => throw new PlatformNotSupportedException())); ObservableGauge gauge2 = meter.CreateObservableGauge("observableGauge2", (Func)(() => throw new NullReferenceException())); + ObservableUpDownCounter upDownCounterCounter1 = meter.CreateObservableUpDownCounter("upDownCounter1", (Func) (() => throw new ArgumentOutOfRangeException())); + ObservableUpDownCounter upDownCounterCounter2 = meter.CreateObservableUpDownCounter("upDownCounter2", (Func) (() => throw new PlatformNotSupportedException())); ObservableCounter counter3 = meter.CreateObservableCounter("observableCounter3", () => 5); ObservableGauge gauge3 = meter.CreateObservableGauge("observableGauge3", () => 7); + ObservableUpDownCounter upDownCounterCounter3 = meter.CreateObservableUpDownCounter("ObservableUpDownCounter3", () => -1); listener.EnableMeasurementEvents(counter1, null); listener.EnableMeasurementEvents(gauge1, null); listener.EnableMeasurementEvents(counter2, null); listener.EnableMeasurementEvents(gauge2, null); + listener.EnableMeasurementEvents(upDownCounterCounter1, null); + listener.EnableMeasurementEvents(upDownCounterCounter2, null); listener.EnableMeasurementEvents(counter3, null); listener.EnableMeasurementEvents(gauge3, null); + listener.EnableMeasurementEvents(upDownCounterCounter3, null); int accumulated = 0; @@ -187,15 +222,17 @@ public void ThrowingExceptionsFromObservableInstrumentCallbacks() Assert.NotNull(exception); Assert.IsType(exception); AggregateException ae = exception as AggregateException; - Assert.Equal(4, ae.InnerExceptions.Count); + Assert.Equal(6, ae.InnerExceptions.Count); Assert.IsType(ae.InnerExceptions[0]); Assert.IsType(ae.InnerExceptions[1]); Assert.IsType(ae.InnerExceptions[2]); Assert.IsType(ae.InnerExceptions[3]); + Assert.IsType(ae.InnerExceptions[4]); + Assert.IsType(ae.InnerExceptions[5]); // Ensure the instruments which didn't throw reported correct measurements. - Assert.Equal(12, accumulated); + Assert.Equal(11, accumulated); } }).Dispose(); @@ -208,46 +245,67 @@ public void InstrumentMeasurementTest() Meter meter = new Meter("InstrumentMeasurementTest"); Counter counter = meter.CreateCounter("byteCounter"); - InstruementMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter, (value, tags) => { counter.Add(value, tags); } ); + + UpDownCounter upDownCounter = meter.CreateUpDownCounter("byteUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter, (value, tags) => { upDownCounter.Add(value, tags); }); Counter counter1 = meter.CreateCounter("shortCounter"); - InstruementMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter1, (value, tags) => { counter1.Add(value, tags); } ); + + UpDownCounter upDownCounter1 = meter.CreateUpDownCounter("shortUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter1, (value, tags) => { upDownCounter1.Add(value, tags); }, true); Counter counter2 = meter.CreateCounter("intCounter"); - InstruementMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter2, (value, tags) => { counter2.Add(value, tags); } ); + + UpDownCounter upDownCounter2 = meter.CreateUpDownCounter("intUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter2, (value, tags) => { upDownCounter2.Add(value, tags); }, true); Counter counter3 = meter.CreateCounter("longCounter"); - InstruementMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter3, (value, tags) => { counter3.Add(value, tags); } ); + + UpDownCounter upDownCounter3 = meter.CreateUpDownCounter("longUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter3, (value, tags) => { upDownCounter3.Add(value, tags); }, true); Counter counter4 = meter.CreateCounter("floatCounter"); - InstruementMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter4, (value, tags) => { counter4.Add(value, tags); } ); + + UpDownCounter upDownCounter4 = meter.CreateUpDownCounter("floatUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter4, (value, tags) => { upDownCounter4.Add(value, tags); }, true); Counter counter5 = meter.CreateCounter("doubleCounter"); - InstruementMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter5, (value, tags) => { counter5.Add(value, tags); } ); + + UpDownCounter upDownCounter5 = meter.CreateUpDownCounter("doubleUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter5, (value, tags) => { upDownCounter5.Add(value, tags); }, true); Counter counter6 = meter.CreateCounter("decimalCounter"); - InstruementMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + InstrumentMeasurementAggregationValidation(counter6, (value, tags) => { counter6.Add(value, tags); } ); + + UpDownCounter upDownCounter6 = meter.CreateUpDownCounter("decimalUpDownCounter"); + InstrumentMeasurementAggregationValidation(upDownCounter6, (value, tags) => { upDownCounter6.Add(value, tags); }, true); Histogram histogram = meter.CreateHistogram("byteHistogram"); - InstruementMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram, (value, tags) => { histogram.Record(value, tags); } ); Histogram histogram1 = meter.CreateHistogram("shortHistogram"); - InstruementMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram1, (value, tags) => { histogram1.Record(value, tags); } ); Histogram histogram2 = meter.CreateHistogram("intHistogram"); - InstruementMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram2, (value, tags) => { histogram2.Record(value, tags); } ); Histogram histogram3 = meter.CreateHistogram("longHistogram"); - InstruementMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram3, (value, tags) => { histogram3.Record(value, tags); } ); Histogram histogram4 = meter.CreateHistogram("floatHistogram"); - InstruementMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram4, (value, tags) => { histogram4.Record(value, tags); } ); Histogram histogram5 = meter.CreateHistogram("doubleHistogram"); - InstruementMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram5, (value, tags) => { histogram5.Record(value, tags); } ); Histogram histogram6 = meter.CreateHistogram("decimalHistogram"); - InstruementMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); + InstrumentMeasurementAggregationValidation(histogram6, (value, tags) => { histogram6.Record(value, tags); } ); }).Dispose(); } @@ -263,99 +321,148 @@ public void ObservableInstrumentMeasurementTest() // CreateObservableCounter using Func // ObservableCounter observableCounter = meter.CreateObservableCounter("ByteObservableCounter", () => 50); - ObservableInstruementMeasurementAggregationValidation(observableCounter, new Measurement[] { new Measurement(50)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter, new Measurement[] { new Measurement(50)}); ObservableCounter observableCounter1 = meter.CreateObservableCounter("ShortObservableCounter", () => 30_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter1, new Measurement[] { new Measurement(30_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter1, new Measurement[] { new Measurement(30_000)}); ObservableCounter observableCounter2 = meter.CreateObservableCounter("IntObservableCounter", () => 1_000_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter2, new Measurement[] { new Measurement(1_000_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter2, new Measurement[] { new Measurement(1_000_000)}); ObservableCounter observableCounter3 = meter.CreateObservableCounter("longObservableCounter", () => 1_000_000_000); - ObservableInstruementMeasurementAggregationValidation(observableCounter3, new Measurement[] { new Measurement(1_000_000_000)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter3, new Measurement[] { new Measurement(1_000_000_000)}); ObservableCounter observableCounter4 = meter.CreateObservableCounter("floatObservableCounter", () => 3.14f); - ObservableInstruementMeasurementAggregationValidation(observableCounter4, new Measurement[] { new Measurement(3.14f)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter4, new Measurement[] { new Measurement(3.14f)}); ObservableCounter observableCounter5 = meter.CreateObservableCounter("doubleObservableCounter", () => 1e6); - ObservableInstruementMeasurementAggregationValidation(observableCounter5, new Measurement[] { new Measurement(1e6)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter5, new Measurement[] { new Measurement(1e6)}); ObservableCounter observableCounter6 = meter.CreateObservableCounter("decimalObservableCounter", () => 1.5E6m); - ObservableInstruementMeasurementAggregationValidation(observableCounter6, new Measurement[] { new Measurement(1.5E6m)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter6, new Measurement[] { new Measurement(1.5E6m)}); + + // + // CreateObservableUpDownCounter using Func + // + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => 10); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter, new Measurement[] { new Measurement(10)}); + ObservableUpDownCounter observableUpDownCounter1 = meter.CreateObservableUpDownCounter("shortObservableUpDownCounter", () => -10); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter1, new Measurement[] { new Measurement(-10)}); + ObservableUpDownCounter observableUpDownCounter2 = meter.CreateObservableUpDownCounter("intObservableUpDownCounter", () => -12); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter2, new Measurement[] { new Measurement(-12)}); + ObservableUpDownCounter observableUpDownCounter3 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => -100); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter3, new Measurement[] { new Measurement(-100)}); + ObservableUpDownCounter observableUpDownCounter4 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => -3.4f); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter4, new Measurement[] { new Measurement(-3.4f)}); + ObservableUpDownCounter observableUpDownCounter5 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => -3.14); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter5, new Measurement[] { new Measurement(-3.14)}); + ObservableUpDownCounter observableUpDownCounter6 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => -32222.14m); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter6, new Measurement[] { new Measurement(-32222.14m)}); // // CreateObservableGauge using Func // ObservableGauge observableGauge = meter.CreateObservableGauge("ByteObservableGauge", () => 100); - ObservableInstruementMeasurementAggregationValidation(observableGauge, new Measurement[] { new Measurement(100)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge, new Measurement[] { new Measurement(100)}); ObservableGauge observableGauge1 = meter.CreateObservableGauge("ShortObservableGauge", () => 30_123); - ObservableInstruementMeasurementAggregationValidation(observableGauge1, new Measurement[] { new Measurement(30_123)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge1, new Measurement[] { new Measurement(30_123)}); ObservableGauge observableGauge2 = meter.CreateObservableGauge("IntObservableGauge", () => 2_123_456); - ObservableInstruementMeasurementAggregationValidation(observableGauge2, new Measurement[] { new Measurement(2_123_456)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge2, new Measurement[] { new Measurement(2_123_456)}); ObservableGauge observableGauge3 = meter.CreateObservableGauge("longObservableGauge", () => 3_123_456_789); - ObservableInstruementMeasurementAggregationValidation(observableGauge3, new Measurement[] { new Measurement(3_123_456_789)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge3, new Measurement[] { new Measurement(3_123_456_789)}); ObservableGauge observableGauge4 = meter.CreateObservableGauge("floatObservableGauge", () => 1.6f); - ObservableInstruementMeasurementAggregationValidation(observableGauge4, new Measurement[] { new Measurement(1.6f)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge4, new Measurement[] { new Measurement(1.6f)}); ObservableGauge observableGauge5 = meter.CreateObservableGauge("doubleObservableGauge", () => 1e5); - ObservableInstruementMeasurementAggregationValidation(observableGauge5, new Measurement[] { new Measurement(1e5)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge5, new Measurement[] { new Measurement(1e5)}); ObservableGauge observableGauge6 = meter.CreateObservableGauge("decimalObservableGauge", () => 2.5E7m); - ObservableInstruementMeasurementAggregationValidation(observableGauge6, new Measurement[] { new Measurement(2.5E7m)}); + ObservableInstrumentMeasurementAggregationValidation(observableGauge6, new Measurement[] { new Measurement(2.5E7m)}); // // CreateObservableCounter using Func> // Measurement byteMeasurement = new Measurement(60, new KeyValuePair[] { new KeyValuePair("T1", "V1"), new KeyValuePair("T2", "V2") }); ObservableCounter observableCounter7 = meter.CreateObservableCounter("ByteObservableCounter", () => byteMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter7, new Measurement[] { byteMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter7, new Measurement[] { byteMeasurement }); Measurement shortMeasurement = new Measurement(20_000, new KeyValuePair[] { new KeyValuePair("T3", "V3"), new KeyValuePair("T4", "V4") }); ObservableCounter observableCounter8 = meter.CreateObservableCounter("ShortObservableCounter", () => shortMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter8, new Measurement[] { shortMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter8, new Measurement[] { shortMeasurement }); Measurement intMeasurement = new Measurement(2_000_000, new KeyValuePair[] { new KeyValuePair("T5", "V5"), new KeyValuePair("T6", "V6") }); ObservableCounter observableCounter9 = meter.CreateObservableCounter("IntObservableCounter", () => intMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter9, new Measurement[] { intMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter9, new Measurement[] { intMeasurement }); Measurement longMeasurement = new Measurement(20_000_000_000, new KeyValuePair[] { new KeyValuePair("T7", "V7"), new KeyValuePair("T8", "V8") }); ObservableCounter observableCounter10 = meter.CreateObservableCounter("longObservableCounter", () => longMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter10, new Measurement[] { longMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter10, new Measurement[] { longMeasurement }); Measurement floatMeasurement = new Measurement(1e2f, new KeyValuePair[] { new KeyValuePair("T9", "V10"), new KeyValuePair("T11", "V12") }); ObservableCounter observableCounter11 = meter.CreateObservableCounter("floatObservableCounter", () => 3.14f); - ObservableInstruementMeasurementAggregationValidation(observableCounter11, new Measurement[] { new Measurement(3.14f)}); + ObservableInstrumentMeasurementAggregationValidation(observableCounter11, new Measurement[] { new Measurement(3.14f)}); Measurement doubleMeasurement = new Measurement(2.5e7, new KeyValuePair[] { new KeyValuePair("T13", "V14"), new KeyValuePair("T15", "V16") }); ObservableCounter observableCounter12 = meter.CreateObservableCounter("doubleObservableCounter", () => doubleMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter12, new Measurement[] { doubleMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter12, new Measurement[] { doubleMeasurement }); Measurement decimalMeasurement = new Measurement(3.2e20m, new KeyValuePair[] { new KeyValuePair("T17", "V18"), new KeyValuePair("T19", "V20") }); ObservableCounter observableCounter13 = meter.CreateObservableCounter("decimalObservableCounter", () => decimalMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableCounter13, new Measurement[] { decimalMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableCounter13, new Measurement[] { decimalMeasurement }); + + // + // CreateObservableUpDownCounter using Func> + // + Measurement byteMeasurement1 = new Measurement(100, new KeyValuePair[] { new KeyValuePair("T1", "V1"), new KeyValuePair("T2", "V2") }); + ObservableUpDownCounter observableUpDownCounter7 = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => byteMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter7, new Measurement[] { byteMeasurement1 }); + + Measurement shortMeasurement1 = new Measurement(-20_000, new KeyValuePair[] { new KeyValuePair("T3", "V3"), new KeyValuePair("T4", "V4") }); + ObservableUpDownCounter observableUpDownCounter8 = meter.CreateObservableUpDownCounter("ShortObservableUpDownCounter", () => shortMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter8, new Measurement[] { shortMeasurement1 }); + + Measurement intMeasurement1 = new Measurement(-2_000_000, new KeyValuePair[] { new KeyValuePair("T5", "V5"), new KeyValuePair("T6", "V6") }); + ObservableUpDownCounter observableUpDownCounter9 = meter.CreateObservableUpDownCounter("IntObservableUpDownCounter", () => intMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter9, new Measurement[] { intMeasurement1 }); + + Measurement longMeasurement1 = new Measurement(-20_000_000_000, new KeyValuePair[] { new KeyValuePair("T7", "V7"), new KeyValuePair("T8", "V8") }); + ObservableUpDownCounter observableUpDownCounter10 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => longMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter10, new Measurement[] { longMeasurement1 }); + + Measurement floatMeasurement1 = new Measurement(-1e2f, new KeyValuePair[] { new KeyValuePair("T9", "V10"), new KeyValuePair("T11", "V12") }); + ObservableUpDownCounter observableUpDownCounter11 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => floatMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter11, new Measurement[] { floatMeasurement1 }); + + Measurement doubleMeasurement1 = new Measurement(-2.5e7, new KeyValuePair[] { new KeyValuePair("T13", "V14"), new KeyValuePair("T15", "V16") }); + ObservableUpDownCounter observableUpDownCounter12 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => doubleMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter12, new Measurement[] { doubleMeasurement1 }); + + Measurement decimalMeasurement1 = new Measurement(-3.2e20m, new KeyValuePair[] { new KeyValuePair("T17", "V18"), new KeyValuePair("T19", "V20") }); + ObservableUpDownCounter observableUpDownCounter13 = meter.CreateObservableUpDownCounter("decimalObservableUpDownCounter", () => decimalMeasurement1); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter13, new Measurement[] { decimalMeasurement1 }); // // CreateObservableGauge using Func> // Measurement byteGaugeMeasurement = new Measurement(35, new KeyValuePair[] { new KeyValuePair("T21", "V22"), new KeyValuePair("T23", "V24") }); ObservableGauge observableGauge7 = meter.CreateObservableGauge("ByteObservableGauge", () => byteGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge7, new Measurement[] { byteGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge7, new Measurement[] { byteGaugeMeasurement }); Measurement shortGaugeMeasurement = new Measurement(23_987, new KeyValuePair[] { new KeyValuePair("T25", "V26"), new KeyValuePair("T27", "V28") }); ObservableGauge observableGauge8 = meter.CreateObservableGauge("ShortObservableGauge", () => shortGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge8, new Measurement[] { shortGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge8, new Measurement[] { shortGaugeMeasurement }); Measurement intGaugeMeasurement = new Measurement(1_987_765, new KeyValuePair[] { new KeyValuePair("T29", "V30"), new KeyValuePair("T31", "V32") }); ObservableGauge observableGauge9 = meter.CreateObservableGauge("IntObservableGauge", () => intGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge9, new Measurement[] { intGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge9, new Measurement[] { intGaugeMeasurement }); Measurement longGaugeMeasurement = new Measurement(10_000_234_343, new KeyValuePair[] { new KeyValuePair("T33", "V342"), new KeyValuePair("T35", "V36") }); ObservableGauge observableGauge10 = meter.CreateObservableGauge("longObservableGauge", () => longGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge10, new Measurement[] { longGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge10, new Measurement[] { longGaugeMeasurement }); Measurement floatGaugeMeasurement = new Measurement(2.1f, new KeyValuePair[] { new KeyValuePair("T37", "V38"), new KeyValuePair("T39", "V40") }); ObservableGauge observableGauge11 = meter.CreateObservableGauge("floatObservableGauge", () => floatGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge11, new Measurement[] { floatGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge11, new Measurement[] { floatGaugeMeasurement }); Measurement doubleGaugeMeasurement = new Measurement(1.5e30, new KeyValuePair[] { new KeyValuePair("T41", "V42"), new KeyValuePair("T43", "V44") }); ObservableGauge observableGauge12 = meter.CreateObservableGauge("doubleObservableGauge", () => doubleGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge12, new Measurement[] { doubleGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge12, new Measurement[] { doubleGaugeMeasurement }); Measurement decimalGaugeMeasurement = new Measurement(2.5e20m, new KeyValuePair[] { new KeyValuePair("T45", "V46"), new KeyValuePair("T47", "V48") }); ObservableGauge observableGauge13 = meter.CreateObservableGauge("decimalObservableGauge", () => decimalGaugeMeasurement); - ObservableInstruementMeasurementAggregationValidation(observableGauge13, new Measurement[] { decimalGaugeMeasurement }); + ObservableInstrumentMeasurementAggregationValidation(observableGauge13, new Measurement[] { decimalGaugeMeasurement }); // // CreateObservableCounter using Func> @@ -366,7 +473,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1, new KeyValuePair[] { new KeyValuePair("T51", "V52"), new KeyValuePair("T53", "V54") }), }; ObservableCounter observableCounter14 = meter.CreateObservableCounter("ByteObservableCounter", () => byteGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter14, byteGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter14, byteGaugeMeasurementList); Measurement[] shortGaugeMeasurementList = new Measurement[] { @@ -374,7 +481,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(30_000, new KeyValuePair[] { new KeyValuePair("T59", "V60"), new KeyValuePair("T61", "V62") }), }; ObservableCounter observableCounter15 = meter.CreateObservableCounter("ShortObservableCounter", () => shortGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter15, shortGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter15, shortGaugeMeasurementList); Measurement[] intGaugeMeasurementList = new Measurement[] { @@ -382,7 +489,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1_000_002, new KeyValuePair[] { new KeyValuePair("T67", "V68"), new KeyValuePair("T69", "V70") }), }; ObservableCounter observableCounter16 = meter.CreateObservableCounter("IntObservableCounter", () => intGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter16, intGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter16, intGaugeMeasurementList); Measurement[] longGaugeMeasurementList = new Measurement[] { @@ -390,7 +497,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(1_000_002_002, new KeyValuePair[] { new KeyValuePair("T75", "V76"), new KeyValuePair("T77", "V78") }), }; ObservableCounter observableCounter17 = meter.CreateObservableCounter("longObservableCounter", () => longGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter17, longGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter17, longGaugeMeasurementList); Measurement[] floatGaugeMeasurementList = new Measurement[] { @@ -398,7 +505,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e6f, new KeyValuePair[] { new KeyValuePair("T83", "V84"), new KeyValuePair("T85", "V86") }), }; ObservableCounter observableCounter18 = meter.CreateObservableCounter("floatObservableCounter", () => floatGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter18, floatGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter18, floatGaugeMeasurementList); Measurement[] doubleGaugeMeasurementList = new Measurement[] { @@ -406,7 +513,7 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e21, new KeyValuePair[] { new KeyValuePair("T91", "V92"), new KeyValuePair("T93", "V94") }), }; ObservableCounter observableCounter19 = meter.CreateObservableCounter("doubleObservableCounter", () => doubleGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter19, doubleGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter19, doubleGaugeMeasurementList); Measurement[] decimalGaugeMeasurementList = new Measurement[] { @@ -414,31 +521,90 @@ public void ObservableInstrumentMeasurementTest() new Measurement(68.15e6m, new KeyValuePair[] { new KeyValuePair("T99", "V100"), new KeyValuePair("T101", "V102") }), }; ObservableCounter observableCounter20 = meter.CreateObservableCounter("decimalObservableCounter", () => decimalGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableCounter20, decimalGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableCounter20, decimalGaugeMeasurementList); + + // + // CreateObservableUpDownCounter using Func> + // + Measurement[] byteUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(10, new KeyValuePair[] { new KeyValuePair("T48", "V49"), new KeyValuePair("T50", "V51") }), + new Measurement(12, new KeyValuePair[] { new KeyValuePair("T51", "V52"), new KeyValuePair("T53", "V54") }), + }; + ObservableUpDownCounter observableUpDownCounter14 = meter.CreateObservableUpDownCounter("ByteObservableUpDownCounter", () => byteUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter14, byteUpDownCounterMeasurementList); + + Measurement[] shortUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-20_000, new KeyValuePair[] { new KeyValuePair("T55", "V56"), new KeyValuePair("T57", "V58") }), + new Measurement(30_000, new KeyValuePair[] { new KeyValuePair("T59", "V60"), new KeyValuePair("T61", "V62") }), + }; + ObservableUpDownCounter observableUpDownCounter15 = meter.CreateObservableUpDownCounter("ShortObservableUpDownCounter", () => shortUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter15, shortUpDownCounterMeasurementList); + + Measurement[] intUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(1_000_001, new KeyValuePair[] { new KeyValuePair("T63", "V64"), new KeyValuePair("T65", "V66") }), + new Measurement(-1_000_002, new KeyValuePair[] { new KeyValuePair("T67", "V68"), new KeyValuePair("T69", "V70") }), + }; + ObservableUpDownCounter observableUpDownCounter16 = meter.CreateObservableUpDownCounter("IntObservableUpDownCounter", () => intUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter16, intUpDownCounterMeasurementList); + + Measurement[] longUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-1_000_001_001, new KeyValuePair[] { new KeyValuePair("T71", "V72"), new KeyValuePair("T73", "V74") }), + new Measurement(1_000_002_002, new KeyValuePair[] { new KeyValuePair("T75", "V76"), new KeyValuePair("T77", "V78") }), + }; + ObservableUpDownCounter observableUpDownCounter17 = meter.CreateObservableUpDownCounter("longObservableUpDownCounter", () => longUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter17, longUpDownCounterMeasurementList); + + Measurement[] floatUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-68.15e8f, new KeyValuePair[] { new KeyValuePair("T79", "V80"), new KeyValuePair("T81", "V82") }), + new Measurement(-68.15e6f, new KeyValuePair[] { new KeyValuePair("T83", "V84"), new KeyValuePair("T85", "V86") }), + }; + ObservableUpDownCounter observableUpDownCounter18 = meter.CreateObservableUpDownCounter("floatObservableUpDownCounter", () => floatUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter18, floatUpDownCounterMeasurementList); + + Measurement[] doubleUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(-68.15e20, new KeyValuePair[] { new KeyValuePair("T87", "V88"), new KeyValuePair("T89", "V90") }), + new Measurement(68.15e21, new KeyValuePair[] { new KeyValuePair("T91", "V92"), new KeyValuePair("T93", "V94") }), + }; + ObservableUpDownCounter observableUpDownCounter19 = meter.CreateObservableUpDownCounter("doubleObservableUpDownCounter", () => doubleUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter19, doubleUpDownCounterMeasurementList); + + Measurement[] decimalUpDownCounterMeasurementList = new Measurement[] + { + new Measurement(68.15e8m, new KeyValuePair[] { new KeyValuePair("T95", "V96"), new KeyValuePair("T97", "V98") }), + new Measurement(-68.15e6m, new KeyValuePair[] { new KeyValuePair("T99", "V100"), new KeyValuePair("T101", "V102") }), + }; + ObservableUpDownCounter observableUpDownCounter20 = meter.CreateObservableUpDownCounter("decimalObservableUpDownCounter", () => decimalUpDownCounterMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableUpDownCounter20, decimalUpDownCounterMeasurementList); // // CreateObservableGauge using IEnumerable> // ObservableGauge observableGauge14 = meter.CreateObservableGauge("ByteObservableGauge", () => byteGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge14, byteGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge14, byteGaugeMeasurementList); ObservableGauge observableGauge15 = meter.CreateObservableGauge("ShortObservableGauge", () => shortGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge15, shortGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge15, shortGaugeMeasurementList); ObservableGauge observableGauge16 = meter.CreateObservableGauge("IntObservableGauge", () => intGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge16, intGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge16, intGaugeMeasurementList); ObservableGauge observableGauge17 = meter.CreateObservableGauge("longObservableGauge", () => longGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge17, longGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge17, longGaugeMeasurementList); ObservableGauge observableGauge18 = meter.CreateObservableGauge("floatObservableGauge", () => floatGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge18, floatGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge18, floatGaugeMeasurementList); ObservableGauge observableGauge19 = meter.CreateObservableGauge("doubleObservableGauge", () => doubleGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge19, doubleGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge19, doubleGaugeMeasurementList); ObservableGauge observableGauge20 = meter.CreateObservableGauge("decimalObservableGauge", () => decimalGaugeMeasurementList); - ObservableInstruementMeasurementAggregationValidation(observableGauge20, decimalGaugeMeasurementList); + ObservableInstrumentMeasurementAggregationValidation(observableGauge20, decimalGaugeMeasurementList); }).Dispose(); } @@ -485,6 +651,42 @@ public void PassingVariableTagsParametersTest() return (decimal)(value * 2); }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (byte)(value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (short)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (int)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (long)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (float)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (double)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateUpDownCounter("Counter"), (instrument, value, tags) => + { + PublishUpDownCounterMeasurement(instrument as UpDownCounter, value, tags); + return (decimal)(-value * 2); + }); + InstrumentPassingVariableTagsParametersTest(meter.CreateHistogram("Histogram"), (instrument, value, tags) => { PublishHistogramMeasurement(instrument as Histogram, value, tags); @@ -531,11 +733,15 @@ public void MeterDisposalsTest() Meter meter2 = new Meter("MeterDisposalsTest2"); Meter meter3 = new Meter("MeterDisposalsTest3"); Meter meter4 = new Meter("MeterDisposalsTest4"); + Meter meter5 = new Meter("MeterDisposalsTest5"); + Meter meter6 = new Meter("MeterDisposalsTest6"); Counter counter = meter1.CreateCounter("Counter"); Histogram histogram = meter2.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter3.CreateObservableCounter("ObservableCounter", () => new Measurement(10, new KeyValuePair[] { new KeyValuePair("Key", "value")})); ObservableGauge observableGauge = meter4.CreateObservableGauge("ObservableGauge", () => new Measurement(5.7m, new KeyValuePair[] { new KeyValuePair("Key", "value")})); + UpDownCounter upDownCounter = meter5.CreateUpDownCounter("UpDownCounter"); + ObservableUpDownCounter observableUpDownCounter = meter6.CreateObservableUpDownCounter("ObservableUpDownCounter", () => new Measurement(-5, new KeyValuePair[] { new KeyValuePair("Key", "value")})); using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => theListener.EnableMeasurementEvents(theInstrument, theInstrument); @@ -543,6 +749,7 @@ public void MeterDisposalsTest() int count = 0; listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); @@ -554,30 +761,41 @@ public void MeterDisposalsTest() counter.Add(1); Assert.Equal(1, count); - histogram.Record(1); + upDownCounter.Add(-1); Assert.Equal(2, count); + histogram.Record(1); + Assert.Equal(3, count); + listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); meter1.Dispose(); counter.Add(1); - Assert.Equal(4, count); + Assert.Equal(6, count); meter2.Dispose(); histogram.Record(1); - Assert.Equal(4, count); + Assert.Equal(6, count); - listener.RecordObservableInstruments(); + meter5.Dispose(); + upDownCounter.Add(-10); Assert.Equal(6, count); + listener.RecordObservableInstruments(); + Assert.Equal(9, count); + meter3.Dispose(); listener.RecordObservableInstruments(); - Assert.Equal(7, count); + Assert.Equal(11, count); meter4.Dispose(); listener.RecordObservableInstruments(); - Assert.Equal(7, count); + Assert.Equal(12, count); + + meter6.Dispose(); + listener.RecordObservableInstruments(); + Assert.Equal(12, count); }).Dispose(); } @@ -589,9 +807,11 @@ public void ListenerDisposalsTest() Meter meter = new Meter("ListenerDisposalsTest"); Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("upDownCounter"); Histogram histogram = meter.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => new Measurement(10, new KeyValuePair[] { new KeyValuePair("Key", "value")})); ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => new Measurement(5.7m, new KeyValuePair[] { new KeyValuePair("Key", "value")})); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => new Measurement(-5.7f, new KeyValuePair[] { new KeyValuePair("Key", "value")})); int completedMeasurements = 0; MeterListener listener = new MeterListener(); @@ -600,7 +820,9 @@ public void ListenerDisposalsTest() int count = 0; + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); + listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); listener.SetMeasurementEventCallback((inst, measurement, tags, state) => count++); @@ -612,23 +834,26 @@ public void ListenerDisposalsTest() counter.Add(1); Assert.Equal(1, count); - histogram.Record(1); + upDownCounter.Add(-1); Assert.Equal(2, count); + histogram.Record(1); + Assert.Equal(3, count); + listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); listener.Dispose(); - Assert.Equal(4, completedMeasurements); + Assert.Equal(6, completedMeasurements); counter.Add(1); - Assert.Equal(4, count); + Assert.Equal(6, count); histogram.Record(1); - Assert.Equal(4, count); + Assert.Equal(6, count); listener.RecordObservableInstruments(); - Assert.Equal(4, count); + Assert.Equal(6, count); }).Dispose(); } @@ -712,8 +937,10 @@ public void ParallelRunningTest() Meter meter = new Meter("ParallelRunningTest"); Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter"); Histogram histogram = meter.CreateHistogram("Histogram"); ObservableCounter observableCounter = meter.CreateObservableCounter("ObservableCounter", () => 1); + ObservableUpDownCounter observableUpDownCounter = meter.CreateObservableUpDownCounter("ObservableUpDownCounter", () => 1); ObservableGauge observableGauge = meter.CreateObservableGauge("ObservableGauge", () => 1); MeterListener listener = new MeterListener(); @@ -723,7 +950,7 @@ public void ParallelRunningTest() listener.SetMeasurementEventCallback((inst, measurement, tags, state) => Interlocked.Add(ref totalCount, measurement)); listener.Start(); - Task[] taskList = new Task[6]; + Task[] taskList = new Task[9]; int loopLength = 10_000; @@ -733,10 +960,13 @@ public void ParallelRunningTest() taskList[3] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { histogram.Record(1); } }); taskList[4] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); taskList[5] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); + taskList[6] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { upDownCounter.Add(1); } }); + taskList[7] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { upDownCounter.Add(1); } }); + taskList[8] = Task.Factory.StartNew(() => { for (int i = 0; i < loopLength; i++) { listener.RecordObservableInstruments(); } }); Task.WaitAll(taskList); - Assert.Equal(loopLength * 8, totalCount); + Assert.Equal(loopLength * 15, totalCount); }).Dispose(); } @@ -817,9 +1047,11 @@ public void TestRecordingMeasurementsWithTagList() using (MeterListener listener = new MeterListener()) { Counter counter = meter.CreateCounter("Counter"); + UpDownCounter upDownCounter = meter.CreateUpDownCounter("UpDownCounter"); Histogram histogram = meter.CreateHistogram("histogram"); listener.EnableMeasurementEvents(counter, counter); + listener.EnableMeasurementEvents(upDownCounter, upDownCounter); listener.EnableMeasurementEvents(histogram, histogram); KeyValuePair[] expectedTags = null; @@ -835,11 +1067,13 @@ public void TestRecordingMeasurementsWithTagList() expectedTags = new KeyValuePair[0]; counter.Add(10, new TagList()); + upDownCounter.Add(-1, new TagList()); histogram.Record(10, new TagList()); // 1 Tags expectedTags = new KeyValuePair[] { new KeyValuePair("Key1", "Value1") }; counter.Add(10, new TagList() { expectedTags[0] }); + upDownCounter.Add(-2, new TagList() { expectedTags[0] }); histogram.Record(10, new TagList() { new KeyValuePair("Key1", "Value1") }); // 2 Tags @@ -850,6 +1084,7 @@ public void TestRecordingMeasurementsWithTagList() }.ToArray(); counter.Add(10, new TagList() { expectedTags[0], expectedTags[1] }); + upDownCounter.Add(-3, new TagList() { expectedTags[0], expectedTags[1] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1] }); // 8 Tags @@ -866,6 +1101,7 @@ public void TestRecordingMeasurementsWithTagList() }.ToArray(); counter.Add(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); + upDownCounter.Add(-4, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7] }); // 13 Tags @@ -888,6 +1124,8 @@ public void TestRecordingMeasurementsWithTagList() counter.Add(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); + upDownCounter.Add(-5, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], + expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); histogram.Record(10, new TagList() { expectedTags[0], expectedTags[1], expectedTags[2], expectedTags[3], expectedTags[4], expectedTags[5], expectedTags[6], expectedTags[7], expectedTags[8], expectedTags[9], expectedTags[10], expectedTags[11], expectedTags[12] }); } @@ -913,6 +1151,24 @@ private void PublishCounterMeasurement(Counter counter, T value, KeyValueP } } + private void PublishUpDownCounterMeasurement(UpDownCounter counter, T value, KeyValuePair[] tags) where T : struct + { + switch (tags.Length) + { + case 0: counter.Add(value); break; + case 1: counter.Add(value, tags[0]); break; + case 2: counter.Add(value, tags[0], tags[1]); break; + case 3: counter.Add(value, tags[0], tags[1], tags[2]); break; + case 4: counter.Add(value, tags[0], tags[1], tags[2], tags[3]); break; + case 5: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4]); break; + case 6: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5]); break; + case 7: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6]); break; + case 8: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6], tags[7]); break; + case 9: counter.Add(value, tags[0], tags[1], tags[2], tags[3], tags[4], tags[5], tags[6], tags[7], tags[8]); break; + default: counter.Add(value, tags); break; + } + } + private void PublishHistogramMeasurement(Histogram histogram, T value, KeyValuePair[] tags) where T : struct { switch (tags.Length) @@ -940,7 +1196,7 @@ private void ValidateInstrumentInfo(Instrument instrument, string name, string u Assert.Equal(isObservable, instrument.IsObservable); } - private void InstruementMeasurementAggregationValidation(Instrument instrument, Action[]> record) where T : struct + private void InstrumentMeasurementAggregationValidation(Instrument instrument, Action[]> record, bool allowNegative = false) where T : struct { using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => @@ -968,17 +1224,28 @@ private void InstruementMeasurementAggregationValidation(Instrument instru listener.Start(); - for (byte i = 0; i < 100; i++) + if (allowNegative && typeof(T) != typeof(Byte)) { - expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); - expectedValue = ConvertValue(i); - record(expectedValue, expectedTags.ToArray()); + for (short i = 0; i < 100; i++) + { + expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); + expectedValue = ConvertValue((short)(i % 2 == 0 ? 2 : -1)); + record(expectedValue, expectedTags.ToArray()); + } + } + else + { + for (short i = 0; i < 100; i++) + { + expectedTags.Add(new KeyValuePair(i.ToString(), i.ToString())); + expectedValue = ConvertValue(i); + record(expectedValue, expectedTags.ToArray()); + } } - Assert.Equal(100, counter); } - private void ObservableInstruementMeasurementAggregationValidation(ObservableInstrument instrument, Measurement[] expectedResult) where T : struct + private void ObservableInstrumentMeasurementAggregationValidation(ObservableInstrument instrument, Measurement[] expectedResult) where T : struct { using MeterListener listener = new MeterListener(); listener.InstrumentPublished = (theInstrument, theListener) => @@ -1121,10 +1388,10 @@ private void InstrumentPassingVariableTagsParametersTest(Instrument instru expectedValue = record(instrument, expectedValue, expectedTags); } - private T ConvertValue(byte value) where T : struct + private T ConvertValue(short value) where T : struct { - if (typeof(T) == typeof(byte)) { return (T)(object)value;} - if (typeof(T) == typeof(short)) { return (T)(object)Convert.ToInt16(value); } + if (typeof(T) == typeof(byte)) { return (T)(object)(byte)value; } + if (typeof(T) == typeof(short)) { return (T)(object)value; } if (typeof(T) == typeof(int)) { return (T)(object)Convert.ToInt32(value); } if (typeof(T) == typeof(long)) { return (T)(object)Convert.ToInt64(value); } if (typeof(T) == typeof(float)) { return (T)(object)Convert.ToSingle(value); } diff --git a/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx index ffeb7516c3a7ea..e0aec25828364b 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.EventLog/src/Resources/Strings.resx @@ -137,9 +137,6 @@ Cannot retrieve all entries. - - Only the first eight characters of a custom log name are significant, and there is already another log on the system using the first eight characters of the name given. Name given: '{0}', name of existing log: '{1}'. - Invalid eventID value '{0}'. It must be in the range between '{1}' and '{2}'. @@ -242,7 +239,4 @@ Log {0} has already been registered as a source on the local computer. - - Opening Win32 devices other than file such as COM ports, printers, disk partitions and tape drives is not supported. Avoid use of "\\\\.\\" in the path. - diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj index 9851685566186c..220c3e850b5f1f 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj @@ -6,6 +6,7 @@ + @@ -18,4 +19,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs new file mode 100644 index 00000000000000..b33f32066185b1 --- /dev/null +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Diagnostics +{ + public readonly partial struct CounterSample : System.IEquatable + { + } +} diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx index 1a5909f5194cfc..829c04125b3732 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/Resources/Strings.resx @@ -158,9 +158,6 @@ Cannot access shared memory, AppDomain has been unloaded. - - Cannot initialize security descriptor initialized. - Cannot create file mapping. @@ -322,7 +319,7 @@ CounterSet '{0}' does not include any counters. - + CounterSet '{0}' already registered. diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 28133feec83ed6..5ebf58e40c57e6 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -3,6 +3,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) $(NoWarn);CA1847 + $(NoWarn);CA1066 annotations true Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters. diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs index c89df23ed9aac6..315ec5a87ccb47 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics /// /// A struct holding the raw data for a performance counter. /// - public readonly struct CounterSample + public readonly struct CounterSample : IEquatable { private readonly long _rawValue; private readonly long _baseValue; diff --git a/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx index 31cd6a75a072af..ddbeed29f973ac 100644 --- a/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.Process/src/Resources/Strings.resx @@ -215,9 +215,6 @@ An async read operation has already been started on the stream. - - Invalid value '{1}' for parameter '{0}'. - Cannot load Category Help data because an invalid index '{0}' was read from the registry. @@ -311,9 +308,6 @@ UseShellExecute is not supported on this platform. - - Retrieving information about local processes is not supported on this platform. - StandardInputEncoding is only supported when standard input is redirected. @@ -338,4 +332,4 @@ sysctl {0} failed with {1} error. - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs index 85525bbe3e8a59..7a776feba46dc6 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.cs @@ -10,11 +10,7 @@ internal static partial class ProcessManager /// true if the machine is remote; false if it's local. public static bool IsRemoteMachine(string machineName) { - if (machineName == null) - throw new ArgumentNullException(nameof(machineName)); - - if (machineName.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidParameter, nameof(machineName), machineName)); + ArgumentException.ThrowIfNullOrEmpty(machineName); return IsRemoteMachineCore(machineName); } diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 18406af45353f4..b9d70837e3d168 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -1147,7 +1147,7 @@ public void GetProcesseses_NullMachineName_ThrowsArgumentNullException() [Fact] public void GetProcesses_EmptyMachineName_ThrowsArgumentException() { - AssertExtensions.Throws(null, () => Process.GetProcesses("")); + AssertExtensions.Throws("machineName", () => Process.GetProcesses("")); } [Fact] @@ -1292,7 +1292,7 @@ public void GetProcessesByName_NullMachineName_ThrowsArgumentNullException() public void GetProcessesByName_EmptyMachineName_ThrowsArgumentException() { Process currentProcess = Process.GetCurrentProcess(); - AssertExtensions.Throws(null, () => Process.GetProcessesByName(currentProcess.ProcessName, "")); + AssertExtensions.Throws("machineName", () => Process.GetProcessesByName(currentProcess.ProcessName, "")); } [Fact] diff --git a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs index 0efbf90bb1da10..60e755ecf790c4 100644 --- a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs +++ b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs @@ -170,7 +170,7 @@ public enum SymAddressKind BitField = 9, NativeSectionOffset = 10, } - public readonly partial struct SymbolToken + public readonly partial struct SymbolToken : System.IEquatable { private readonly int _dummyPrimitive; public SymbolToken(int val) { throw null; } diff --git a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs index b6a894f144fc90..8b27f618770fb7 100644 --- a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs +++ b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.SymbolStore { - public readonly struct SymbolToken + public readonly struct SymbolToken : IEquatable { private readonly int _token; diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx index 12b248f4ddec28..b994dce1b5ab60 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -57,10 +58,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - '{0}' can not be empty string. - Trace - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs index 6c399ae77bc405..52454f94c69068 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/DelimitedListTraceListener.cs @@ -63,11 +63,7 @@ public string Delimiter } set { - if (value == null) - throw new ArgumentNullException(nameof(Delimiter)); - - if (value.Length == 0) - throw new ArgumentException(SR.Format(SR.Generic_ArgCantBeEmptyString, nameof(Delimiter))); + ArgumentException.ThrowIfNullOrEmpty(value, nameof(Delimiter)); lock (this) { diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs index f7620b442c5c19..352d0d1a6b29cb 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/CtorsDelimiterTests.cs @@ -90,8 +90,8 @@ public static void TestDelimiterProperty() { var target = new DelimitedListTraceListener(FileStream.Null); Assert.Equal(DefaultDelimiter, target.Delimiter); - Assert.Throws(() => target.Delimiter = null); - AssertExtensions.Throws(null, () => target.Delimiter = string.Empty); + AssertExtensions.Throws("Delimiter", () => target.Delimiter = null); + AssertExtensions.Throws("Delimiter", () => target.Delimiter = string.Empty); } [Fact] diff --git a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx index 8b4f1d87314133..4062db3292bae6 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx +++ b/src/libraries/System.Diagnostics.TraceSource/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -87,7 +88,4 @@ Attempted to set {0} to a value that is too high. Setting level to TraceLevel.Verbose - - Argument {0} cannot be null or zero-length. - - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs index 4b474c82442af1..18b00fdf83f638 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/SwitchAttribute.cs @@ -26,10 +26,7 @@ public string SwitchName [MemberNotNull(nameof(_name))] set { - if (value == null) - throw new ArgumentNullException(nameof(value)); - if (value.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidNullEmptyArgument, nameof(value)), nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _name = value; } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs index aa786154cbb567..4aedca7d878f59 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceSource.cs @@ -28,10 +28,7 @@ public TraceSource(string name) public TraceSource(string name, SourceLevels defaultLevel) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(SR.Format(SR.InvalidNullEmptyArgument, nameof(name)), nameof(name)); + ArgumentException.ThrowIfNullOrEmpty(name); _sourceName = name; _switchLevel = defaultLevel; diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs index 2ee59adf59464f..012a03bcad1c16 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsManifestNegative.cs @@ -82,13 +82,13 @@ public void Test_GenerateManifest_InvalidEventSources() Assert.NotNull(EventSource.GenerateManifest(typeof(Sdt.EventWithReturnEventSource), string.Empty, EventManifestOptions.AllowEventSourceOverride)); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty, strictOptions)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.NegativeEventIdEventSource), string.Empty, EventManifestOptions.AllowEventSourceOverride)); - AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId", "WriteInteger"), e); + AsserExceptionStringsEqual(() => GetResourceString("EventSource_NeedPositiveId"), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.OutOfRangeKwdEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, @@ -124,7 +124,7 @@ public void Test_GenerateManifest_InvalidEventSources() e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EnumKindMismatchEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EnumKindMismatch", "Op1", "EventKeywords", "Opcodes"), + GetResourceString("EventSource_EnumKindMismatch", "EventKeywords", "Opcodes"), GetResourceString("EventSource_UndefinedKeyword", "0x1", "WriteInteger")), e); @@ -144,14 +144,14 @@ public void Test_GenerateManifest_InvalidEventSources() e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EventIdReusedEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1, "WriteInteger1"), + GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1), GetResourceString("EventSource_TaskOpcodePairReused", "WriteInteger2", 1, "WriteInteger1", 1)), e); e = AssertExtensions.Throws(null, () => EventSource.GenerateManifest(typeof(Sdt.EventIdReusedEventSource), string.Empty, strictOptions)); AsserExceptionStringsEqual(() => string.Join(Environment.NewLine, - GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1, "WriteInteger1"), + GetResourceString("EventSource_EventIdReused", "WriteInteger2", 1), GetResourceString("EventSource_TaskOpcodePairReused", "WriteInteger2", 1, "WriteInteger1", 1)), e); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx index 4510671778d18a..dbe197a32bbf49 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/Resources/Strings.resx @@ -131,12 +131,6 @@ This store does not support this method. - - The PrincipalContext can only be set on an unpersisted Principal. - - - Principals in this type of store do not support the property '{0}'. - Principals in this version of the store do not support the property '{0}'. @@ -164,30 +158,12 @@ The Principal object must be persisted before this method can be called. - - This type of identity information is not supported on principals in this type of store. - - - This type of identity information can not be cleared on principals in this type of store. - - - This type of store does not permit changing the SAM account name after the principal has been persisted. - - - The identityType parameter cannot be empty. - Persisted Principal objects cannot be used as query filters. - - A PrincipalContext must first be assigned to the PrincipalSearcher before the query can be performed. - A QueryFilter must first be assigned to the PrincipalSearcher before the query can be performed. - - A PrincipalContext must first be assigned to the PrincipalSearcher before the underlying searcher can be retrieved. - There is no underlying searcher for the type of store associated with the PrincipalContext. @@ -212,9 +188,6 @@ The enumerator is positioned before the first element of the collection or after the last element. - - More than one matching identity was found. - Multiple principals contain a matching Identity. @@ -242,9 +215,6 @@ The enumerator is positioned before the first element of the collection or after the last element. - - The Principal object already exists in the collection. - The subtype parameter must be either AuthenticablePrincipal or a subtype of AuthenticablePrincipal. @@ -254,12 +224,6 @@ A PrincipalContext must first be assigned to the unpersisted User object before this method can be called. - - Domain users are not supported on this platform. - - - Local machine users not supported on this platform. - The User object for the current user could not be found. You may not have access to it. @@ -305,21 +269,12 @@ The samAccountName IdentityType must be in the form "domainname\\userName", "machinename\\userName", or "userName". - - This store does not support setting IdentityClaims with a restricted range of times for which the IdentityClaim is valid. - The Group object can not be saved until the unpersisted Principal object in its Members property is either saved or removed from the collection. The Principal object must have a valid SID IdentityType in order to perform this operation. - - An exception occurred while updating the group membership on the store. - - - An exception occurred while saving the changes to the store. - Only domain Principal objects can be inserted into groups in this store. @@ -371,9 +326,6 @@ Computer accounts in this store can not have their passwords expired. - - This store does not permit changing the IdentityClaims on a principal once the principal has been persisted. - One of the Principal objects to be inserted into or removed from the group's membership does not contain a SID. @@ -407,33 +359,6 @@ An error occurred while enumerating the groups. The group could not be found. - - The '{0}' element can only appear once in the configuration file. - - - The '{0}' attribute for element '{1}' of the configuration file must be set to 'true' or 'false'. - - - The '{0}' attribute for element '{1}' of the configuration file is set to an unknown value. - - - The '{0}' attribute for element '{1}' of the configuration file must be set to a string. - - - Unknown element '{0}' was found in the configuration file. - - - The target parameter is not a PrincipalPermission. - - - The SecurityElement is not a permission. - - - The SecurityElement does not have a valid version. Version '1' was expected. - - - The SecurityElement does not contain a valid value for the 'Unrestricted' attribute. - The options value is invalid. The Machine store only supports Negotiate. @@ -452,9 +377,6 @@ Property is not valid for this store type. - - {0} is not supported by the {1} ContextType. - SamAccountName or Name must be assigned to a newly-created Principal object in this store prior to saving. diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs index 709ccb1601f734..2d8eebfc84ee79 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs @@ -1357,6 +1357,12 @@ protected static void ExtensionCacheToLdapConverter(Principal p, string property valueCollection = (ICollection)kvp.Value.Value; } + // We make a local copy of all elements to set, instead of adding them to the real property + // directly. This allows us to override all existing elements without using Clear() and then Add(), + // as that order sends a Clear operation and then a number of Append operations, which will fail. + // Instead, setting the new list all at once will send a Clear operation and then an Update operation. + var propertyValueList = new List(); + foreach (object oVal in valueCollection) { if (null != oVal) @@ -1373,8 +1379,11 @@ protected static void ExtensionCacheToLdapConverter(Principal p, string property if (p.unpersisted && null == oVal) continue; - de.Properties[kvp.Key].Add(oVal); + propertyValueList.Add(oVal); } + + de.Properties[kvp.Key].Value = propertyValueList.ToArray(); + GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "ExtensionCacheToLdapConverter - Collection complete"); } else diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs index b132723c385ace..3a04bcc8a4b77c 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs @@ -44,7 +44,7 @@ internal static class CapabilityMap public const string LDAP_CAP_ACTIVE_DIRECTORY_V61_OID = "1.2.840.113556.1.4.1935"; } - internal sealed class CredentialValidator + internal sealed class CredentialValidator : IDisposable { private enum AuthMethod { @@ -341,6 +341,14 @@ public bool Validate(string userName, string password, ContextOptions connection return (BindSam(_serverName, userName, password)); } } + + public void Dispose() + { + foreach (LdapConnection connection in _connCache.Values) + { + connection.Dispose(); + } + } } // ******************************************** public class PrincipalContext : IDisposable @@ -1014,6 +1022,8 @@ public void Dispose() if (_queryCtx != null) _queryCtx.Dispose(); + _credValidate.Dispose(); + _disposed = true; GC.SuppressFinalize(this); } diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs index 4796aa44515585..33de32cb836c09 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/tests/AccountManagementTests.cs @@ -7,6 +7,7 @@ using System.DirectoryServices.Tests; using System.Linq; using Xunit; +using System.Collections.Generic; namespace System.DirectoryServices.AccountManagement.Tests { @@ -16,6 +17,42 @@ public class AccountManagementTests internal static bool IsActiveDirectoryServer => IsLdapConfigurationExist && LdapConfiguration.Configuration.IsActiveDirectoryServer; internal static bool IsDomainJoinedClient => !Environment.MachineName.Equals(Environment.UserDomainName, StringComparison.OrdinalIgnoreCase); + [Fact] + public void TestConstructors() + { + using var context = new PrincipalContext(ContextType.Machine); + + using (var principal = new ComputerPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Empty(principal.ServicePrincipalNames); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new ComputerPrincipal(null)); + Assert.Throws(() => new ComputerPrincipal(null, "samAccountName", "password", true)); + Assert.Throws(() => new ComputerPrincipal(context, null, "password", true)); + Assert.Throws(() => new ComputerPrincipal(context, "samAccountName", null, true)); + + using (var principal = new UserPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new UserPrincipal(null)); + Assert.Throws(() => new UserPrincipal(null, "samAccountName", "password", true)); + Assert.Throws(() => new UserPrincipal(context, null, "password", true)); + Assert.Throws(() => new UserPrincipal(context, "samAccountName", null, true)); + + using (var principal = new GroupPrincipal(context)) + { + Assert.Same(context, principal.Context); + Assert.Equal(ContextType.Machine, principal.ContextType); + } + Assert.Throws(() => new GroupPrincipal(null)); + Assert.Throws(() => new GroupPrincipal(null, "samAccountName")); + Assert.Throws(() => new GroupPrincipal(context, null)); + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestCurrentUser() { @@ -23,7 +60,7 @@ public void TestCurrentUser() using (UserPrincipal p = FindUser(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) { Assert.NotNull(p); - Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.Name); + Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.SamAccountName); } } @@ -34,6 +71,7 @@ public void TestCurrentUserContext() using (UserPrincipal p = FindUser(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) using (UserPrincipal cu = UserPrincipal.Current) { + Assert.NotNull(cu); Assert.NotEqual(cu.Context.Name, p.Context.Name); } } @@ -45,7 +83,7 @@ public void TestCurrentUserUsingSearchFilter() using (UserPrincipal p = FindUserUsingFilter(LdapConfiguration.Configuration.UserNameWithNoDomain, context)) { Assert.NotNull(p); - Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.Name); + Assert.Equal(LdapConfiguration.Configuration.UserNameWithNoDomain, p.SamAccountName); } } @@ -278,6 +316,27 @@ public void TestNegativeCases() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestInvalidSaves() + { + UserData u1 = UserData.GenerateUserData("CoreFxUser9"); + + DeleteUser(u1.Name); + + try + { + using var context = DomainContext; + using var user = new UserPrincipal(context, u1.Name, u1.Password, true); + + Assert.Throws(() => user.Save(null)); + Assert.Throws(() => user.Save(new PrincipalContext(ContextType.Machine))); + } + finally + { + DeleteUser(u1.Name); + } + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestComputerContext() { @@ -306,6 +365,13 @@ public void TestComputerContext() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestComputerNegativeCases() + { + using var context = DomainContext; + + } + [ConditionalFact(nameof(IsActiveDirectoryServer))] public void TestUpdateUserAndGroupData() { @@ -325,6 +391,7 @@ public void TestUpdateUserAndGroupData() using (GroupPrincipal gp = FindGroup(g1.Name, context)) { Assert.Equal(group.DisplayName, gp.DisplayName); } user.DisplayName = "Updated CoreFx Test Child User 4"; + user.Save(); group.DisplayName = "Updated CoreFX Test Group Container 4"; group.Save(); @@ -365,6 +432,91 @@ public void TestCredentials() } } + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestCustomUserAttributes() + { + var userData = CustomUserData.GenerateUserData("CustomCoreFxUser1"); + + DeleteUser(userData.Name); + + try + { + using var context = DomainContext; + using (var principal = CreateCustomUser(context, userData)) + { + Assert.NotNull(principal); + ValidateRecentAddedUser(context, userData); + ValidateUserUsingPrincipal(context, principal); + + using var foundPrincipal = FindCustomUser(userData.Name, context); + Assert.NotNull(foundPrincipal); + + Assert.Equal(userData.PostalCode, foundPrincipal.PostalCode); + Assert.Equal(principal.PostalCode, foundPrincipal.PostalCode); + + Assert.Equal(userData.PostalAddress, foundPrincipal.PostalAddress); + Assert.Equal(principal.PostalAddress, foundPrincipal.PostalAddress); + } + } + finally + { + DeleteUser(userData.Name); + } + } + + [ConditionalFact(nameof(IsActiveDirectoryServer))] + public void TestMultiValueCustomAttributes() + { + var userData = CustomUserData.GenerateUserData("CustomCoreFxUser2"); + userData.PostalAddress.Add("Second address"); + + DeleteUser(userData.Name); + + // Check whether directory-data is equivalent to expected data + void CheckAddressWithDirectory(PrincipalContext context, List address) + { + using var foundPrincipal = FindCustomUser(userData.Name, context); + Assert.NotNull(foundPrincipal); + Assert.Equal(address.ToHashSet(), foundPrincipal.PostalAddress.ToHashSet()); + }; + + // Helper to update list + void UpdateAddressList(CustomUserPrincipal principal, Action> update) + { + var localCopy = principal.PostalAddress; + update(localCopy); + principal.PostalAddress = localCopy; + principal.Save(); + } + + try + { + // Initial setup + using var context = DomainContext; + using var principal = CreateCustomUser(context, userData); + Assert.NotNull(principal); + Assert.Equal(userData.PostalAddress, principal.PostalAddress); + + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Add address + UpdateAddressList(principal, addresses => addresses.Add("Third address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Remove address + UpdateAddressList(principal, addresses => addresses.Remove("Second address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + + // Remove address so we have one remaining + UpdateAddressList(principal, addresses => addresses.Remove("Third address")); + CheckAddressWithDirectory(context, principal.PostalAddress); + } + finally + { + DeleteUser(userData.Name); + } + } + private void ValidateRecentAddedUser(PrincipalContext context, UserData userData) { using (UserPrincipal p = FindUser(userData.Name, context)) @@ -440,6 +592,20 @@ private UserPrincipal CreateUser(PrincipalContext context, UserData userData) return user; } + private CustomUserPrincipal CreateCustomUser(PrincipalContext context, CustomUserData userData) + { + CustomUserPrincipal user = new CustomUserPrincipal(context, userData.Name, userData.Password, true); + + // assign some properties to the custom user principal + user.GivenName = userData.FirstName; + user.Surname = userData.LastName; + user.DisplayName = userData.DisplayName; + user.PostalCode = userData.PostalCode; + user.PostalAddress = userData.PostalAddress; + user.Save(); + return user; + } + private GroupPrincipal CreateGroup(PrincipalContext context, GroupData groupData) { GroupPrincipal group = new GroupPrincipal(context, groupData.Name); @@ -490,7 +656,12 @@ private GroupPrincipal FindGroup(string groupName, PrincipalContext context) private UserPrincipal FindUser(string userName, PrincipalContext context) { - return UserPrincipal.FindByIdentity(context, IdentityType.Name, userName); + return UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName); + } + + private CustomUserPrincipal FindCustomUser(string userName, PrincipalContext context) + { + return CustomUserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName); } private UserPrincipal FindUserUsingFilter(string userName, PrincipalContext context) @@ -528,6 +699,23 @@ internal static UserData GenerateUserData(string name) internal string DisplayName { get; set; } } + internal class CustomUserData : UserData + { + internal static new CustomUserData GenerateUserData(string name) => new CustomUserData + { + Name = name, + Password = Guid.NewGuid().ToString() + "#1aZ", + FirstName = "First " + name, + LastName = "Last " + name, + DisplayName = "Display " + name, + PostalAddress = new List { "Postal Address " + name }, + PostalCode = "Code " + name + }; + + internal string PostalCode { get; set; } + internal List PostalAddress { get; set; } + } + internal class GroupData { internal static GroupData GenerateGroupData(string name) @@ -545,11 +733,14 @@ internal static GroupData GenerateGroupData(string name) } [DirectoryObjectClass("user")] + [DirectoryRdnPrefix("CN")] public class CustomUserPrincipal : UserPrincipal { private CustomFilter _customFilter; public CustomUserPrincipal(PrincipalContext context) : base(context) { } + public CustomUserPrincipal(PrincipalContext context, string samAccountName, string password, bool enabled) + : base(context, samAccountName, password, enabled) { } public void SetUserNameFilter(string name) { @@ -568,6 +759,27 @@ public override AdvancedFilters AdvancedSearchFilter return _customFilter; } } + + // Custom properties + [DirectoryProperty("postalCode")] + public string PostalCode + { + get => ExtensionGet("postalCode").FirstOrDefault() as string; + set => ExtensionSet("postalCode", value); + } + + [DirectoryProperty("postalAddress")] + public List PostalAddress + { + get => ExtensionGet("postalAddress").OfType().ToList(); + set => ExtensionSet("postalAddress", value == null || value?.Count == 0 ? null : value.ToArray()); + } + + // Method overrides + public new static CustomUserPrincipal FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue) + { + return FindByIdentityWithType(context, typeof(CustomUserPrincipal), identityType, identityValue) as CustomUserPrincipal; + } } public class CustomFilter : AdvancedFilters @@ -576,7 +788,7 @@ public CustomFilter(Principal p) : base(p) { } public void SetFilter(string userName) { - this.AdvancedFilterSet("cn", userName, typeof(string), MatchType.Equals); + this.AdvancedFilterSet("samAccountName", userName, typeof(string), MatchType.Equals); } } } diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs deleted file mode 100644 index ce6b8cf70565b9..00000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/ComputerPrincipalTest.cs +++ /dev/null @@ -1,83 +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 Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class ComputerPrincipalTest : PrincipalTest - { - [Fact] - public void Ctor_Context() - { - var context = new PrincipalContext(ContextType.Machine); - var principal = new ComputerPrincipal(context); - Assert.Same(context, principal.Context); - Assert.Empty(principal.ServicePrincipalNames); - } - - [Fact] - public void Ctor_NullContext_ThrowsArgumentException() - { - AssertExtensions.Throws(null, () => new ComputerPrincipal(null)); - AssertExtensions.Throws(null, () => new ComputerPrincipal(null, "samAccountName", "password", enabled: true)); - } - - [Fact] - public void Ctor_NullSamAccountName_ThrowsArgumentException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws(null, () => new ComputerPrincipal(context, null, "password", enabled: true)); - } - - [Fact] - public void Ctor_EmptySamAccountName_ThrowsArgumentNullException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws("value", null, () => new ComputerPrincipal(context, string.Empty, "password", enabled: true)); - } - - [Fact] - public void Ctor_NullPassword_ThrowsArgumentException() - { - var context = new PrincipalContext(ContextType.Machine); - AssertExtensions.Throws(null, () => new ComputerPrincipal(context, "samAccountName", null, enabled: true)); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoNorServerCore), nameof(PlatformDetection.IsNotWindowsIoTCore))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34442", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - public void Ctor_MachineContext_NoException() - { - var context = new PrincipalContext(ContextType.Machine); - var principal = new ComputerPrincipal(context, "samAccountName", "password", enabled: true); - Assert.Equal(ContextType.Machine, principal.ContextType); - } - - [Fact] - public void ComputerPrincipalConstructorTest() - { - if (DomainContext == null) - { - return; - } - - ComputerPrincipal computer = new ComputerPrincipal(DomainContext); - computer.Dispose(); - } - - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new ComputerPrincipal(context) { Name = name }; - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs deleted file mode 100644 index 7f378a13acf430..00000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/ExtendedUserPrincipal.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.DirectoryServices.AccountManagement.Tests -{ - [DirectoryRdnPrefix("CN")] - [DirectoryObjectClass("User")] - public class ExtendedUserPrincipal : UserPrincipal, IExtendedPrincipalTest - { - public ExtendedUserPrincipal(PrincipalContext context) : base(context) { } - - public static new ExtendedUserPrincipal FindByIdentity(PrincipalContext context,string identityValue) - { - return (ExtendedUserPrincipal)FindByIdentityWithType(context, typeof(ExtendedUserPrincipal), identityValue); - } - - [DirectoryProperty("jpegPhoto")] - public byte[] ByteArrayExtension - { - get => (byte[])ExtensionGet("jpegPhoto")[0]; - set => ExtensionSet("jpegPhoto", value); - } - - public object ObjectExtension - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public object[] ObjectArrayExtension - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs deleted file mode 100644 index 8817afbddd186a..00000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/GroupPrincipalTest.cs +++ /dev/null @@ -1,68 +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 Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class GroupPrincipalTest : PrincipalTest - { - [Fact] - public void GroupPrincipalConstructorTest() - { - if (DomainContext == null) - { - return; - } - - GroupPrincipal group = new GroupPrincipal(DomainContext); - group.Dispose(); - } - - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new GroupPrincipal(context, name); - } - - [Fact] - public void IsMemberOfTest() - { - if (DomainContext == null) - { - return; - } - - using (GroupPrincipal group = GroupPrincipal.FindByIdentity(DomainContext, "TestLargeGroup")) - { - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1499-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1500-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user1501-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user3000-LargeGroup").IsMemberOf(group)); - Assert.True(UserPrincipal.FindByIdentity(DomainContext, "user3001-LargeGroup").IsMemberOf(group)); - Assert.False(UserPrincipal.FindByIdentity(DomainContext, "userNotInLargeGroup").IsMemberOf(group)); - } - } - - private void CreateManyUsersInGroup(GroupPrincipal group) - { - for (int i = 1; i < 3002; i++) - { - string name = $"user{i:0000}-LargeGroup"; - UserPrincipal user = new UserPrincipal(DomainContext, name, "Adrumble@6", false); - user.Save(); - group.Members.Add(user); - } - group.Save(); - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs deleted file mode 100644 index a0078001f74f46..00000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/PrincipalTest.cs +++ /dev/null @@ -1,143 +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.Collections.Generic; -using System.Security.Principal; -using Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public abstract class PrincipalTest : IDisposable - { - public PrincipalContext DomainContext { get; private set; } - - public PrincipalTest() => RefreshContext(); - - private void RefreshContext() - { - string username = "Administrator"; - string password = Environment.GetEnvironmentVariable("TESTPASSWORD"); - string OU = "Tests"; - string baseDomain = WindowsIdentity.GetCurrent().Name.Split(new char[] { '\\' })[1] + "-TEST"; - string domain = $"{baseDomain}.nttest.microsoft.com"; - string container = $"ou={OU},dc={baseDomain},dc=nttest,dc=microsoft,dc=com"; - DomainContext?.Dispose(); - try - { - DomainContext = new PrincipalContext(ContextType.Domain, domain, container, username, password); - } - catch - { - } - } - - public void Dispose() => DomainContext?.Dispose(); - - [Fact] - public void AddExistingPrincipal() - { - if (DomainContext == null) - { - return; - } - - // use new GUID for the user name so we be sure this user does not exist yet - string name = Guid.NewGuid().ToString(); - using (Principal principal = CreatePrincipal(DomainContext, name)) - { - principal.Save(); - } - - Assert.NotNull(Principal.FindByIdentity(DomainContext, name)); - - // this previously caused the user to be deleted. it is still expected to throw an exception, but not delete the user - bool exceptionThrown = false; - try - { - using (Principal principal = CreatePrincipal(DomainContext, name)) - { - principal.Save(); - } - } - catch (PrincipalExistsException) - { - exceptionThrown = true; - } - - // validate that we correctly throw an exception when trying to add an existing principal - Assert.True(exceptionThrown); - - // validate that we did not delete incorrectly delete the first principal - using (Principal principal2 = Principal.FindByIdentity(DomainContext, name)) - { - Assert.NotNull(principal2); - - // explicitly delete the user and check it was really deleted - principal2.Delete(); - } - - // ensure we cleaned up the test principal - Assert.Null(Principal.FindByIdentity(DomainContext, name)); - } - - [Fact] - public void TestExtendedPrincipal() - { - if (DomainContext == null) - { - return; - } - - string name = Guid.NewGuid().ToString(); - byte[] writtenArray = new byte[] { 10, 20, 30 }; - using (Principal principal = CreateExtendedPrincipal(DomainContext, name)) - { - IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal; - extendedPrincipal.ByteArrayExtension = writtenArray; - principal.Save(); - } - - RefreshContext(); - using (Principal principal = FindExtendedPrincipal(DomainContext, name)) - { - IExtendedPrincipalTest extendedPrincipal = (IExtendedPrincipalTest)principal; - byte[] readArray = extendedPrincipal.ByteArrayExtension; - principal.Delete(); - } - } - - [Theory] - [MemberData(nameof(TestDebuggerAttributes_Inputs))] - public void Save_ThrowsInvalidOperationException(PrincipalContext context) - { - if (DomainContext == null) - { - return; - } - - using (Principal principal = CreateExtendedPrincipal(DomainContext, Guid.NewGuid().ToString())) - { - Assert.Throws(() => principal.Save(context)); - } - } - - public static IEnumerable TestDebuggerAttributes_Inputs() - { - yield return new object[] { null }; - yield return new object[] { new PrincipalContext(ContextType.Machine) }; - } - - public abstract Principal CreatePrincipal(PrincipalContext context, string name); - - public abstract Principal CreateExtendedPrincipal(PrincipalContext context, string name); - - public abstract Principal FindExtendedPrincipal(PrincipalContext context, string name); - } - - public interface IExtendedPrincipalTest - { - object ObjectExtension { get; set; } - byte[] ByteArrayExtension { get; set; } - object[] ObjectArrayExtension { get; set; } - } -} diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj b/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj index 6ee1a6b7217ba6..0bb24c8eadd87d 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/tests/System.DirectoryServices.AccountManagement.Tests.csproj @@ -3,15 +3,9 @@ $(NetCoreAppCurrent)-windows;net48 - - - - - - + diff --git a/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs b/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs deleted file mode 100644 index 53b99ab5c939cc..00000000000000 --- a/src/libraries/System.DirectoryServices.AccountManagement/tests/UserPrincipalTest.cs +++ /dev/null @@ -1,32 +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.Security.Principal; -using Xunit; - -namespace System.DirectoryServices.AccountManagement.Tests -{ - public class UserPrincipalTest : PrincipalTest - { - public override Principal CreatePrincipal(PrincipalContext context, string name) - { - return new UserPrincipal(context) { Name = name }; - } - - public override Principal CreateExtendedPrincipal(PrincipalContext context, string name) - { - return new ExtendedUserPrincipal(context) { Name = name }; - } - - public override Principal FindExtendedPrincipal(PrincipalContext context, string name) - { - return ExtendedUserPrincipal.FindByIdentity(context, name); - } - - public void UserPrincipalConstructorTest() - { - UserPrincipal user = new UserPrincipal(DomainContext); - user.Dispose(); - } - } -} diff --git a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx index b469e621c1be10..b63f103619fbdb 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices.Protocols/src/Resources/Strings.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The URI that is supplied must be either "http" or "https". - A negative value is not permitted for the time limit. @@ -129,18 +126,12 @@ The DSML document could not be parsed. - - The server failed to return a session identifier. - The server failed to return a DirectoryResponse. An ErrorResponse DSML element was returned. - - The server returned an invalid DSML control. - A null reference cannot be added to DirectoryAttribute or DirectoryAttributeModification objects. @@ -162,54 +153,9 @@ An unspecified operation error occurred. - - The LDAP filter string is invalid. - The property is read-only. - - The operation response is missing the result code. - - - The distinguished name is missing in the SearchResultEntry of the search response. - - - The search result is missing the attribute name. - - - The server returned an unknown result code "{0}". - - - The error response is missing the type attribute. - - - The error response contains an invalid type attribute "{0}". - - - This property is not supported on a DsmlErrorResponse. - - - The value is invalid base-64-encoded data. - - - The DsmlSoapHttpConnection does not support "{0}" authentication type. - - - An active session already exists for this connection. - - - The document is read-only. - - - The response from the server is not a well-formed DSML document. - - - No active session exists for this connection. - - - The server returned an unknown response element. - ClientCertificates can contain only zero or one certificate. @@ -312,9 +258,6 @@ The call completed successfully. - - The server failed to return a session identifier. - An operation error occurred. @@ -447,9 +390,6 @@ The value must be a string, byte[], or Uri type. - - Transport layer security is not supported on Windows 2000. - The specified parameter should be a "{0}" type. @@ -459,9 +399,6 @@ The collection cannot contain a null DirectoryControl object. - - The filter type "{0}" is invalid. - The value "{0}" is not the return value from BeginSendRequest. @@ -474,12 +411,6 @@ The array should not contain null reference. - - A non-CLSCompliant exception is thrown. - - - Fast concurrent bind is only supported on Windows 2003 and later operating systems. - The value exceeds the maximum allowed. diff --git a/src/libraries/System.DirectoryServices/src/Resources/Strings.resx b/src/libraries/System.DirectoryServices/src/Resources/Strings.resx index 64f8ba2d1f0467..437bbe46dcf95b 100644 --- a/src/libraries/System.DirectoryServices/src/Resources/Strings.resx +++ b/src/libraries/System.DirectoryServices/src/Resources/Strings.resx @@ -221,9 +221,6 @@ Only one type of operation can be performed in a sequence. - - The '{0}' section can only appear once in a configuration file. - An unknown error occurred. @@ -314,9 +311,6 @@ The specified string parameter is empty. - - The System.DirectoryServices.ActiveDirectory namespace is only supported on computers running Windows 2000 and later operating systems. - The name specified in the directory context must be an ADAM instance. @@ -467,9 +461,6 @@ The local computer is not joined to a domain or the domain cannot be contacted. - - Failed to get the version of the operating system, error is "{0}". - Unable to obtain DNS hostname of Active Directory domain controller with ntdsa object name "{0}". diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs index f9d987de24d1c1..1514ee19e8c331 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs @@ -6,6 +6,10 @@ namespace System.Drawing { + public partial struct CharacterRange : System.IEquatable + { + public bool Equals(System.Drawing.CharacterRange other) { throw null; } + } public sealed partial class Graphics { public void DrawRectangle(System.Drawing.Pen pen, System.Drawing.RectangleF rect) { } diff --git a/src/libraries/System.Drawing.Common/src/Resources/Strings.resx b/src/libraries/System.Drawing.Common/src/Resources/Strings.resx index 2d3d8134aabce0..eb89ee9ebb7a58 100644 --- a/src/libraries/System.Drawing.Common/src/Resources/Strings.resx +++ b/src/libraries/System.Drawing.Common/src/Resources/Strings.resx @@ -128,9 +128,6 @@ The color {0} is not a system color. - - .NET Component - Function was ended. @@ -224,18 +221,6 @@ '{0}' data length expected {1}, read {2} - - Toolbox item cannot be modified. - - - Property {0} requires an argument of type {1}. - - - Data type {0} is not serializable. Items added to a property dictionary must be serializable. - - - Argument should be a non-empty string. - Internal state of the {0} class is invalid. @@ -263,15 +248,12 @@ Value of '{1}' is not valid for '{0}'. - + Value of '{0}' is not valid for font size unit. Value of '{1}' is not valid for '{0}'. '{0}' should be greater than {2} and less than or equal to {3}. - - Class name is not valid. - Color '{0}' is not valid. @@ -290,9 +272,6 @@ Value of '{1}' is not valid for '{0}'. '{0}' must be greater than or equal to {2}. - - Permission level is not valid. - Permission state is not valid. @@ -350,21 +329,12 @@ Occurs before each page is printed. Useful for changing PageSettings for a particular page. - - System.Drawing is not supported on this platform. - System.Drawing.Common is not supported on non-Windows platforms. See https://aka.ms/systemdrawingnonwindows for more information. Defines an object that sends output to a printer. - - XML is not valid. - - - Permission level must be between PrintingPermissionLevel.NoPrinting and PrintingPermissionLevel.AllPrinting. - IDictionary parameter contains at least one entry that is not valid. Ensure all values are consistent with the object's properties. @@ -374,9 +344,6 @@ Resource '{1}' cannot be found in class '{0}'. - - Target does not have permission to print. - Text "{0}" cannot be parsed. The expected text format is "{1}". @@ -407,12 +374,6 @@ Invalid Blend object. The positions array must have 1.0 as its last element. - - Unable to load DLL '{0}': The specified module could not be found. - - - Unable to find an entry point named '{0}' in DLL '{1}'. - {0} only available on WMF files. diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs index 157533b84283c6..a0dccdc4b28765 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs @@ -7,51 +7,43 @@ namespace System.Drawing { [StructLayout(LayoutKind.Sequential)] - public struct CharacterRange + public struct CharacterRange : IEquatable { private int _first; private int _length; - /// - /// Initializes a new instance of the class with the specified coordinates. - /// + /// Initializes a new instance of the class with the specified coordinates. public CharacterRange(int First, int Length) { _first = First; _length = Length; } - /// - /// Gets the First character position of this . - /// + /// Gets the First character position of this . public int First { get => _first; set => _first = value; } - /// - /// Gets the Length of this . - /// + /// Gets the Length of this . public int Length { get => _length; set => _length = value; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (!(obj is CharacterRange cr)) - { - return false; - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is CharacterRange other && Equals(other); - return First == cr.First && Length == cr.Length; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CharacterRange other) => First == other.First && Length == other.Length; public static bool operator ==(CharacterRange cr1, CharacterRange cr2) => cr1.Equals(cr2); - public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !(cr1 == cr2); + public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !cr1.Equals(cr2); public override int GetHashCode() => HashCode.Combine(First, Length); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs index 665a642a3e4f36..bb7b163d1ce958 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs @@ -1,9 +1,12 @@ // 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.Diagnostics.CodeAnalysis; + namespace System.Drawing.Printing { - internal readonly partial struct TriState + internal readonly partial struct TriState : IEquatable { private readonly byte _value; // 0 is "default", not false @@ -11,73 +14,46 @@ internal readonly partial struct TriState public static readonly TriState False = new TriState(1); public static readonly TriState True = new TriState(2); - private TriState(byte value) - { - _value = value; - } + private TriState(byte value) => _value = value; - public bool IsDefault - { - get { return this == Default; } - } + public bool IsDefault => this == Default; - public bool IsFalse - { - get { return this == False; } - } + public bool IsFalse => this == False; - public bool IsNotDefault - { - get { return this != Default; } - } + public bool IsNotDefault => this != Default; - public bool IsTrue - { - get { return this == True; } - } + public bool IsTrue => this == True; - public static bool operator ==(TriState left, TriState right) - { - return left._value == right._value; - } + public static bool operator ==(TriState left, TriState right) => left.Equals(right); - public static bool operator !=(TriState left, TriState right) - { - return !(left == right); - } + public static bool operator !=(TriState left, TriState right) => !left.Equals(right); - public override bool Equals(object? o) + public override bool Equals([NotNullWhen(true)] object? o) { - TriState state = (TriState)o!; - return _value == state._value; + Debug.Assert(o is TriState); + return Equals((TriState)o); } - public override int GetHashCode() - { - return _value; - } + public bool Equals(TriState other) => _value == other._value; - public static implicit operator TriState(bool value) - { - return (value) ? True : False; - } + public override int GetHashCode() => _value; + + public static implicit operator TriState(bool value) => value ? True : False; public static explicit operator bool(TriState value) { if (value.IsDefault) + { throw new InvalidCastException(SR.TriStateCompareError); - else - return (value == TriState.True); - } + } - /// - /// Provides some interesting information about the TriState in String form. - /// - public override string ToString() - { - if (this == Default) return "Default"; - else if (this == False) return "False"; - else return "True"; + return (value == TriState.True); } + + /// Provides some interesting information about the TriState in String form. + public override string ToString() => + this == Default ? "Default" : + this == False ? "False" : + "True"; } } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs index 445d7c72c6dd49..098830cbf4a613 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/RectangleConverter.cs @@ -83,7 +83,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } else { throw new ArgumentException(SR.Format(SR.TextParseFailedFormat, - "text", text, "x, y, width, height")); } diff --git a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs index 7147cb809be6bb..989ee85c093120 100644 --- a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs +++ b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs @@ -84,6 +84,7 @@ public void Equals_Invoke_ReturnsExpected(CharacterRange range, object obj, bool Assert.Equal(expected, range.Equals(obj)); if (obj is CharacterRange otherRange) { + Assert.Equal(expected, range.Equals(otherRange)); Assert.Equal(expected, range == otherRange); Assert.Equal(!expected, range != otherRange); Assert.Equal(expected, range.GetHashCode().Equals(otherRange.GetHashCode())); diff --git a/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj b/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj index 162b5d563a72d3..e8328af20cde96 100644 --- a/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj +++ b/src/libraries/System.Drawing.Primitives/src/System.Drawing.Primitives.csproj @@ -36,7 +36,6 @@ Link="Common\Interop\Windows\User32\Interop.Win32SystemColors.cs" /> - diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs index 6b20ca15a3101d..7d8df542caf682 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.GeneralizedTime.cs @@ -62,12 +62,7 @@ private void WriteGeneralizedTimeCore( // where "f?" is anything from "f" to "fffffff" (tenth of a second down to 100ns/1-tick) // with no trailing zeros. DateTimeOffset normalized = value.ToUniversalTime(); - - if (normalized.Year > 9999) - { - // This is unreachable since DateTimeOffset guards against this internally. - throw new ArgumentOutOfRangeException(nameof(value)); - } + Debug.Assert(normalized.Year <= 9999, "DateTimeOffset guards against this internally"); // We're only loading in sub-second ticks. // Ticks are defined as 1e-7 seconds, so their printed form diff --git a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj index 29b98e85415777..c4783ca29c1670 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -49,7 +49,6 @@ System.Formats.Cbor.CborWriter - diff --git a/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx b/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx index 8c18769cabcdcb..355df1fd20412a 100644 --- a/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx +++ b/src/libraries/System.IO.Compression.Brotli/src/Resources/Strings.resx @@ -132,9 +132,6 @@ Positive number required. - - Offset plus count is larger than the length of target array. - Only one asynchronous reader or writer is allowed time at one time. diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index 5d800c1f62ca71..fe725937441e24 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -83,7 +83,7 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination { File.SetLastWriteTime(destinationFileName, source.LastWriteTime.DateTime); } - catch (UnauthorizedAccessException) + catch { // some OSes like Android (#35374) might not support setting the last write time, the extraction should not fail because of that } diff --git a/src/libraries/System.IO.Compression/src/Resources/Strings.resx b/src/libraries/System.IO.Compression/src/Resources/Strings.resx index cac801aa8fcc47..08e13fd1bb1445 100644 --- a/src/libraries/System.IO.Compression/src/Resources/Strings.resx +++ b/src/libraries/System.IO.Compression/src/Resources/Strings.resx @@ -131,9 +131,6 @@ Found invalid data while decoding. - - Offset plus count is larger than the length of target array. - Only one asynchronous reader or writer is allowed time at one time. @@ -179,9 +176,6 @@ The underlying compression routine returned an unexpected error code. - - The argument must be non-negative. - String cannot be empty. @@ -266,9 +260,6 @@ Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. - - The offset and length parameters are not valid for the array that was given. - This stream from ZipArchiveEntry does not support reading. diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs index ec71718a511d3d..ca31e978b332f0 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/DeflateManagedStream.cs @@ -310,16 +310,8 @@ protected override void Dispose(bool disposing) finally { _stream = null!; - - try - { - _inflater?.Dispose(); - } - finally - { - _inflater = null!; - base.Dispose(disposing); - } + _inflater = null!; + base.Dispose(disposing); } } } diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs index a127d93bd1d44b..7222011895309e 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs @@ -689,7 +689,5 @@ private bool DecodeDynamicBlockHeader() _state = InflaterState.DecodeTop; return true; } - - public void Dispose() { } } } diff --git a/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs b/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs index 64455bbc92ccb6..ae5a0e9562c7d3 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs +++ b/src/libraries/System.IO.FileSystem.AccessControl/ref/System.IO.FileSystem.AccessControl.cs @@ -9,7 +9,7 @@ namespace System.IO public static partial class FileSystemAclExtensions { public static void Create(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.DirectorySecurity directorySecurity) { } - public static System.IO.FileStream Create(this System.IO.FileInfo fileInfo, System.IO.FileMode mode, System.Security.AccessControl.FileSystemRights rights, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options, System.Security.AccessControl.FileSecurity fileSecurity) { throw null; } + public static System.IO.FileStream Create(this System.IO.FileInfo fileInfo, System.IO.FileMode mode, System.Security.AccessControl.FileSystemRights rights, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options, System.Security.AccessControl.FileSecurity? fileSecurity) { throw null; } public static System.IO.DirectoryInfo CreateDirectory(this System.Security.AccessControl.DirectorySecurity directorySecurity, string path) { throw null; } public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo) { throw null; } public static System.Security.AccessControl.DirectorySecurity GetAccessControl(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.AccessControlSections includeSections) { throw null; } diff --git a/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx b/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx index d71dfd08146e4d..60ea3e762eb475 100644 --- a/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx +++ b/src/libraries/System.IO.FileSystem.AccessControl/src/Resources/Strings.resx @@ -1,3 +1,4 @@ + The specified file name or path is too long, or a component of the specified path is too long. diff --git a/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs b/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs index 5b2ab1f81e8789..efe700c1e9c753 100644 --- a/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs +++ b/src/libraries/System.IO/tests/Stream/Stream.NullTests.cs @@ -123,6 +123,16 @@ public static void TestNullStream_WriteByte() Assert.Equal(0, source.Position); } + [Theory] + [MemberData(nameof(NullReaders))] + public static void TestNullTextReaderDispose(TextReader input) + { + // dispose should be a no-op + input.Dispose(); + input.Dispose(); + Assert.Equal("", input.ReadToEnd()); + } + [Theory] [MemberData(nameof(NullReaders))] public static void TestNullTextReader(TextReader input) @@ -131,16 +141,54 @@ public static void TestNullTextReader(TextReader input) if (sr != null) Assert.True(sr.EndOfStream, "EndOfStream property didn't return true"); - input.ReadLine(); - input.Dispose(); - - input.ReadLine(); + Assert.Null(input.ReadLine()); if (sr != null) Assert.True(sr.EndOfStream, "EndOfStream property didn't return true"); - input.Read(); - input.Peek(); - input.Read(new char[2], 0, 2); - input.ReadToEnd(); + + Assert.Equal(-1, input.Read()); + Assert.Equal(-1, input.Peek()); + var chars = new char[2]; + Assert.Equal(0, input.Read(chars, 0, chars.Length)); + Assert.Equal(0, input.Read(chars.AsSpan())); + Assert.Equal(0, input.ReadBlock(chars, 0, chars.Length)); + Assert.Equal(0, input.ReadBlock(chars.AsSpan())); + Assert.Equal("", input.ReadToEnd()); + input.Dispose(); + } + + [Theory] + [MemberData(nameof(NullReaders))] + public static async Task TestNullTextReaderAsync(TextReader input) + { + var chars = new char[2]; + Assert.Equal(0, await input.ReadAsync(chars, 0, chars.Length)); + Assert.Equal(0, await input.ReadAsync(chars.AsMemory(), default)); + Assert.Equal(0, await input.ReadBlockAsync(chars, 0, chars.Length)); + Assert.Equal(0, await input.ReadBlockAsync(chars.AsMemory(), default)); + Assert.Null(await input.ReadLineAsync()); + Assert.Null(await input.ReadLineAsync(default)); + Assert.Equal("", await input.ReadToEndAsync()); + Assert.Equal("", await input.ReadToEndAsync(default)); + input.Dispose(); + } + + [Theory] + [MemberData(nameof(NullReaders))] + public static async Task TestCanceledNullTextReaderAsync(TextReader input) + { + using CancellationTokenSource tokenSource = new CancellationTokenSource(); + tokenSource.Cancel(); + var token = tokenSource.Token; + var chars = new char[2]; + OperationCanceledException ex; + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadAsync(chars.AsMemory(), token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadBlockAsync(chars.AsMemory(), token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadLineAsync(token)); + Assert.Equal(token, ex.CancellationToken); + ex = await Assert.ThrowsAnyAsync(async () => await input.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); input.Dispose(); } diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs index 2e19dd283ebbb1..b96ed8532d383c 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs @@ -19,10 +19,10 @@ public static void NullArgs_ThrowsArgumentNullException() AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, null)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, -1)); - AssertExtensions.Throws("encoding", () => new StreamReader("", (Encoding)null)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, null)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, -1)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", (Encoding)null)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true, null)); + AssertExtensions.Throws("encoding", () => new StreamReader("path", null, true, -1)); AssertExtensions.Throws("options", () => new StreamReader("path", (FileStreamOptions)null)); AssertExtensions.Throws("options", () => new StreamReader("path", Encoding.UTF8, true, null)); @@ -32,12 +32,12 @@ public static void NullArgs_ThrowsArgumentNullException() public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception - AssertExtensions.Throws(null, () => new StreamReader("")); - AssertExtensions.Throws(null, () => new StreamReader("", new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8)); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true)); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, -1)); + AssertExtensions.Throws("path", () => new StreamReader("")); + AssertExtensions.Throws("path", () => new StreamReader("", new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8)); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true)); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true, new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamReader("", Encoding.UTF8, true, -1)); } [Fact] diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs index 4a2b91f8862b57..fccc269868ed7e 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs @@ -110,6 +110,44 @@ public async Task ReadToEndAsync() Assert.Equal(5000, result.Length); } + [Fact] + public async Task ReadToEndAsync_WithCancellationToken() + { + using var sw = new StreamReader(GetLargeStream()); + var result = await sw.ReadToEndAsync(default); + + Assert.Equal(5000, result.Length); + } + + [Fact] + public async Task ReadToEndAsync_WithCanceledCancellationToken() + { + using var sw = new StreamReader(GetLargeStream()); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await sw.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + + [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")] + public async Task ReadToEndAsync_WithCancellation() + { + string path = GetTestFilePath(); + + // create large (~100MB) file + File.WriteAllLines(path, Enumerable.Repeat("A very large file used for testing StreamReader cancellation. 0123456789012345678901234567890123456789.", 1_000_000)); + + using StreamReader reader = File.OpenText(path); + using CancellationTokenSource cts = new (TimeSpan.FromMilliseconds(50)); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await reader.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + [Fact] public void GetBaseStream() { @@ -301,6 +339,27 @@ public void VanillaReadLines2() Assert.Equal(valueString.Substring(1, valueString.IndexOf('\r') - 1), data); } + [Fact] + public async Task VanillaReadLineAsync() + { + var baseInfo = GetCharArrayStream(); + var sr = baseInfo.Item2; + + string valueString = new string(baseInfo.Item1); + + var data = await sr.ReadLineAsync(); + Assert.Equal(valueString.Substring(0, valueString.IndexOf('\r')), data); + + data = await sr.ReadLineAsync(default); + Assert.Equal(valueString.Substring(valueString.IndexOf('\r') + 1, 3), data); + + data = await sr.ReadLineAsync(); + Assert.Equal(valueString.Substring(valueString.IndexOf('\n') + 1, 2), data); + + data = await sr.ReadLineAsync(default); + Assert.Equal((valueString.Substring(valueString.LastIndexOf('\n') + 1)), data); + } + [Fact] public async Task ContinuousNewLinesAndTabsAsync() { diff --git a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs index 841ff591aeff23..6900fb973843b9 100644 --- a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -22,21 +22,18 @@ public static void NullArgs_ThrowsArgumentNullException() AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", null, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null, -1)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", null, null)); - AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null, -1)); } [Fact] public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception - AssertExtensions.Throws(null, () => new StreamWriter("")); - AssertExtensions.Throws(null, () => new StreamWriter("", new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamWriter("", true)); - AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8)); - AssertExtensions.Throws(null, () => new StreamWriter("", Encoding.UTF8, new FileStreamOptions())); - AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8, -1)); + AssertExtensions.Throws("path", () => new StreamWriter("")); + AssertExtensions.Throws("path", () => new StreamWriter("", new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamWriter("", true)); + AssertExtensions.Throws("path", () => new StreamWriter("", true, Encoding.UTF8)); + AssertExtensions.Throws("path", () => new StreamWriter("", Encoding.UTF8, new FileStreamOptions())); + AssertExtensions.Throws("path", () => new StreamWriter("", true, Encoding.UTF8, -1)); } [Fact] diff --git a/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs b/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs index 9e500923164f38..3c4446f07f47a7 100644 --- a/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs +++ b/src/libraries/System.IO/tests/StringReader/StringReader.CtorTests.cs @@ -68,6 +68,23 @@ public static void ReadLine() } } + [Fact] + public static async Task ReadLineAsync() + { + string str1 = "Hello\0\t\v \\ World"; + string str2 = str1 + Environment.NewLine + str1; + + using (StringReader sr = new StringReader(str1)) + { + Assert.Equal(str1, await sr.ReadLineAsync()); + } + using (StringReader sr = new StringReader(str2)) + { + Assert.Equal(str1, await sr.ReadLineAsync(default)); + Assert.Equal(str1, await sr.ReadLineAsync(default)); + } + } + [Fact] public static void ReadPseudoRandomString() { @@ -155,6 +172,14 @@ public static void ReadToEndPseudoRandom() { Assert.Equal(str1, sr.ReadToEnd()); } + [Fact] + public static async Task ReadToEndAsyncString() + { + string str1 = "Hello\0\t\v \\ World"; + StringReader sr = new StringReader(str1); + Assert.Equal(str1, await sr.ReadToEndAsync(default)); + } + [Fact] public static void Closed_DisposedExceptions() { @@ -278,6 +303,8 @@ public async Task Precanceled_ThrowsException() await Assert.ThrowsAnyAsync(() => reader.ReadAsync(Memory.Empty, new CancellationToken(true)).AsTask()); await Assert.ThrowsAnyAsync(() => reader.ReadBlockAsync(Memory.Empty, new CancellationToken(true)).AsTask()); + await Assert.ThrowsAnyAsync(() => reader.ReadLineAsync(new CancellationToken(true)).AsTask()); + await Assert.ThrowsAnyAsync(() => reader.ReadToEndAsync(new CancellationToken(true))); } private static void ValidateDisposedExceptions(StringReader sr) diff --git a/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs b/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs index e6ba6d818f2867..48f83d7108e53d 100644 --- a/src/libraries/System.IO/tests/TextReader/TextReaderTests.cs +++ b/src/libraries/System.IO/tests/TextReader/TextReaderTests.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.Threading; using System.Threading.Tasks; using Xunit; @@ -54,6 +55,26 @@ public async Task ReadToEndAsync() } } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public async Task ReadToEndAsync_WithCancellationToken() + { + using var tr = new CharArrayTextReader(TestDataProvider.LargeData); + var result = await tr.ReadToEndAsync(default); + Assert.Equal(5000, result.Length); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public async Task ReadToEndAsync_WithCanceledCancellationToken() + { + using var tr = new CharArrayTextReader(TestDataProvider.LargeData); + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var token = cts.Token; + + var ex = await Assert.ThrowsAnyAsync(async () => await tr.ReadToEndAsync(token)); + Assert.Equal(token, ex.CancellationToken); + } + [Fact] public void TestRead() { diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs index 8125fc9ac1159a..e481185ffa57a9 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/ContractUtils.cs @@ -20,7 +20,7 @@ public static Exception Unreachable get { Debug.Fail("Unreachable"); - return new InvalidOperationException("Code supposed to be unreachable"); + return new UnreachableException(); } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs index d078d82a597f4e..f42254df42dd3e 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs @@ -44,7 +44,7 @@ public override string ToString() => string.Create(CultureInfo.InvariantCulture, $"{Index}: {(IsBoxed ? "boxed" : null)} {(InClosure ? "in closure" : null)}"); } - internal readonly struct LocalDefinition + internal readonly struct LocalDefinition : IEquatable { internal LocalDefinition(int localIndex, ParameterExpression parameter) { @@ -53,27 +53,14 @@ internal LocalDefinition(int localIndex, ParameterExpression parameter) } public int Index { get; } + public ParameterExpression Parameter { get; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is LocalDefinition) - { - LocalDefinition other = (LocalDefinition)obj; - return other.Index == Index && other.Parameter == Parameter; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is LocalDefinition other && Equals(other); - return false; - } + public bool Equals(LocalDefinition other) => other.Index == Index && other.Parameter == Parameter; - public override int GetHashCode() - { - if (Parameter == null) - { - return 0; - } - return Parameter.GetHashCode() ^ Index.GetHashCode(); - } + public override int GetHashCode() => Parameter is null ? 0 : Parameter.GetHashCode() ^ Index.GetHashCode(); } internal sealed class LocalVariables diff --git a/src/libraries/System.Memory/src/Resources/Strings.resx b/src/libraries/System.Memory/src/Resources/Strings.resx index 3734871f888dac..6a69c1128e1525 100644 --- a/src/libraries/System.Memory/src/Resources/Strings.resx +++ b/src/libraries/System.Memory/src/Resources/Strings.resx @@ -141,9 +141,6 @@ End position was not reached during enumeration. - - Unexpected segment type. - Cannot advance past the end of the buffer, which has a size of {0}. diff --git a/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs b/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs index 33250569da2da8..1a9027d0fc7447 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfSequence.byte.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -115,5 +117,104 @@ public static void IndexOfSequenceLengthOneValueJustPasttVeryEnd_Byte() int index = span.IndexOf(value); Assert.Equal(-1, index); } + + public static IEnumerable IndexOfSubSeqData_Byte() + { + // searchSpace, value, expected IndexOf value, expected LastIndexOf value + yield return new object[] { new byte[]{0,0,0,0,0},new byte[]{0,0,0}, 0, 2}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0},new byte[]{0,71,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0},new byte[]{0,0,0}, 0, 7}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,71,0,1,0}, 10, 10}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,71,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0},new byte[]{0,1,0,0,0}, 12, 12}; + yield return new object[] { new byte[]{0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0},new byte[]{0,1,0,0,0}, 11, 11}; + yield return new object[] { new byte[]{0,0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0},new byte[]{0,1,0,0,0}, 6, 6}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,0,0,0,0,1,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1},new byte[]{0,1,0,0,0,0,0}, 5, 5}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0}, 0, 44}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0}, 0, 43}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0}, 7, 42}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0}, 7, 41}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0}, 7, 11}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0}, 7, 10}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0}, 7, 9}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0}, 7, 7}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0}, 5, 48}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,0}, 44, 44}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0,0,0}, 5, 19}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,1,0,0,0,1,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0}, 7, 11}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,1,0,0,1,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,1,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,1,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,1,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{0,0,0,0,71,0,1,0,0,0,0,0,0,0,0,0,0,0,71,0,1,0,0,0,0,1,1,0,2,0,1,1,0,1,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0},new byte[]{0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0}, -1, -1}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{159,133,159,133,159,133}, 0, 22}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{159,133,255,159,133}, -1, -1}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,160,86,160,86,160,86,160,86,160,80},new byte[]{160,86,160,86,160,86,160,86,160,80}, 40, 40}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,159,127,160,86,160,86,160,86,160,86,160,80,160,80,160,80,160,80,160,80,160,80,160,80,160,86,160,86,160,86,160,86},new byte[]{160,86,160,86,160,86,160,86}, 40, 62}; + yield return new object[] { new byte[]{159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133,159,133},new byte[]{0,0,0,1}, -1, -1}; + yield return new object[] { new byte[]{255,160,82,159,134,159,127,255,159,141,160,85,160,82,160,88,255,159,141,159,127,159,134,255,160,88,160,85,160,82,159,141,159,127,159,134,160,88,160,85,160,82,159,141,255,159,127,159,134,160,88,160,85,160,82,159,141,159,127,159,134,160,88,159,141,160,85,255,160,82,159,134,159,141,159,134,160,85,160,82,159,141,159,127,159,134,160,82,159,141,160,85,159,134,255,160,88,159,127,160,82,160,85,159,134,255,159,141,159,127,159,134,160,85,159,141},new byte[]{255,159,141,159,127,159,134,255}, 16, 16}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{49,49}, 29, 29}; + yield return new object[] { new byte[]{49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,49}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49},new byte[]{49,49,49}, 29, 29}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49,50},new byte[]{49,49,49}, 29, 29}; + yield return new object[] { new byte[]{49,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,49,49}, 0, 1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,49,50},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{49,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{48,48,48}, -1, -1}; + yield return new object[] { new byte[]{48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,49,50},new byte[]{48,49,48,48}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{49,48,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,48,49,50},new byte[]{160,80,48,160,80,160,80}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 15}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 17}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 18, 32}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,49,49,49,49,49,49,49,49,49,49,49,49}, 20, 20}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49}, -1, -1}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49},new byte[]{49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49}, 0, 0}; + yield return new object[] { new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71},new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71}, 60, 60}; + yield return new object[] { new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,49,48,49,49,49,49,49,49,71,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,49,48,49,49,49,49,49,49,49,49,49,49,49,49,71,71,71,71,71,71,71,71,71,71,71,71,71,71},new byte[]{71,71,71,71,71,71,71,71,71,71,71,71,71,71,71}, 0, 0}; + } + + [Theory] + [MemberData(nameof(IndexOfSubSeqData_Byte))] + public static void ValueStartsAndEndsWithTheSameBytes(byte[] searchSpace, byte[] value, int expectedIndexOfValue, int expectedLastIndexOfValue) + { + Assert.Equal(expectedIndexOfValue, searchSpace.AsSpan().IndexOf(value)); + Assert.Equal(expectedLastIndexOfValue, searchSpace.AsSpan().LastIndexOf(value)); + } } } diff --git a/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs b/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs index bda626153a5d09..b341a79c9b1f33 100644 --- a/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs +++ b/src/libraries/System.Memory/tests/Span/IndexOfSequence.char.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Collections.Generic; +using System.Runtime.InteropServices; namespace System.SpanTests { @@ -115,5 +117,104 @@ public static void IndexOfSequenceLengthOneValueJustPasttVeryEnd_Char() int index = span.IndexOf(value); Assert.Equal(-1, index); } + + public static IEnumerable IndexOfSubSeqData_Char() + { + // searchSpace, value, expected IndexOf value, expected LastIndexOf value + yield return new object[] { "11111", "111", 0, 2 }; + yield return new object[] { "1111111111", "1x1", -1, -1 }; + yield return new object[] { "1111111111", "111", 0, 7 }; + yield return new object[] { "11111111111x12111", "1x121", 10, 10 }; + yield return new object[] { "11111111111x12111", "11121", -1, -1 }; + yield return new object[] { "1111111111x121111", "11121", -1, -1 }; + yield return new object[] { "11111x12111111111", "11121", -1, -1 }; + yield return new object[] { "11111111111x12111", "1x211", -1, -1 }; + yield return new object[] { "11111111111x12111", "11211", -1, -1 }; + yield return new object[] { "1111111111x121111", "11211", -1, -1 }; + yield return new object[] { "11111x12111111111", "11211", -1, -1 }; + yield return new object[] { "11111111111x12111", "12111", 12, 12 }; + yield return new object[] { "1111111111x121111", "12111", 11, 11 }; + yield return new object[] { "11111x12111111111", "12111", 6, 6 }; + yield return new object[] { "1111x1211111111111x12", "11121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "11121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1111121", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1211211", -1, -1 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12", "1211111", 5, 5 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111", 0, 44 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111", 0, 43 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111", 7, 42 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111", 7, 41 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111", 7, 11 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111", 7, 10 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111", 7, 9 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111", 7, 7 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1211", 5, 48 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11121", 44, 44 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "121111", 5, 19 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "12111211", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111", 7, 11 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1121121111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111211111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111111211111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1121111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11122111112111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "1111111211111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "111211111111111111", -1, -1 }; + yield return new object[] { "1111x1211111111111x12111122131221221211221111112121121", "11111211111121111111", -1, -1 }; + yield return new object[] { "жжжжжжжжжжжжжж", "жжж", 0, 11 }; + yield return new object[] { "жжжжжжжжжжжжжжжжжжжжжжжжжжжж", "ж0ж", -1, -1 }; + yield return new object[] { "жжжжжаааааааааааааааччччс", "ччччс", 20, 20 }; + yield return new object[] { "жжжжжаааааааааааааааччччсссссссчччч", "чччч", 20, 31 }; + yield return new object[] { "жжжжжжжжжжжжжжжжжжжжжжжжжжжж", "1112", -1, -1 }; + yield return new object[] { "0уза0оцущ0оаз0щцуоазщцуо0азщцуоазщоц0узозцуоазуоцз0щауцз0оазцо", "0оаз0", 9, 9 }; + yield return new object[] { "abababababababababababababababbc", "bb", 29, 29 }; + yield return new object[] { "abababababababababababababababb", "bb", 29, 29 }; + yield return new object[] { "abababababababababababababababbc", "bb", 29, 29 }; + yield return new object[] { "babababababababababababababababc", "bb", -1, -1 }; + yield return new object[] { "abababababababababababababababbb", "bbb", 29, 29 }; + yield return new object[] { "abababababababababababababababbbc", "bbb", 29, 29 }; + yield return new object[] { "bbbbabababababababababababababababc", "bbb", 0, 1 }; + yield return new object[] { "abababababababababababababababbc", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababb", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababbc", "aa", -1, -1 }; + yield return new object[] { "babababababababababababababababc", "aa", -1, -1 }; + yield return new object[] { "abababababababababababababababbb", "aaa", -1, -1 }; + yield return new object[] { "abababababababababababababababbbc", "aaa", -1, -1 }; + yield return new object[] { "bbbbabababababababababababababababc", "aaa", -1, -1 }; + yield return new object[] { "ababababababababababababababababbc", "abaa", -1, -1 }; + yield return new object[] { "babbbabababababababababababababababc", "babb", 0, 0 }; + yield return new object[] { "babbbabababababababababababababababc", "сaсс", -1, -1 }; + yield return new object[] { "babbbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 15 }; + yield return new object[] { "babbbbbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 0, 17 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbbbbbbb", 18, 32 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "bbbbbbbbbbbbb", 20, 20 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbb", -1, -1 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", 0, 0 }; + yield return new object[] { "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbb", "babbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbb", 0, 0 }; + yield return new object[] { "xxxxxxxxxxxxxxbabbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxx", 60, 60 }; + yield return new object[] { "xxxxxxxxxxxxxxxbabbbbbbxbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbbbbbbxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxx", 0, 0 }; + } + + [Theory] + [MemberData(nameof(IndexOfSubSeqData_Char))] + public static void ValueStartsAndEndsWithTheSameChars(string searchSpace, string value, int expectedIndexOfValue, int expectedLastIndexOfValue) + { + Assert.Equal(expectedIndexOfValue, searchSpace.AsSpan().IndexOf(value)); + Assert.Equal(expectedLastIndexOfValue, searchSpace.AsSpan().LastIndexOf(value)); + } } } diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 7464b6aa14086a..9e9afe1491426f 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -123,9 +123,6 @@ The format of the HTTP method is invalid. - - The HTTP method '{0}' is not supported on this platform. - The reason phrase must not contain new-line characters. @@ -231,9 +228,6 @@ Buffering more than {0} bytes is not supported. - - The value '{0}' is not supported for property '{1}'. - The read operation failed, see inner exception. @@ -297,9 +291,6 @@ Access to the path '{0}' is denied. - - The stream does not support concurrent read operations. - The username for a credential object cannot be null or empty. @@ -357,9 +348,6 @@ Received an HTTP/2 pseudo-header as a trailing header. - - The handler was disposed of while active operations were in progress. - The buffer was not long enough. @@ -381,12 +369,6 @@ Cannot access a closed stream. - - Using this feature requires Windows 10 Version 1607. - - - Client certificate was not found in the personal (\"MY\") certificate store. In UWP, client certificates are only supported if they have been added to that certificate store. - Only the 'http', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies. @@ -516,9 +498,6 @@ End of headers reached with incomplete token. - - Failed to HPACK encode the headers. - The HTTP headers length exceeded the set limit of {0} bytes. @@ -528,9 +507,6 @@ The HTTP/3 server sent invalid data on the connection. HTTP/3 error code '{0}' (0x{1}). - - The HTTP/3 server sent invalid data on the stream. HTTP/3 error code '{0}' (0x{1}). - The server is unable to process the request using the current HTTP version and indicates the request should be retried on an older HTTP version. @@ -549,9 +525,6 @@ Connection aborted by peer ({0}). - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. @@ -570,9 +543,6 @@ Requesting HTTP version {0} with version policy {1} while unable to establish HTTP/{2} connection. - - Requesting HTTP version {0} with version policy {1} while server returned HTTP/1.1 in ALPN. - Requesting HTTP version {0} with version policy {1} while server offers only version fallback. diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs index 724e00b571556f..d14bbbf2799cfa 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs @@ -21,16 +21,16 @@ public partial class HttpClientHandler : HttpMessageHandler private const string GetHttpMessageHandlerType = "Android.Runtime.AndroidEnvironment, Mono.Android"; #elif TARGET_IOS private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.iOS"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.iOS"; + private const string AssemblyName = "Microsoft.iOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.iOS"; #elif TARGET_MACCATALYST private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.MacCatalyst"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.MacCatalyst"; + private const string AssemblyName = "Microsoft.MacCatalyst"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.MacCatalyst"; #elif TARGET_TVOS private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.TVOS"; - private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Xamarin.TVOS"; + private const string AssemblyName = "Microsoft.tvOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.tvOS"; #else #error Unknown target #endif diff --git a/src/libraries/System.Net.Mail/src/Resources/Strings.resx b/src/libraries/System.Net.Mail/src/Resources/Strings.resx index a72e327927cce5..06521daf4ca9d5 100644 --- a/src/libraries/System.Net.Mail/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Mail/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -57,19 +58,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - The parameter '{0}' cannot be an empty string. - The IAsyncResult object was not returned from the corresponding asynchronous method on this class. {0} can only be called once for each asynchronous operation. - - This property cannot be set to an empty string. - This method is not implemented by this class. diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index aaca28f6a4c8cb..4fc0954e945210 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -68,15 +68,7 @@ protected virtual void Dispose(bool disposing) internal void SetContentFromFile(string fileName, ContentType? contentType) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - if (fileName.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); - } + ArgumentException.ThrowIfNullOrEmpty(fileName); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); _part.SetContent(stream, contentType); @@ -84,15 +76,7 @@ internal void SetContentFromFile(string fileName, ContentType? contentType) internal void SetContentFromFile(string fileName, string? mediaType) { - if (fileName == null) - { - throw new ArgumentNullException(nameof(fileName)); - } - - if (fileName.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(fileName)), nameof(fileName)); - } + ArgumentException.ThrowIfNullOrEmpty(fileName); Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); _part.SetContent(stream, null, mediaType); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs index 1acfc449c5afdb..ae8940ef25f926 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs @@ -119,15 +119,12 @@ public static bool TryCreate(string address, string? displayName, Encoding? disp private static bool TryParse(string address, string? displayName, Encoding? displayNameEncoding, out (string displayName, string user, string host, Encoding displayNameEncoding) parsedData, bool throwExceptionIfFail) { - if (string.IsNullOrEmpty(address)) + if (throwExceptionIfFail) + { + ArgumentException.ThrowIfNullOrEmpty(address); + } + else if (string.IsNullOrEmpty(address)) { - if (throwExceptionIfFail) - { - throw address is null ? - new ArgumentNullException(nameof(address)) : - new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(address)), nameof(address)); - } - parsedData = default; return false; } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs index 88bea09486e767..41d3ba32a70219 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressCollection.cs @@ -18,14 +18,7 @@ public MailAddressCollection() public void Add(string addresses) { - if (addresses == null) - { - throw new ArgumentNullException(nameof(addresses)); - } - if (addresses.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(addresses)), nameof(addresses)); - } + ArgumentException.ThrowIfNullOrEmpty(addresses); ParseValue(addresses); } diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs index 4e7ad597cabf9c..dfa63b9641f7ca 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailMessage.cs @@ -37,17 +37,8 @@ public MailMessage() public MailMessage(string from, string to) { - if (from == null) - throw new ArgumentNullException(nameof(from)); - - if (to == null) - throw new ArgumentNullException(nameof(to)); - - if (from.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - - if (to.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); + ArgumentException.ThrowIfNullOrEmpty(from); + ArgumentException.ThrowIfNullOrEmpty(to); _message = new Message(from, to); if (NetEventSource.Log.IsEnabled()) NetEventSource.Associate(this, _message); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs index 53e41d8f86e6c1..e6536a48e2b456 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailPriority.cs @@ -44,17 +44,8 @@ internal Message() internal Message(string from, string to) : this() { - if (from == null) - throw new ArgumentNullException(nameof(from)); - - if (to == null) - throw new ArgumentNullException(nameof(to)); - - if (from.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(from)), nameof(from)); - - if (to.Length == 0) - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(to)), nameof(to)); + ArgumentException.ThrowIfNullOrEmpty(from); + ArgumentException.ThrowIfNullOrEmpty(to); _from = new MailAddress(from); MailAddressCollection collection = new MailAddressCollection(); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs index beeea14766bca5..71f0af271d14b2 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs @@ -168,15 +168,7 @@ public string? Host throw new InvalidOperationException(SR.SmtpInvalidOperationDuringSend); } - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); value = value.Trim(); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs index b3ca5f87ac5090..028e9456ce3d1e 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentDisposition.cs @@ -79,14 +79,7 @@ public string DispositionType get { return _dispositionType; } set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); _isChanged = true; _dispositionType = value; diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs index 5595f7aab22288..08bcb5e7c6e729 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/ContentType.cs @@ -45,14 +45,7 @@ public ContentType() : this(Default) /// Unparsed value of the Content-Type header. public ContentType(string contentType) { - if (contentType == null) - { - throw new ArgumentNullException(nameof(contentType)); - } - if (contentType.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(contentType)), nameof(contentType)); - } + ArgumentException.ThrowIfNullOrEmpty(contentType); _isChanged = true; _type = contentType; @@ -99,15 +92,7 @@ public string MediaType get { return _mediaType + "/" + _subType; } set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.net_emptystringset, nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(value); int offset = 0; _mediaType = MailBnfHelper.ReadToken(value, ref offset, null); diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs index 89f988930f6ef7..c77b6abdbaac44 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mime/HeaderCollection.cs @@ -22,15 +22,7 @@ internal HeaderCollection() : base(StringComparer.OrdinalIgnoreCase) public override void Remove(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); base.Remove(name); } @@ -40,15 +32,7 @@ public override void Remove(string name) public override string? Get(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); return base.Get(name); } @@ -57,15 +41,7 @@ public override void Remove(string name) public override string[]? GetValues(string name) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); return base.GetValues(name); } @@ -93,25 +69,8 @@ internal void InternalAdd(string name, string value) public override void Set(string name, string value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } - - if (value.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(value); if (!MimeBasePart.IsAscii(name, false)) { @@ -131,22 +90,8 @@ public override void Set(string name, string value) public override void Add(string name, string value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(name)), nameof(name)); - } - if (value.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(value)), nameof(value)); - } + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentException.ThrowIfNullOrEmpty(value); MailBnfHelper.ValidateHeaderName(name); diff --git a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs index 5da904a7c6f9d4..a0127f539bc6c7 100644 --- a/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs +++ b/src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs @@ -47,7 +47,7 @@ public static IPHostEntry GetHostEntry(IPAddress address) if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(address))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(address)); } IPHostEntry ipHostEntry = GetHostEntryCore(address, AddressFamily.Unspecified); @@ -81,7 +81,7 @@ public static IPHostEntry GetHostEntry(string hostNameOrAddress, AddressFamily f if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(hostNameOrAddress))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(hostNameOrAddress)); } ipHostEntry = GetHostEntryCore(address, family); @@ -207,7 +207,7 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress, AddressFami if (address.Equals(IPAddress.Any) || address.Equals(IPAddress.IPv6Any)) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(address, $"Invalid address '{address}'"); - throw new ArgumentException(SR.Format(SR.net_invalid_ip_addr, nameof(hostNameOrAddress))); + throw new ArgumentException(SR.net_invalid_ip_addr, nameof(hostNameOrAddress)); } addresses = (family == AddressFamily.Unspecified || address.AddressFamily == family) ? new IPAddress[] { address } : Array.Empty(); diff --git a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs index 5ae74af0bd538c..d2c0b1fc229c65 100644 --- a/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.cs +++ b/src/libraries/System.Net.NameResolution/tests/PalTests/NameResolutionPalTests.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 Microsoft.Win32; using System.IO; +using System.Linq; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Threading; @@ -15,6 +17,33 @@ public class NameResolutionPalTests { private readonly ITestOutputHelper _output; + private static Lazy s_ipv6LocalHostNameLookupBrokenByNrpRule = new Lazy(() => + { + // On some machines using Microsoft corporate VPN, something sometimes installs an DNS Name Resolution Policy rule + // that breaks reverse lookup of ipv6 localhost names. + if (PlatformDetection.IsWindows) + { + // Equivalent of `Get-DnsClientNrptRule -Name .ip6.arpa` + using RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig"); + if (key != null) + { + // Also filtering out anything not written by MSFTVPN + foreach (string name in key.GetSubKeyNames().Where(name => name.Contains("MSFTVPN"))) + { + using RegistryKey? key2 = key.OpenSubKey(name); + if (key2 != null && key2.GetValue("Name") is string[] values && values.Length == 1 && values[0] == ".ip6.arpa") + { + return true; + } + } + } + } + + return false; + }); + + private static bool Ipv6LocalHostNameLookupNotBrokenByNrpRule => !s_ipv6LocalHostNameLookupBrokenByNrpRule.Value; + public NameResolutionPalTests(ITestOutputHelper output) { _output = output; @@ -131,7 +160,7 @@ public void TryGetNameInfo_LocalHost_IPv4() Assert.NotNull(name); } - [Fact] + [ConditionalFact(nameof(Ipv6LocalHostNameLookupNotBrokenByNrpRule))] public void TryGetNameInfo_LocalHost_IPv6() { SocketError error; @@ -230,7 +259,7 @@ public void TryGetNameInfo_LocalHost_IPv4_TryGetAddrInfo(bool justAddresses) Assert.NotNull(addresses); } - [Theory] + [ConditionalTheory(nameof(Ipv6LocalHostNameLookupNotBrokenByNrpRule))] [InlineData(false)] [InlineData(true)] public void TryGetNameInfo_LocalHost_IPv6_TryGetAddrInfo(bool justAddresses) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs index 5d95e8b2b9733d..30bd2f7713d842 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Threading.Tasks; using System.Threading; namespace System.Net.NetworkInformation @@ -12,7 +11,7 @@ namespace System.Net.NetworkInformation // Linux implementation of NetworkChange public partial class NetworkChange { - private static volatile int s_socket; + private static volatile SocketWrapper? s_socket; // Lock controlling access to delegate subscriptions, socket initialization, availability-changed state and timer. private static readonly object s_gate = new object(); @@ -34,7 +33,7 @@ public static event NetworkAddressChangedEventHandler? NetworkAddressChanged { lock (s_gate) { - if (s_socket == 0) + if (s_socket == null) { CreateSocket(); } @@ -51,8 +50,8 @@ public static event NetworkAddressChangedEventHandler? NetworkAddressChanged { if (s_addressChangedSubscribers.Count == 0 && s_availabilityChangedSubscribers.Count == 0) { - Debug.Assert(s_socket == 0, - "s_socket != 0, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); + Debug.Assert(s_socket == null, + "s_socket is not null, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); return; } @@ -74,7 +73,7 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC { lock (s_gate) { - if (s_socket == 0) + if (s_socket == null) { CreateSocket(); } @@ -113,8 +112,8 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC { if (s_addressChangedSubscribers.Count == 0 && s_availabilityChangedSubscribers.Count == 0) { - Debug.Assert(s_socket == 0, - "s_socket != 0, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); + Debug.Assert(s_socket == null, + "s_socket is not null, but there are no subscribers to NetworkAddressChanged or NetworkAvailabilityChanged."); return; } @@ -140,7 +139,7 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC private static unsafe void CreateSocket() { - Debug.Assert(s_socket == 0, "s_socket != 0, must close existing socket before opening another."); + Debug.Assert(s_socket == null, "s_socket is not null, must close existing socket before opening another."); int newSocket; Interop.Error result = Interop.Sys.CreateNetworkChangeListenerSocket(&newSocket); if (result != Interop.Error.SUCCESS) @@ -149,32 +148,34 @@ private static unsafe void CreateSocket() throw new NetworkInformationException(message); } - s_socket = newSocket; - new Thread(s => LoopReadSocket((int)s!)) + s_socket = new SocketWrapper(newSocket); + + new Thread(args => LoopReadSocket((SocketWrapper)args!)) { IsBackground = true, Name = ".NET Network Address Change" - }.UnsafeStart(newSocket); + }.UnsafeStart(s_socket); } private static void CloseSocket() { - Debug.Assert(s_socket != 0, "s_socket was 0 when CloseSocket was called."); - Interop.Error result = Interop.Sys.CloseNetworkChangeListenerSocket(s_socket); + Debug.Assert(s_socket != null, "s_socket was null when CloseSocket was called."); + Interop.Error result = Interop.Sys.CloseNetworkChangeListenerSocket(s_socket != null ? s_socket.Socket : -1); if (result != Interop.Error.SUCCESS) { string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); throw new NetworkInformationException(message); } - s_socket = 0; + s_socket = null; } - private static unsafe void LoopReadSocket(int socket) + private static unsafe void LoopReadSocket(SocketWrapper initiallyCreatedSocket) { - while (socket == s_socket) + while (s_socket == initiallyCreatedSocket) //if both references are equal then s_socket was not changed { - Interop.Sys.ReadEvents(socket, &ProcessEvent); + //we can continue processing events + Interop.Sys.ReadEvents(initiallyCreatedSocket.Socket, &ProcessEvent); } } @@ -185,7 +186,7 @@ private static void ProcessEvent(int socket, Interop.Sys.NetworkChangeKind kind) { lock (s_gate) { - if (socket == s_socket) + if (s_socket != null && socket == s_socket.Socket) { OnSocketEvent(kind); } @@ -290,5 +291,19 @@ private static void OnAvailabilityTimerFired(object? state) } } } + + // SocketWrapper class was introduced to prevent event thread leaks on Linux + // as described on GitHub: https://github.com/dotnet/runtime/issues/63788 + // For each CreateSocket() new s_socket instance is created and we pass it to ".NET Network Address Change" thread. + // We then continue loop in LoopReadSocket method as long as both references are equal. + private class SocketWrapper + { + public SocketWrapper(int socket) + { + Socket = socket; + } + + public int Socket { get; } + } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs index ef5fb68547fc7f..2af54c4938ca4b 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs @@ -379,8 +379,8 @@ public override UnicastIPAddressInformationCollection GetUnicastAddresses() => public override async Task GetUnicastAddressesAsync() { // Wait for the address table to stabilize. - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + if (!TeredoHelper.UnsafeNotifyStableUnicastIpAddressTable(s => ((TaskCompletionSource)s).TrySetResult(), tcs)) { await tcs.Task.ConfigureAwait(false); } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs index 6a2a07a81fa0a8..c99f15dcfd4753 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkAddressChangedTests.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Diagnostics; +using System.Threading; +using System.Linq; namespace System.Net.NetworkInformation.Tests { @@ -23,5 +26,31 @@ public void NetworkAddressChanged_JustRemove_Success() { NetworkChange.NetworkAddressChanged -= _addressHandler; } + + [PlatformSpecific(TestPlatforms.Linux)] + [OuterLoop("May take several seconds")] + [ConditionalFact(nameof(SupportsGettingThreadsWithPsCommand))] + public void NetworkAddressChanged_AddRemoveMultipleTimes_CheckForLeakingThreads() + { + for (int i = 1; i <= 10; i++) + { + NetworkChange.NetworkAddressChanged += _addressHandler; + NetworkChange.NetworkAddressChanged -= _addressHandler; + } + + Thread.Sleep(2000); //allow some time for threads to exit + + //We are searching for threads containing ".NET Network Ad" + //because ps command trims actual thread name ".NET Network Address Change". + //This thread is created in: + // src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs + int numberOfNetworkAddressChangeThreads = ProcessUtil.GetProcessThreadsWithPsCommand(Process.GetCurrentProcess().Id) + .Where(e => e.IndexOf(".NET Network Ad") > 0).Count(); + + Assert.Equal(0, numberOfNetworkAddressChangeThreads); //there should be no threads because there are no event subscribers + } + + private static bool SupportsGettingThreadsWithPsCommand + => TestConfiguration.SupportsGettingThreadsWithPsCommand; } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs new file mode 100644 index 00000000000000..842c20672ce702 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/ProcessUtil.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; + +namespace System.Net.NetworkInformation.Tests +{ + internal static class ProcessUtil + { + public static IEnumerable GetProcessThreadsWithPsCommand(int pid, int? timeoutInMilliseconds = null) + { + ProcessStartInfo psi = new ProcessStartInfo("ps", $"-T --no-headers -p {pid}"); + psi.RedirectStandardOutput = true; + + Process? process; + + try + { + process = Process.Start(psi); + } + catch (Exception ex) + { + throw new Exception($"Exception while trying to run 'ps' command", ex); + } + + if (process == null) + { + throw new Exception("Could not create process 'ps'"); + } + + try + { + if (timeoutInMilliseconds.HasValue) + { + if (!process.WaitForExit(timeoutInMilliseconds.Value)) + { + throw new Exception($"Process 'ps' did not exit after {timeoutInMilliseconds} milliseconds"); + } + } + else + { + process.WaitForExit(); + } + + string output = process.StandardOutput.ReadToEnd(); + if (process.ExitCode != 0) + { + throw new Exception($"Process 'ps' returned exit code {process.ExitCode}"); + } + + using StringReader sr = new StringReader(output); + + while (true) + { + string? line = sr.ReadLine(); + if (line == null) + { + break; + } + + yield return line; + } + } + finally + { + process.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj index 911dc187186c32..efd19ba3094f1f 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/System.Net.NetworkInformation.Functional.Tests.csproj @@ -40,6 +40,8 @@ + + diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs new file mode 100644 index 00000000000000..058f13d49d7009 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/TestConfiguration.cs @@ -0,0 +1,29 @@ +// 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.Linq; + +namespace System.Net.NetworkInformation.Tests +{ + internal static class TestConfiguration + { + public static bool SupportsGettingThreadsWithPsCommand { get { return s_supportsGettingThreadsWithPsCommand.Value; } } + + private static Lazy s_supportsGettingThreadsWithPsCommand = new Lazy(() => + { + if (OperatingSystem.IsWindows()) + { + return false; + } + + // On other platforms we will try it. + try + { + _ = ProcessUtil.GetProcessThreadsWithPsCommand(Process.GetCurrentProcess().Id).ToArray(); + return true; + } + catch { return false; } + }); + } +} \ No newline at end of file diff --git a/src/libraries/System.Net.Ping/src/Resources/Strings.resx b/src/libraries/System.Net.Ping/src/Resources/Strings.resx index 1ad9023082ef59..1a1c7112b5d30d 100644 --- a/src/libraries/System.Net.Ping/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Ping/src/Resources/Strings.resx @@ -84,9 +84,6 @@ IPv6 is not installed. - - Ping functionality is not currently supported in UWP. - System.Net.Ping is not supported on this platform. diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs index 0d81532f2bc144..94cdeb2fe890c6 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.RawSocket.cs @@ -19,6 +19,7 @@ public partial class Ping private const int MinIpHeaderLengthInBytes = 20; private const int MaxIpHeaderLengthInBytes = 60; private const int IpV6HeaderLengthInBytes = 40; + private static ushort DontFragment = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)0x4000) : (ushort)0x4000; private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, int timeout, PingOptions? options) { @@ -29,15 +30,17 @@ private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, in bool ipv4 = address.AddressFamily == AddressFamily.InterNetwork; bool sendIpHeader = ipv4 && options != null && SendIpHeader; + int totalLength = 0; if (sendIpHeader) { iph.VersionAndLength = 0x45; + totalLength = sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length); // On OSX this strangely must be host byte order. - iph.TotalLength = (ushort)(sizeof(IpHeader) + checked(sizeof(IcmpHeader) + buffer.Length)); + iph.TotalLength = OperatingSystem.IsFreeBSD() ? (ushort)IPAddress.HostToNetworkOrder((short)totalLength) : (ushort)totalLength; iph.Protocol = 1; // ICMP iph.Ttl = (byte)options!.Ttl; - iph.Flags = (ushort)(options.DontFragment ? 0x4000 : 0); + iph.Flags = (ushort)(options.DontFragment ? DontFragment : 0); #pragma warning disable 618 iph.DestinationAddress = (uint)address.Address; #pragma warning restore 618 @@ -52,7 +55,7 @@ private unsafe SocketConfig GetSocketConfig(IPAddress address, byte[] buffer, in { Type = ipv4 ? (byte)IcmpV4MessageType.EchoRequest : (byte)IcmpV6MessageType.EchoRequest, Identifier = id, - }, buffer)); + }, buffer, totalLength)); } private Socket GetRawSocket(SocketConfig socketConfig) @@ -405,14 +408,14 @@ public SocketConfig(EndPoint endPoint, int timeout, PingOptions? options, bool i public readonly byte[] SendBuffer; } - private static unsafe byte[] CreateSendMessageBuffer(IpHeader ipHeader, IcmpHeader icmpHeader, byte[] payload) + private static unsafe byte[] CreateSendMessageBuffer(IpHeader ipHeader, IcmpHeader icmpHeader, byte[] payload, int totalLength = 0) { int icmpHeaderSize = sizeof(IcmpHeader); int offset = 0; - int packetSize = ipHeader.TotalLength != 0 ? ipHeader.TotalLength : checked(icmpHeaderSize + payload.Length); + int packetSize = totalLength != 0 ? totalLength : checked(icmpHeaderSize + payload.Length); byte[] result = new byte[packetSize]; - if (ipHeader.TotalLength != 0) + if (totalLength != 0) { int ipHeaderSize = sizeof(IpHeader); new Span(&ipHeader, sizeof(IpHeader)).CopyTo(result); diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs index 3897853f6d856f..987d0462d70cae 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Unix.cs @@ -15,7 +15,7 @@ namespace System.Net.NetworkInformation { public partial class Ping { - private static bool SendIpHeader => false; + private static bool SendIpHeader => OperatingSystem.IsFreeBSD(); private static bool NeedsConnect => OperatingSystem.IsLinux(); private static bool SupportsDualMode => true; diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs b/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs index a36d4f93deb02b..8a87d2f0111e67 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/TestSettings.cs @@ -14,7 +14,9 @@ internal static class TestSettings public const int PingTimeout = 10 * 1000; public const string PayloadAsString = "'Post hoc ergo propter hoc'. 'After it, therefore because of it'. It means one thing follows the other, therefore it was caused by the other. But it's not always true. In fact it's hardly ever true."; - public static readonly byte[] PayloadAsBytes = Encoding.UTF8.GetBytes(TestSettings.PayloadAsString); + + // By default, FreeBSD supports buffer only up to 56 bytes + public static readonly byte[] PayloadAsBytes = Encoding.UTF8.GetBytes(OperatingSystem.IsFreeBSD() ? TestSettings.PayloadAsString.Substring(0, 55) : TestSettings.PayloadAsString); public static readonly byte[] PayloadAsBytesShort = Encoding.UTF8.GetBytes("ABCDEF0123456789"); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 8ed63ef9f97b3b..4d0bfa918fd242 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -717,7 +717,7 @@ public override bool Equals([NotNullWhen(true)] object? comparand) && string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(Value, other.Value, StringComparison.Ordinal) && string.Equals(Path, other.Path, StringComparison.Ordinal) - && string.Equals(Domain, other.Domain, StringComparison.OrdinalIgnoreCase) + && CookieComparer.EqualDomains(Domain, other.Domain) && (Version == other.Version); } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs b/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs index e8c7c78b68c0b5..edfe5ce52551ae 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CookieCollection.cs @@ -203,7 +203,7 @@ internal int InternalAdd(Cookie cookie, bool isStrict) for (int i = 0; i < listCount; i++) { Cookie c = (Cookie)m_list[i]!; - if (CookieComparer.Compare(cookie, c) == 0) + if (CookieComparer.Equals(cookie, c)) { ret = 0; // Will replace or reject @@ -237,7 +237,7 @@ internal int IndexOf(Cookie cookie) int idx = 0; foreach (Cookie? c in m_list) { - if (CookieComparer.Compare(cookie, c!) == 0) + if (CookieComparer.Equals(cookie, c!)) { return idx; } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs index f0e19c005ab7fb..d12a7b9d0751b3 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/CredentialCache.cs @@ -57,20 +57,8 @@ public void Add(Uri uriPrefix, string authType, NetworkCredential cred) public void Add(string host, int port, string authenticationType, NetworkCredential credential) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - - if (authenticationType == null) - { - throw new ArgumentNullException(nameof(authenticationType)); - } - - if (host.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host)), nameof(host)); - } + ArgumentException.ThrowIfNullOrEmpty(host); + ArgumentNullException.ThrowIfNull(authenticationType); if (port < 0) { @@ -200,18 +188,8 @@ public void Remove(string? host, int port, string? authenticationType) public NetworkCredential? GetCredential(string host, int port, string authenticationType) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - if (authenticationType == null) - { - throw new ArgumentNullException(nameof(authenticationType)); - } - if (host.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host)), nameof(host)); - } + ArgumentException.ThrowIfNullOrEmpty(host); + ArgumentNullException.ThrowIfNull(authenticationType); if (port < 0) { throw new ArgumentOutOfRangeException(nameof(port)); diff --git a/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs b/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs index fc6fb3b9177bbc..1cdc3c5774cc7f 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/DnsEndPoint.cs @@ -16,15 +16,7 @@ public DnsEndPoint(string host, int port) : this(host, port, AddressFamily.Unspe public DnsEndPoint(string host, int port, AddressFamily addressFamily) { - if (host == null) - { - throw new ArgumentNullException(nameof(host)); - } - - if (string.IsNullOrEmpty(host)) - { - throw new ArgumentException(SR.Format(SR.net_emptystringcall, nameof(host))); - } + ArgumentException.ThrowIfNullOrEmpty(host); if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) { diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs index b43ac159ead52e..4d826d0e61afa2 100644 --- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs +++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/DnsEndPointTest.cs @@ -30,8 +30,8 @@ public static void Ctor_HostPort_AddressFamily_Success() [Fact] public static void Ctor_HostPortAddressFamily_Invalid() { - Assert.Throws(() => new DnsEndPoint(null, 500, AddressFamily.InterNetwork)); //Null host - AssertExtensions.Throws(null, () => new DnsEndPoint("", 500, AddressFamily.InterNetwork)); //Empty host + AssertExtensions.Throws("host", () => new DnsEndPoint(null, 500, AddressFamily.InterNetwork)); //Null host + AssertExtensions.Throws("host", () => new DnsEndPoint("", 500, AddressFamily.InterNetwork)); //Empty host Assert.Throws(() => new DnsEndPoint("host", IPEndPoint.MinPort - 1, AddressFamily.InterNetwork)); //Port < min port (0) Assert.Throws(() => new DnsEndPoint("host", IPEndPoint.MaxPort + 1, AddressFamily.InterNetwork)); //Port > max port (65535) diff --git a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs index b3673331aebcd6..53cb06963caa7f 100644 --- a/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs +++ b/src/libraries/System.Net.Primitives/tests/UnitTests/CookieContainerTest.cs @@ -866,6 +866,51 @@ public void SetCookies_DomainCheckFailure_IgnoresAbsenceOfLeadingDot(string doma Assert.Throws(() => container.SetCookies(uri, cookie)); } + [Theory] + [InlineData("example.com", "example.com" )] + [InlineData("example.com", ".example.com" )] + [InlineData(".example.com", "example.com" )] + [InlineData(".example.com", ".example.com")] + public void SetCookies_DomainCheckSuccess_IgnoresLeadingDot(params string[] domains) + { + var uri = new Uri($"https://{domains[0].Trim('.')}/", UriKind.Absolute); + var container = new CookieContainer(); + + // First HTTP response... + container.SetCookies(uri, $"foo=bar; Path=/; Domain={domains[0]}"); + + // Second HTTP response... + container.SetCookies(uri, $"foo=baz; Path=/; Domain={domains[1]}"); + + CookieCollection acceptedCookies = container.GetCookies(uri); + Assert.Equal(1, acceptedCookies.Count); + Assert.Equal(domains[1], acceptedCookies[0].Domain); + } + + [Theory] + [InlineData("test.example.com", "example.com")] + [InlineData("test.example.com", ".example.com")] + [InlineData("example.com", "test.example.com")] + [InlineData(".example.com", "test.example.com")] + public void SetCookies_DomainCheckFailure_IgnoresLeadingDot(params string[] domains) + { + var uri = new Uri($"https://test.example.com/", UriKind.Absolute); + var container = new CookieContainer(); + + // First HTTP response... + container.SetCookies(uri, $"foo=bar; Path=/; Domain={domains[0]}"); + + // Second HTTP response... + container.SetCookies(uri, $"foo=baz; Path=/; Domain={domains[1]}"); + + CookieCollection acceptedCookies = container.GetCookies(uri); + Assert.Equal(2, acceptedCookies.Count); + foreach (Cookie cookie in acceptedCookies) + { + Assert.Contains(cookie.Domain, domains); + } + } + // Test default-path calculation as defined in // https://tools.ietf.org/html/rfc6265#section-5.1.4 public static readonly TheoryData DefaultPathData = new TheoryData() diff --git a/src/libraries/System.Net.Quic/src/Resources/Strings.resx b/src/libraries/System.Net.Quic/src/Resources/Strings.resx index a692407e183640..f1e227448e030a 100644 --- a/src/libraries/System.Net.Quic/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Quic/src/Resources/Strings.resx @@ -123,12 +123,6 @@ Connection aborted by peer ({0}). - - Must pass loopback address and port 0 - - - QUIC is not supported on this platform. See https://aka.ms/dotnetquic - Operation aborted. diff --git a/src/libraries/System.Net.Requests/src/Resources/Strings.resx b/src/libraries/System.Net.Requests/src/Resources/Strings.resx index a3b2bb922d3c78..e93fad131a92c4 100644 --- a/src/libraries/System.Net.Requests/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Requests/src/Resources/Strings.resx @@ -87,9 +87,6 @@ This method is not implemented by this class. - - This operation is not supported. - This property is not implemented by this class. diff --git a/src/libraries/System.Net.Security/src/Resources/Strings.resx b/src/libraries/System.Net.Security/src/Resources/Strings.resx index e33b4122a7d53d..5373ba6ee33071 100644 --- a/src/libraries/System.Net.Security/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/src/Resources/Strings.resx @@ -221,9 +221,6 @@ Authentication failed on the remote side (the stream might still be available for additional authentication attempts). - - Re-authentication failed because the remote party continued to encrypt more than {0} bytes before answering re-authentication. - Protocol error: A received message contains a valid signature but it was not encrypted as required by the effective Protection Level. @@ -233,9 +230,6 @@ Received an invalid authentication frame. The message size is limited to {0} bytes, attempted to read {1} bytes. - - Received incomplete authentication message. Remote party has probably closed the connection. - Cannot determine the frame size or a corrupted frame was received. @@ -245,78 +239,9 @@ The specified value is not valid in the '{0}' enumeration. - - Enumerating security packages: - - - Security package '{0}' was not found. - - - {0}(In-Buffer length={1}, Out-Buffer length={2}, returned code={3}). - - - {0}(In-Buffers count={1}, Out-Buffer length={2}, returned code={3}). - - - {0}(Protocol={1}, Cipher={2} {3} bit strength, Hash={4} {5} bit strength, Key Exchange={6} {7} bit strength). - - - Remote certificate: {0}. - - - Locating the private key for the certificate: {0}. - - - Certificate is of type X509Certificate2 and contains the private key. - - - Found the certificate in the {0} store. - - - Cannot find the certificate in either the LocalMachine store or the CurrentUser store. - Opening Certificate store {0} failed, exception: {1}. - - Got a certificate from the client delegate. - - - Client delegate did not provide a certificate; and there are not other user-provided certificates. Need to attempt a session restart. - - - Client delegate did not provide a certificate; but there are other user-provided certificates. - - - Attempting to restart the session using the user-provided certificate: {0}. - - - We have user-provided certificates. The server has not specified any issuers, so try all the certificates. - - - We have user-provided certificates. The server has specified {0} issuer(s). Looking for certificates that match any of the issuers. - - - Selected certificate: {0}. - - - Left with {0} client certificates to choose from. - - - Trying to find a matching certificate in the certificate store. - - - Using the cached credential handle. - - - Remote certificate was verified as valid by the user. - - - Remote certificate was verified as invalid by the user. - - - Remote certificate has no errors. - Remote certificate has errors: @@ -341,9 +266,6 @@ The ServiceNameCollection must contain at least one service name. - - A service name must not be null or empty. - Failed to allocate SSL/TLS context, OpenSSL error - {0}. @@ -374,9 +296,6 @@ SSL Write BIO failed with OpenSSL error - {0}. - - Failed to push X509_NAME into stack. - Getting SSL connection info failed with OpenSSL error - {0}. @@ -457,7 +376,7 @@ Client stream needs to be drained before renegotiation. - + Setting an SNI hostname is not supported on this API level. diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 9f90dbd3951f05..047cbdcc98aea9 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -363,6 +363,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs b/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs new file mode 100644 index 00000000000000..bdf3547912c911 --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/MD4.cs @@ -0,0 +1,256 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// MD4.cs - Message Digest 4 Abstract class +// +// Author: +// Sebastien Pouliot (sebastien@xamarin.com) +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright 2013 Xamarin Inc. (http://www.xamarin.com) +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System.Buffers.Binary; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; + +// +// This class is a port of the Mono managed implementation of the MD4 algorithm +// and required to support NTLM in Android only. +// It's an implementation detail and is not intended to be a public API. +// Assuming that NTLM would be System.Net.Security, it makes sense to put MD4 here as well. +// +namespace System.Net.Security +{ + internal sealed class MD4 + { + private const int S11 = 3; + private const int S12 = 7; + private const int S13 = 11; + private const int S14 = 19; + private const int S21 = 3; + private const int S22 = 5; + private const int S23 = 9; + private const int S24 = 13; + private const int S31 = 3; + private const int S32 = 9; + private const int S33 = 11; + private const int S34 = 15; + + internal static void HashData(ReadOnlySpan source, Span destination) + { + Debug.Assert(destination.Length == 128 >> 3); + + Span buffer = stackalloc byte[64]; + buffer.Clear(); + // Initialize the context + Span state = stackalloc uint[4] { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }; + Span count = stackalloc uint[2] { 0, 0 }; + + HashCore(source, state, count, buffer); + + // Save number of bits + Span bits = stackalloc byte[8]; + Encode(bits, count); + + // Pad out to 56 mod 64 + uint index = ((count[0] >> 3) & 0x3f); + int padLen = (int)((index < 56) ? (56 - index) : (120 - index)); + Span padding = stackalloc byte[padLen]; + padding.Clear(); + padding[0] = 0x80; + HashCore(padding, state, count, buffer); + + // Append length (before padding) + HashCore(bits, state, count, buffer); + + // Write state to destination + Encode(destination, state); + } + + private static void HashCore(ReadOnlySpan input, Span state, Span count, Span buffer) + { + // Compute number of bytes mod 64 + int index = (int)((count[0] >> 3) & 0x3F); + // Update number of bits + count[0] += (uint)(input.Length << 3); + if (count[0] < (input.Length << 3)) + { + count[1]++; + } + + count[1] += (uint)(input.Length >> 29); + + int partLen = 64 - index; + int i = 0; + // Transform as many times as possible. + if (input.Length >= partLen) + { + if (index != 0) + { + input.Slice(0, partLen).CopyTo(buffer.Slice(index)); + MD4Transform(state, buffer); + index = 0; + } + else + { + partLen = 0; + } + + for (i = partLen; i + 63 < input.Length; i += 64) + { + MD4Transform(state, input.Slice(i)); + } + } + + // Buffer remaining input + input.Slice(i).CopyTo(buffer.Slice(index)); + } + + //--- private methods --------------------------------------------------- + + // F, G and H are basic MD4 functions. + private static uint F(uint x, uint y, uint z) + { + return (uint)(((x) & (y)) | ((~x) & (z))); + } + + private static uint G(uint x, uint y, uint z) + { + return (uint)(((x) & (y)) | ((x) & (z)) | ((y) & (z))); + } + + private static uint H(uint x, uint y, uint z) + { + return (uint)((x) ^ (y) ^ (z)); + } + + // FF, GG and HH are transformations for rounds 1, 2 and 3. + // Rotation is separate from addition to prevent recomputation. + private static void FF(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += F(b, c, d) + x; + a = BitOperations.RotateLeft(a, s); + } + + private static void GG(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += G(b, c, d) + x + 0x5a827999; + a = BitOperations.RotateLeft(a, s); + } + + private static void HH(ref uint a, uint b, uint c, uint d, uint x, byte s) + { + a += H(b, c, d) + x + 0x6ed9eba1; + a = BitOperations.RotateLeft(a, s); + } + + private static void Encode(Span output, Span input) + { + for (int i = 0, j = 0; j < output.Length; i++, j += 4) + { + BinaryPrimitives.WriteUInt32LittleEndian(output.Slice(j), input[i]); + } + } + + private static void Decode(Span output, ReadOnlySpan input) + { + for (int i = 0, j = 0; i < output.Length; i++, j += 4) + { + output[i] = BinaryPrimitives.ReadUInt32LittleEndian(input.Slice(j)); + } + } + + private static void MD4Transform(Span state, ReadOnlySpan block) + { + uint a = state[0]; + uint b = state[1]; + uint c = state[2]; + uint d = state[3]; + Span x = stackalloc uint[16]; + + Decode(x, block); + + // Round 1 + FF(ref a, b, c, d, x[0], S11); // 1 + FF(ref d, a, b, c, x[1], S12); // 2 + FF(ref c, d, a, b, x[2], S13); // 3 + FF(ref b, c, d, a, x[3], S14); // 4 + FF(ref a, b, c, d, x[4], S11); // 5 + FF(ref d, a, b, c, x[5], S12); // 6 + FF(ref c, d, a, b, x[6], S13); // 7 + FF(ref b, c, d, a, x[7], S14); // 8 + FF(ref a, b, c, d, x[8], S11); // 9 + FF(ref d, a, b, c, x[9], S12); // 10 + FF(ref c, d, a, b, x[10], S13); // 11 + FF(ref b, c, d, a, x[11], S14); // 12 + FF(ref a, b, c, d, x[12], S11); // 13 + FF(ref d, a, b, c, x[13], S12); // 14 + FF(ref c, d, a, b, x[14], S13); // 15 + FF(ref b, c, d, a, x[15], S14); // 16 + + // Round 2 + GG(ref a, b, c, d, x[0], S21); // 17 + GG(ref d, a, b, c, x[4], S22); // 18 + GG(ref c, d, a, b, x[8], S23); // 19 + GG(ref b, c, d, a, x[12], S24); // 20 + GG(ref a, b, c, d, x[1], S21); // 21 + GG(ref d, a, b, c, x[5], S22); // 22 + GG(ref c, d, a, b, x[9], S23); // 23 + GG(ref b, c, d, a, x[13], S24); // 24 + GG(ref a, b, c, d, x[2], S21); // 25 + GG(ref d, a, b, c, x[6], S22); // 26 + GG(ref c, d, a, b, x[10], S23); // 27 + GG(ref b, c, d, a, x[14], S24); // 28 + GG(ref a, b, c, d, x[3], S21); // 29 + GG(ref d, a, b, c, x[7], S22); // 30 + GG(ref c, d, a, b, x[11], S23); // 31 + GG(ref b, c, d, a, x[15], S24); // 32 + + HH(ref a, b, c, d, x[0], S31); // 33 + HH(ref d, a, b, c, x[8], S32); // 34 + HH(ref c, d, a, b, x[4], S33); // 35 + HH(ref b, c, d, a, x[12], S34); // 36 + HH(ref a, b, c, d, x[2], S31); // 37 + HH(ref d, a, b, c, x[10], S32); // 38 + HH(ref c, d, a, b, x[6], S33); // 39 + HH(ref b, c, d, a, x[14], S34); // 40 + HH(ref a, b, c, d, x[1], S31); // 41 + HH(ref d, a, b, c, x[9], S32); // 42 + HH(ref c, d, a, b, x[5], S33); // 43 + HH(ref b, c, d, a, x[13], S34); // 44 + HH(ref a, b, c, d, x[3], S31); // 45 + HH(ref d, a, b, c, x[11], S32); // 46 + HH(ref c, d, a, b, x[7], S33); // 47 + HH(ref b, c, d, a, x[15], S34); // 48 + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + } + } +} diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs index 3690837e33f679..9e1a445d9dc750 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/Pal.OSX/SafeDeleteSslContext.cs @@ -130,6 +130,7 @@ private static SafeSslHandle CreateSslContext(SafeFreeSslCredentials credential, SetCertificate(sslContext, credential.CertificateContext); } + Interop.AppleCrypto.SslBreakOnCertRequested(sslContext, true); Interop.AppleCrypto.SslBreakOnServerAuth(sslContext, true); Interop.AppleCrypto.SslBreakOnClientAuth(sslContext, true); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs index 6a2135616f1d55..e3363ddc1c34a2 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs @@ -295,62 +295,24 @@ private string[] GetRequestCertificateAuthorities() return issuers; } - /*++ - AcquireCredentials - Attempts to find Client Credential - Information, that can be sent to the server. In our case, - this is only Client Certificates, that we have Credential Info. - - How it works: - case 0: Cert Selection delegate is present - Always use its result as the client cert answer. - Try to use cached credential handle whenever feasible. - Do not use cached anonymous creds if the delegate has returned null - and the collection is not empty (allow responding with the cert later). - - case 1: Certs collection is empty - Always use the same statically acquired anonymous SSL Credential - - case 2: Before our Connection with the Server - If we have a cached credential handle keyed by first X509Certificate - **content** in the passed collection, then we use that cached - credential and hoping to restart a session. - - Otherwise create a new anonymous (allow responding with the cert later). - - case 3: After our Connection with the Server (i.e. during handshake or re-handshake) - The server has requested that we send it a Certificate then - we Enumerate a list of server sent Issuers trying to match against - our list of Certificates, the first match is sent to the server. - - Once we got a cert we again try to match cached credential handle if possible. - This will not restart a session but helps minimizing the number of handles we create. - - In the case of an error getting a Certificate or checking its private Key we fall back - to the behavior of having no certs, case 1. - - Returns: True if cached creds were used, false otherwise. - - --*/ - - private bool AcquireClientCredentials(ref byte[]? thumbPrint) + internal X509Certificate2? SelectClientCertificate(out bool sessionRestartAttempt) { - // Acquire possible Client Certificate information and set it on the handle. - X509Certificate? clientCertificate = null; // This is a candidate that can come from the user callback or be guessed when targeting a session restart. - List? filteredCerts = null; // This is an intermediate client certs collection that try to use if no selectedCert is available yet. - string[] issuers; // This is a list of issuers sent by the server, only valid is we do know what the server cert is. + sessionRestartAttempt = false; - bool sessionRestartAttempt = false; // If true and no cached creds we will use anonymous creds. + X509Certificate? clientCertificate = null; // candidate certificate that can come from the user callback or be guessed when targeting a session restart. + X509Certificate2? selectedCert = null; // final selected cert (ensured that it does have private key with it). + List? filteredCerts = null; // This is an intermediate client certs collection that try to use if no selectedCert is available yet. + string[] issuers; // This is a list of issuers sent by the server, only valid if we do know what the server cert is. if (_sslAuthenticationOptions.CertSelectionDelegate != null) { - issuers = GetRequestCertificateAuthorities(); - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "Calling CertificateSelectionCallback"); X509Certificate2? remoteCert = null; try { + issuers = GetRequestCertificateAuthorities(); remoteCert = CertificateValidationPal.GetRemoteCertificate(_securityContext!); if (_sslAuthenticationOptions.ClientCertificates == null) { @@ -363,7 +325,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) remoteCert?.Dispose(); } - if (clientCertificate != null) { if (_credentialsHandle == null) @@ -505,9 +466,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) } } - bool cachedCred = false; // This is a return result from this method. - X509Certificate2? selectedCert = null; // This is a final selected cert (ensured that it does have private key with it). - clientCertificate = null; if (NetEventSource.Log.IsEnabled()) @@ -550,6 +508,56 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Selected cert = {selectedCert}"); + _selectedClientCertificate = clientCertificate; + return selectedCert; + } + + /*++ + AcquireCredentials - Attempts to find Client Credential + Information, that can be sent to the server. In our case, + this is only Client Certificates, that we have Credential Info. + + How it works: + case 0: Cert Selection delegate is present + Always use its result as the client cert answer. + Try to use cached credential handle whenever feasible. + Do not use cached anonymous creds if the delegate has returned null + and the collection is not empty (allow responding with the cert later). + + case 1: Certs collection is empty + Always use the same statically acquired anonymous SSL Credential + + case 2: Before our Connection with the Server + If we have a cached credential handle keyed by first X509Certificate + **content** in the passed collection, then we use that cached + credential and hoping to restart a session. + + Otherwise create a new anonymous (allow responding with the cert later). + + case 3: After our Connection with the Server (i.e. during handshake or re-handshake) + The server has requested that we send it a Certificate then + we Enumerate a list of server sent Issuers trying to match against + our list of Certificates, the first match is sent to the server. + + Once we got a cert we again try to match cached credential handle if possible. + This will not restart a session but helps minimizing the number of handles we create. + + In the case of an error getting a Certificate or checking its private Key we fall back + to the behavior of having no certs, case 1. + + Returns: True if cached creds were used, false otherwise. + + --*/ + + private bool AcquireClientCredentials(ref byte[]? thumbPrint) + { + // Acquire possible Client Certificate information and set it on the handle. + + bool sessionRestartAttempt; // If true and no cached creds we will use anonymous creds. + bool cachedCred = false; // this is a return result from this method. + + X509Certificate2? selectedCert = SelectClientCertificate(out sessionRestartAttempt); + try { // Try to locate cached creds first. @@ -574,14 +582,14 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) // So we don't want to reuse **anonymous** cached credential for a new SSL connection if the client has passed some certificate. // The following block happens if client did specify a certificate but no cached creds were found in the cache. // Since we don't restart a session the server side can still challenge for a client cert. - if ((object?)clientCertificate != (object?)selectedCert) + if ((object?)_selectedClientCertificate != (object?)selectedCert) { selectedCert.Dispose(); } guessedThumbPrint = null; selectedCert = null; - clientCertificate = null; + _selectedClientCertificate = null; } if (cachedCredentialHandle != null) @@ -589,7 +597,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.UsingCachedCredential(this); _credentialsHandle = cachedCredentialHandle; - _selectedClientCertificate = clientCertificate; cachedCred = true; if (selectedCert != null) { @@ -607,7 +614,6 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.EncryptionPolicy, _sslAuthenticationOptions.IsServer); thumbPrint = guessedThumbPrint; // Delay until here in case something above threw. - _selectedClientCertificate = clientCertificate; } } finally @@ -792,6 +798,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte if (_sslAuthenticationOptions.IsServer) { status = SslStreamPal.AcceptSecurityContext( + this, ref _credentialsHandle!, ref _securityContext, inputBuffer, @@ -801,6 +808,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte else { status = SslStreamPal.InitializeSecurityContext( + this, ref _credentialsHandle!, ref _securityContext, _sslAuthenticationOptions.TargetHost, @@ -841,6 +849,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte internal SecurityStatusPal Renegotiate(out byte[]? output) { return SslStreamPal.Renegotiate( + this, ref _credentialsHandle!, ref _securityContext, _sslAuthenticationOptions, diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 9e6ad7475d7663..58156e3d76a94d 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -21,18 +21,6 @@ public partial class SslStream private int _nestedAuth; private bool _isRenego; - private enum Framing - { - Unknown = 0, // Initial before any frame is processed. - BeforeSSL3, // SSlv2 - SinceSSL3, // SSlv3 & TLS - Unified, // Intermediate on first frame until response is processes. - Invalid // Something is wrong. - } - - // This is set on the first packet to figure out the framing style. - private Framing _framing = Framing.Unknown; - private TlsFrameHelper.TlsFrameInfo _lastFrame; private object _handshakeLock => _sslAuthenticationOptions!; @@ -270,7 +258,7 @@ private async Task RenegotiateAsync(TIOAdapter adapter) try { - if (_decryptedBytesCount is not 0) + if ((_decryptedBytesCount | _internalBufferCount) != 0) { throw new InvalidOperationException(SR.net_ssl_renegotiate_buffer); } @@ -460,27 +448,12 @@ private async ValueTask ReceiveBlobAsync(TIOAdapter a where TIOAdapter : IReadWriteAdapter { await FillHandshakeBufferAsync(adapter, SecureChannel.ReadHeaderSize).ConfigureAwait(false); - if (_framing == Framing.Unified || _framing == Framing.Unknown) - { - _framing = DetectFraming(_handshakeBuffer.ActiveReadOnlySpan); - } - - if (_framing != Framing.SinceSSL3) - { -#pragma warning disable 0618 - _lastFrame.Header.Version = SslProtocols.Ssl2; -#pragma warning restore 0618 - _lastFrame.Header.Length = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan) - TlsFrameHelper.HeaderSize; - } - else - { - TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); - } + TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); if (_lastFrame.Header.Length < 0) { if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, "invalid TLS frame size"); - throw new IOException(SR.net_frame_read_size); + throw new AuthenticationException(SR.net_frame_read_size); } // Header length is content only so we must add header size as well. @@ -560,29 +533,26 @@ private ProtocolToken ProcessBlob(int frameSize) // ActiveSpan will exclude the "discarded" data. _handshakeBuffer.Discard(frameSize); - if (_framing == Framing.SinceSSL3) + // Often more TLS messages fit into same packet. Get as many complete frames as we can. + while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) { - // Often more TLS messages fit into same packet. Get as many complete frames as we can. - while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) - { - TlsFrameHeader nextHeader = default; - - if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) - { - break; - } + TlsFrameHeader nextHeader = default; - frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; - // Can process more handshake frames in single step, but we should avoid processing too much so as to preserve API boundary between handshake and I/O. - if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) || frameSize > _handshakeBuffer.ActiveLength) - { - // We don't have full frame left or we already have app data which needs to be processed by decrypt. - break; - } + if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) + { + break; + } - chunkSize += frameSize; - _handshakeBuffer.Discard(frameSize); + frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; + // Can process more handshake frames in single step, but we should avoid processing too much so as to preserve API boundary between handshake and I/O. + if ((nextHeader.Type != TlsContentType.Handshake && nextHeader.Type != TlsContentType.ChangeCipherSpec) || frameSize > _handshakeBuffer.ActiveLength) + { + // We don't have full frame left or we already have app data which needs to be processed by decrypt. + break; } + + chunkSize += frameSize; + _handshakeBuffer.Discard(frameSize); } return _context!.NextMessage(availableData.Slice(0, chunkSize)); @@ -1199,204 +1169,15 @@ private void ResetReadBuffer() } } - // We need at least 5 bytes to determine what we have. - private Framing DetectFraming(ReadOnlySpan bytes) - { - /* PCTv1.0 Hello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * PCT1_CLIENT_HELLO (must be equal) - * PCT1_CLIENT_VERSION_MSB (if version greater than PCTv1) - * PCT1_CLIENT_VERSION_LSB (if version greater than PCTv1) - * - * ... PCT hello ... - */ - - /* Microsoft Unihello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 Compatible Hello ... - */ - - /* SSLv2 CLIENT_HELLO starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 CLIENT_HELLO ... - */ - - /* SSLv2 SERVER_HELLO starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_SERVER_HELLO (must be equal) - * SSL2_SESSION_ID_HIT (ignore) - * SSL2_CERTIFICATE_TYPE (ignore) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv2) ( or v3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv2) ( or v3) - * - * ... SSLv2 SERVER_HELLO ... - */ - - /* SSLv3 Type 2 Hello starts with - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * SSL2_CLIENT_HELLO (must be equal) - * SSL2_CLIENT_VERSION_MSB (if version greater than SSLv3) - * SSL2_CLIENT_VERSION_LSB (if version greater than SSLv3) - * - * ... SSLv2 Compatible Hello ... - */ - - /* SSLv3 Type 3 Hello starts with - * 22 (HANDSHAKE MESSAGE) - * VERSION MSB - * VERSION LSB - * RECORD_LENGTH_MSB (ignore) - * RECORD_LENGTH_LSB (ignore) - * HS TYPE (CLIENT_HELLO) - * 3 bytes HS record length - * HS Version - * HS Version - */ - - /* SSLv2 message codes - * SSL_MT_ERROR 0 - * SSL_MT_CLIENT_HELLO 1 - * SSL_MT_CLIENT_MASTER_KEY 2 - * SSL_MT_CLIENT_FINISHED 3 - * SSL_MT_SERVER_HELLO 4 - * SSL_MT_SERVER_VERIFY 5 - * SSL_MT_SERVER_FINISHED 6 - * SSL_MT_REQUEST_CERTIFICATE 7 - * SSL_MT_CLIENT_CERTIFICATE 8 - */ - - int version = -1; - - Debug.Assert(bytes.Length != 0, "Header buffer is not allocated."); - - // If the first byte is SSL3 HandShake, then check if we have a SSLv3 Type3 client hello. - if (bytes[0] == (byte)TlsContentType.Handshake || bytes[0] == (byte)TlsContentType.AppData - || bytes[0] == (byte)TlsContentType.Alert) - { - if (bytes.Length < 3) - { - return Framing.Invalid; - } - - version = (bytes[1] << 8) | bytes[2]; - if (version < 0x300 || version >= 0x500) - { - return Framing.Invalid; - } - - // - // This is an SSL3 Framing - // - return Framing.SinceSSL3; - } - - if (bytes.Length < 3) - { - return Framing.Invalid; - } - - if (bytes[2] > 8) - { - return Framing.Invalid; - } - - if (bytes[2] == 0x1) // SSL_MT_CLIENT_HELLO - { - if (bytes.Length >= 5) - { - version = (bytes[3] << 8) | bytes[4]; - } - } - else if (bytes[2] == 0x4) // SSL_MT_SERVER_HELLO - { - if (bytes.Length >= 7) - { - version = (bytes[5] << 8) | bytes[6]; - } - } - - if (version != -1) - { - // If this is the first packet, the client may start with an SSL2 packet - // but stating that the version is 3.x, so check the full range. - // For the subsequent packets we assume that an SSL2 packet should have a 2.x version. - if (_framing == Framing.Unknown) - { - if (version != 0x0002 && (version < 0x200 || version >= 0x500)) - { - return Framing.Invalid; - } - } - else - { - if (version != 0x0002) - { - return Framing.Invalid; - } - } - } - - // When server has replied the framing is already fixed depending on the prior client packet - if (!_context!.IsServer || _framing == Framing.Unified) - { - return Framing.BeforeSSL3; - } - - return Framing.Unified; // Will use Ssl2 just for this frame. - } - - // Returns TLS Frame size. + // Returns TLS Frame size including header size. private int GetFrameSize(ReadOnlySpan buffer) { - int payloadSize; - switch (_framing) + if (buffer.Length < SecureChannel.ReadHeaderSize) { - case Framing.Unified: - case Framing.BeforeSSL3: - if (buffer.Length < 2) - { - throw new IOException(SR.net_ssl_io_frame); - } - // Note: Cannot detect version mismatch for <= SSL2 - - if ((buffer[0] & 0x80) != 0) - { - // Two bytes - payloadSize = (((buffer[0] & 0x7f) << 8) | buffer[1]) + 2; - } - else - { - // Three bytes - payloadSize = (((buffer[0] & 0x3f) << 8) | buffer[1]) + 3; - } - - break; - case Framing.SinceSSL3: - if (buffer.Length < 5) - { - throw new IOException(SR.net_ssl_io_frame); - } - - payloadSize = ((buffer[3] << 8) | buffer[4]) + 5; - break; - default: - throw new IOException(SR.net_frame_read_size); + throw new IOException(SR.net_ssl_io_frame); } - return payloadSize; + return ((buffer[3] << 8) | buffer[4]) + SecureChannel.ReadHeaderSize; } } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs index 27c854c99168e7..54187a60c6c293 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs @@ -25,6 +25,7 @@ public static void VerifyPackageInfo() } public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, @@ -35,6 +36,7 @@ public static SecurityStatusPal AcceptSecurityContext( } public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, string? targetName, @@ -45,7 +47,12 @@ public static SecurityStatusPal InitializeSecurityContext( return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { throw new PlatformNotSupportedException(); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs index 7043b7afe19f4d..6b1b13ca9f2a70 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs @@ -20,7 +20,7 @@ public static Exception GetException(SecurityStatusPal status) return status.Exception ?? new Win32Exception((int)status.ErrorCode); } - internal const bool StartMutualAuthAsAnonymous = false; + internal const bool StartMutualAuthAsAnonymous = true; // SecureTransport is okay with a 0 byte input, but it produces a 0 byte output. // Since ST is not producing the framed empty message just call this false and avoid the @@ -32,16 +32,18 @@ public static void VerifyPackageInfo() } public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, ref SafeFreeCredentials credential, ref SafeDeleteSslContext? context, string? targetName, @@ -49,10 +51,15 @@ public static SecurityStatusPal InitializeSecurityContext( ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { throw new PlatformNotSupportedException(); } @@ -224,6 +231,7 @@ public static void QueryContextConnectionInfo( } private static SecurityStatusPal HandshakeInternal( + SecureChannel secureChannel, SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, @@ -268,28 +276,11 @@ private static SecurityStatusPal HandshakeInternal( SecurityStatusPal status = PerformHandshake(sslHandle); if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { - // we should not be here if CertSelectionDelegate is null but better check before dereferencing.. - if (sslAuthenticationOptions.CertSelectionDelegate != null) + X509Certificate2? clientCertificate = secureChannel.SelectClientCertificate(out _); + if (clientCertificate != null) { - X509Certificate2? remoteCert = null; - try - { - string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context); - remoteCert = CertificateValidationPal.GetRemoteCertificate(context); - if (sslAuthenticationOptions.ClientCertificates == null) - { - sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection(); - } - X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost!, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers); - if (clientCertificate != null) - { - SafeDeleteSslContext.SetCertificate(sslContext.SslContext, SslStreamCertificateContext.Create(clientCertificate)); - } - } - finally - { - remoteCert?.Dispose(); - } + sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); + SafeDeleteSslContext.SetCertificate(sslContext.SslContext, sslAuthenticationOptions.CertificateContext); } // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK. diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs index 63c4efc1edb655..a9192681444bef 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Unix.cs @@ -17,23 +17,34 @@ public static Exception GetException(SecurityStatusPal status) return status.Exception ?? new Interop.OpenSsl.SslException((int)status.ErrorCode); } - internal const bool StartMutualAuthAsAnonymous = false; + internal const bool StartMutualAuthAsAnonymous = true; internal const bool CanEncryptEmptyMessage = false; public static void VerifyPackageInfo() { } - public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, - ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credential, + ref SafeDeleteSslContext? context, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } - public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials? credential, ref SafeDeleteSslContext? context, string? targetName, - ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credential, + ref SafeDeleteSslContext? context, + string? targetName, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { - return HandshakeInternal(credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credential!, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions); } public static SafeFreeCredentials AcquireCredentialsHandle(SslStreamCertificateContext? certificateContext, @@ -116,7 +127,12 @@ Interop.Ssl.SslErrorCode.SSL_ERROR_NONE or return bindingHandle; } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? securityContext, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? securityContext, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer) { var sslContext = ((SafeDeleteSslContext)securityContext!).SslContext; SecurityStatusPal status = Interop.OpenSsl.SslRenegotiate(sslContext, out _); @@ -126,7 +142,7 @@ public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentials { return status; } - return HandshakeInternal(credentialsHandle!, ref securityContext, null, ref outputBuffer, sslAuthenticationOptions); + return HandshakeInternal(secureChannel, credentialsHandle!, ref securityContext, null, ref outputBuffer, sslAuthenticationOptions); } public static void QueryContextStreamSizes(SafeDeleteContext? securityContext, out StreamSizes streamSizes) @@ -139,7 +155,7 @@ public static void QueryContextConnectionInfo(SafeDeleteSslContext securityConte connectionInfo = new SslConnectionInfo(securityContext.SslContext); } - private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteSslContext? context, + private static SecurityStatusPal HandshakeInternal(SecureChannel secureChannel, SafeFreeCredentials credential, ref SafeDeleteSslContext? context, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Debug.Assert(!credential.IsInvalid); @@ -158,34 +174,17 @@ private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credentia if (errorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { - if (sslAuthenticationOptions.CertSelectionDelegate != null) + X509Certificate2? clientCertificate = secureChannel.SelectClientCertificate(out _); + if (clientCertificate != null) { - X509Certificate2? remoteCert = null; - string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context); - try - { - remoteCert = CertificateValidationPal.GetRemoteCertificate(context); - if (sslAuthenticationOptions.ClientCertificates == null) - { - sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection(); - } - X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost!, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers); - if (clientCertificate != null && clientCertificate.HasPrivateKey) - { - sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); - } - } - finally - { - remoteCert?.Dispose(); - } + sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); } Interop.OpenSsl.UpdateClientCertiticate(((SafeDeleteSslContext)context).SslContext, sslAuthenticationOptions); errorCode = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, out output, out outputSize); } - // sometimes during renegotiation processing messgae does not yield new output. + // sometimes during renegotiation processing message does not yield new output. // That seems to be flaw in OpenSSL state machine and we have workaround to peek it and try it again. if (outputSize == 0 && Interop.Ssl.IsSslRenegotiatePending(((SafeDeleteSslContext)context).SslContext)) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 2fb36e595b20da..2cb0f2ec14e66c 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -52,7 +52,13 @@ public static byte[] ConvertAlpnProtocolListToByteArray(List inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal AcceptSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; @@ -82,7 +88,14 @@ public static SecurityStatusPal AcceptSecurityContext(ref SafeFreeCredentials? c return SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode); } - public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, string? targetName, ReadOnlySpan inputBuffer, ref byte[]? outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) + public static SecurityStatusPal InitializeSecurityContext( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + string? targetName, + ReadOnlySpan inputBuffer, + ref byte[]? outputBuffer, + SslAuthenticationOptions sslAuthenticationOptions) { Interop.SspiCli.ContextFlags unusedAttributes = default; @@ -112,10 +125,15 @@ public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredential return SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode); } - public static SecurityStatusPal Renegotiate(ref SafeFreeCredentials? credentialsHandle, ref SafeDeleteSslContext? context, SslAuthenticationOptions sslAuthenticationOptions, out byte[]? outputBuffer ) + public static SecurityStatusPal Renegotiate( + SecureChannel secureChannel, + ref SafeFreeCredentials? credentialsHandle, + ref SafeDeleteSslContext? context, + SslAuthenticationOptions sslAuthenticationOptions, + out byte[]? outputBuffer ) { byte[]? output = Array.Empty(); - SecurityStatusPal status = AcceptSecurityContext(ref credentialsHandle, ref context, Span.Empty, ref output, sslAuthenticationOptions); + SecurityStatusPal status = AcceptSecurityContext(secureChannel, ref credentialsHandle, ref context, Span.Empty, ref output, sslAuthenticationOptions); outputBuffer = output; return status; } diff --git a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs index 43260e11d3e7d2..88d8087c42c355 100644 --- a/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs +++ b/src/libraries/System.Net.Security/src/System/Security/Authentication/ExtendedProtection/ServiceNameCollection.cs @@ -135,10 +135,7 @@ private void AddIfNew(IList serviceNames) /// private void AddIfNew(string serviceName) { - if (string.IsNullOrEmpty(serviceName)) - { - throw new ArgumentException(SR.security_ServiceNameCollection_EmptyServiceName); - } + ArgumentException.ThrowIfNullOrEmpty(serviceName); serviceName = NormalizeServiceName(serviceName); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 50dd158345ff77..a0e76e49354fbd 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -52,20 +52,6 @@ public async Task ClientAsyncAuthenticate_EachSupportedProtocol_Success(SslProto await ClientAsyncSslHelper(protocol, protocol); } - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public async Task ClientAsyncAuthenticate_Ssl2WithSelf_Success() - { - // Test Ssl2 against itself. This is a standalone test as even on versions where Windows supports Ssl2, - // it appears to have rules around not using it when other protocols are mentioned. - if (PlatformDetection.SupportsSsl2) - { -#pragma warning disable 0618 - await ClientAsyncSslHelper(SslProtocols.Ssl2, SslProtocols.Ssl2); -#pragma warning restore 0618 - } - } - [Theory] [MemberData(nameof(ProtocolMismatchData))] public async Task ClientAsyncAuthenticate_MismatchProtocols_Fails( diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx b/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx index c747b327c487eb..232060e5f83171 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/Resources/Strings.resx @@ -72,15 +72,6 @@ NTLM authentication requires the GSSAPI plugin 'gss-ntlmssp'. - - GSSAPI security context establishment failed with status: {0} (Minor status: {1}) - - - GSSAPI encryption or signing failed with status: {0} (Minor status: {1}) - - - GSSAPI decryption or signature verification failed with status: {0} (Minor status: {1}) - Insufficient buffer space. Required: {0} Actual: {1} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 6edcace7d85a54..1e01be34ca3ded 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -317,14 +317,7 @@ public async Task ServerAsyncAuthenticate_InvalidHello_Throws(bool close) await t2.WaitAsync(TestConfiguration.PassingTestTimeout); } - if (close) - { - await Assert.ThrowsAsync(() => t1); - } - else - { - await Assert.ThrowsAsync(() => t1); - } + await Assert.ThrowsAsync(() => t1); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs index 0fe53d560a4bfe..95458836321cda 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServiceNameCollectionTest.cs @@ -17,14 +17,16 @@ public void Constructor_NullParam_Throws() Assert.Throws(() => new ServiceNameCollection(null)); } - [Theory] - [InlineData(null)] - [InlineData("")] - public void Constructor_CollectionContainsNullOrEmpty_Throws(string item) + [Fact] + public void Constructor_CollectionContainsNullOrEmpty_Throws() { - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { item })); - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { "first", item })); - AssertExtensions.Throws(null, () => new ServiceNameCollection(new[] { item, "second" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { (string)null })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "first", null })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { null, "second" })); + + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "first", "" })); + AssertExtensions.Throws("serviceName", () => new ServiceNameCollection(new[] { "", "second" })); } [Fact] @@ -184,8 +186,8 @@ public void Enumerator_BehavesAsExpected() public void Merge_NullOrEmptyString_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge((string)null)); - AssertExtensions.Throws(null, () => collection.Merge(string.Empty)); + AssertExtensions.Throws("serviceName", () => collection.Merge((string)null)); + AssertExtensions.Throws("serviceName", () => collection.Merge(string.Empty)); } [Fact] @@ -220,22 +222,22 @@ public void Merge_NullEnumerable_Throws() Assert.Throws(() => collection.Merge((IEnumerable)null)); } - [Theory] - [InlineData(null)] - [InlineData("")] - public void Merge_EnumerableContainingNullOrEmpty_Throws(string item) + [Fact] + public void Merge_EnumerableContainingNullOrEmpty_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge(new[] { item })); - AssertExtensions.Throws(null, () => collection.Merge(new[] { "third", item })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { (string)null })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "third", null })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "" })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { "third", "" })); } [Fact] public void Merge_NonStringEnumerable_Throws() { var collection = new ServiceNameCollection(new[] { "first", "second" }); - AssertExtensions.Throws(null, () => collection.Merge(new[] { 3 })); - AssertExtensions.Throws(null, () => collection.Merge(new[] { new object() })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { 3 })); + AssertExtensions.Throws("serviceName", () => collection.Merge(new[] { new object() })); } public static object[][] MergeCollectionsTestData = diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs new file mode 100644 index 00000000000000..adf161fabd49f1 --- /dev/null +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Threading.Tasks; +using System.Net.Test.Common; +using System.Security.Cryptography.X509Certificates; + +using Xunit; + +namespace System.Net.Security.Tests +{ + using Configuration = System.Net.Test.Common.Configuration; + + public class SslStreamMutualAuthenticationTest + { + private readonly X509Certificate2 _clientCertificate; + private readonly X509Certificate2 _serverCertificate; + + public SslStreamMutualAuthenticationTest() + { + _serverCertificate = Configuration.Certificates.GetServerCertificate(); + _clientCertificate = Configuration.Certificates.GetClientCertificate(); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public async Task SslStream_RequireClientCert_IsMutuallyAuthenticated_ReturnsTrue(bool clientCertificateRequired, bool useClientSelectionCallback) + { + (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); + using (var client = new SslStream(stream1, false, AllowAnyCertificate)) + using (var server = new SslStream(stream2, false, AllowAnyCertificate)) + { + Task t2 = client.AuthenticateAsClientAsync(new SslClientAuthenticationOptions + { + ClientCertificates = useClientSelectionCallback ? null : new X509CertificateCollection() { _clientCertificate }, + LocalCertificateSelectionCallback = useClientSelectionCallback ? ClientCertSelectionCallback : null, + TargetHost = _clientCertificate.GetNameInfo(X509NameType.SimpleName, false) + }); + Task t1 = server.AuthenticateAsServerAsync(new SslServerAuthenticationOptions + { + ServerCertificate = _serverCertificate, + ClientCertificateRequired = clientCertificateRequired + }); + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); + + if (Capability.IsTrustedRootCertificateInstalled()) + { + // https://technet.microsoft.com/en-us/library/hh831771.aspx#BKMK_Changes2012R2 + // Starting with Windows 8, the "Management of trusted issuers for client authentication" has changed: + // The behavior to send the Trusted Issuers List by default is off. + // + // In Windows 7 the Trusted Issuers List is sent within the Server Hello TLS record. This list is built + // by the server using certificates from the Trusted Root Authorities certificate store. + // The client side will use the Trusted Issuers List, if not empty, to filter proposed certificates. + + if (clientCertificateRequired) + { + Assert.True(client.IsMutuallyAuthenticated, "client.IsMutuallyAuthenticated"); + Assert.True(server.IsMutuallyAuthenticated, "server.IsMutuallyAuthenticated"); + } + else + { + // Even though the certificate was provided, it was not requested by the server and thus the client + // was not authenticated. + Assert.False(client.IsMutuallyAuthenticated, "client.IsMutuallyAuthenticated"); + Assert.False(server.IsMutuallyAuthenticated, "server.IsMutuallyAuthenticated"); + } + } + } + } + + private static bool AllowAnyCertificate( + object sender, + X509Certificate certificate, + X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + return true; + } + private X509Certificate ClientCertSelectionCallback( + object sender, + string targetHost, + X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, + string[] acceptableIssuers) + { + return _clientCertificate; + } + } +} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index ce44c047929797..aec32cd84a418a 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -352,21 +352,25 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( // Send application data instead of Client hello. await client.WriteAsync(new byte[500], cts.Token); - // Fail as it is not allowed to receive non hnadshake frames during handshake. + // Fail as it is not allowed to receive non handshake frames during handshake. await Assert.ThrowsAsync(()=> t); } } [ConditionalFact(nameof(SupportsRenegotiation))] [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] - public async Task SslStream_NegotiateClientCertificateAsync_ServerDontDrainClientData() + public async Task SslStream_NegotiateClientCertificateAsync_IncompleteIncomingTlsFrame_Throws() { using CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(TestConfiguration.PassingTestTimeout); - (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); - using (client) - using (server) + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); + + // use ManualChunkingStream in the middle to enforce partial TLS frame receive later + ManualChunkingStream clientChunkingStream = new ManualChunkingStream(clientStream, false); + + using (SslStream server = new SslStream(serverStream)) + using (SslStream client = new SslStream(clientChunkingStream)) { using X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate(); using X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate(); @@ -386,26 +390,86 @@ public async Task SslStream_NegotiateClientCertificateAsync_ServerDontDrainClien await TestConfiguration.WhenAllOrAnyFailedWithTimeout( client.AuthenticateAsClientAsync(clientOptions, cts.Token), server.AuthenticateAsServerAsync(serverOptions, cts.Token)); - Assert.Null(server.RemoteCertificate); - // Send application data instead of Client hello. - await client.WriteAsync(new byte[500], cts.Token); - // Server don't drain the client data - await server.ReadAsync(new byte[1]); - // Fail as it is not allowed to receive non hnadshake frames during handshake. + // manually approve all future writes + clientChunkingStream.SetWriteChunking(true); + + // TLS packets are maximum 16 kB, sending 20 kB of data guarantees at least 2 packets to be sent + byte[] buffer = new byte[20 * 1024]; + client.Write(buffer); + + // delay receiving last few B so that only an incomplete TLS frame is received + await clientChunkingStream.CommitWriteAsync(clientChunkingStream.PendingWriteLength - 100); + int read = await server.ReadAsync(buffer, cts.Token); + + // Fail as there are still some undrained data (incomplete incoming TLS frame) await Assert.ThrowsAsync(()=> server.NegotiateClientCertificateAsync(cts.Token) ); - // Drain client data. - await server.ReadAsync(new byte[499]); + // no more delaying needed, drain client data. + clientChunkingStream.SetWriteChunking(false); + while (read < buffer.Length) + { + read += await server.ReadAsync(buffer); + } + // Verify that the session is usable even renego request failed. await TestHelper.PingPong(client, server, cts.Token); await TestHelper.PingPong(server, client, cts.Token); } } + [ConditionalFact(nameof(SupportsRenegotiation))] + [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] + public async Task SslStream_NegotiateClientCertificateAsync_PendingDecryptedData_Throws() + { + using CancellationTokenSource cts = new CancellationTokenSource(); + cts.CancelAfter(TestConfiguration.PassingTestTimeout); + + (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + using (client) + using (server) + { + using X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate(); + using X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate(); + + SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() + { + TargetHost = Guid.NewGuid().ToString("N"), + ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate }) + }; + clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; + + SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() { ServerCertificate = serverCertificate }; + serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; + + await TestConfiguration.WhenAllOrAnyFailedWithTimeout( + client.AuthenticateAsClientAsync(clientOptions, cts.Token), + server.AuthenticateAsServerAsync(serverOptions, cts.Token)); + + await TestHelper.PingPong(client, server, cts.Token); + Assert.Null(server.RemoteCertificate); + + // This should go out in single TLS frame + await client.WriteAsync(new byte[200], cts.Token); + byte[] readBuffer = new byte[10]; + // when we read part of the frame, remaining part should left decrypted + int read = await server.ReadAsync(readBuffer, cts.Token); + + await Assert.ThrowsAsync(() => server.NegotiateClientCertificateAsync(cts.Token)); + + while (read < 200) + { + read += await server.ReadAsync(readBuffer, cts.Token); + } + + // verify that the session is usable with or without client's certificate + await TestHelper.PingPong(client, server, cts.Token); + await TestHelper.PingPong(server, client, cts.Token); + } + } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsTls13))] [InlineData(true)] @@ -587,46 +651,6 @@ await TestConfiguration.WhenAllOrAnyFailedWithTimeout( } } - [Fact] - [PlatformSpecific(TestPlatforms.Windows)] - public async Task NegotiateClientCertificateAsync_PendingData_Throws() - { - using CancellationTokenSource cts = new CancellationTokenSource(); - cts.CancelAfter(TestConfiguration.PassingTestTimeout); - - (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); - using (client) - using (server) - using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate()) - using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate()) - { - SslClientAuthenticationOptions clientOptions = new SslClientAuthenticationOptions() - { - TargetHost = Guid.NewGuid().ToString("N"), - ClientCertificates = new X509CertificateCollection(new X509Certificate2[] { clientCertificate }) - }; - clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; - - SslServerAuthenticationOptions serverOptions = new SslServerAuthenticationOptions() { ServerCertificate = serverCertificate }; - serverOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; - - await TestConfiguration.WhenAllOrAnyFailedWithTimeout( - client.AuthenticateAsClientAsync(clientOptions, cts.Token), - server.AuthenticateAsServerAsync(serverOptions, cts.Token)); - - await TestHelper.PingPong(client, server, cts.Token); - Assert.Null(server.RemoteCertificate); - - // This should go out in single TLS frame - await client.WriteAsync(new byte[200], cts.Token); - byte[] readBuffer = new byte[10]; - // when we read part of the frame, remaining part should left decrypted - await server.ReadAsync(readBuffer, cts.Token); - - await Assert.ThrowsAsync(() => server.NegotiateClientCertificateAsync(cts.Token)); - } - } - [Fact] public async Task SslStream_NestedAuth_Throws() { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index a6a21cc91e155b..72ef0e0c581326 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -28,6 +28,7 @@ + @@ -52,6 +53,8 @@ Link="Common\System\Net\SslStreamCertificatePolicy.cs" /> + input = new byte[0]; + ReadOnlySpan expected = new byte[] { 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }; + Verify(input, expected); + } + + // // MD4("a") = bde52cb31de33e46245e05fbdbd6fb24 + [Fact] + public void TryEncrypt_SingleLetter() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("a")); + ReadOnlySpan expected = new byte[] { 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }; + Verify(input, expected); + } + + // MD4("abc") = a448017aaf21d8525fc10ae87aa6729d + [Fact] + public void TryEncrypt_ThreeLetters() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("abc")); + ReadOnlySpan expected = new byte[] { 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }; + Verify(input, expected); + } + + // MD4("message digest") = d9130a8164549fe818874806e1c7014b + [Fact] + public void TryEncrypt_Phrase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("message digest")); + ReadOnlySpan expected = new byte[] { 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }; + Verify(input, expected); + } + + // MD4("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 + [Fact] + public void TryEncrypt_AlphabetInLowercase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("abcdefghijklmnopqrstuvwxyz")); + ReadOnlySpan expected = new byte[] { 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 + [Fact] + public void TryEncrypt_AlphabetInUpperLowerCasesAndNumbers() + { + ReadOnlySpan input = new ReadOnlySpan((Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))); + ReadOnlySpan expected = new byte[] { 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }; + Verify(input, expected); + } + + // MD4("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 + [Fact] + public void TryEncrypt_RepeatedSequenceOfNumbers() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("12345678901234567890123456789012345678901234567890123456789012345678901234567890")); + ReadOnlySpan expected = new byte[] { 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012") = 14fdf2056bf88b3491c385d8ac4f48e6 + // 55 bytes (padLen == 56 - 55 => 1) + [Fact] + public void TryEncrypt_55bytes_HitsEdgeCaseForPaddingLength() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012")); + ReadOnlySpan expected = new byte[] { 0x14, 0xfd, 0xf2, 0x05, 0x6b, 0xf8, 0x8b, 0x34, 0x91, 0xc3, 0x85, 0xd8, 0xac, 0x4f, 0x48, 0xe6 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123") = db837dbb6098a50a2d3974bc1cc76133 + // 56 bytes (padLen == 120 - 56 => 64) + [Fact] + public void TryEncrypt_56bytes_HitsEdgeCaseForPaddingLength() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123")); + ReadOnlySpan expected = new byte[] { 0xdb, 0x83, 0x7d, 0xbb, 0x60, 0x98, 0xa5, 0x0a, 0x2d, 0x39, 0x74, 0xbc, 0x1c, 0xc7, 0x61, 0x33 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890") = ce64c40ecfbe896462f3c1a925884624 + [Fact] + public void TryEncrypt_63bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890")); + ReadOnlySpan expected = new byte[] { 0xce, 0x64, 0xc4, 0x0e, 0xcf, 0xbe, 0x89, 0x64, 0x62, 0xf3, 0xc1, 0xa9, 0x25, 0x88, 0x46, 0x24 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901") = 4b0e77758d2ede1eb21d267d492ae70b + [Fact] + public void TryEncrypt_64bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901")); + ReadOnlySpan expected = new byte[] { 0x4b, 0x0e, 0x77, 0x75, 0x8d, 0x2e, 0xde, 0x1e, 0xb2, 0x1d, 0x26, 0x7d, 0x49, 0x2a, 0xe7, 0x0b }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012") = 3b46ad159b3fd800d254e3c4cc71fe36 + [Fact] + public void TryEncrypt_65bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012")); + ReadOnlySpan expected = new byte[] { 0x3b, 0x46, 0xad, 0x15, 0x9b, 0x3f, 0xd8, 0x00, 0xd2, 0x54, 0xe3, 0xc4, 0xcc, 0x71, 0xfe, 0x36 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890") = a3e23048e4ade47a0f00fa8aed2a0248 + [Fact] + public void TryEncrypt_127bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890")); + ReadOnlySpan expected = new byte[] { 0xa3, 0xe2, 0x30, 0x48, 0xe4, 0xad, 0xe4, 0x7a, 0x0f, 0x00, 0xfa, 0x8a, 0xed, 0x2a, 0x02, 0x48 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901") = de49da96c105be37b242f2bee86c4759 + [Fact] + public void TryEncrypt_128bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901")); + ReadOnlySpan expected = new byte[] { 0xde, 0x49, 0xda, 0x96, 0xc1, 0x05, 0xbe, 0x37, 0xb2, 0x42, 0xf2, 0xbe, 0xe8, 0x6c, 0x47, 0x59 }; + Verify(input, expected); + } + + // MD4("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012") = a6c10c320f8827d08248a2d8b124b040 + [Fact] + public void TryEncrypt_129bytes_HitsEdgeCase() + { + ReadOnlySpan input = new ReadOnlySpan(Encoding.Default.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678901ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789012")); + ReadOnlySpan expected = new byte[] { 0xa6, 0xc1, 0x0c, 0x32, 0x0f, 0x88, 0x27, 0xd0, 0x82, 0x48, 0xa2, 0xd8, 0xb1, 0x24, 0xb0, 0x40 }; + Verify(input, expected); + } + + private void Verify(ReadOnlySpan input, ReadOnlySpan expected) + { + Span output = stackalloc byte[expected.Length]; + MD4.HashData(input, output); + Assert.Equal(expected.ToArray(), output.ToArray()); + } + } +} diff --git a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj index da4dde4e192b90..28b3f81b02b3d7 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/UnitTests/System.Net.Security.Unit.Tests.csproj @@ -10,13 +10,17 @@ 436 $(NoWarn);3021 - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-Android annotations true + + + + diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 212c063b3b3308..e813cca044ee04 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -74,13 +74,14 @@ public enum IOControlCode : long [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] AddressListSort = (long)3355443225, } - public partial struct IPPacketInformation + public partial struct IPPacketInformation : System.IEquatable { private object _dummy; private int _dummyPrimitive; public System.Net.IPAddress Address { get { throw null; } } public int Interface { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? comparand) { throw null; } + public bool Equals(System.Net.Sockets.IPPacketInformation other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } public static bool operator !=(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } diff --git a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx index 69eff9dbb985e6..57d1a94b6ae6bd 100644 --- a/src/libraries/System.Net.Sockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Sockets/src/Resources/Strings.resx @@ -324,9 +324,6 @@ System.Net.Sockets is not supported on this platform. - - This platform does not support receiving data with Socket.BeginAccept/EndAccept. Instead, make a separate call to ReceiveAsync or BeginReceive/EndReceive. - Handle is already used by another Socket. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs index 06d4eca31750b0..b0597b626c4804 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs @@ -5,7 +5,7 @@ namespace System.Net.Sockets { - public struct IPPacketInformation + public struct IPPacketInformation : IEquatable { private readonly IPAddress _address; private readonly int _networkInterface; @@ -16,41 +16,27 @@ internal IPPacketInformation(IPAddress address, int networkInterface) _networkInterface = networkInterface; } - public IPAddress Address - { - get - { - return _address; - } - } + public IPAddress Address => _address; - public int Interface - { - get - { - return _networkInterface; - } - } + public int Interface => _networkInterface; - public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return packetInformation1._networkInterface == packetInformation2._networkInterface && - ((packetInformation1._address == null && packetInformation2._address == null) || - (packetInformation1._address != null && packetInformation1._address.Equals(packetInformation2._address))); - } + public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + packetInformation1.Equals(packetInformation2); - public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return !(packetInformation1 == packetInformation2); - } + public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + !packetInformation1.Equals(packetInformation2); public override bool Equals([NotNullWhen(true)] object? comparand) => - comparand is IPPacketInformation other && this == other; + comparand is IPPacketInformation other && Equals(other); - public override int GetHashCode() - { - return unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + - (_address == null ? 0 : _address.GetHashCode()); - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(IPPacketInformation other) => + _networkInterface == other._networkInterface && + (_address is null ? other._address is null : _address.Equals(other._address)); + + public override int GetHashCode() => + unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + (_address?.GetHashCode() ?? 0); } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs index 6c79043631eb72..faf0d9f204c7cf 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs @@ -153,7 +153,7 @@ public IList>? BufferList if (!_buffer.Equals(default)) { // Can't have both set - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(Buffer))); + throw new ArgumentException(SR.net_ambiguousbuffers); } // Copy the user-provided list into our internal buffer list, @@ -358,7 +358,7 @@ public void SetBuffer(byte[]? buffer, int offset, int count) // Can't have both Buffer and BufferList. if (_bufferList != null) { - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + throw new ArgumentException(SR.net_ambiguousbuffers); } // Offset and count can't be negative and the @@ -391,7 +391,7 @@ public void SetBuffer(Memory buffer) { if (buffer.Length != 0 && _bufferList != null) { - throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + throw new ArgumentException(SR.net_ambiguousbuffers); } _buffer = buffer; @@ -559,7 +559,7 @@ internal void StartOperationAccept() // Caller specified a buffer - see if it is large enough if (_count < _acceptAddressBufferCount) { - throw new ArgumentException(SR.Format(SR.net_buffercounttoosmall, nameof(Count))); + throw new ArgumentException(SR.net_buffercounttoosmall, nameof(Count)); } } else diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs index 443924b66d2b44..19dbc7f470d007 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs @@ -13,7 +13,10 @@ public class IPPacketInformationTest public void Equals_DefaultValues_Success() { Assert.Equal(default(IPPacketInformation), default(IPPacketInformation)); + Assert.True(default(IPPacketInformation) == default(IPPacketInformation)); + Assert.True(default(IPPacketInformation).Equals(default(IPPacketInformation))); + Assert.False(default(IPPacketInformation) != default(IPPacketInformation)); } @@ -31,10 +34,14 @@ public void Equals_NonDefaultValue_Success() Assert.Equal(packetInfo, packetInfoCopy); Assert.True(packetInfo == packetInfoCopy); + Assert.True(packetInfo.Equals(packetInfoCopy)); + Assert.True(packetInfo.Equals((object)packetInfoCopy)); Assert.False(packetInfo != packetInfoCopy); Assert.NotEqual(default, packetInfo); Assert.False(packetInfo == default(IPPacketInformation)); + Assert.False(packetInfo.Equals(default(IPPacketInformation))); + Assert.False(packetInfo.Equals((object)default(IPPacketInformation))); Assert.True(packetInfo != default(IPPacketInformation)); int ignored = packetInfo.Interface; // just make sure it doesn't throw, nothing else to verify diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs index 8e257352fd18c3..b59c5ebd92a33e 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Drawing.Drawing2D; using System.IO; using System.IO.Pipes; using System.Runtime.Serialization.Formatters.Binary; diff --git a/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx b/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx index eb1e5a6487164e..86b29067c6aa94 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebHeaderCollection/src/Resources/Strings.resx @@ -1,4 +1,5 @@ - + + @@ -63,9 +64,6 @@ This collection holds request headers and cannot contain the specified response header. - - The parameter '{0}' cannot be an empty string. - Specified value has invalid Control characters. diff --git a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs index 1a97af3ccfb4fc..99563163a1ec79 100644 --- a/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs +++ b/src/libraries/System.Net.WebHeaderCollection/src/System/Net/WebHeaderCollection.cs @@ -344,14 +344,7 @@ public void Add(string header) public override void Add(string name, string? value) #pragma warning restore CS8765 { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - if (name.Length == 0) - { - throw new ArgumentException(SR.Format(SR.net_emptyStringCall, nameof(name)), nameof(name)); - } + ArgumentException.ThrowIfNullOrEmpty(name); name = HttpValidationHelpers.CheckBadHeaderNameChars(name); value = HttpValidationHelpers.CheckBadHeaderValueChars(value); diff --git a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx index 7b4718b554a151..360d9f9a337e12 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets.Client/src/Resources/Strings.resx @@ -123,21 +123,6 @@ The requested security protocol is not supported. - - Client certificates in UWP are unsupported in Windows 10 version 1703 and earlier versions. Please upgrade Windows 10 to a later release. - - - Client certificate was not found in the personal (\"MY\") certificate store. In UWP, client certificates are only supported if they have been added to that certificate store. - - - ClientWebSocketOptions.RemoteCertificateValidationCallback is not supported on this platform. - - - Connection was aborted. - - - WebSocket binary type '{0}' not supported. - The WebSocket failed to negotiate max server window bits. The client requested {0} but the server responded with {1}. diff --git a/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs b/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs new file mode 100644 index 00000000000000..a1f427d0af7f11 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/Internal/Console.Android.cs @@ -0,0 +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; +using System.Runtime.InteropServices; + +namespace Internal +{ + public static partial class Console + { + public static unsafe void Write(string s) + { + Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Debug, "DOTNET", s ?? string.Empty); + } + + public static partial class Error + { + public static unsafe void Write(string s) + { + Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Error, "DOTNET", s ?? string.Empty); + } + } + } +} \ No newline at end of file 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 348c7762ec9015..8a601345ee00a2 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 @@ -186,7 +186,7 @@ internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess a { long fileLength; Interop.Sys.Permissions filePermissions; - return Open(fullPath, mode, access, share, options, preallocationSize, openPermissions, out fileLength, out filePermissions, null); + return Open(fullPath, mode, access, share, options, preallocationSize, openPermissions, out fileLength, out filePermissions, createOpenException); } private static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize, diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index f98789424343b4..7b47a57ac9632e 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -528,6 +528,9 @@ Type passed must be an interface. + + Object must be of type NFloat. + Type must be a Pointer. @@ -786,6 +789,9 @@ Unknown TypeCode value. + + The program executed an instruction that was thought to be unreachable. + Missing parameter does not have a default value. @@ -903,9 +909,6 @@ Cannot use function evaluation to create a TypedReference object. - - Cannot get TypeToken for a ByRef type. - Cannot set parent to an interface. @@ -1002,18 +1005,12 @@ EmitWriteLine does not support this field or local type. - - Decimal separator cannot be the empty string. - Empty file name is not legal. Empty name is not legal. - - Empty path name is not legal. - Waithandle array may not be empty. @@ -1107,8 +1104,8 @@ Target array type is not compatible with the type of items in the collection. - - Assembly names may not begin with whitespace or contain the characters '/', or '\\' or ':'. + + The given assembly name or codebase was invalid. Not a valid calendar for the given culture. @@ -1480,9 +1477,6 @@ The first char in the string is the null character. - - String cannot be of zero length. - The structure must not be a value class. @@ -3880,9 +3874,6 @@ A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property. - - The given assembly name or codebase was invalid - Invalid assembly public key. 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 ebbc2d77b6a93a..321e2c0477ea87 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 @@ -261,6 +261,7 @@ + @@ -285,6 +286,7 @@ + @@ -562,6 +564,8 @@ + + @@ -745,6 +749,7 @@ + @@ -2120,7 +2125,14 @@ Common\System\IO\PathInternal.Unix.cs - + + + + Common\Interop\Android\Interop.Logcat.cs + + + Common\Interop\Android\Interop.Libraries.cs + @@ -2129,7 +2141,7 @@ - + @@ -2174,10 +2186,8 @@ - - + + Common\Interop\Unix\System.Native\Interop.GetPwUid.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 6b28c7b2a561d7..87488c1dfe280a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -94,10 +94,7 @@ internal static void OnProcessExit() /// A return value of true represents that the switch was set and contains the value of the switch public static bool TryGetSwitch(string switchName, out bool isEnabled) { - if (switchName == null) - throw new ArgumentNullException(nameof(switchName)); - if (switchName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(switchName)); + ArgumentException.ThrowIfNullOrEmpty(switchName); if (s_switches != null) { @@ -124,10 +121,7 @@ public static bool TryGetSwitch(string switchName, out bool isEnabled) /// The value to assign public static void SetSwitch(string switchName, bool isEnabled) { - if (switchName == null) - throw new ArgumentNullException(nameof(switchName)); - if (switchName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyName, nameof(switchName)); + ArgumentException.ThrowIfNullOrEmpty(switchName); if (s_switches == null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index 3e4e8a2317e4df..cff98ca55ee2f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -80,13 +80,10 @@ public event EventHandler? ProcessExit public string ApplyPolicy(string assemblyName) { - if (assemblyName == null) - { - throw new ArgumentNullException(nameof(assemblyName)); - } - if (assemblyName.Length == 0 || assemblyName[0] == '\0') + ArgumentException.ThrowIfNullOrEmpty(assemblyName); + if (assemblyName[0] == '\0') { - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(assemblyName)); + throw new ArgumentException(SR.Argument_EmptyString, nameof(assemblyName)); } return assemblyName; diff --git a/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs b/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs index ed537c244392bf..1511f8db1bd7ac 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ApplicationId.cs @@ -12,10 +12,9 @@ public sealed class ApplicationId public ApplicationId(byte[] publicKeyToken, string name, Version version, string? processorArchitecture, string? culture) { - if (name == null) throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) throw new ArgumentException(SR.Argument_EmptyString, nameof(name)); - if (version == null) throw new ArgumentNullException(nameof(version)); - if (publicKeyToken == null) throw new ArgumentNullException(nameof(publicKeyToken)); + ArgumentException.ThrowIfNullOrEmpty(name); + ArgumentNullException.ThrowIfNull(version); + ArgumentNullException.ThrowIfNull(publicKeyToken); _publicKeyToken = (byte[])publicKeyToken.Clone(); Name = name; diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs index 3e223bd4789fdf..0e898e511a46ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs @@ -10,6 +10,8 @@ ** =============================================================================*/ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -97,5 +99,24 @@ private void SetMessageField() } public virtual string? ParamName => _paramName; + + /// Throws an exception if is null or empty. + /// The string argument to validate as non-null and non-empty. + /// The name of the parameter with which corresponds. + /// is null. + /// is empty. + public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression("argument")] string? paramName = null) + { + if (string.IsNullOrEmpty(argument)) + { + ThrowNullOrEmptyException(argument, paramName); + } + } + + [DoesNotReturn] + private static void ThrowNullOrEmptyException(string? argument, string? paramName) => + throw (argument is null ? + new ArgumentNullException(paramName) : + new ArgumentException(SR.Argument_EmptyString, paramName)); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs index 06c31c4d6e0097..2d6c817b872686 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs @@ -26,8 +26,16 @@ namespace System // (ie, users could assign a new value to the old location). [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] +#pragma warning disable CA1066 // adding IEquatable implementation could change semantics of code like that in xunit that queries for IEquatable vs enumerating contents public readonly struct ArraySegment : IList, IReadOnlyList +#pragma warning restore CA1066 { + // ArraySegment doesn't implement IEquatable, even though it provides a strongly-typed + // Equals(T), as that results in different comparison semantics than comparing item-by-item + // the elements returned from its IEnumerable implementation. This then is a breaking change + // for usage like that in xunit's Assert.Equal, which will prioritize using an instance's IEquatable + // over its IEnumerable. + // Do not replace the array allocation with Array.Empty. We don't want to have the overhead of // instantiating another generic type in addition to ArraySegment for new type parameters. #pragma warning disable CA1825 @@ -120,7 +128,7 @@ public void CopyTo(ArraySegment destination) } public override bool Equals([NotNullWhen(true)] object? obj) => - obj is ArraySegment && Equals((ArraySegment)obj); + obj is ArraySegment other && Equals(other); public bool Equals(ArraySegment obj) => obj._array == _array && obj._offset == _offset && obj._count == _count; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs index 01b9cdb3c737ad..d311cd0c94bbde 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs @@ -260,7 +260,7 @@ public Hashtable(int capacity, float loadFactor) if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum); if (!(loadFactor >= 0.1f && loadFactor <= 1.0f)) - throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.Format(SR.ArgumentOutOfRange_HashtableLoadFactor, .1, 1.0)); + throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.ArgumentOutOfRange_HashtableLoadFactor); // Based on perf work, .72 is the optimal load factor for this table. _loadFactor = 0.72f * loadFactor; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index e6fbd541653294..25bd0d15bb8b3f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -817,15 +817,13 @@ public string ToString(string? format, IFormatProvider? provider) return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); default: - charsWritten = 0; - return false; + throw new FormatException(SR.Argument_BadFormatSpecifier); } } if (!DateTimeFormat.IsValidCustomDateFormat(format, throwOnError: false)) { - charsWritten = 0; - return false; + throw new FormatException(SR.Format(SR.Format_DateTimeOnlyContainsNoneDateParts, format.ToString(), nameof(DateOnly))); } return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs new file mode 100644 index 00000000000000..f776dd576c84e0 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.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. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, and callers + /// do not need to set any required members themselves. + /// + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class SetsRequiredMembersAttribute : Attribute + { } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs index c3994e613a3160..b1aaccd7f7f7c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs @@ -15,7 +15,7 @@ namespace System.Diagnostics.Tracing #if ES_BUILD_STANDALONE [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] #endif - internal struct EventDescriptor + internal readonly struct EventDescriptor : IEquatable { #region private [FieldOffset(0)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs index f8d6e9c6ff114d..b54a5a50ba62ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource.cs @@ -3280,7 +3280,7 @@ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAt } else if (eventAttribute.EventId <= 0) { - manifest.ManifestError(SR.Format(SR.EventSource_NeedPositiveId, method.Name), true); + manifest.ManifestError(SR.EventSource_NeedPositiveId, true); continue; // don't validate anything else for this event } if (method.Name.LastIndexOf('.') >= 0) @@ -3501,7 +3501,7 @@ private static void AddProviderEnumKind(ManifestBuilder manifest, FieldInfo stat #endif return; Error: - manifest.ManifestError(SR.Format(SR.EventSource_EnumKindMismatch, staticField.Name, staticField.FieldType.Name, providerEnumKind)); + manifest.ManifestError(SR.Format(SR.EventSource_EnumKindMismatch, staticField.FieldType.Name, providerEnumKind)); } // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method @@ -3630,7 +3630,7 @@ private static void DebugCheckEvent(ref Dictionary? eventsByName if (evtId < eventData.Length && eventData[evtId].Descriptor.EventId != 0) { - manifest.ManifestError(SR.Format(SR.EventSource_EventIdReused, evtName, evtId, eventData[evtId].Name), true); + manifest.ManifestError(SR.Format(SR.EventSource_EventIdReused, evtName, evtId), true); } // We give a task to things if they don't have one. diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs new file mode 100644 index 00000000000000..be8ff08940eebe --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics +{ + /// + /// Exception thrown when the program executes an instruction that was thought to be unreachable. + /// + public sealed class UnreachableException : Exception + { + /// + /// Initializes a new instance of the class with the default error message. + /// + public UnreachableException() + : base(SR.Arg_UnreachableException) + { + } + + /// + /// Initializes a new instance of the + /// class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public UnreachableException(string? message) + : base(message) + { + } + + /// + /// Initializes a new instance of the + /// class with a specified error message and a reference to the inner exception that is the cause of + /// this exception. + /// + /// The error message that explains the reason for the exception. + /// The exception that is the cause of the current exception. + public UnreachableException(string? message, Exception? innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 5a05ee1f33c71c..414db07d199e64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -77,12 +77,7 @@ public static string CurrentDirectory get => CurrentDirectoryCore; set { - if (value == null) - throw new ArgumentNullException(nameof(value)); - - if (value.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(value)); - + ArgumentException.ThrowIfNullOrEmpty(value); CurrentDirectoryCore = value; } } @@ -239,11 +234,7 @@ private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget t private static void ValidateVariableAndValue(string variable, ref string? value) { - if (variable == null) - throw new ArgumentNullException(nameof(variable)); - - if (variable.Length == 0) - throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable)); + ArgumentException.ThrowIfNullOrEmpty(variable); if (variable[0] == '\0') throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index e72e7885566401..f8c1745c1e4994 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -62,8 +62,8 @@ Patterns Format Description Example "M" "0" month w/o leading zero 2 "MM" "00" month with leading zero 02 "MMM" short month name (abbreviation) Feb - "MMMM" full month name Febuary - "MMMM*" full month name Febuary + "MMMM" full month name February + "MMMM*" full month name February "y" "0" two digit year (year % 100) w/o leading zero 0 "yy" "00" two digit year (year % 100) with leading zero 00 @@ -734,7 +734,7 @@ private static StringBuilder FormatCustomized( break; case '\\': // Escaped character. Can be used to insert a character into the format string. - // For exmple, "\d" will insert the character 'd' into the string. + // For example, "\d" will insert the character 'd' into the string. // // NOTENOTE : we can remove this format character if we enforce the enforced quote // character rule. @@ -966,7 +966,7 @@ private static string ExpandPredefinedFormat(ReadOnlySpan format, ref Date // This format is not supported by DateTimeOffset throw new FormatException(SR.Format_InvalidString); } - // Universal time is always in Greogrian calendar. + // Universal time is always in Gregorian calendar. // // Change the Calendar to be Gregorian Calendar. // diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index 78ca2a731f3d27..8387dd024d17fd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -80,27 +80,6 @@ public NumberFormatInfo() { } - private static void VerifyDecimalSeparator(string decSep, string propertyName) - { - if (decSep == null) - { - throw new ArgumentNullException(propertyName); - } - - if (decSep.Length == 0) - { - throw new ArgumentException(SR.Argument_EmptyDecString, propertyName); - } - } - - private static void VerifyGroupSeparator(string groupSep, string propertyName) - { - if (groupSep == null) - { - throw new ArgumentNullException(propertyName); - } - } - private static void VerifyNativeDigits(string[] nativeDig, string propertyName) { if (nativeDig == null) @@ -264,7 +243,7 @@ public string CurrencyDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _currencyDecimalSeparator = value; } } @@ -355,7 +334,7 @@ public string CurrencyGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _currencyGroupSeparator = value; } } @@ -542,7 +521,7 @@ public string NumberDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _numberDecimalSeparator = value; } } @@ -553,7 +532,7 @@ public string NumberGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _numberGroupSeparator = value; } } @@ -631,7 +610,7 @@ public string PercentDecimalSeparator set { VerifyWritable(); - VerifyDecimalSeparator(value, nameof(value)); + ArgumentException.ThrowIfNullOrEmpty(value); _percentDecimalSeparator = value; } } @@ -642,7 +621,7 @@ public string PercentGroupSeparator set { VerifyWritable(); - VerifyGroupSeparator(value, nameof(value)); + ArgumentNullException.ThrowIfNull(value); _percentGroupSeparator = value; } } @@ -652,11 +631,7 @@ public string PercentSymbol get => _percentSymbol; set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - + ArgumentNullException.ThrowIfNull(value); VerifyWritable(); _percentSymbol = value; } diff --git a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs index d9735f05b44348..f40830e416d368 100644 --- a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs @@ -47,6 +47,8 @@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { // xxHash32 is used for the hash code. 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 2bfcd01604047f..eea2cda3f8c974 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs @@ -13,11 +13,7 @@ public static partial class Directory { public static DirectoryInfo? GetParent(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); string fullPath = Path.GetFullPath(path); @@ -29,10 +25,7 @@ public static partial class Directory public static DirectoryInfo CreateDirectory(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); string fullPath = Path.GetFullPath(path); @@ -228,25 +221,15 @@ public static string GetDirectoryRoot(string path) public static void SetCurrentDirectory(string path) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_PathEmpty, nameof(path)); + ArgumentException.ThrowIfNullOrEmpty(path); Environment.CurrentDirectory = Path.GetFullPath(path); } public static void Move(string sourceDirName, string destDirName) { - if (sourceDirName == null) - throw new ArgumentNullException(nameof(sourceDirName)); - if (sourceDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceDirName)); - - if (destDirName == null) - throw new ArgumentNullException(nameof(destDirName)); - if (destDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName)); + ArgumentException.ThrowIfNullOrEmpty(sourceDirName); + ArgumentException.ThrowIfNullOrEmpty(destDirName); string fullsourceDirName = Path.GetFullPath(sourceDirName); string sourcePath = PathInternal.EnsureTrailingSeparator(fullsourceDirName); 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 1aeef2f7501a81..771b5e69a05ccd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs @@ -188,10 +188,7 @@ private IEnumerable InternalEnumerateInfos( public void MoveTo(string destDirName) { - if (destDirName == null) - throw new ArgumentNullException(nameof(destDirName)); - if (destDirName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName)); + ArgumentException.ThrowIfNullOrEmpty(destDirName); string destination = Path.GetFullPath(destDirName); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs index 89c38584eea320..3c7fb6504473ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs @@ -11,6 +11,7 @@ namespace System.IO.Enumeration public unsafe ref partial struct FileSystemEntry { private Interop.Sys.DirectoryEntry _directoryEntry; + private bool _isDirectory; private FileStatus _status; private Span _pathBuffer; private ReadOnlySpan _fullPath; @@ -32,8 +33,8 @@ internal static FileAttributes Initialize( entry._pathBuffer = pathBuffer; entry._fullPath = ReadOnlySpan.Empty; entry._fileName = ReadOnlySpan.Empty; + entry._isDirectory = false; entry._status.InvalidateCaches(); - entry._status.InitiallyDirectory = false; bool isDirectory = directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR; bool isSymlink = directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK; @@ -41,15 +42,15 @@ internal static FileAttributes Initialize( if (isDirectory) { - entry._status.InitiallyDirectory = true; + entry._isDirectory = true; } else if (isSymlink) { - entry._status.InitiallyDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); + entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); } else if (isUnknown) { - entry._status.InitiallyDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); + entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true); if (entry._status.IsSymbolicLink(entry.FullPath, continueOnError: true)) { entry._directoryEntry.InodeType = Interop.Sys.NodeType.DT_LNK; @@ -145,16 +146,17 @@ public FileAttributes Attributes public DateTimeOffset CreationTimeUtc => _status.GetCreationTime(FullPath, continueOnError: true); public DateTimeOffset LastAccessTimeUtc => _status.GetLastAccessTime(FullPath, continueOnError: true); public DateTimeOffset LastWriteTimeUtc => _status.GetLastWriteTime(FullPath, continueOnError: true); + public bool IsHidden => _status.IsFileSystemEntryHidden(FullPath, FileName); internal bool IsReadOnly => _status.IsReadOnly(FullPath, continueOnError: true); - public bool IsDirectory => _status.InitiallyDirectory; + public bool IsDirectory => _isDirectory; internal bool IsSymbolicLink => _directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK; public FileSystemInfo ToFileSystemInfo() { string fullPath = ToFullPath(); - return FileSystemInfo.Create(fullPath, new string(FileName), ref _status); + return FileSystemInfo.Create(fullPath, new string(FileName), _isDirectory, ref _status); } /// 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 2b4c61f1eb0baa..d8b1124ed9b1b9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -49,14 +49,8 @@ public static void Copy(string sourceFileName, string destFileName) /// public static void Copy(string sourceFileName, string destFileName, bool overwrite) { - if (sourceFileName == null) - throw new ArgumentNullException(nameof(sourceFileName), SR.ArgumentNull_FileName); - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (sourceFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(sourceFileName); + ArgumentException.ThrowIfNullOrEmpty(destFileName); FileSystem.CopyFile(Path.GetFullPath(sourceFileName), Path.GetFullPath(destFileName), overwrite); } @@ -292,12 +286,8 @@ public static byte[] ReadAllBytes(string path) public static void WriteAllBytes(string path, byte[] bytes) { - if (path == null) - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - if (bytes == null) - throw new ArgumentNullException(nameof(bytes)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read); RandomAccess.WriteAtOffset(sfh, bytes, 0); @@ -418,14 +408,8 @@ public static void Move(string sourceFileName, string destFileName) public static void Move(string sourceFileName, string destFileName, bool overwrite) { - if (sourceFileName == null) - throw new ArgumentNullException(nameof(sourceFileName), SR.ArgumentNull_FileName); - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (sourceFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(sourceFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(sourceFileName); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string fullSourceFileName = Path.GetFullPath(sourceFileName); string fullDestFileName = Path.GetFullPath(destFileName); @@ -609,12 +593,8 @@ private static async Task InternalReadAllBytesUnknownLengthAsync(SafeFil public static Task WriteAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path), SR.ArgumentNull_Path); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - if (bytes == null) - throw new ArgumentNullException(nameof(bytes)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(bytes); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -649,7 +629,7 @@ private static async Task InternalReadAllLinesAsync(string path, Encod cancellationToken.ThrowIfCancellationRequested(); string? line; List lines = new List(); - while ((line = await sr.ReadLineAsync().ConfigureAwait(false)) != null) + while ((line = await sr.ReadLineAsync(cancellationToken).ConfigureAwait(false)) != null) { lines.Add(line); cancellationToken.ThrowIfCancellationRequested(); @@ -764,12 +744,8 @@ public static FileSystemInfo CreateSymbolicLink(string path, string pathToTarget 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)); + ArgumentException.ThrowIfNullOrEmpty(path); + ArgumentNullException.ThrowIfNull(encoding); } private static byte[] ReadAllBytesUnknownLength(SafeFileHandle sfh) 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 2ce33d996d61ea..0d9db030f900dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs @@ -89,10 +89,7 @@ public StreamWriter AppendText() public FileInfo CopyTo(string destFileName, bool overwrite) { - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName), SR.ArgumentNull_FileName); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string destinationPath = Path.GetFullPath(destFileName); FileSystem.CopyFile(FullPath, destinationPath, overwrite); @@ -139,10 +136,7 @@ public void MoveTo(string destFileName) // This method does work across volumes. public void MoveTo(string destFileName, bool overwrite) { - if (destFileName == null) - throw new ArgumentNullException(nameof(destFileName)); - if (destFileName.Length == 0) - throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destFileName)); + ArgumentException.ThrowIfNullOrEmpty(destFileName); string fullDestFileName = Path.GetFullPath(destFileName); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs index 23c46bae4a0125..40a887e7210be8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OSX.cs @@ -7,7 +7,7 @@ namespace System.IO { internal partial struct FileStatus { - internal void SetCreationTime(string path, DateTimeOffset time) + internal void SetCreationTime(string path, DateTimeOffset time, bool asDirectory) { // Try to set the attribute on the file system entry using setattrlist, // if we get ENOTSUP then it means that "The volume does not support @@ -27,11 +27,11 @@ internal void SetCreationTime(string path, DateTimeOffset time) } else if (error == Interop.Error.ENOTSUP) { - SetAccessOrWriteTimeCore(path, time, isAccessTime: false, checkCreationTime: false); + SetAccessOrWriteTimeCore(path, time, isAccessTime: false, checkCreationTime: false, asDirectory); } else { - Interop.CheckIo(error, path, InitiallyDirectory); + Interop.CheckIo(error, path, asDirectory); } } @@ -54,7 +54,7 @@ private unsafe Interop.Error SetCreationTimeCore(string path, long seconds, long return error; } - private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime) => - SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: true); + private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime, bool asDirectory) => + SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: true, asDirectory); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs index d9d9b1eeb7c920..85b01fde17d7c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.SetTimes.OtherUnix.cs @@ -7,11 +7,11 @@ namespace System.IO { internal partial struct FileStatus { - internal void SetCreationTime(string path, DateTimeOffset time) => - SetLastWriteTime(path, time); + internal void SetCreationTime(string path, DateTimeOffset time, bool asDirectory) => + SetLastWriteTime(path, time, asDirectory); - private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime) => - SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: false); + private void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime, bool asDirectory) => + SetAccessOrWriteTimeCore(path, time, isAccessTime, checkCreationTime: false, asDirectory); // This is not used on these platforms, but is needed for source compat private Interop.Error SetCreationTimeCore(string path, long seconds, long nanoseconds) => diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs index 20961a8fbbc2e4..91e67d1b9f74c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs @@ -10,44 +10,44 @@ internal partial struct FileStatus { private const int NanosecondsPerTick = 100; - // The last cached lstat information about the file + private const int InitializedExistsDir = -3; // target is directory. + private const int InitializedExistsFile = -2; // target is file. + private const int InitializedNotExists = -1; // entry does not exist. + private const int Uninitialized = 0; // uninitialized, '0' to make default(FileStatus) uninitialized. + + // Tracks the initialization state. + // < 0 : initialized succesfully. Value is InitializedNotExists, InitializedExistsFile or InitializedExistsDir. + // 0 : uninitialized. + // > 0 : initialized with error. Value is raw errno. + private int _state; + + // The last cached lstat information about the file. + // Must only be used after calling EnsureCachesInitialized and checking EntryExists is true. private Interop.Sys.FileStatus _fileCache; - // -1: if the file cache isn't initialized - Refresh should always change this value - // 0: if the file cache was initialized with no errors - // Positive number: the error code returned by the lstat call - private int _initializedFileCache; - - // We track intent of creation to know whether or not we want to (1) create a - // DirectoryInfo around this status struct or (2) actually are part of a DirectoryInfo. - // Set to true during initialization when the DirectoryEntry's INodeType describes a directory - internal bool InitiallyDirectory { get; set; } - - // Is a directory as of the last refresh - // Its value can come from either the main path or the symbolic link path - private bool _isDirectory; - - // Exists as of the last refresh - private bool _exists; - - private bool IsFileCacheInitialized => _initializedFileCache == 0; - - // Check if the main path (without following symlinks) has the hidden attribute set - // Ideally, use this if Refresh has been successfully called at least once. - // But since it is also used for soft retrieval during FileSystemEntry initialization, - // we return false early if the cache has not been initialized - internal bool HasHiddenFlag => IsFileCacheInitialized && - (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN; - - // Checks if the main path (without following symlinks) has the read-only attribute set - // Ideally, use this if Refresh has been successfully called at least once. - // But since it is also used for soft retrieval during FileSystemEntry initialization, - // we return false early if the cache has not been initialized - internal bool HasReadOnlyFlag + private bool EntryExists => _state <= InitializedExistsFile; + + private bool IsDir => _state == InitializedExistsDir; + + // Check if the main path (without following symlinks) has the hidden attribute set. + private bool HasHiddenFlag { get { - if (!IsFileCacheInitialized) + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + return EntryExists && (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN; + } + } + + // Checks if the main path (without following symlinks) has the read-only attribute set. + private bool HasReadOnlyFlag + { + get + { + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + if (!EntryExists) { return false; } @@ -78,6 +78,7 @@ internal bool HasReadOnlyFlag #if !TARGET_BROWSER // HasReadOnlyFlag cache. + // Must only be used after calling EnsureCachesInitialized. private int _isReadOnlyCache; private bool IsModeReadOnlyCore() @@ -123,20 +124,20 @@ private bool IsModeReadOnlyCore() #endif // Checks if the main path is a symbolic link - // Only call if Refresh has been successfully called at least once private bool HasSymbolicLinkFlag { get { - Debug.Assert(IsFileCacheInitialized); - return (_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK; + Debug.Assert(_state != Uninitialized); // Use this after EnsureCachesInitialized has been called. + + return EntryExists && (_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK; } } - // Sets the cache initialization flags to -1, which means the caches are now uninitialized + // Sets the cache initialization flags to 0, which means the caches are now uninitialized internal void InvalidateCaches() { - _initializedFileCache = -1; + _state = Uninitialized; } internal bool IsReadOnly(ReadOnlySpan path, bool continueOnError = false) @@ -169,7 +170,7 @@ internal bool IsFileSystemEntryHidden(ReadOnlySpan path, ReadOnlySpan path, bool continueOnError = false) { EnsureCachesInitialized(path, continueOnError); - return _isDirectory; + return IsDir; } internal bool IsSymbolicLink(ReadOnlySpan path, bool continueOnError = false) @@ -182,7 +183,7 @@ internal FileAttributes GetAttributes(ReadOnlySpan path, ReadOnlySpan path, ReadOnlySpan path, ReadOnlySpan