diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 015825df43d7a6..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.22062.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 72acfd8440a06d..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 more info` 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": [
@@ -1017,7 +1010,7 @@
{
"name": "hasLabel",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
},
{
@@ -1030,13 +1023,13 @@
{
"name": "addLabel",
"parameters": {
- "label": "needs further triage"
+ "label": "needs-further-triage"
}
},
{
"name": "removeLabel",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
}
],
@@ -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,
@@ -1575,7 +1568,7 @@
{
"name": "hasLabel",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
},
{
@@ -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"
}
}
]
@@ -5416,7 +5409,7 @@
{
"name": "labelAdded",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
}
]
@@ -5426,12 +5419,12 @@
"issues",
"project_card"
],
- "taskName": "Needs more info notification",
+ "taskName": "Needs-author-action notification",
"actions": [
{
"name": "addReply",
"parameters": {
- "comment": "This issue has been marked `needs more info` since it may be missing important information. Please refer to our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md#writing-a-good-bug-report) for tips on how to report issues effectively."
+ "comment": "This issue has been marked `needs-author-action` since it may be missing important information. Please refer to our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md#writing-a-good-bug-report) for tips on how to report issues effectively."
}
}
]
@@ -5951,7 +5944,7 @@
{
"name": "labelAdded",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
},
{
@@ -6003,25 +5996,7 @@
{
"name": "hasLabel",
"parameters": {
- "label": "area-System.Collections"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "area-System.Linq"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "area-System.Text.Json"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "area-System.Xml"
+ "label": "area-Meta"
}
}
]
@@ -6032,7 +6007,7 @@
{
"name": "isInProject",
"parameters": {
- "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "projectName": "Area Pod: Eric / Jeff - PRs",
"isOrgProject": true
}
}
@@ -6046,12 +6021,12 @@
"issues",
"project_card"
],
- "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Add new PR to Board",
+ "taskName": "[Area Pod: Eric / Jeff - PRs] Add new PR to Board",
"actions": [
{
"name": "addToProject",
"parameters": {
- "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "projectName": "Area Pod: Eric / Jeff - PRs",
"columnName": "Needs Champion",
"isOrgProject": true
}
@@ -6686,7 +6661,7 @@
{
"name": "labelAdded",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
},
{
@@ -6723,6 +6698,119 @@
]
}
},
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
{
"taskType": "trigger",
"capabilityId": "IssueResponder",
@@ -7257,7 +7345,7 @@
{
"name": "labelAdded",
"parameters": {
- "label": "needs more info"
+ "label": "needs-author-action"
}
},
{
@@ -7294,6 +7382,77 @@
]
}
},
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
{
"taskType": "trigger",
"capabilityId": "IssueResponder",
@@ -7379,5 +7538,2436 @@
}
]
}
+ },
+ {
+ "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-DependencyModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-DependencyModel"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - 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-DependencyModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ },
+ {
+ "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: Eric / Maryam / Tarek - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - 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: Eric / Maryam / Tarek - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-DependencyModel"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - Issue Triage",
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "addedToMilestone",
+ "parameters": {}
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "needs more info"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "api-ready-for-review"
+ }
+ },
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "closed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - 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-DependencyModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - 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: Eric / Maryam / Tarek - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-DependencyModel"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Caching"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-DependencyInjection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Hosting"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Logging"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Options"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Extensions-Primitives"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.ComponentModel.Composition"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Composition"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Diagnostics.Activity"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Globalization"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Maryam / Tarek - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Maryam / Tarek - 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-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/features/standalone-gc-loading.md b/docs/design/features/standalone-gc-loading.md
index 3373bf5559f553..ed7440002e8da8 100644
--- a/docs/design/features/standalone-gc-loading.md
+++ b/docs/design/features/standalone-gc-loading.md
@@ -47,7 +47,7 @@ Worth noting is that the JIT (both RyuJIT and the legacy JIT(s) before it) can b
and have realized these same benefits. The existence of an interface and an implementation loadable
from shared libraries has enabled RyuJIT in particular to be used as the code generator for both the
CoreRT compiler and crossgen, while still being flexible enough to be tested using tools that implement
-very non-standard execution engines such as [SuperPMI](https://github.com/dotnet/runtime/blob/main/src/coreclr/ToolBox/superpmi/readme.txt).
+very non-standard execution engines such as [SuperPMI](https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/superpmi/readme.md).
The below loading protocol is inspired directly by the JIT loader and many aspects of the GC loader are identical
to what the JIT does when loading dynamic shared libraries.
diff --git a/docs/design/libraries/DllImportGenerator/StructMarshalling.md b/docs/design/libraries/DllImportGenerator/StructMarshalling.md
index ab332616b74132..63781d6d77dbb2 100644
--- a/docs/design/libraries/DllImportGenerator/StructMarshalling.md
+++ b/docs/design/libraries/DllImportGenerator/StructMarshalling.md
@@ -6,10 +6,11 @@ These types pose an interesting problem for a number of reasons listed below. Wi
## Problems
-- Unmanaged vs Blittable
- - The C# language (and Roslyn) do not have a concept of "blittable types". It only has the concept of "unmanaged types", which is similar to blittable, but differs for `bool`s and `char`s. `bool` and `char` types are "unmanaged", but are never (in the case of `bool`), or only sometimes (in the case of `char`) blittable. As a result, we cannot use the "is this type unmanaged" check in Roslyn for structures.
+- What types require marshalling and what types can be passed as-is to native code?
+ - Unmanaged vs Blittable
+ - The C# language (and Roslyn) do not have a concept of "blittable types". It only has the concept of "unmanaged types", which is similar to blittable, but differs for `bool`s and `char`s. `bool` and `char` types are "unmanaged", but are never (in the case of `bool`), or only sometimes (in the case of `char`) blittable. As a result, we cannot use the "is this type unmanaged" check in Roslyn for structures without an additional mechanism provided by the runtime.
- Limited type information in ref assemblies.
- - In the ref assemblies generated by dotnet/runtime, we save space and prevent users from relying on private implementation details of structures by emitting limited information about their fields. Structures that have at least one non-object field are given a private `int` field, and structures that have at least one field that transitively contains an object are given one private `object`-typed field. As a result, we do not have full type information at code-generation time for any structures defined in the BCL when compiling a library that uses the ref assemblies.
+ - In the ref assemblies generated by dotnet/arcade's GenAPI (used in dotnet/runtime), we save space and prevent users from relying on private implementation details of structures by emitting limited information about their fields. Structures that have at least one non-object field are given a private `int` field, and structures that have at least one field that transitively contains an object are given one private `object`-typed field. As a result, we do not have full type information at code-generation time for any structures defined in the BCL when compiling a library that uses the ref assemblies.
- Private reflection
- Even when we do have information about all of the fields, we can't emit code that references them if they are private, so we would have to emit unsafe code and calculate offsets manually to support marshaling them.
@@ -19,16 +20,13 @@ We've been working around another problem for a while in the runtime-integrated
I propose an opt-in design where the owner of a struct has to explicitly opt-in to usage for interop. This enables our team to add special support as desired for various types such as `Span` while also avoiding the private reflection and limited type information issues mentioned above.
-This design would use these attributes:
+All design options would use these attributes:
```csharp
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
public class GeneratedMarshallingAttribute : Attribute {}
-[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
-public class BlittableTypeAttribute : Attribute {}
-
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
public class NativeMarshallingAttribute : Attribute
{
@@ -42,7 +40,7 @@ public class MarshalUsingAttribute : Attribute
}
```
-The `NativeMarshallingAttribute` and `MarshalUsingAttribute` attributes would require that the provided native type `TNative` is a blittable `struct` and has a subset of three methods with the following names and shapes (with the managed type named TManaged):
+The `NativeMarshallingAttribute` and `MarshalUsingAttribute` attributes would require that the provided native type `TNative` is a `struct` that does not require any marshalling and has a subset of three methods with the following names and shapes (with the managed type named TManaged):
```csharp
partial struct TNative
@@ -59,7 +57,7 @@ The analyzer will report an error if neither the constructor nor the `ToManaged`
> :question: Does this API surface and shape work for all marshalling scenarios we plan on supporting? It may have issues with the current "layout class" by-value `[Out]` parameter marshalling where the runtime updates a `class` typed object in place. We already recommend against using classes for interop for performance reasons and a struct value passed via `ref` or `out` with the same members would cover this scenario.
-If the native type `TNative` also has a public `Value` property, then the value of the `Value` property will be passed to native code instead of the `TNative` value itself. As a result, the type `TNative` will be allowed to be non-blittable and the type of the `Value` property will be required to be blittable. If the `Value` property is settable, then when marshalling in the native-to-managed direction, a default value of `TNative` will have its `Value` property set to the native value. If `Value` does not have a setter, then marshalling from native to managed is not supported.
+If the native type `TNative` also has a public `Value` property, then the value of the `Value` property will be passed to native code instead of the `TNative` value itself. As a result, the type `TNative` will be allowed to require marshalling and the type of the `Value` property will be required be passable to native code without any additional marshalling. If the `Value` property is settable, then when marshalling in the native-to-managed direction, a default value of `TNative` will have its `Value` property set to the native value. If `Value` does not have a setter, then marshalling from native to managed is not supported.
If a `Value` property is provided, the developer may also provide a ref-returning or readonly-ref-returning `GetPinnableReference` method. The `GetPinnableReference` method will be called before the `Value` property getter is called. The ref returned by `GetPinnableReference` will be pinned with a `fixed` statement, but the pinned value will not be used (it acts exclusively as a side-effect).
@@ -90,7 +88,7 @@ public struct TMarshaler
#### Pinning
-Since C# 7.3 added a feature to enable custom pinning logic for user types, we should also add support for custom pinning logic. If the user provides a `GetPinnableReference` method on the managed type that matches the requirements to be used in a `fixed` statement and the pointed-to type is blittable, then we will support using pinning to marshal the managed value when possible. The analyzer should issue a warning when the pointed-to type would not match the final native type, accounting for the `Value` property on the native type. Since `MarshalUsingAttribute` is applied at usage time instead of at type authoring time, we will not enable the pinning feature since the implementation of `GetPinnableReference` is likely designed to match the default marshalling rules provided by the type author, not the rules provided by the marshaller provided by the `MarshalUsingAttribute`.
+Since C# 7.3 added a feature to enable custom pinning logic for user types, we should also add support for custom pinning logic. If the user provides a `GetPinnableReference` method on the managed type that matches the requirements to be used in a `fixed` statement and the pointed-to type would not require any additional marshalling, then we will support using pinning to marshal the managed value when possible. The analyzer should issue a warning when the pointed-to type would not match the final native type, accounting for the `Value` property on the native type. Since `MarshalUsingAttribute` is applied at usage time instead of at type authoring time, we will not enable the pinning feature since the implementation of `GetPinnableReference` is likely designed to match the default marshalling rules provided by the type author, not the rules provided by the marshaller provided by the `MarshalUsingAttribute`.
#### Caller-allocated memory
@@ -111,27 +109,18 @@ When these members are present, the source generator will call the two-parameter
Type authors can pass down the `buffer` pointer to native code by defining a `Value` property that returns a pointer to the first element, generally through code using `MemoryMarshal.GetReference()` and `Unsafe.AsPointer`. If `RequiresStackBuffer` is not provided or set to `false`, the `buffer` span must be pinned to be used safely. The `buffer` span can be pinned by defining a `GetPinnableReference()` method on the native type that returns a reference to the first element of the span.
-### Usage
-
-There are 2 usage mechanisms of these attributes.
-
-#### Usage 1, Source-generated interop
-
-The user can apply the `GeneratedMarshallingAttribute` to their structure `S`. The source generator will determine if the type is blittable. If it is blittable, the source generator will generate a partial definition and apply the `BlittableTypeAttribute` to the struct type `S`. Otherwise, it will generate a blittable representation of the struct with the aformentioned required shape and apply the `NativeMarshallingAttribute` and point it to the blittable representation. The blittable representation can either be generated as a separate top-level type or as a nested type on `S`.
+### Determining if a type is doesn't need marshalling
-#### Usage 2, Manual interop
-
-The user may want to manually mark their types as marshalable in this system due to specific restrictions in their code base around marshaling specific types that the source generator does not account for. We could also use this internally to support custom types in source instead of in the code generator. In this scenario, the user would apply either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` attribute to their struct type. An analyzer would validate that the struct is blittable if the `BlittableTypeAttribute` is applied or validate that the native struct type is blittable and has marshalling methods of the required shape when the `NativeMarshallingAttribute` is applied.
-
-The P/Invoke source generator (as well as the struct source generator when nested struct types are used) would use the `BlittableTypeAttribute` and `NativeMarshallingAttribute` to determine how to marshal a value type parameter or field instead of looking at the fields of the struct directly.
+For this design, we need to decide how to determine a type doesn't need to be marshalled and already has a representation we can pass directly to native code - that is, we need a definition for "does not require marshalling". We have two designs that we have experimented with below, and we have decided to go with design 2.
-If a structure type does not have either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` applied at the type definition, the user can supply a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a native type matching the same requirements as `NativeMarshallingAttribute`'s native type.
-
-All generated stubs will be marked with [`SkipLocalsInitAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute) on supported frameworks. This does require attention when performing custom marshalling as the state of stub allocated memory will be in an undefined state.
+#### Design 1: Introducing `BlittableTypeAttribute`
-### Why do we need `BlittableTypeAttribute`?
+Traditionally, the concept of "does not require marshalling" is referred to as "blittable". The built-in runtime marshalling system has an issue as mentioned above that the concept of `unmanaged` is not the same as the concept of `blittable`. Additionally, due to the ref assembly issue above, we cannot rely on ref assemblies to have accurate information in terms of fields of a type. To solve these issues in combination with the desire to enable manual interop, we need to provide a way for users to signal that a given type should be blittable and that the source generator should not generate marshalling code. We'll introduce a new attribute, the `BlittableTypeAttribute`:
-Based on the design above, it seems that we wouldn't need `BlittableTypeAttribute`. However, due to the ref assembly issue above in combination with the desire to enable manual interop, we need to provide a way for users to signal that a given type should be blittable and that the source generator should not generate marshalling code.
+```csharp
+[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
+public class BlittableTypeAttribute : Attribute {}
+```
I'll give a specific example for where we need the `BlittableTypeAttribute` below. Let's take a scenario where we don't have `BlittableTypeAttribute`.
@@ -210,7 +199,7 @@ When the source generator (either Struct, P/Invoke, Reverse P/Invoke, etc.) enco
If someone actively disables the analyzer or writes their types in IL, then they have stepped out of the supported scenarios and marshalling code generated for their types may be inaccurate.
-#### Exception: Generics
+##### Exception: Generics
Because the Roslyn compiler needs to be able to validate that there are not recursive struct definitions, reference assemblies have to contain a field of a type parameter type in the reference assembly if they do in the runtime assembly. As a result, we can inspect private generic fields reliably.
@@ -221,6 +210,32 @@ To enable blittable generics support in this struct marshalling model, we extend
Since all fields typed with non-parameterized types are validated to be blittable at type definition time, we know that they are all blittable at type usage time. So, we only need to validate that the generic fields are instantiated with blittable types.
+#### Design 2: [`DisableRuntimeMarshallingAttribute`](https://github.com/dotnet/runtime/issues/60639)
+
+As an alternative design, we can use a different definition of "does not require marshalling". This design proposes changing the definition from "the runtime's definition of blittable" to "types considered `unmanaged` in C#". The `DisableRuntimeMarshallingAttribute` attribute helps us solve this problem. When applied to an assembly, this attribute causes the runtime to not do any marshalling for any types that are `unmanaged` types and do not have any auto-layout fields for all P/Invokes in the assembly; this includes when the types do not fit the runtime's definition of "blittable". This definition of "does not require marshalling" will work for all of our scenarios, with one issue listed below.
+
+For the auto-layout clause, we have one small issue; today, our ref-assemblies do not expose if a value type is marked as `[StructLayout(LayoutKind.Auto)]`, so we'd still have some cases where we might have runtime failures. However, we can update the tooling used in dotnet/runtime, GenAPI, to expose this information if we so desire. Once that case is handled, we have a mechanism that we can safely use to determine, at compile time, which types will not require marshalling. If we decide to not cover this case (as cases where users mark types as `LayoutKind.Auto` manually are exceptionally rare), we still have a solid design as Roslyn will automatically determine for us if a type is `unmanaged`, so we don't need to do any additional work.
+
+As `unmanaged` is a C# language concept, we can use Roslyn's APIs to determine if a type is `unmanaged` to determine if it does not require marshalling without needing to define any new attributes and reshape the ecosystem. However, to enable this work, the DllImportGenerator, as well as any other source generators that generate calls to native code using the interop team's infrastructure, will need to require that the user applies the `DisableRuntimeMarshallingAttribute` to their assembly when custom user-defined types are used. As we believe that users should be able to move over their assemblies to the new source-generated interop world as a whole assembly, we do not believe that this will cause any serious issues in adoption. To help support users in this case, the interop team will provide a code-fix that will generate the `DisableRuntimeMarshallingAttribute` for users when they use the source generator.
+
+### Usage
+
+There are 2 usage mechanisms of these attributes.
+
+#### Usage 1, Source-generated interop
+
+The user can apply the `GeneratedMarshallingAttribute` to their structure `S`. The source generator will determine if the type requires marshalling. If it does, it will generate a representation of the struct that does not require marshalling with the aformentioned required shape and apply the `NativeMarshallingAttribute` and point it to that new type. This generated representation can either be generated as a separate top-level type or as a nested type on `S`.
+
+#### Usage 2, Manual interop
+
+The user may want to manually mark their types as marshalable with custom marshalling rules in this system due to specific restrictions in their code base around marshaling specific types that the source generator does not account for. We could also use this internally to support custom types in source instead of in the code generator. In this scenario, the user would apply either the `NativeMarshallingAttribute` attribute to their struct type. An analyzer would validate that the native struct type does not require marshalling and has marshalling methods of the required shape when the `NativeMarshallingAttribute` is applied.
+
+The P/Invoke source generator (as well as the struct source generator when nested struct types are used) would use the `NativeMarshallingAttribute` to determine how to marshal a parameter or field with an unknown type.
+
+If a structure type does not meet the requirements to not require marshalling or does not have the `NativeMarshallingAttribute` applied at the type definition, the user can supply a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a native type matching the same requirements as `NativeMarshallingAttribute`'s native type.
+
+All generated stubs will be marked with [`SkipLocalsInitAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute) on supported frameworks. This does require attention when performing custom marshalling as the state of stub allocated memory will be in an undefined state.
+
### Special case: Transparent Structures
There has been discussion about Transparent Structures, structure types that are treated as their underlying types when passed to native code. The support for a `Value` property on a generated marshalling type supports the transparent struct support. For example, we could support strongly typed `HRESULT` returns with this model as shown below:
@@ -250,7 +265,7 @@ struct HRESULT
In this case, the underlying native type would actually be an `int`, but the user could use the strongly-typed `HResult` type as the public surface area.
-> :question: Should we support transparent structures on manually annotated blittable types? If we do, we should do so in an opt-in manner to make it possible to have a `Value` property on the blittable type.
+> :question: Should we support transparent structures on manually annotated types that wouldn't need marshalling otherwise? If we do, we should do so in an opt-in manner to make it possible to have a `Value` property on the type without assuming that it is for interop in all cases.
#### Example: ComWrappers marshalling with Transparent Structures
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/pr-builds.md b/docs/pr-builds.md
new file mode 100644
index 00000000000000..f5f7555ae7e675
--- /dev/null
+++ b/docs/pr-builds.md
@@ -0,0 +1,94 @@
+## PR Builds
+When submitting a PR to the `dotnet/runtime` repository various builds will run validation in many areas to ensure we keep productivity and quality high.
+
+The `dotnet/runtime` validation system can become overwhelming as we need to cover a lot of build scenarios and test in all the platforms that we support. In order to try to make this more reliable and spend the least amount of time testing what the PR changes need we have various pipelines, required and optional that are covered in this document.
+
+Most of the repository pipelines use a custom mechanism to evaluate paths based on the changes contained in the PR to try and build/test the least that we can without compromising quality. This is the initial step on every pipeline that depends on this infrastructure, called "Evalute Paths". In this step you can see the result of the evaluation for each subset of the repository. For more details on which subsets we have based on paths see [here](https://github.com/dotnet/runtime/blob/513fe2863ad5ec6dc453d223d4b60f787a0ffa78/eng/pipelines/common/evaluate-default-paths.yml). Also to understand how this mechanism works you can read this [comment](https://github.com/dotnet/runtime/blob/513fe2863ad5ec6dc453d223d4b60f787a0ffa78/eng/pipelines/evaluate-changed-paths.sh#L3-L12).
+
+### Runtime pipeline
+This is the "main" pipeline for the runtime product. In this pipeline we include the most critical tests and platforms where we have enough test resources in order to deliver test results in a reasonable amount of time. The tests executed in this pipeline for runtime and libraries are considered innerloop, are the tests that are executed locally when one runs tests locally.
+
+For mobile platforms and wasm we run some smoke tests that aim to protect the quality of these platforms. We had to move to a smoke test approach given the hardware and time limitations that we encountered and contributors were affected by this with unstability and long wait times for their PRs to finish validation.
+
+### Runtime-dev-innerloop pipeline
+This pipeline is also required, and its intent is to cover a developer innerloop scenarios that could be affected by any change, like running a specific build command or running tests inside Visual Studio, etc.
+
+### Dotnet-linker-tests
+This is also a required pipeline. The purpose of this pipeline is to test that the libraries code is linker friendly. Meaning that when we trim our libraries using the ILLink, we don't have any trimming bugs, like a required method on a specific scenario is trimmed away by accident.
+
+### Runtime-staging
+This pipeline runs on every change, however it behaves a little different than the other pipelines. This pipeline, will not fail if there are test failures, however it will fail if there is a timeout or a build failure. The reason why we fail on build failures is because we want to protect the developer innerloop (building the repository) for this platform.
+
+The tests will not fail because the intent of this platform is to stage new platforms where the test infrastructure is new and we need to test if we have enough capacity to include that new platform on the "main" runtime pipeline without causing flakiness. Once we analyze data and a platform is stable when running on PRs in this pipeline for at least a weak it can be promoted either to the `runtime-extra-platforms` pipeline or to the `runtime` pipeline.
+
+### Runtime-extra-platforms
+This pipeline does not run by default as it is not required for a PR, but it runs twice a day, and it can also be invoked in specific PRs by commenting `/azp run runtime-extra-platforms`. However, this pipeline is still an important part of our testing.
+
+This pipeline runs innerloop tests on platforms where we don't have enough hardware capacity to run tests (mobile, browser) or on platforms where we believe tests should organically pass based on the coverage we have in the "main" runtime pipeline. For example, in the "main" pipeline we run tests on Ubuntu 21.10 but since we also support Ubuntu 18.04 which is an LTS release, we run tests on Ubuntu 18.04 of this pipeline just to make sure we have healthy tests on those platforms which we are releasing a product for.
+
+Another concrete scenario would be windows arm64 for libraries tests. Where we don't have enough hardware, but the JIT is the most important piece to test as that is what generates the native code to run on that platform, so we run JIT tests on arm64 in the "main" pipeline, but our libraries tests are only run on the `runtime-extra-platforms` pipeline.
+
+### Outerloop pipelines
+We have various pipelines that their names contain `Outerloop` on them. These pipelines will not run by default on every PR, they can also be invoked using the `/azp run` comment and will run on a daily basis to analyze test results.
+
+These pipelines will run tests that take very long, that are not very stable (i.e some networking tests), or that modify machine state. Such tests are called `Outerloop` tests rather than `innerloop`.
+
+## Rerunning Validation
+
+Validation may fail for several reasons:
+
+### Option 1: You have a defect in your PR
+
+* Simply push the fix to your PR branch, and validation will start over.
+
+### Option 2: There is a flaky test that is not related to your PR
+
+* Your assumption should be that a failed test indicates a problem in your PR. (If we don't operate this way, chaos ensues.) If the test fails when run again, it is almost surely a failure caused by your PR. However, there are occasions where unrelated failures occur. Here's some ways to know:
+ * Perhaps you see the same failure in CI results for unrelated active PR's.
+ * It's a known issue listed in our [big tracking issue](https://github.com/dotnet/runtime/issues/702) or tagged `blocking-clean-ci` [(query here)](https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Ablocking-clean-ci+)
+ * It's otherwise beyond any reasonable doubt that your code changes could not have caused this.
+ * If the tests pass on rerun, that may suggest it's not related.
+* In this situation, you want to re-run but not necessarily rebase on main.
+ * To rerun just the failed leg(s):
+ * Click on any leg. Navigate through the Azure DevOps UI, find the "..." button and choose "Retry failed legs"
+ * Or, on the GitHub Checks tab choose "re-run failed checks". This will not rebase your change.
+ * To rerun all validation:
+ * Add a comment `/azp run runtime`
+ * Or, click on "re-run all checks" in the GitHub Checks tab
+ * Or, simply close and reopen the PR.
+* If you have established that it is an unrelated failure, please ensure we have an active issue for it. See the [unrelated failure](#what-to-do-if-you-determine-the-failure-is-unrelated) section below.
+* Whoever merges the PR should be satisfied that the failure is unrelated, is not introduced by the change, and that we are appropriately tracking it.
+
+### Option 3: The state of the main branch HEAD is bad.
+
+* This is the very rare case where there was a build break in main, and you got unlucky. Hopefully the break has been fixed, and you want CI to rebase your change and rerun validation.
+* To rebase and rerun all validation:
+ * Add a comment `/azp run runtime`
+ * Or, click on "re-run all checks" in the GitHub Checks tab
+ * Or, simply close and reopen the PR.
+ * Or, ammend your commit with `--amend --no-edit` and force push to your branch.
+
+### Additional information:
+ * You can list the available pipelines by adding a comment like `/azp list` or get the available commands by adding a comment like `azp help`.
+ * In the rare case the license/cla check fails to register a response, it can be rerun by issuing a GET request to `https://cla.dotnetfoundation.org/check/dotnet/runtime?pullRequest={pr_number}`. A successful response may be a redirect to `https://github.com`.
+ * Reach out to the infrastructure team for assistance on [Teams channel](https://teams.microsoft.com/l/channel/19%3ab27b36ecd10a46398da76b02f0411de7%40thread.skype/Infrastructure?groupId=014ca51d-be57-47fa-9628-a15efcc3c376&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) (for corpnet users) or on [Gitter](https://gitter.im/dotnet/community) in other cases.
+
+## What to do if you determine the failure is unrelated
+
+If you have determined the failure is definitely not caused by changes in your PR, please do this:
+
+* Search for an [existing issue](https://github.com/dotnet/runtime/issues). Usually the test method name or (if a crash/hang) the test assembly name are good search parameters.
+ * If there's an existing issue, add a comment with
+ * a) the link to the build
+ * b) the affected configuration (ie `net6.0-windows-Release-x64-Windows.81.Amd64.Open`)
+ * c) all console output including the error message and stack trace from the Azure DevOps tab (This is necessary as retention policies are in place that recycle old builds.)
+ * d) if there's a dump file (see Attachments tab in Azure DevOps) include that
+ * If the issue is already closed, reopen it and update the labels to reflect the current failure state.
+ * If there's no existing issue, create an issue with the same information listed above.
+ * Update the original pull request with a comment linking to the new or existing issue.
+* In a follow-up Pull Request, disable the failing test(s) with the corresponding issue link tracking the disable.
+ * Update the tracking issue with the label `disabled-test`.
+ * For libraries tests add a [`[ActiveIssue(link)]`](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/Attributes/ActiveIssueAttribute.cs) attribute on the test method. You can narrow the disabling down to runtime variant, flavor, and platform. For an example see [File_AppendAllLinesAsync_Encoded](https://github.com/dotnet/runtime/blob/cf49643711ad8aa4685a8054286c1348cef6e1d8/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs#L74)
+ * For runtime tests found under `src/tests`, please edit [`issues.targets`](https://github.com/dotnet/runtime/blob/main/src/tests/issues.targets). There are several groups for different types of disable (mono vs. coreclr, different platforms, different scenarios). Add the folder containing the test and issue mimicking any of the samples in the file.
+
+There are plenty of possible bugs, e.g. race conditions, where a failure might highlight a real problem and it won't manifest again on a retry. Therefore these steps should be followed for every iteration of the PR build, e.g. before retrying/rebuilding.
\ No newline at end of file
diff --git a/docs/pr-guide.md b/docs/pr-guide.md
index b250efd6e12dd9..eb7dea7a01ba7e 100644
--- a/docs/pr-guide.md
+++ b/docs/pr-guide.md
@@ -24,71 +24,10 @@ Anyone with write access can merge a pull request manually or by setting the [au
* The PR has been approved by at least one reviewer and any other objections are addressed.
* You can request another review from the original reviewer.
-* The PR successfully builds and passes all tests in the Continuous Integration (CI) system.
- * Depending on your change, you may need to re-run validation. See [rerunning validation](#rerunning-validation) below.
+* The PR successfully builds and passes all tests in the Continuous Integration (CI) system. For more information please read to our [PR Builds](pr-builds.md) doc.
Typically, PRs are merged as one commit. It creates a simpler history than a Merge Commit. "Special circumstances" are rare, and typically mean that there are a series of cleanly separated changes that will be too hard to understand if squashed together, or for some reason we want to preserve the ability to bisect them.
-## Rerunning Validation
-
-Validation may fail for several reasons:
-
-### Option 1: You have a defect in your PR
-
-* Simply push the fix to your PR branch, and validation will start over.
-
-### Option 2: There is a flaky test that is not related to your PR
-
-* Your assumption should be that a failed test indicates a problem in your PR. (If we don't operate this way, chaos ensues.) If the test fails when run again, it is almost surely a failure caused by your PR. However, there are occasions where unrelated failures occur. Here's some ways to know:
- * Perhaps you see the same failure in CI results for unrelated active PR's.
- * It's a known issue listed in our [big tracking issue](https://github.com/dotnet/runtime/issues/702) or tagged `blocking-clean-ci` [(query here)](https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Ablocking-clean-ci+)
- * Its otherwise beyond any reasonable doubt that your code changes could not have caused this.
- * If the tests pass on rerun, that may suggest it's not related.
-* In this situation, you want to re-run but not necessarily rebase on main.
- * To rerun just the failed leg(s):
- * Click on any leg. Navigate through the Azure DevOps UI, find the "..." button and choose "Retry failed legs"
- * Or, on the GitHub Checks tab choose "re-run failed checks". This will not rebase your change.
- * To rerun all validation:
- * Add a comment `/azp run runtime`
- * Or, click on "re-run all checks" in the GitHub Checks tab
- * Or, simply close and reopen the PR.
-* If you have established that it is an unrelated failure, please ensure we have an active issue for it. See the [unrelated failure](#what-to-do-if-you-determine-the-failure-is-unrelated) section below.
-* Whoever merges the PR should be satisfied that the failure is unrelated, is not introduced by the change, and that we are appropriately tracking it.
-
-### Option 3: The state of the main branch HEAD is bad.
-
-* This is the very rare case where there was a build break in main, and you got unlucky. Hopefully the break has been fixed, and you want CI to rebase your change and rerun validation.
-* To rebase and rerun all validation:
- * Add a comment `/azp run runtime`
- * Or, click on "re-run all checks" in the GitHub Checks tab
- * Or, simply close and reopen the PR.
- * Or, ammend your commit with `--amend --no-edit` and force push to your branch.
-
-### Additional information:
- * You can list the available pipelines by adding a comment like `/azp list` or get the available commands by adding a comment like `azp help`.
- * In the rare case the license/cla check fails to register a response, it can be rerun by issuing a GET request to `https://cla.dotnetfoundation.org/check/dotnet/runtime?pullRequest={pr_number}`. A successful response may be a redirect to `https://github.com`.
- * Reach out to the infrastructure team for assistance on [Teams channel](https://teams.microsoft.com/l/channel/19%3ab27b36ecd10a46398da76b02f0411de7%40thread.skype/Infrastructure?groupId=014ca51d-be57-47fa-9628-a15efcc3c376&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47) (for corpnet users) or on [Gitter](https://gitter.im/dotnet/community) in other cases.
-
-## What to do if you determine the failure is unrelated
-
-If you have determined the failure is definitely not caused by changes in your PR, please do this:
-
-* Search for an [existing issue](https://github.com/dotnet/runtime/issues). Usually the test method name or (if a crash/hang) the test assembly name are good search parameters.
- * If there's an existing issue, add a comment with
- * a) the link to the build
- * b) the affected configuration (ie `net6.0-windows-Release-x64-Windows.81.Amd64.Open`)
- * c) all console output including the error message and stack trace from the Azure DevOps tab (This is necessary as retention policies are in place that recycle old builds.)
- * d) if there's a dump file (see Attachments tab in Azure DevOps) include that
- * If the issue is already closed, reopen it and update the labels to reflect the current failure state.
- * If there's no existing issue, create an issue with the same information listed above.
- * Update the original pull request with a comment linking to the new or existing issue.
-* In a follow-up Pull Request, disable the failing test(s) with the corresponding issue link tracking the disable.
- * Update the tracking issue with the label `disabled-test`.
- * For libraries tests add a [`[ActiveIssue(link)]`](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/Attributes/ActiveIssueAttribute.cs) attribute on the test method. You can narrow the disabling down to runtime variant, flavor, and platform. For an example see [File_AppendAllLinesAsync_Encoded](https://github.com/dotnet/runtime/blob/a259ec2e967d502f82163beba6b84da5319c5e08/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs#L899)
- * For runtime tests found under `src/tests`, please edit [`issues.targets`](https://github.com/dotnet/runtime/blob/main/src/tests/issues.targets). There are several groups for different types of disable (mono vs. coreclr, different platforms, different scenarios). Add the folder containing the test and issue mimicking any of the samples in the file.
-
-There are plenty of possible bugs, e.g. race conditions, where a failure might highlight a real problem and it won't manifest again on a retry. Therefore these steps should be followed for every iteration of the PR build, e.g. before retrying/rebuilding.
-
## Blocking Pull Request Merging
If for whatever reason you would like to move your pull request back to an in-progress status to avoid merging it in the current form, you can do that by adding [WIP] prefix to the pull request title.
diff --git a/docs/project/glossary.md b/docs/project/glossary.md
index cb7e0b21538b8c..28fed9e8e160d5 100644
--- a/docs/project/glossary.md
+++ b/docs/project/glossary.md
@@ -43,7 +43,7 @@ terminology.
| SDK | Software Development Kit. The [.NET SDK](https://docs.microsoft.com/dotnet/core/sdk) contains the .NET CLI, .NET libraries and runtime, and the dotnet driver. |
| SEH | [Structured Exception Handling](https://docs.microsoft.com/windows/win32/debug/structured-exception-handling). Unified mechanism for handling hardware and software exceptions on Windows. |
| SOS | [Son of Strike](https://docs.microsoft.com/archive/blogs/jasonz/sos-debugging-of-the-clr-part-1). The debugging extension for DbgEng based debuggers. Uses the DAC as an abstraction layer for its operation. |
-| SuperPMI | JIT component test framework (super fast JIT testing - it mocks/replays EE in EE-JIT interface) - see [SuperPMI details](https://github.com/dotnet/runtime/blob/main/src/coreclr/ToolBox/superpmi/readme.txt). |
+| SuperPMI | JIT component test framework (super fast JIT testing - it mocks/replays EE in EE-JIT interface) - see [SuperPMI details](https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/superpmi/readme.md). |
| SVR | The CLR used to be built as two variants, with one called "mscorsvr.dll", to mean the "server" version. In particular, it contained the server GC implementation, which was intended for multi-threaded apps capable of taking advantage of multiple processors. In the .NET Framework 2 release, the two variants were merged into "mscorwks.dll". The WKS version was the default, however the SVR version remained available. |
| TFM | [Target Framework Moniker](https://docs.microsoft.com/dotnet/standard/frameworks) such as `net6.0` or `netstandard2.0`. |
| TPA | Trusted Platform Assemblies used to be a special set of assemblies that comprised the platform assemblies, when it was originally designed. As of today, it is simply the set of assemblies known to constitute the application. |
@@ -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/building/coreclr/osx-instructions.md b/docs/workflow/building/coreclr/osx-instructions.md
index d8bf4fe604fcb8..41e8d87de1a7ec 100644
--- a/docs/workflow/building/coreclr/osx-instructions.md
+++ b/docs/workflow/building/coreclr/osx-instructions.md
@@ -1,49 +1,12 @@
-Build CoreCLR on OS X
+Build CoreCLR on macOS
=====================
-This guide will walk you through building CoreCLR on OS X. We'll start by showing how to set up your environment from scratch.
+This guide will walk you through building CoreCLR on macOS. We'll start by showing how to set up your environment from scratch.
Environment
===========
-These instructions were validated on macOS 10.12. Sierra. On older versions coreFX will fail to build properly because of SSL API changes.
-
-If your machine has Command Line Tools for XCode 6.3 installed, you'll need to update them to the 6.3.1 version or higher in order to successfully build. There was an issue with the headers that shipped with version 6.3 that was subsequently fixed in 6.3.1.
-
-Git Setup
----------
-
-Clone the CoreCLR and CoreFX repositories (either upstream or a fork).
-
-```sh
-git clone https://github.com/dotnet/runtime
-# Cloning into 'runtime'...
-```
-
-CMake
------
-
-CoreCLR has a dependency on CMake for the build. You can install it with [Homebrew](https://brew.sh/).
-
-```sh
-brew install cmake
-```
-
-ICU
----
-ICU (International Components for Unicode) is also required to build and run. It can be obtained via [Homebrew](https://brew.sh/).
-
-```sh
-brew install icu4c
-```
-
-pkg-config
-----------
-pkg-config is also required to build. It can be obtained via [Homebrew](https://brew.sh/).
-
-```sh
-brew install pkg-config
-```
+Ensure you have all of the prerequisites installed from the [macOS Requirements](/docs/workflow/requirements/macos-requirements.md).
Build the Runtime and System.Private.CoreLib
============================================
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/CodeAnalysis.test.globalconfig b/eng/CodeAnalysis.test.globalconfig
index 572310d3b86d0a..f56a38cfa707c0 100644
--- a/eng/CodeAnalysis.test.globalconfig
+++ b/eng/CodeAnalysis.test.globalconfig
@@ -1681,7 +1681,7 @@ dotnet_diagnostic.xUnit2012.severity = warning
dotnet_diagnostic.xUnit2013.severity = none
# xUnit2014: Do not use throws check to check for asynchronously thrown exception
-dotnet_diagnostic.xUnit2014.severity = warning
+dotnet_diagnostic.xUnit2014.severity = none
# xUnit2015: Do not use typeof expression to check the exception type
dotnet_diagnostic.xUnit2015.severity = warning
diff --git a/eng/Subsets.props b/eng/Subsets.props
index 772fbfcb995329..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
@@ -58,7 +58,7 @@
- clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs
+ clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.spmi
clr.iltools+clr.packages
@@ -106,12 +106,14 @@
-
+
+
+
@@ -202,10 +204,14 @@
$(ClrRuntimeBuildSubsets);ClrILToolsSubset=true
-
+
$(ClrRuntimeBuildSubsets);ClrNativeAotSubset=true
+
+ $(ClrRuntimeBuildSubsets);ClrSpmiSubset=true
+
+
@@ -358,6 +364,7 @@
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index a2cfe2c769fe8f..3da43d2ed21e24 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,258 +1,258 @@
-
+
https://github.com/dotnet/icu
- aae7d341a8ee7841ed0cb1cf298ab17fe04c187b
+ 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
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/llvm-project
- e7e0ebc663c70ccb19c331af50d418a06dc92df8
+ afc9070f64d110ce2bf029a4a624b9dd1c6dbffd
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 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
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/llvm-project
- 662aff66999c435aec09c58643e9fd703eadc3e0
+ 44adf6c047663fe20c388bfb769e18dd3c91f7e0
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/runtime
- a2af6294767b4a3f4c2ce787c5dda2abeeda7a00
+ 09ff1acdad2e7789908b5db9bb89896144c13042
-
+
https://github.com/dotnet/linker
- 1a6468ff722c8d362f37638989ec01ab9975ac28
+ e485816b48273d03bd6266a64dad9bea97f861d5
-
+
https://github.com/dotnet/xharness
- d33e67a6c2cc5fe415917c6f9bd17046a929dcc0
+ 0137095821e2e5a9e030d97248503387b8d72a18
-
+
https://github.com/dotnet/xharness
- d33e67a6c2cc5fe415917c6f9bd17046a929dcc0
+ 0137095821e2e5a9e030d97248503387b8d72a18
-
+
https://github.com/dotnet/xharness
- d33e67a6c2cc5fe415917c6f9bd17046a929dcc0
+ 0137095821e2e5a9e030d97248503387b8d72a18
-
+
https://github.com/dotnet/arcade
- 34bc5b1611e13bd0ee6a9f38ab8524d2ee489be5
+ 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
@@ -270,17 +270,17 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
91d6b3c1f51888d166701510189505f35714665c
-
+
https://github.com/dotnet/hotreload-utils
- 5bc948c6242bc9423c3269d122dcdf0ad6c06a83
+ d3e96c2e8ed4d58de217c44423c9ba3b90333724
-
+
https://github.com/dotnet/runtime-assets
- a597df23119faf540d95cebab14b82f084c47384
+ 8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7
-
+
https://github.com/dotnet/roslyn-analyzers
- e101c379c6e3c7011562ee3af3e3de066da0048f
+ f471d3381584f10f9908432e0b2b2b8ef07a0aa6
https://github.com/dotnet/sdk
diff --git a/eng/Versions.props b/eng/Versions.props
index 8bc9373cc09ac7..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
@@ -50,42 +50,42 @@
3.3.2
4.0.1
4.0.1
- 7.0.0-preview1.21613.1
+ 7.0.0-preview1.22068.2
2.0.0-alpha.1.21525.11
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 2.5.1-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.6
- 7.0.0-beta.22056.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
+ 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.22059.2
- 7.0.0-alpha.1.22059.2
- 7.0.0-alpha.1.22059.2
+ 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.22059.2
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.1
- 1.0.0-alpha.1.22060.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.22059.2
- 7.0.0-alpha.1.22059.2
+ 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.22059.2
+ 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,11 +160,12 @@
1.0.1-prerelease-00006
16.9.0-preview-20201201-01
- 1.0.0-prerelease.22062.1
- 1.0.0-prerelease.22062.1
- 1.0.0-prerelease.22062.1
- 1.0.2-alpha.0.22060.2
- 2.4.2-pre.9
+ 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
3.1.0
12.0.3
@@ -174,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.22053.1
+ 7.0.100-1.22063.2
$(MicrosoftNETILLinkTasksVersion)
- 7.0.0-alpha.1.22060.1
+ 7.0.0-preview.2.22074.5
7.0.0-alpha.1.21529.3
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
- 11.1.0-alpha.1.21615.1
+ 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/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index f7878dddd39211..fba2afda438b66 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -37,6 +37,13 @@ elseif(TARGET_ARCH_NAME STREQUAL "arm")
if(TIZEN)
set(TIZEN_TOOLCHAIN "armv7hl-tizen-linux-gnueabihf/9.2.0")
endif()
+elseif(TARGET_ARCH_NAME STREQUAL "armv6")
+ set(CMAKE_SYSTEM_PROCESSOR armv6l)
+ if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
+ set(TOOLCHAIN "armv6-alpine-linux-musleabihf")
+ else()
+ set(TOOLCHAIN "arm-linux-gnueabihf")
+ endif()
elseif(TARGET_ARCH_NAME STREQUAL "arm64")
set(CMAKE_SYSTEM_PROCESSOR aarch64)
if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/aarch64-alpine-linux-musl)
@@ -60,7 +67,7 @@ elseif (ILLUMOS)
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
set(TOOLCHAIN "x86_64-illumos")
else()
- message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, arm64, s390x and x86 are supported!")
+ message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, armv6, arm64, s390x and x86 are supported!")
endif()
if(DEFINED ENV{TOOLCHAIN})
@@ -194,7 +201,7 @@ endif()
# Specify compile options
-if((TARGET_ARCH_NAME MATCHES "^(arm|armel|arm64|s390x)$" AND NOT ANDROID) OR ILLUMOS)
+if((TARGET_ARCH_NAME MATCHES "^(arm|armv6|armel|arm64|s390x)$" AND NOT ANDROID) OR ILLUMOS)
set(CMAKE_C_COMPILER_TARGET ${TOOLCHAIN})
set(CMAKE_CXX_COMPILER_TARGET ${TOOLCHAIN})
set(CMAKE_ASM_COMPILER_TARGET ${TOOLCHAIN})
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/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1
index 2427ca6b6aec74..8508397d77640e 100644
--- a/eng/common/post-build/publish-using-darc.ps1
+++ b/eng/common/post-build/publish-using-darc.ps1
@@ -5,13 +5,8 @@ param(
[Parameter(Mandatory=$true)][string] $MaestroToken,
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com',
[Parameter(Mandatory=$true)][string] $WaitPublishingFinish,
- [Parameter(Mandatory=$false)][string] $EnableSourceLinkValidation,
- [Parameter(Mandatory=$false)][string] $EnableSigningValidation,
- [Parameter(Mandatory=$false)][string] $EnableNugetValidation,
- [Parameter(Mandatory=$false)][string] $PublishInstallersAndChecksums,
[Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters,
- [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters,
- [Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters
+ [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters
)
try {
@@ -35,27 +30,6 @@ try {
$optionalParams.Add("--no-wait") | Out-Null
}
- if ("false" -ne $PublishInstallersAndChecksums) {
- $optionalParams.Add("--publish-installers-and-checksums") | Out-Null
- }
-
- if ("true" -eq $EnableNugetValidation) {
- $optionalParams.Add("--validate-nuget") | Out-Null
- }
-
- if ("true" -eq $EnableSourceLinkValidation) {
- $optionalParams.Add("--validate-sourcelinkchecksums") | Out-Null
- }
-
- if ("true" -eq $EnableSigningValidation) {
- $optionalParams.Add("--validate-signingchecksums") | Out-Null
-
- if ("" -ne $SigningValidationAdditionalParameters) {
- $optionalParams.Add("--signing-validation-parameters") | Out-Null
- $optionalParams.Add($SigningValidationAdditionalParameters) | Out-Null
- }
- }
-
& $darc add-build-to-channel `
--id $buildId `
--publishing-infra-version $PublishingInfraVersion `
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/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml
deleted file mode 100644
index 8990dfc8c87cc3..00000000000000
--- a/eng/common/templates/post-build/channels/generic-internal-channel.yml
+++ /dev/null
@@ -1,190 +0,0 @@
-parameters:
- BARBuildId: ''
- PromoteToChannelIds: ''
- artifactsPublishingAdditionalParameters: ''
- dependsOn:
- - Validate
- publishInstallersAndChecksums: true
- symbolPublishingAdditionalParameters: ''
- stageName: ''
- channelName: ''
- channelId: ''
- transportFeed: ''
- shippingFeed: ''
- symbolsFeed: ''
-
-stages:
-- stage: ${{ parameters.stageName }}
- dependsOn: ${{ parameters.dependsOn }}
- variables:
- - template: ../common-variables.yml
- displayName: ${{ parameters.channelName }} Publishing
- jobs:
- - template: ../setup-maestro-vars.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
-
- - job: publish_symbols
- displayName: Symbol Publishing
- dependsOn: setupMaestroVars
- condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} ))
- variables:
- - group: DotNet-Symbol-Server-Pats
- - 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'
- steps:
- - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions."
- displayName: Warn about v2 Arcade Publishing Usage
-
- # This is necessary whenever we want to publish/restore to an AzDO private feed
- - task: NuGetAuthenticate@0
- displayName: 'Authenticate to AzDO Feeds'
-
- - task: DownloadBuildArtifacts@0
- displayName: Download Build Assets
- continueOnError: true
- inputs:
- buildType: specific
- buildVersionToDownload: specific
- project: $(AzDOProjectName)
- pipeline: $(AzDOPipelineId)
- buildId: $(AzDOBuildId)
- downloadType: 'specific'
- itemPattern: |
- PdbArtifacts/**
- BlobArtifacts/**
- downloadPath: '$(Build.ArtifactStagingDirectory)'
- checkDownloadedFiles: true
-
- # This is necessary whenever we want to publish/restore to an AzDO private feed
- # Since sdk-task.ps1 tries to restore packages we need to do this authentication here
- # otherwise it'll complain about accessing a private feed.
- - task: NuGetAuthenticate@0
- displayName: 'Authenticate to AzDO Feeds'
-
- - task: PowerShell@2
- displayName: Enable cross-org publishing
- inputs:
- filePath: eng\common\enable-cross-org-publishing.ps1
- arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
-
- - task: PowerShell@2
- displayName: Publish
- inputs:
- filePath: eng\common\sdk-task.ps1
- arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet
- /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat)
- /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat)
- /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/'
- /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
- /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt'
- /p:Configuration=Release
- /p:PublishToMSDL=false
- ${{ parameters.symbolPublishingAdditionalParameters }}
-
- - template: ../../steps/publish-logs.yml
- parameters:
- StageLabel: '${{ parameters.stageName }}'
- JobLabel: 'SymbolPublishing'
-
- - job: publish_assets
- displayName: Publish Assets
- dependsOn: setupMaestroVars
- timeoutInMinutes: 120
- variables:
- - name: BARBuildId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- - name: IsStableBuild
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
- - name: AzDOProjectName
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
- - name: AzDOPipelineId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
- - name: AzDOBuildId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
- condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} ))
- pool:
- vmImage: 'windows-2019'
- steps:
- - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions."
- displayName: Warn about v2 Arcade Publishing Usage
-
- - task: DownloadBuildArtifacts@0
- displayName: Download Build Assets
- continueOnError: true
- inputs:
- buildType: specific
- buildVersionToDownload: specific
- project: $(AzDOProjectName)
- pipeline: $(AzDOPipelineId)
- buildId: $(AzDOBuildId)
- downloadType: 'specific'
- itemPattern: |
- PackageArtifacts/**
- BlobArtifacts/**
- AssetManifests/**
- downloadPath: '$(Build.ArtifactStagingDirectory)'
- checkDownloadedFiles: true
-
- - task: NuGetToolInstaller@1
- displayName: 'Install NuGet.exe'
-
- # This is necessary whenever we want to publish/restore to an AzDO private feed
- - task: NuGetAuthenticate@0
- displayName: 'Authenticate to AzDO Feeds'
-
- - task: PowerShell@2
- displayName: Enable cross-org publishing
- inputs:
- filePath: eng\common\enable-cross-org-publishing.ps1
- arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
-
- - task: PowerShell@2
- displayName: Publish Assets
- inputs:
- filePath: eng\common\sdk-task.ps1
- arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
- /p:PublishingInfraVersion=2
- /p:IsStableBuild=$(IsStableBuild)
- /p:IsInternalBuild=$(IsInternalBuild)
- /p:RepositoryName=$(Build.Repository.Name)
- /p:CommitSha=$(Build.SourceVersion)
- /p:NugetPath=$(NuGetExeToolPath)
- /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)'
- /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
- /p:BARBuildId=$(BARBuildId)
- /p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
- /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
- /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
- /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
- /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
- /p:Configuration=Release
- /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }}
- /p:ChecksumsTargetStaticFeed=$(InternalChecksumsBlobFeedUrl)
- /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey)
- /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl)
- /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey)
- /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}'
- /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}'
- /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}'
- /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:PublishToMSDL=false
- ${{ parameters.artifactsPublishingAdditionalParameters }}
-
- - template: ../../steps/publish-logs.yml
- parameters:
- StageLabel: '${{ parameters.stageName }}'
- JobLabel: 'AssetsPublishing'
-
- - template: ../../steps/add-build-to-channel.yml
- parameters:
- ChannelId: ${{ parameters.channelId }}
diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml
deleted file mode 100644
index 3220c6a4f92ffb..00000000000000
--- a/eng/common/templates/post-build/channels/generic-public-channel.yml
+++ /dev/null
@@ -1,192 +0,0 @@
-parameters:
- BARBuildId: ''
- PromoteToChannelIds: ''
- artifactsPublishingAdditionalParameters: ''
- dependsOn:
- - Validate
- publishInstallersAndChecksums: true
- symbolPublishingAdditionalParameters: ''
- stageName: ''
- channelName: ''
- channelId: ''
- transportFeed: ''
- shippingFeed: ''
- symbolsFeed: ''
- # If the channel name is empty, no links will be generated
- akaMSChannelName: ''
-
-stages:
-- stage: ${{ parameters.stageName }}
- dependsOn: ${{ parameters.dependsOn }}
- variables:
- - template: ../common-variables.yml
- displayName: ${{ parameters.channelName }} Publishing
- jobs:
- - template: ../setup-maestro-vars.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
-
- - job: publish_symbols
- displayName: Symbol Publishing
- dependsOn: setupMaestroVars
- condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} ))
- variables:
- - group: DotNet-Symbol-Server-Pats
- - 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'
- steps:
- - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions."
- displayName: Warn about v2 Arcade Publishing Usage
-
- - task: DownloadBuildArtifacts@0
- displayName: Download Build Assets
- continueOnError: true
- inputs:
- buildType: specific
- buildVersionToDownload: specific
- project: $(AzDOProjectName)
- pipeline: $(AzDOPipelineId)
- buildId: $(AzDOBuildId)
- downloadType: 'specific'
- itemPattern: |
- PdbArtifacts/**
- BlobArtifacts/**
- downloadPath: '$(Build.ArtifactStagingDirectory)'
- checkDownloadedFiles: true
-
- # This is necessary whenever we want to publish/restore to an AzDO private feed
- # Since sdk-task.ps1 tries to restore packages we need to do this authentication here
- # otherwise it'll complain about accessing a private feed.
- - task: NuGetAuthenticate@0
- displayName: 'Authenticate to AzDO Feeds'
-
- - task: PowerShell@2
- displayName: Enable cross-org publishing
- inputs:
- filePath: eng\common\enable-cross-org-publishing.ps1
- arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
-
- - task: PowerShell@2
- displayName: Publish
- inputs:
- filePath: eng\common\sdk-task.ps1
- arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet
- /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat)
- /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat)
- /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/'
- /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
- /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt'
- /p:Configuration=Release
- ${{ parameters.symbolPublishingAdditionalParameters }}
-
- - template: ../../steps/publish-logs.yml
- parameters:
- StageLabel: '${{ parameters.stageName }}'
- JobLabel: 'SymbolPublishing'
-
- - job: publish_assets
- displayName: Publish Assets
- dependsOn: setupMaestroVars
- timeoutInMinutes: 120
- variables:
- - name: BARBuildId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- - name: IsStableBuild
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
- - name: AzDOProjectName
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
- - name: AzDOPipelineId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
- - name: AzDOBuildId
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
- - name: ArtifactsCategory
- value: ${{ coalesce(variables._DotNetArtifactsCategory, '.NETCore') }}
- condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} ))
- pool:
- vmImage: 'windows-2019'
- steps:
- - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions."
- displayName: Warn about v2 Arcade Publishing Usage
-
- - task: DownloadBuildArtifacts@0
- displayName: Download Build Assets
- continueOnError: true
- inputs:
- buildType: specific
- buildVersionToDownload: specific
- project: $(AzDOProjectName)
- pipeline: $(AzDOPipelineId)
- buildId: $(AzDOBuildId)
- downloadType: 'specific'
- itemPattern: |
- PackageArtifacts/**
- BlobArtifacts/**
- AssetManifests/**
- downloadPath: '$(Build.ArtifactStagingDirectory)'
- checkDownloadedFiles: true
-
- - task: NuGetToolInstaller@1
- displayName: 'Install NuGet.exe'
-
- # This is necessary whenever we want to publish/restore to an AzDO private feed
- - task: NuGetAuthenticate@0
- displayName: 'Authenticate to AzDO Feeds'
-
- - task: PowerShell@2
- displayName: Enable cross-org publishing
- inputs:
- filePath: eng\common\enable-cross-org-publishing.ps1
- arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
-
- - task: PowerShell@2
- displayName: Publish Assets
- inputs:
- filePath: eng\common\sdk-task.ps1
- arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
- /p:PublishingInfraVersion=2
- /p:ArtifactsCategory=$(ArtifactsCategory)
- /p:IsStableBuild=$(IsStableBuild)
- /p:IsInternalBuild=$(IsInternalBuild)
- /p:RepositoryName=$(Build.Repository.Name)
- /p:CommitSha=$(Build.SourceVersion)
- /p:NugetPath=$(NuGetExeToolPath)
- /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)'
- /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
- /p:BARBuildId=$(BARBuildId)
- /p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
- /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
- /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
- /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
- /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
- /p:Configuration=Release
- /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }}
- /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl)
- /p:InstallersAzureAccountKey=$(dotnetcli-storage-key)
- /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl)
- /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key)
- /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}'
- /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}'
- /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}'
- /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
- /p:LatestLinkShortUrlPrefix=dotnet/'${{ parameters.akaMSChannelName }}'
- /p:AkaMSClientId=$(akams-client-id)
- /p:AkaMSClientSecret=$(akams-client-secret)
- ${{ parameters.artifactsPublishingAdditionalParameters }}
-
- - template: ../../steps/publish-logs.yml
- parameters:
- StageLabel: '${{ parameters.stageName }}'
- JobLabel: 'AssetsPublishing'
-
- - template: ../../steps/add-build-to-channel.yml
- parameters:
- ChannelId: ${{ parameters.channelId }}
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 4f79cf0f33703f..2f176571f020cf 100644
--- a/eng/common/templates/post-build/post-build.yml
+++ b/eng/common/templates/post-build/post-build.yml
@@ -1,113 +1,114 @@
parameters:
- # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST.
- # Publishing V2 accepts optionally outlining the publishing stages - default is inline.
- # Publishing V3 DOES NOT accept inlining the publishing stages.
- publishingInfraVersion: 2
- # When set to true the publishing templates from the repo will be used
- # otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline
- inline: true
-
- # Only used if inline==false. When set to true will stall the current build until
- # the Promotion Pipeline build finishes. Otherwise, the current build will continue
- # execution concurrently with the promotion build.
- waitPublishingFinish: true
-
- BARBuildId: ''
- PromoteToChannelIds: ''
-
- enableSourceLinkValidation: false
- enableSigningValidation: true
- enableSymbolValidation: false
- enableNugetValidation: true
- publishInstallersAndChecksums: true
- SDLValidationParameters:
- enable: false
- continueOnError: false
- params: ''
- artifactNames: ''
- downloadArtifacts: true
+ # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST.
+ # Publishing V1 is no longer supported
+ # Publishing V2 is no longer supported
+ # Publishing V3 is the default
+ - name: publishingInfraVersion
+ displayName: Which version of publishing should be used to promote the build definition?
+ type: number
+ default: 3
+ values:
+ - 3
+
+ - name: BARBuildId
+ displayName: BAR Build Id
+ type: number
+ default: 0
+
+ - name: PromoteToChannelIds
+ displayName: Channel to promote BARBuildId to
+ type: string
+ default: ''
+
+ - name: enableSourceLinkValidation
+ displayName: Enable SourceLink validation
+ type: boolean
+ default: false
+
+ - name: enableSigningValidation
+ displayName: Enable signing validation
+ type: boolean
+ default: true
+
+ - name: enableSymbolValidation
+ displayName: Enable symbol validation
+ type: boolean
+ default: false
+
+ - name: enableNugetValidation
+ displayName: Enable NuGet validation
+ type: boolean
+ default: true
+
+ - name: publishInstallersAndChecksums
+ displayName: Publish installers and checksums
+ type: boolean
+ default: true
+
+ - name: SDLValidationParameters
+ type: object
+ default:
+ enable: false
+ continueOnError: false
+ params: ''
+ artifactNames: ''
+ downloadArtifacts: true
# These parameters let the user customize the call to sdk-task.ps1 for publishing
# symbols & general artifacts as well as for signing validation
- symbolPublishingAdditionalParameters: ''
- artifactsPublishingAdditionalParameters: ''
- signingValidationAdditionalParameters: ''
+ - name: symbolPublishingAdditionalParameters
+ displayName: Symbol publishing additional parameters
+ type: string
+ default: ''
+
+ - name: artifactsPublishingAdditionalParameters
+ displayName: Artifact publishing additional parameters
+ type: string
+ default: ''
+
+ - name: signingValidationAdditionalParameters
+ displayName: Signing validation additional parameters
+ type: string
+ default: ''
# Which stages should finish execution before post-build stages start
- validateDependsOn:
- - build
- publishDependsOn:
- - Validate
+ - name: validateDependsOn
+ type: object
+ default:
+ - build
- # Channel ID's instantiated in this file.
- # When adding a new channel implementation the call to `check-channel-consistency.ps1`
- # needs to be updated with the new channel ID
- NetEngLatestChannelId: 2
- NetEngValidationChannelId: 9
- NetDev5ChannelId: 131
- NetDev6ChannelId: 1296
- GeneralTestingChannelId: 529
- NETCoreToolingDevChannelId: 548
- NETCoreToolingReleaseChannelId: 549
- NETInternalToolingChannelId: 551
- NETCoreExperimentalChannelId: 562
- NetEngServicesIntChannelId: 678
- NetEngServicesProdChannelId: 679
- NetCoreSDK313xxChannelId: 759
- NetCoreSDK313xxInternalChannelId: 760
- NetCoreSDK314xxChannelId: 921
- NetCoreSDK314xxInternalChannelId: 922
- VS166ChannelId: 1010
- VS167ChannelId: 1011
- VS168ChannelId: 1154
- VSMasterChannelId: 1012
- VS169ChannelId: 1473
- VS1610ChannelId: 1692
+ - name: publishDependsOn
+ type: object
+ default:
+ - Validate
stages:
-- ${{ if or(and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')), eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}:
+- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}:
- stage: Validate
dependsOn: ${{ parameters.validateDependsOn }}
displayName: Validate Build Assets
variables:
- template: common-variables.yml
jobs:
- - template: setup-maestro-vars.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
-
- - ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}:
- - job:
- displayName: Post-build Checks
- dependsOn: setupMaestroVars
- variables:
- - name: TargetChannels
- value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ]
- pool:
- vmImage: 'windows-2019'
- steps:
- - task: PowerShell@2
- displayName: Maestro Channels Consistency
- inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
- arguments: -PromoteToChannels "$(TargetChannels)"
- -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}},${{parameters.VS169ChannelId}},${{parameters.VS1610ChannelId}}
-
- 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:
@@ -128,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:
@@ -185,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:
@@ -223,367 +230,48 @@ 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 }}
downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }}
-- ${{ if or(ge(parameters.publishingInfraVersion, 3), eq(parameters.inline, 'false')) }}:
- - stage: publish_using_darc
- ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}:
- dependsOn: ${{ parameters.publishDependsOn }}
- ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}:
- dependsOn: ${{ parameters.validateDependsOn }}
- displayName: Publish using Darc
- 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'
- steps:
- - task: PowerShell@2
- displayName: Publish Using Darc
- inputs:
- filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
- arguments: -BuildId $(BARBuildId)
- -PublishingInfraVersion ${{ parameters.PublishingInfraVersion }}
- -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
- -MaestroToken '$(MaestroApiAccessToken)'
- -WaitPublishingFinish ${{ parameters.waitPublishingFinish }}
- -PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }}
- -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}'
- -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}'
-
-- ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}:
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NetCore_Dev5_Publish'
- channelName: '.NET 5 Dev'
- akaMSChannelName: 'net5/dev'
- channelId: ${{ parameters.NetDev5ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NetCore_Dev6_Publish'
- channelName: '.NET 6 Dev'
- akaMSChannelName: 'net6/dev'
- channelId: ${{ parameters.NetDev6ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'Net_Eng_Latest_Publish'
- channelName: '.NET Eng - Latest'
- akaMSChannelName: 'eng/daily'
- channelId: ${{ parameters.NetEngLatestChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'Net_Eng_Validation_Publish'
- channelName: '.NET Eng - Validation'
- akaMSChannelName: 'eng/validation'
- channelId: ${{ parameters.NetEngValidationChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'General_Testing_Publish'
- channelName: 'General Testing'
- akaMSChannelName: 'generaltesting'
- channelId: ${{ parameters.GeneralTestingChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_Tooling_Dev_Publishing'
- channelName: '.NET Core Tooling Dev'
- channelId: ${{ parameters.NETCoreToolingDevChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_Tooling_Release_Publishing'
- channelName: '.NET Core Tooling Release'
- channelId: ${{ parameters.NETCoreToolingReleaseChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NET_Internal_Tooling_Publishing'
- channelName: '.NET Internal Tooling'
- channelId: ${{ parameters.NETInternalToolingChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_Experimental_Publishing'
- channelName: '.NET Core Experimental'
- channelId: ${{ parameters.NETCoreExperimentalChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'Net_Eng_Services_Int_Publish'
- channelName: '.NET Eng Services - Int'
- channelId: ${{ parameters.NetEngServicesIntChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'Net_Eng_Services_Prod_Publish'
- channelName: '.NET Eng Services - Prod'
- channelId: ${{ parameters.NetEngServicesProdChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_SDK_314xx_Publishing'
- channelName: '.NET Core SDK 3.1.4xx'
- channelId: ${{ parameters.NetCoreSDK314xxChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_SDK_314xx_Internal_Publishing'
- channelName: '.NET Core SDK 3.1.4xx Internal'
- channelId: ${{ parameters.NetCoreSDK314xxInternalChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_SDK_313xx_Publishing'
- channelName: '.NET Core SDK 3.1.3xx'
- channelId: ${{ parameters.NetCoreSDK313xxChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'NETCore_SDK_313xx_Internal_Publishing'
- channelName: '.NET Core SDK 3.1.3xx Internal'
- channelId: ${{ parameters.NetCoreSDK313xxInternalChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS16_6_Publishing'
- channelName: 'VS 16.6'
- channelId: ${{ parameters.VS166ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS16_7_Publishing'
- channelName: 'VS 16.7'
- channelId: ${{ parameters.VS167ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS16_8_Publishing'
- channelName: 'VS 16.8'
- channelId: ${{ parameters.VS168ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS_Master_Publishing'
- channelName: 'VS Master'
- channelId: ${{ parameters.VSMasterChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS_16_9_Publishing'
- channelName: 'VS 16.9'
- channelId: ${{ parameters.VS169ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
-
- - template: \eng\common\templates\post-build\channels\generic-public-channel.yml
- parameters:
- BARBuildId: ${{ parameters.BARBuildId }}
- PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
- artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
- dependsOn: ${{ parameters.publishDependsOn }}
- publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
- stageName: 'VS_16_10_Publishing'
- channelName: 'VS 16.10'
- channelId: ${{ parameters.VS1610ChannelId }}
- transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json'
- shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
- symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
+- stage: publish_using_darc
+ ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}:
+ dependsOn: ${{ parameters.publishDependsOn }}
+ ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}:
+ dependsOn: ${{ parameters.validateDependsOn }}
+ displayName: Publish using Darc
+ variables:
+ - template: common-variables.yml
+ jobs:
+ - job:
+ displayName: Publish Using Darc
+ timeoutInMinutes: 120
+ 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
+ steps:
+ - template: setup-maestro-vars.yml
+ parameters:
+ BARBuildId: ${{ parameters.BARBuildId }}
+ PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
+
+ - task: NuGetAuthenticate@0
+
+ - task: PowerShell@2
+ displayName: Publish Using Darc
+ inputs:
+ filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
+ arguments: -BuildId $(BARBuildId)
+ -PublishingInfraVersion ${{ parameters.publishingInfraVersion }}
+ -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
+ -MaestroToken '$(MaestroApiAccessToken)'
+ -WaitPublishingFinish true
+ -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}'
+ -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}'
\ No newline at end of file
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/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml
index ba40dc82f1411b..d85d6d07d5c7b0 100644
--- a/eng/common/templates/steps/source-build.yml
+++ b/eng/common/templates/steps/source-build.yml
@@ -23,7 +23,7 @@ steps:
# In addition, add an msbuild argument to copy the WIP from the repo to the target build location.
# This is because SetupNuGetSources.sh will alter the current NuGet.config file, and we need to preserve those
# changes.
- $internalRestoreArgs=
+ internalRestoreArgs=
if [ '$(dn-bot-dnceng-artifact-feeds-rw)' != '$''(dn-bot-dnceng-artifact-feeds-rw)' ]; then
# Temporarily work around https://github.com/dotnet/arcade/issues/7709
chmod +x $(Build.SourcesDirectory)/eng/common/SetupNugetSources.sh
diff --git a/eng/formatting/format.sh b/eng/formatting/format.sh
old mode 100644
new mode 100755
diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets
index bc2e7e5dff9a01..aab934c42ae6b6 100644
--- a/eng/liveBuilds.targets
+++ b/eng/liveBuilds.targets
@@ -24,6 +24,9 @@
$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'sharedFramework'))
$([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'crossgen2'))
+ $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'ilc'))
+ $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'aotsdk'))
+ $([MSBuild]::NormalizeDirectory('$(CoreCLRArtifactsPath)', 'build'))
$([MSBuild]::NormalizeDirectory('$(MonoArtifactsPath)', 'cross', $(TargetOS.ToLowerInvariant())-$(TargetArchitecture.ToLowerInvariant())))
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/global-build-job.yml b/eng/pipelines/common/global-build-job.yml
index cf30d702dda60d..c9015681d1e17c 100644
--- a/eng/pipelines/common/global-build-job.yml
+++ b/eng/pipelines/common/global-build-job.yml
@@ -3,6 +3,7 @@ parameters:
nameSuffix: ''
buildArgs: ''
archType: ''
+ hostedOs: ''
osGroup: ''
osSubgroup: ''
container: ''
@@ -35,8 +36,12 @@ parameters:
jobs:
- template: /eng/common/templates/job/job.yml
parameters:
- name: ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }}
- displayName: ${{ format('Build {0}{1} {2} {3} {4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }}
+ ${{ if eq(parameters.hostedOs, '') }}:
+ name: ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }}
+ displayName: ${{ format('Build {0}{1} {2} {3} {4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.nameSuffix) }}
+ ${{ if ne(parameters.hostedOs, '') }}:
+ name: ${{ format('build_{0}{1}_{2}_{3}_{4}_{5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.hostedOs, parameters.buildConfig, parameters.nameSuffix) }}
+ displayName: ${{ format('Build {0}{1} {2} {3} {4} {5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.hostedOs, parameters.buildConfig, parameters.nameSuffix) }}
pool: ${{ parameters.pool }}
container: ${{ parameters.container }}
condition: and(succeeded(), ${{ parameters.condition }})
@@ -136,7 +141,7 @@ jobs:
df -h
displayName: Disk Usage before Build
- - ${{ if contains(parameters.nameSuffix, 'Windows_wasm') }}:
+ - ${{ if eq(parameters.platform, 'Browser_wasm_win') }}:
# Update machine certs
- task: PowerShell@2
displayName: Update machine certs
diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml
index ade8c7aab981b6..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')) }}:
@@ -273,7 +298,6 @@ jobs:
jobTemplate: ${{ parameters.jobTemplate }}
helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }}
variables: ${{ parameters.variables }}
- hostedOs: Linux
osGroup: Browser
archType: wasm
targetRid: browser-wasm
@@ -282,6 +306,7 @@ jobs:
image: ubuntu-18.04-webassembly-20210707133424-12f133e
registry: mcr
jobParameters:
+ hostedOs: Linux
runtimeFlavor: ${{ parameters.runtimeFlavor }}
stagedBuild: ${{ parameters.stagedBuild }}
buildConfig: ${{ parameters.buildConfig }}
@@ -297,12 +322,12 @@ jobs:
jobTemplate: ${{ parameters.jobTemplate }}
helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }}
variables: ${{ parameters.variables }}
- hostedOs: windows
osGroup: Browser
archType: wasm
targetRid: browser-wasm
platform: Browser_wasm_win
jobParameters:
+ hostedOs: windows
runtimeFlavor: ${{ parameters.runtimeFlavor }}
stagedBuild: ${{ parameters.stagedBuild }}
buildConfig: ${{ parameters.buildConfig }}
diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml
index 04399d26a6a22e..f944ad47ba2037 100644
--- a/eng/pipelines/common/templates/runtimes/run-test-job.yml
+++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml
@@ -73,7 +73,7 @@ jobs:
- ${{ if not(or(eq(parameters.runtimeVariant, 'minijit'), eq(parameters.runtimeVariant, 'monointerpreter'))) }}:
- ${{ if eq(parameters.runtimeVariant, 'llvmfullaot') }}:
- ${{ format('{0}_llvmaot_product_build_{1}{2}_{3}_{4}', parameters.runtimeFlavor, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
- - ${{ if not(eq(parameters.runtimeVariant, 'llvmfullaot')) }}:
+ - ${{ if ne(parameters.runtimeVariant, 'llvmfullaot') }}:
- ${{ format('{0}_{1}_product_build_{2}{3}_{4}_{5}', parameters.runtimeFlavor, parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
- ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}:
- ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }}
@@ -109,7 +109,7 @@ jobs:
- name: runtimeVariantArg
value: ''
- - ${{ if not(eq(parameters.runtimeVariant, '')) }}:
+ - ${{ if ne(parameters.runtimeVariant, '') }}:
- name: runtimeVariantArg
value: '/p:RuntimeVariant=${{ parameters.runtimeVariant }}'
@@ -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-
@@ -546,6 +546,7 @@ jobs:
- jitosr
- jitosr_stress
- jitosr_pgo
+ - jitosr_stress_random
- jitpartialcompilation
- jitpartialcompilation_osr
- jitpartialcompilation_osr_pgo
diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml
index d6b84f837c3276..6e378369aa4fc6 100644
--- a/eng/pipelines/common/variables.yml
+++ b/eng/pipelines/common/variables.yml
@@ -11,19 +11,17 @@ variables:
- name: isOfficialBuild
value: ${{ and(ne(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}
-- name: isFullMatrix
+- name: isRollingBuild
value: ${{ and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}
-- name: isNotFullMatrix
- value: ${{ and(eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}
-- name: isNotManualAndIsPR
- value: ${{ and(not(in(variables['Build.DefinitionName'], 'runtime-staging-manual', 'runtime-manual')), eq(variables['System.TeamProject'], 'public'), eq(variables['Build.Reason'], 'PullRequest')) }}
-- name: isManualOrIsNotPR
- value: ${{ or(in(variables['Build.DefinitionName'], 'runtime-staging-manual', 'runtime-manual'), and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest'))) }}
+- name: isExtraPlatformsBuild
+ value: ${{ eq(variables['Build.DefinitionName'], 'runtime-extra-platforms') }}
+- name: isNotExtraPlatformsBuild
+ value: ${{ ne(variables['Build.DefinitionName'], 'runtime-extra-platforms') }}
# We only run evaluate paths on runtime, runtime-staging and runtime-community pipelines on PRs
# keep in sync with /eng/pipelines/common/xplat-setup.yml
- name: dependOnEvaluatePaths
- value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }}
+ value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community', 'runtime-extra-platforms')) }}
- name: debugOnPrReleaseOnRolling
${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
value: Release
diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml
index 05a6bc7c4a63c4..e397bcdd456a60 100644
--- a/eng/pipelines/common/xplat-setup.yml
+++ b/eng/pipelines/common/xplat-setup.yml
@@ -22,8 +22,7 @@ jobs:
shouldContinueOnError: ${{ and(endsWith(variables['Build.DefinitionName'], 'staging'), eq(variables['Build.Reason'], 'PullRequest')) }}
# keep in sync with /eng/pipelines/common/variables.yml
- nonPRBuild: ${{ and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }}
- dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }}
+ dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community', 'runtime-extra-platforms')) }}
variables:
# Disable component governance in our CI builds. These builds are not shipping nor
@@ -50,8 +49,12 @@ jobs:
value: $(buildConfigUpper)
- name: _runSmokeTestsOnlyArg
- value: '/p:RunSmokeTestsOnly=$(isNotManualAndIsPR)'
- - ${{ if or(eq(parameters.osGroup, 'windows'), eq(parameters.hostedOs, 'windows')) }}:
+ value: '/p:RunSmokeTestsOnly=$(isNotExtraPlatformsBuild)'
+
+ - name: _hostedOs
+ value: ${{ parameters.jobParameters.hostedOs }}
+
+ - ${{ if or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')) }}:
- name: archiveExtension
value: '.zip'
- name: archiveType
@@ -69,7 +72,7 @@ jobs:
- name: logRootNameArg
value: 'log '
- - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.hostedOs, 'windows')) }}:
+ - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.jobParameters.hostedOs, 'windows')) }}:
- name: archiveExtension
value: '.tar.gz'
- name: archiveType
@@ -117,12 +120,12 @@ jobs:
${{ if eq(parameters.jobParameters.pool, '') }}:
pool:
# Public Linux Build Pool
- ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}:
+ ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}:
name: NetCore1ESPool-Public
demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open
# Official Build Linux Pool
- ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}:
+ ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.jobParameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}:
name: NetCore1ESPool-Internal
demands: ImageOverride -equals Build.Ubuntu.1804.Amd64
@@ -136,7 +139,7 @@ jobs:
demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019
# Public Windows Build Pool
- ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}:
+ ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.jobParameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}:
name: NetCore1ESPool-Public
demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Open
diff --git a/eng/pipelines/coreclr/templates/build-jit-job.yml b/eng/pipelines/coreclr/templates/build-jit-job.yml
index c251c06f286793..b5ff3df213af30 100644
--- a/eng/pipelines/coreclr/templates/build-jit-job.yml
+++ b/eng/pipelines/coreclr/templates/build-jit-job.yml
@@ -107,10 +107,10 @@ jobs:
# Build CoreCLR JIT
- ${{ if ne(parameters.osGroup, 'windows') }}:
- - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) -ci $(compilerArg) -component alljits
+ - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) -ci $(compilerArg) -component alljits -component spmi
displayName: Build CoreCLR JIT
- ${{ if eq(parameters.osGroup, 'windows') }}:
- - script: set __TestIntermediateDir=int&&$(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) -ci -component alljits
+ - script: set __TestIntermediateDir=int&&$(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) -ci -component alljits -component spmi
displayName: Build CoreCLR JIT
- ${{ if eq(parameters.uploadAs, 'azureBlob') }}:
@@ -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 b89cd621eda1ee..9048e8ed4fe8a2 100644
--- a/eng/pipelines/coreclr/templates/build-job.yml
+++ b/eng/pipelines/coreclr/templates/build-job.yml
@@ -132,10 +132,10 @@ jobs:
value: ''
- ${{ if ne(parameters.testGroup, 'innerloop') }}:
- name: clrRuntimeComponentsBuildArg
- value: '-component runtime -component alljits -component paltests -component nativeaot '
+ value: '-component runtime -component alljits -component paltests -component nativeaot -component spmi '
- ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.archType, 'x86')) }}:
- name: clrRuntimeComponentsBuildArg
- value: '-component runtime -component jit -component iltools '
+ value: '-component runtime -component jit -component iltools -component spmi '
- name: pgoInstrumentArg
value: ''
@@ -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/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index 1a5a3467587025..0b2e6f7f80ed2a 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -21,6 +21,7 @@ jobs:
archType: ${{ parameters.archType }}
container: ${{ parameters.container }}
pool: ${{ parameters.pool }}
+ platform: ${{ parameters.platform }}
shouldContinueOnError: ${{ parameters.shouldContinueOnError }}
dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths}}
runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }}
diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml
index dd1ff0ebd3b242..627d42fd7add18 100644
--- a/eng/pipelines/coreclr/templates/perf-job.yml
+++ b/eng/pipelines/coreclr/templates/perf-job.yml
@@ -57,7 +57,7 @@ jobs:
- ${{ if and(eq(parameters.runtimeType, 'mono'), ne(parameters.codeGenType, 'AOT')) }}:
- ${{ format('mono_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
- ${{ if eq(parameters.runtimeType, 'wasm')}}:
- - ${{ format('build_{0}{1}_{2}_{3}_{4}', 'Browser', '', 'wasm', parameters.buildConfig, parameters.runtimeType) }}
+ - ${{ format('build_{0}{1}_{2}_{3}_{4}_{5}', 'Browser', '', 'wasm', 'Linux', parameters.buildConfig, parameters.runtimeType) }}
- ${{ if and(eq(parameters.codeGenType, 'AOT'), ne(parameters.runtimeType, 'wasm'))}}:
- ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.codeGenType) }}
- ${{ if eq(parameters.runtimeType, 'AndroidMono')}}:
diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index ac074ab9903f8f..f82e09c9e0a124 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -21,6 +21,7 @@ jobs:
archType: ${{ parameters.archType }}
container: ${{ parameters.container }}
pool: ${{ parameters.pool }}
+ platform: ${{ parameters.platform }}
shouldContinueOnError: ${{ parameters.shouldContinueOnError }}
dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths}}
runtimeFlavorDisplayName: ${{ parameters.runtimeFlavorDisplayName }}
@@ -28,26 +29,31 @@ jobs:
# Linux arm
- ${{ if eq(parameters.platform, 'Linux_arm') }}:
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (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 eq(parameters.jobParameters.isFullMatrix, true) }}:
- - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-20210106155927-56c6673
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Ubuntu.2110.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-arm64v8-20211116135000-0f8d97e
- - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}:
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-20210106155927-56c6673
# Linux musl x64
- ${{ if eq(parameters.platform, 'Linux_musl_x64') }}:
- - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
+ - (Alpine.314.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- (Alpine.313.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-amd64-20210910135845-8a6f4f3
# Linux musl arm64
- - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), eq(parameters.jobParameters.isFullMatrix, true)) }}:
+ - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true))) }}:
- (Alpine.313.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm64v8-20210910135808-8a6f4f3
- (Alpine.314.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3
@@ -62,21 +68,16 @@ jobs:
- (Ubuntu.2110.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-amd64-20211116135132-0f8d97e
- (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006
- ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
- - (Centos.7.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af
- - (Centos.8.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759
- - RedHat.7.Amd64.Open
- - Ubuntu.1804.Amd64.Open
- - SLES.12.Amd64.Open
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
+ - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759
- SLES.15.Amd64.Open
- - (Fedora.34.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125
- - (Ubuntu.2110.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.10-helix-amd64-20211116135132-0f8d97e
- - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673
+ - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125
+ - (Ubuntu.2110.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-21.04-helix-amd64-20210922170909-34a2d72
- (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20210304164428-5a7c380
- - (Mariner.1.0.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620
- - (openSUSE.15.2.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20211018152525-9cc02fe
- - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}:
- - (Centos.7.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af
+ - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620
+ - (openSUSE.15.2.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:opensuse-15.2-helix-amd64-20211018152525-9cc02fe
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
+ - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af
- RedHat.7.Amd64.Open
- (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673
- Ubuntu.1804.Amd64.Open
@@ -94,10 +95,9 @@ jobs:
# OSX x64
- ${{ if eq(parameters.platform, 'OSX_x64') }}:
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- OSX.1014.Amd64.Open
- - OSX.1015.Amd64.Open
- - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}:
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- OSX.1015.Amd64.Open
# Android
@@ -126,18 +126,18 @@ jobs:
- ${{ if eq(parameters.platform, 'windows_x64') }}:
# netcoreapp
- ${{ if notIn(parameters.jobParameters.framework, 'net48') }}:
+ # libraries on mono outerloop
- ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- Windows.81.Amd64.Open
- Windows.10.Amd64.Server19H1.Open
+ # libraries on coreclr (outerloop and innerloop), or libraries on mono innerloop
- ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
- - Windows.81.Amd64.Open
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- Windows.10.Amd64.ServerRS5.Open
- - Windows.10.Amd64.Server19H1.Open
- - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}:
- - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504
+ - ${{ if ne(parameters.jobParameters.testScope, 'outerloop') }}:
+ - Windows.10.Amd64.Server19H1.Open
- (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c
- - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}:
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- Windows.81.Amd64.Open
- Windows.10.Amd64.Server19H1.ES.Open
- Windows.11.Amd64.ClientPre.Open
@@ -154,20 +154,18 @@ jobs:
- ${{ if eq(parameters.platform, 'windows_x86') }}:
# netcoreapp
- ${{ if notIn(parameters.jobParameters.framework, 'net48') }}:
+ # mono outerloop
- ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- Windows.7.Amd64.Open
- Windows.10.Amd64.ServerRS5.Open
+ # libraries on coreclr (outerloop and innerloop), or libraries on mono innerloop
- ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}:
- - Windows.7.Amd64.Open
+ - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- Windows.10.Amd64.ServerRS5.Open
- Windows.10.Amd64.Server19H1.Open
- - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}:
- - ${{ if eq(parameters.jobParameters.buildConfig, 'Release') }}:
- - Windows.10.Amd64.Server19H1.ES.Open
- - ${{ if eq(parameters.jobParameters.buildConfig, 'Debug') }}:
- - Windows.7.Amd64.Open
- - Windows.10.Amd64.Server19H1.Open
+ - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
+ - Windows.10.Amd64.Server19H1.ES.Open
+ - Windows.7.Amd64.Open
# .NETFramework
- ${{ if eq(parameters.jobParameters.framework, 'net48') }}:
diff --git a/eng/pipelines/libraries/outerloop-mono.yml b/eng/pipelines/libraries/outerloop-mono.yml
index 1267cf72a62dea..17a7101e26004a 100644
--- a/eng/pipelines/libraries/outerloop-mono.yml
+++ b/eng/pipelines/libraries/outerloop-mono.yml
@@ -23,7 +23,7 @@ jobs:
platforms:
- windows_x86
- Browser_wasm
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- windows_x64
- Linux_x64
- Linux_arm
@@ -34,7 +34,7 @@ jobs:
nameSuffix: AllSubsets_Mono
buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true
timeoutInMinutes: 180
- isFullMatrix: ${{ variables['isFullMatrix'] }}
+ includeAllPlatforms: ${{ variables['isRollingBuild'] }}
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -44,7 +44,7 @@ jobs:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- - ${{ if eq(variables['isFullMatrix'], false) }}:
+ - ${{ if eq(variables['isRollingBuild'], false) }}:
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
@@ -61,7 +61,7 @@ jobs:
nameSuffix: AllSubsets_Mono
buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) -testscope outerloop /p:ArchiveTests=true
timeoutInMinutes: 180
- isFullMatrix: ${{ variables['isFullMatrix'] }}
+ includeAllPlatforms: ${{ variables['isRollingBuild'] }}
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
diff --git a/eng/pipelines/libraries/outerloop.yml b/eng/pipelines/libraries/outerloop.yml
index 28932a0baff3ce..72c2de49363a25 100644
--- a/eng/pipelines/libraries/outerloop.yml
+++ b/eng/pipelines/libraries/outerloop.yml
@@ -27,7 +27,7 @@ jobs:
- ${{ if eq(variables['includeLinuxOuterloop'], true) }}:
- Linux_x64
- Linux_musl_x64
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- Linux_arm
- Linux_arm64
- Linux_musl_arm64
@@ -46,27 +46,27 @@ jobs:
platforms:
- ${{ if eq(variables['includeWindowsOuterloop'], true) }}:
- windows_x86
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- windows_x64
- ${{ if eq(variables['includeLinuxOuterloop'], true) }}:
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- Linux_x64
- Linux_arm
- Linux_arm64
- Linux_musl_x64
- Linux_musl_arm64
- - ${{ if and(eq(variables['includeOsxOuterloop'], true), eq(variables['isFullMatrix'], true)) }}:
+ - ${{ if and(eq(variables['includeOsxOuterloop'], true), eq(variables['isRollingBuild'], true)) }}:
- OSX_arm64
- OSX_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: ${{ variables['isOfficialBuild'] }}
- isFullMatrix: ${{ variables['isFullMatrix'] }}
+ includeAllPlatforms: ${{ variables['isRollingBuild'] }}
runTests: true
testScope: outerloop
liveRuntimeBuildConfig: release
- - ${{ if eq(variables['isFullMatrix'], false) }}:
+ - ${{ if eq(variables['isRollingBuild'], false) }}:
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/libraries/build-job.yml
@@ -83,7 +83,7 @@ jobs:
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: ${{ variables['isOfficialBuild'] }}
- isFullMatrix: ${{ variables['isFullMatrix'] }}
+ includeAllPlatforms: ${{ variables['isRollingBuild'] }}
runTests: true
testScope: outerloop
liveRuntimeBuildConfig: release
@@ -95,12 +95,12 @@ jobs:
buildConfig: Release
platforms:
- windows_x86
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- windows_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: ${{ variables['isOfficialBuild'] }}
- isFullMatrix: ${{ variables['isFullMatrix'] }}
+ includeAllPlatforms: ${{ variables['isRollingBuild'] }}
framework: net48
runTests: true
testScope: outerloop
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/libraries/variables.yml b/eng/pipelines/libraries/variables.yml
index 9bb89d7d493847..2abd5adabe2c9f 100644
--- a/eng/pipelines/libraries/variables.yml
+++ b/eng/pipelines/libraries/variables.yml
@@ -6,7 +6,7 @@ variables:
value: $(Build.SourcesDirectory)/src/libraries
- name: pipelinesPath
value: /eng/pipelines/libraries
- - name: isFullMatrix
+ - name: isRollingBuild
value: ${{ notIn(variables['Build.Reason'], 'PullRequest') }}
- name: includeWindowsOuterloop
value: ${{ or(endsWith(variables['Build.DefinitionName'], 'windows'), endsWith(variables['Build.DefinitionName'], 'outerloop')) }}
diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml
index 5bebcc00a2663e..f588ad52b0f330 100644
--- a/eng/pipelines/runtime-community.yml
+++ b/eng/pipelines/runtime-community.yml
@@ -46,7 +46,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -56,4 +56,4 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
diff --git a/eng/pipelines/runtime-manual.yml b/eng/pipelines/runtime-extra-platforms.yml
similarity index 59%
rename from eng/pipelines/runtime-manual.yml
rename to eng/pipelines/runtime-extra-platforms.yml
index 997849ed2b86c1..a0642f4ab521c7 100644
--- a/eng/pipelines/runtime-manual.yml
+++ b/eng/pipelines/runtime-extra-platforms.yml
@@ -1,295 +1,217 @@
+# This pipeline includes the platforms that we don't have resources to run on every PR but that we want
+# to still have test coverage, we run this pipeline on a schedule and also developers can run it
+# via /azp run command on PRs. This pipeline permits us to have the main runtime pipeline run the same
+# platforms in PRs and Scheduled builds.
+
+# Setting batch to true, triggers one build at a time.
+# if there is a push while a build in progress, it will wait,
+# until the running build finishes, and produce a build with all the changes
+# that happened during the last build.
trigger: none
+schedules:
+ - cron: "0 9,21 * * *" # run at 9:00 and 21:00 (UTC) which is 1:00 and 13:00 (PST).
+ displayName: Runtime extra main schedule
+ branches:
+ include:
+ - main
+ always: false # run only if there were changes since the last successful scheduled run.
+ - cron: "0 6,18 * * *" # run at 6:00 and 18:00 (UTC) which is 22:00 and 10:00 (PST).
+ displayName: Runtime extra release schedule
+ branches:
+ include:
+ - release/*
+ always: false # run only if there were changes since the last successful scheduled run.
+
variables:
- template: /eng/pipelines/common/variables.yml
jobs:
#
-# iOS/tvOS interp - requires AOT Compilation and Interp flags
-# Build the whole product using Mono and run libraries tests
+# Evaluate paths
#
-- 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:
- - iOSSimulator_x64
- - tvOSSimulator_x64
- - iOSSimulator_arm64
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true
- timeoutInMinutes: 180
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- interpreter: true
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+- ${{ if eq(variables.dependOnEvaluatePaths, true) }}:
+ - template: /eng/pipelines/common/evaluate-default-paths.yml
#
-# MacCatalyst interp - requires AOT Compilation and Interp flags
-# Build the whole product using Mono and run libraries tests
+# Build CoreCLR release
+# Always as they are needed by Installer and we always build and test the Installer.
#
- 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
+ jobTemplate: /eng/pipelines/coreclr/templates/build-job.yml
+ buildConfig: release
platforms:
- - MacCatalyst_x64
- # don't run tests on arm64 PRs until we can get significantly more devices
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - MacCatalyst_arm64
+ - Linux_x64
+ - Linux_arm
+ - Linux_arm64
+ - Linux_musl_x64
+ - OSX_x64
+ - windows_x64
+ - windows_x86
+ - windows_arm64
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true
- timeoutInMinutes: 180
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- interpreter: true
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
#
-# MacCatalyst interp - requires AOT Compilation and Interp flags
-# Build the whole product using Mono and run libraries tests
-# The test app is built with the App Sandbox entitlement
+# Build libraries using live CoreLib
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ jobTemplate: /eng/pipelines/libraries/build-job.yml
buildConfig: Release
- runtimeFlavor: mono
platforms:
- - MacCatalyst_x64
- # don't run tests on arm64 PRs until we can get significantly more devices
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - MacCatalyst_arm64
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono_AppSandbox
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true /p:EnableAppSandbox=true
- timeoutInMinutes: 180
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- interpreter: true
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ - Linux_x64
+ - Linux_arm
+ - Linux_arm64
+ - Linux_musl_x64
+ - OSX_x64
+ - windows_x64
+ - windows_x86
+ - windows_arm64
#
-# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size
-# Build the whole product using Mono and run libraries tests
+# Libraries Release Test Execution against a release coreclr runtime
+# Only when the PR contains a libraries change
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ jobTemplate: /eng/pipelines/libraries/run-test-job.yml
buildConfig: Release
- runtimeFlavor: mono
platforms:
- - iOS_arm64
- - tvOS_arm64
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true
- timeoutInMinutes: 180
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:NeedsToBuildAppsOnHelix=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
+ - Linux_x64
+ - Linux_arm
+ - Linux_arm64
+ - Linux_musl_x64
+ - OSX_x64
+ - windows_x64
+ - windows_x86
+ - windows_arm64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: Release
- runtimeFlavor: mono
- platforms:
- - Android_x86
- - Android_x64
jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg)
- timeoutInMinutes: 180
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ isOfficialBuild: false
+ isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
+ testScope: innerloop
+ liveRuntimeBuildConfig: release
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+# Run net48 tests on win-x64
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ jobTemplate: /eng/pipelines/libraries/build-job.yml
buildConfig: Release
- runtimeFlavor: mono
platforms:
- - Android_arm
- - Android_arm64
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg)
- timeoutInMinutes: 180
- # 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 libraries tests
-#
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
+ - windows_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: Release
- runtimeFlavor: mono
- platforms:
- - Windows_x64
jobParameters:
+ framework: net48
+ runTests: true
testScope: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true
- timeoutInMinutes: 120
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+
+#### MONO LEGS
#
-# Build the whole product using Mono for Android and run runtime tests with interpreter
+# 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/coreclr/templates/helix-queues-setup.yml
+ helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Android_x64
+ # BuildWasmApps should only happen on the extra platforms build as we already have coverage for this build on PRs.
+ - Browser_wasm
+ - Browser_wasm_win
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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
+ # map dependencies variables to local variables
+ - name: wasmbuildtestsContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ]
jobParameters:
+ isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests_Interp
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
- runtimeVariant: monointerpreter
+ 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: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
- extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ testRunNamePrefixSuffix: Mono_$(_BuildConfig)_$(_hostedOs)
+ extraHelixArguments: /p:BrowserHost=$(_hostedOs)
+ scenarios:
+ - buildwasmapps
+ condition: >-
+ or(
+ eq(variables['wasmbuildtestsContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
-# Build the whole product using Mono and run runtime tests with the JIT.
+# 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/coreclr/templates/helix-queues-setup.yml
- buildConfig: Release
+ helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ buildConfig: release
runtimeFlavor: mono
platforms:
- - iOSSimulator_x64
+ - Browser_wasm_win
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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
+ # map dependencies variables to local variables
+ - name: librariesContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
+ - name: monoContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
+ 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),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
- extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
-
-#
-# Build the whole product using Mono for Android and run runtime tests with Android devices
-#
-- 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:
- - Android_arm64
- 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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
- # don't run tests on PRs until we can get significantly more devices
- # Turn off the testing for now, until https://github.com/dotnet/xharness/issues/663 gets resolved
- # ${{ if eq(variables['isFullMatrix'], true) }}:
- # # extra steps, run tests
- # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
- # extraStepsParameters:
- # creator: dotnet-bot
- # testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ 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 Browser_wasm, on windows, run console and browser tests
+# Build for Browser/wasm, with EnableAggressiveTrimming=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
+ buildConfig: Release
runtimeFlavor: mono
platforms:
- - Browser_wasm_win
+ - Browser_wasm
variables:
# map dependencies variables to local variables
- name: librariesContainsChange
@@ -297,78 +219,86 @@ jobs:
- name: monoContainsChange
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
+ isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
testGroup: innerloop
- nameSuffix: Windows_wasm
- buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows
+ 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: >-
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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows
+ extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg)
scenarios:
- normal
- - WasmTestOnBrowser
- - WasmTestOnNodeJs
condition: >-
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], 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
+ buildConfig: Release
runtimeFlavor: mono
platforms:
+ - Browser_wasm
- Browser_wasm_win
variables:
# map dependencies variables to local variables
- - name: wasmbuildtestsContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ]
+ - 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: Windows_wasm_WBT
- buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:TestWasmBuildTests=true /p:TestAssemblies=false
+ 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_wasmbuildtests.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ 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))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows
+ testRunNamePrefixSuffix: Mono_AOT_$(_BuildConfig)_$(_hostedOs)
+ extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) /p:BrowserHost=$(_hostedOs)
scenarios:
- - buildwasmapps
+ - normal
condition: >-
or(
- eq(variables['wasmbuildtestsContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['librariesContainsChange'], true),
+ 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
+ buildConfig: Release
runtimeFlavor: mono
platforms:
- - Browser_wasm_win
+ - Windows_x64
variables:
# map dependencies variables to local variables
- name: librariesContainsChange
@@ -376,34 +306,30 @@ jobs:
- name: monoContainsChange
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
- testGroup: innerloop
- nameSuffix: Windows_wasm_AOT
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg)
- timeoutInMinutes: 180
+ testScope: innerloop
+ nameSuffix: AllSubsets_Mono
+ buildArgs: -s mono+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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg)
- scenarios:
- - normal
condition: >-
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
-# Build for Browser/wasm, with EnableAggressiveTrimming=true
+# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size
+# Build the whole product using Mono and run libraries tests
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -412,7 +338,8 @@ jobs:
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Browser_wasm
+ - iOS_arm64
+ - tvOS_arm64
variables:
# map dependencies variables to local variables
- name: librariesContainsChange
@@ -421,21 +348,26 @@ jobs:
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_EAT
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=false /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=false
+ nameSuffix: AllSubsets_Mono
+ buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true
timeoutInMinutes: 180
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true /p:RunSmokeTestsOnly=false
- scenarios:
- - normal
+ extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
+ 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
@@ -443,7 +375,8 @@ jobs:
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Browser_wasm
+ - Android_arm
+ - Android_arm64
variables:
# map dependencies variables to local variables
- name: librariesContainsChange
@@ -452,17 +385,24 @@ jobs:
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_AOT
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=false /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true
+ nameSuffix: AllSubsets_Mono
+ buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg)
timeoutInMinutes: 180
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true /p:RunSmokeTestsOnly=false
- scenarios:
- - normal
+ condition: >-
+ or(
+ eq(variables['librariesContainsChange'], true),
+ eq(variables['monoContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
# Build for Browser/wasm and test it on v8, browser, and nodejs
@@ -477,8 +417,6 @@ jobs:
- Browser_wasm
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:
@@ -488,8 +426,8 @@ jobs:
timeoutInMinutes: 180
condition: >-
or(
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -501,44 +439,46 @@ jobs:
- WasmTestOnNodeJs
condition: >-
or(
- eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run runtime tests
+# Build Mono release
+# Only when libraries, mono, or the runtime tests changed
+# Currently only these architectures are needed for the runtime tests.
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/mono/templates/build-job.yml
+ runtimeFlavor: mono
+ buildConfig: release
+ platforms:
+ - Linux_arm64
+ jobParameters:
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+
#
+# Mono Test builds with CoreCLR runtime tests using live libraries debug build
+# Only when Mono is changed
- 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
+ jobTemplate: /eng/pipelines/common/templates/runtimes/build-test-job.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
+ - CoreClrTestBuildHost # Either OSX_x64 or Linux_x64
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 180
- # NOTE: Per PR test execution is not recommended for mobile runtime tests
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/common/templates/runtimes/wasm-runtime-and-send-to-helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# Wasm debugger tests
- template: /eng/pipelines/common/platform-matrix.yml
@@ -561,8 +501,7 @@ jobs:
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -586,14 +525,13 @@ 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: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -630,9 +568,100 @@ jobs:
nameSuffix: AllSubsets_Mono_RuntimeTests
buildArgs: -s mono+libs -c $(_BuildConfig)
timeoutInMinutes: 240
- # NOTE: Per PR test execution is not recommended for mobile runtime tests
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+
+#
+# Build the whole product using Mono for Android and run runtime tests with interpreter
+#
+- 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:
+ - Android_x64
+ 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: 60
+ - name: timeoutPerTestCollectionInMinutes
+ value: 180
+ jobParameters:
+ testGroup: innerloop
+ nameSuffix: AllSubsets_Mono_RuntimeTests_Interp
+ buildArgs: -s mono+libs -c $(_BuildConfig)
+ timeoutInMinutes: 240
+ runtimeVariant: monointerpreter
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+ # NOTE: Per PR test execution is not recommended for runtime tests
+ ${{ if eq(variables['isRollingBuild'], true) }}:
+ # extra steps, run tests
+ extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ extraStepsParameters:
+ creator: dotnet-bot
+ testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+
+#
+# Mono CoreCLR runtime Test executions using live libraries in jit mode
+# Only when Mono is changed
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/templates/runtimes/run-test-job.yml
+ buildConfig: release
+ runtimeFlavor: mono
+ platforms:
+ - Linux_arm64
+ helixQueueGroup: pr
+ helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
+ jobParameters:
+ testGroup: innerloop
+ liveLibrariesBuildConfig: Release
+ liveRuntimeBuildConfig: release
+ runtimeVariant: minijit
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+
+#
+# Mono CoreCLR runtime Test executions using live libraries in interpreter mode
+# Only when Mono is changed
+- template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/templates/runtimes/run-test-job.yml
+ buildConfig: release
+ runtimeFlavor: mono
+ platforms:
+ - Linux_arm64
+ helixQueueGroup: pr
+ helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
+ jobParameters:
+ testGroup: innerloop
+ liveLibrariesBuildConfig: Release
+ liveRuntimeBuildConfig: release
+ runtimeVariant: monointerpreter
+ condition: >-
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml
index 34b0ae68c78e25..1ad7ad72d31716 100644
--- a/eng/pipelines/runtime-official.yml
+++ b/eng/pipelines/runtime-official.yml
@@ -416,7 +416,7 @@ stages:
- Build_Android_arm64_release_AllSubsets_Mono
- Build_Android_x86_release_AllSubsets_Mono
- Build_Android_x64_release_AllSubsets_Mono
- - Build_Browser_wasm_release_AllSubsets_Mono
+ - Build_Browser_wasm_Linux_release_AllSubsets_Mono
- Build_iOS_arm_release_AllSubsets_Mono
- Build_iOS_arm64_release_AllSubsets_Mono
- Build_iOSSimulator_x64_release_AllSubsets_Mono
diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml
index 4288d372433df7..c51d639d29f0f2 100644
--- a/eng/pipelines/runtime-staging.yml
+++ b/eng/pipelines/runtime-staging.yml
@@ -75,7 +75,7 @@ jobs:
- iOSSimulator_x64
- tvOSSimulator_x64
# don't run tests on arm64 PRs until we can get significantly more devices
- - ${{ if eq(variables['isManualOrIsNotPR'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- iOSSimulator_arm64
variables:
# map dependencies variables to local variables
@@ -93,8 +93,7 @@ jobs:
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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -105,8 +104,7 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# MacCatalyst interp - requires AOT Compilation and Interp flags
@@ -121,7 +119,7 @@ jobs:
platforms:
- MacCatalyst_x64
# don't run tests on arm64 PRs until we can get significantly more devices
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- MacCatalyst_arm64
variables:
# map dependencies variables to local variables
@@ -139,8 +137,7 @@ jobs:
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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -149,10 +146,9 @@ jobs:
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
condition: >-
or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['librariesContainsChange'], true),
+ eq(variables['monoContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
# MacCatalyst interp - requires AOT Compilation and Interp flags
@@ -168,7 +164,7 @@ jobs:
platforms:
- MacCatalyst_x64
# don't run tests on arm64 PRs until we can get significantly more devices
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- MacCatalyst_arm64
variables:
# map dependencies variables to local variables
@@ -185,8 +181,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -195,53 +190,9 @@ jobs:
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
condition: >-
or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isFullMatrix'], true))
-
-#
-# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size
-# 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:
- - iOS_arm64
- - tvOS_arm64
- variables:
- # map dependencies variables to local variables
- - name: librariesContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
- - name: monoContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:NeedsToBuildAppsOnHelix=true
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['librariesContainsChange'], true),
+ eq(variables['monoContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run libraries tests
@@ -271,8 +222,7 @@ jobs:
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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -282,47 +232,7 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], 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:
- - Android_arm
- - Android_arm64
- variables:
- # map dependencies variables to local variables
- - name: librariesContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
- - name: monoContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg)
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run libraries tests
@@ -334,7 +244,7 @@ jobs:
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Windows_x64
+ - Linux_armv6
variables:
# map dependencies variables to local variables
- name: librariesContainsChange
@@ -344,65 +254,17 @@ jobs:
jobParameters:
testScope: innerloop
nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true
+ 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['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
-
-#
-# Build the whole product using Mono for Android and run runtime tests with interpreter
-#
-- 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:
- - Android_x64
- 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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
- jobParameters:
- testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests_Interp
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
- runtimeVariant: monointerpreter
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- # NOTE: Per PR test execution is not recommended for runtime tests
- ${{ if eq(variables['isManualOrIsNotPR'], true) }}:
+ eq(variables['isRollingBuild'], true))
+ ${{ if eq(variables['isRollingBuild'], true) }}:
# extra steps, run tests
- extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
@@ -438,9 +300,8 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- ${{ if eq(variables['isManualOrIsNotPR'], true) }}:
+ eq(variables['isRollingBuild'], true))
+ ${{ if eq(variables['isRollingBuild'], true) }}:
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
extraStepsParameters:
@@ -448,46 +309,38 @@ jobs:
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
#
-# Build the whole product using Mono for Android and run runtime tests with Android devices
+# 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/coreclr/templates/helix-queues-setup.yml
+ helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Android_arm64
+ - Browser_wasm_win
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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
+ # map dependencies variables to local variables
+ - name: wasmbuildtestsContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ]
jobParameters:
+ isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
+ 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: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
- # don't run tests on PRs until we can get significantly more devices
- # Turn off the testing for now, until https://github.com/dotnet/runtime/issues/60128 gets resolved
- # ${{ if eq(variables['isFullMatrix'], true) }}:
- # # extra steps, run tests
- # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
- # extraStepsParameters:
- # creator: dotnet-bot
- # testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ 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
@@ -508,41 +361,37 @@ jobs:
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: Windows_wasm
- buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows $(_runSmokeTestsOnlyArg)
+ 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),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], 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_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows $(_runSmokeTestsOnlyArg)
+ testRunNamePrefixSuffix: Windows_wasm_$(_BuildConfig)
+ extraHelixArguments: /p:BrowserHost=windows
scenarios:
- normal
- - WasmTestOnBrowser
+ - wasmtestonbrowser
condition: >-
or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['librariesContainsChange'], true),
+ eq(variables['monoContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
-# Build Browser_wasm, on windows, and run tests with AOT
+# Build for Browser/wasm with RunAOTCompilation=true
#
-# Disabled due to https://github.com/dotnet/runtime/issues/61721
- 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
+ buildConfig: Release
runtimeFlavor: mono
platforms:
- Browser_wasm_win
@@ -553,55 +402,49 @@ jobs:
- name: monoContainsChange
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
+ isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
testGroup: innerloop
- nameSuffix: Windows_wasm_AOT
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:EnableAggressiveTrimming=true /p:BuildAOTTestsOnHelix=true /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg)
+ 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),
- eq(variables['isFullMatrix'], 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_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg)
+ 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),
- eq(variables['isFullMatrix'], true))
+ eq(variables['monoContainsChange'], true))
-#
-# Build Browser_wasm, on windows, and run Wasm.Build.Tests
-#
+# 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
+ 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'] ]
+ - name: wasmdebuggertestsContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: Windows_wasm_WBT
- buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows /p:TestWasmBuildTests=true /p:TestAssemblies=false
+ 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: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true)
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -609,12 +452,7 @@ jobs:
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
extraHelixArguments: /p:BrowserHost=windows
scenarios:
- - buildwasmapps
- condition: >-
- or(
- eq(variables['wasmbuildtestsContainsChange'], true),
- eq(variables['isManualOrIsNotPR'], true),
- eq(variables['isFullMatrix'], true))
+ - wasmdebuggertests
# Wasm debugger tests
- template: /eng/pipelines/common/platform-matrix.yml
@@ -635,9 +473,7 @@ jobs:
buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false
timeoutInMinutes: 180
condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true)
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -646,36 +482,46 @@ jobs:
scenarios:
- wasmdebuggertests
-# Wasm debugger tests - windows
+#
+# Build the whole product using Mono for Android and run runtime tests with Android devices
+#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
+ helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
buildConfig: Release
runtimeFlavor: mono
platforms:
- - Browser_wasm_win
+ - Android_arm64
variables:
- # map dependencies variables to local variables
- - name: wasmdebuggertestsContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ]
+ - ${{ 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: 60
+ - name: timeoutPerTestCollectionInMinutes
+ value: 180
jobParameters:
testGroup: innerloop
- nameSuffix: Windows_wasm_DebuggerTests
- buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows
- timeoutInMinutes: 180
+ nameSuffix: AllSubsets_Mono_RuntimeTests
+ buildArgs: -s mono+libs -c $(_BuildConfig)
+ timeoutInMinutes: 240
condition: >-
or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows
- scenarios:
- - wasmdebuggertests
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+ # don't run tests on PRs until we can get significantly more devices
+ # Turn off the testing for now, until https://github.com/dotnet/runtime/issues/60128 gets resolved
+ # ${{ if eq(variables['isRollingBuild'], true) }}:
+ # # extra steps, run tests
+ # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ # extraStepsParameters:
+ # creator: dotnet-bot
+ # testRunNamePrefixSuffix: Mono_$(_BuildConfig)
#
# CoreCLR Build for running Apple Silicon libraries-innerloop
@@ -685,7 +531,7 @@ jobs:
jobTemplate: /eng/pipelines/coreclr/templates/build-job.yml
buildConfig: release
platforms:
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- OSX_arm64
jobParameters:
testGroup: innerloop
@@ -697,12 +543,11 @@ jobs:
jobTemplate: /eng/pipelines/libraries/build-job.yml
buildConfig: Release
platforms:
- - ${{ if eq(variables['isFullMatrix'], true) }}:
+ - ${{ if eq(variables['isRollingBuild'], true) }}:
- OSX_arm64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: ${{ variables['isOfficialBuild'] }}
- isFullMatrix: ${{ variables['isFullMatrix'] }}
runTests: true
testScope: innerloop
liveRuntimeBuildConfig: release
diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml
index 5d7f3ffde2f81b..9d3bbfe477d8e0 100644
--- a/eng/pipelines/runtime.yml
+++ b/eng/pipelines/runtime.yml
@@ -91,7 +91,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using GNU compiler toolchain
@@ -114,7 +114,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build CoreCLR OSX_x64 checked
@@ -133,7 +133,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build CoreCLR release
@@ -178,7 +178,7 @@ jobs:
#
# Build CoreCLR Formatting Job
# Only when CoreCLR is changed, and only in the 'main' branch (no release branches;
-# both CI and PR builds).
+# both Rolling and PR builds).
#
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -194,7 +194,7 @@ jobs:
eq(variables['System.PullRequest.TargetBranch'], 'main')),
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr_jit.containsChange'], true),
- eq(variables['isFullMatrix'], true)))
+ eq(variables['isRollingBuild'], true)))
#
# CoreCLR NativeAOT debug build and smoke tests
@@ -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(
@@ -277,7 +277,7 @@ jobs:
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# Build Mono AOT offset headers once, for consumption elsewhere
# Only when mono changed
@@ -297,7 +297,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# Build the whole product using Mono runtime
# Only when libraries, mono or installer are changed
@@ -323,7 +323,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -343,7 +343,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run libraries tests, multi-scenario
@@ -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: >-
@@ -372,7 +372,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -385,7 +385,7 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests
@@ -404,13 +404,13 @@ 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: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -420,8 +420,8 @@ jobs:
- buildwasmapps
condition: >-
or(
- eq(variables['wasmbuildtestsContainsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['wasmbuildtestsContainsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
# Build for Browser/wasm, with EnableAggressiveTrimming=true
@@ -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: >-
@@ -450,7 +450,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -463,7 +463,7 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build for Browser/wasm with RunAOTCompilation=true
@@ -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: >-
@@ -492,7 +492,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -505,29 +505,7 @@ jobs:
or(
eq(variables['librariesContainsChange'], true),
eq(variables['monoContainsChange'], true),
- eq(variables['isFullMatrix'], true))
-
-# Build and test libraries under single-file publishing
-- 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
- platforms:
- - windows_x64
- - Linux_x64
- jobParameters:
- testGroup: innerloop
- isFullMatrix: ${{ variables.isFullMatrix }}
- isSingleFile: true
- nameSuffix: SingleFile
- buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) /p:TestSingleFile=true /p:ArchiveTests=true
- timeoutInMinutes: 120
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: SingleFile_$(_BuildConfig)
+ eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run runtime tests
@@ -557,49 +535,35 @@ jobs:
buildArgs: -s mono+libs -c $(_BuildConfig)
timeoutInMinutes: 180
condition: >-
- eq(variables['isFullMatrix'], true)
- # NOTE: Per PR test execution is not recommended for mobile runtime tests
- # extra steps, run tests
+ 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 for Android and run runtime tests with Android emulator
-#
+# Build and test libraries under single-file publishing
- 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
+ helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
buildConfig: Release
- runtimeFlavor: mono
platforms:
- - Android_x64
- 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: 60
- - name: timeoutPerTestCollectionInMinutes
- value: 180
+ - windows_x64
+ - Linux_x64
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono_RuntimeTests
- buildArgs: -s mono+libs -c $(_BuildConfig)
- timeoutInMinutes: 240
- condition: >-
- eq(variables['isFullMatrix'], true)
- # NOTE: Per PR test execution is not recommended for mobile runtime tests
+ isSingleFile: true
+ nameSuffix: SingleFile
+ buildArgs: -s clr+libs+libs.tests -c $(_BuildConfig) /p:TestSingleFile=true /p:ArchiveTests=true
+ timeoutInMinutes: 120
# extra steps, run tests
- extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml
+ extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ testRunNamePrefixSuffix: SingleFile_$(_BuildConfig)
#
# Build Mono and Installer on LLVMJIT mode
@@ -621,7 +585,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -641,7 +605,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono and Installer on LLVMAOT mode
@@ -664,7 +628,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -683,7 +647,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono debug
@@ -709,7 +673,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono release AOT cross-compilers
@@ -740,7 +704,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -767,7 +731,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono release
@@ -790,7 +754,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono release
@@ -810,7 +774,7 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build Mono release with LLVM AOT
@@ -830,7 +794,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Build libraries using live CoreLib
@@ -849,8 +813,6 @@ jobs:
- windows_arm
- windows_arm64
- windows_x86
- jobParameters:
- liveRuntimeBuildConfig: release
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -864,9 +826,12 @@ jobs:
- OSX_x64
- windows_x64
- FreeBSD_x64
+ - ${{ if eq(variables['isRollingBuild'], false) }}:
+ # we need to build windows_x86 for debug on PRs in order to test
+ # against a checked runtime when the PR contains coreclr changes
+ - windows_x86
jobParameters:
testScope: innerloop
- liveRuntimeBuildConfig: release
#
# Libraries Build that only run when coreclr is changed
@@ -874,7 +839,7 @@ jobs:
# and those are already built above
#
-- ${{ if eq(variables['isFullMatrix'], false) }}:
+- ${{ if eq(variables['isRollingBuild'], false) }}:
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/libraries/build-job.yml
@@ -884,45 +849,24 @@ jobs:
- Linux_musl_arm
- Linux_musl_arm64
jobParameters:
- liveRuntimeBuildConfig: release
condition: >-
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true)
-#
-# Libraries Build that only run when libraries is changed
-#
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/libraries/build-job.yml
- buildConfig: ${{ variables.debugOnPrReleaseOnRolling }}
- platforms:
- - ${{ if eq(variables['isFullMatrix'], false) }}:
- - windows_x86
- jobParameters:
- liveRuntimeBuildConfig: release
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
-
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/libraries/build-job.yml
buildConfig: Release
platforms:
- windows_x86
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - windows_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
- isFullMatrix: ${{ variables.isFullMatrix }}
framework: net48
runTests: true
testScope: innerloop
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -931,14 +875,13 @@ jobs:
platforms:
- windows_x64
jobParameters:
- isFullMatrix: ${{ variables.isFullMatrix }}
framework: allConfigurations
runTests: true
useHelix: false
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Installer Build and Test
@@ -1006,7 +949,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# CoreCLR Test executions using live libraries
@@ -1029,7 +972,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -1049,7 +992,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -1065,7 +1008,7 @@ jobs:
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr_AppleSilicon.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Mono Test builds with CoreCLR runtime tests using live libraries debug build
@@ -1083,7 +1026,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Mono CoreCLR runtime Test executions using live libraries in jit mode
@@ -1095,8 +1038,6 @@ jobs:
runtimeFlavor: mono
platforms:
- OSX_x64
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - Linux_arm64
helixQueueGroup: pr
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
jobParameters:
@@ -1108,7 +1049,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Mono CoreCLR runtime Test executions using live libraries in interpreter mode
@@ -1120,8 +1061,6 @@ jobs:
runtimeFlavor: mono
platforms:
- OSX_x64
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - Linux_arm64
helixQueueGroup: pr
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
jobParameters:
@@ -1133,7 +1072,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Mono CoreCLR runtime Test executions using live libraries and LLVM AOT
# Only when Mono is changed
@@ -1158,7 +1097,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Mono CoreCLR runtime Test executions using live libraries and LLVM Full AOT
@@ -1171,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:
@@ -1184,7 +1122,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Release Test Execution against a release mono runtime.
@@ -1203,7 +1141,6 @@ jobs:
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: false
- isFullMatrix: ${{ variables.isFullMatrix }}
runtimeDisplayName: mono
testScope: innerloop
liveRuntimeBuildConfig: release
@@ -1211,7 +1148,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Release Test Execution against a release mono interpreter runtime.
@@ -1229,7 +1166,6 @@ jobs:
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: false
- isFullMatrix: ${{ variables.isFullMatrix }}
interpreter: true
runtimeDisplayName: mono_interpreter
testScope: innerloop
@@ -1238,7 +1174,7 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Release Test Execution against a release coreclr runtime
@@ -1250,18 +1186,15 @@ jobs:
buildConfig: Release
platforms:
- windows_x86
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - windows_arm64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: false
- isFullMatrix: ${{ variables.isFullMatrix }}
testScope: innerloop
liveRuntimeBuildConfig: release
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Debug Test Execution against a release coreclr runtime
@@ -1276,20 +1209,15 @@ jobs:
- OSX_x64
- Linux_x64
- Linux_musl_x64
- - ${{ if eq(variables['isFullMatrix'], true) }}:
- - Linux_arm64
- - ${{ if eq(variables['isFullMatrix'], false) }}:
- - windows_x86
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
isOfficialBuild: false
- isFullMatrix: ${{ variables.isFullMatrix }}
testScope: innerloop
liveRuntimeBuildConfig: release
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Test Execution against a checked runtime
@@ -1313,7 +1241,7 @@ jobs:
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
#
# Libraries Test Execution against a checked runtime
@@ -1335,7 +1263,7 @@ jobs:
condition: >-
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
@@ -1352,4 +1280,4 @@ jobs:
or(
eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(variables['isFullMatrix'], true))
+ eq(variables['isRollingBuild'], true))
diff --git a/eng/pipelines/runtimelab.yml b/eng/pipelines/runtimelab.yml
index 9f1cd90822e832..27e954a9a70267 100644
--- a/eng/pipelines/runtimelab.yml
+++ b/eng/pipelines/runtimelab.yml
@@ -190,7 +190,7 @@ stages:
- Linux_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
- isFullMatrix: false
+ isRollingBuild: false
isOfficialBuild: false
testScope: innerloop
liveRuntimeBuildConfig: Release
@@ -207,7 +207,7 @@ stages:
- windows_x64
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
jobParameters:
- isFullMatrix: false
+ isRollingBuild: false
isOfficialBuild: false
testScope: innerloop
liveRuntimeBuildConfig: Release
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/eng/testing/tests.props b/eng/testing/tests.props
index 86c661d4bb2813..3025ab62335049 100644
--- a/eng/testing/tests.props
+++ b/eng/testing/tests.props
@@ -7,6 +7,7 @@
$(TestDependsOn);GenerateRunScript;RunTests
true
$(MSBuildThisFileDirectory)ILLinkDescriptors\
+ true
diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets
index 85ee6deb32db34..e6783add3640a3 100644
--- a/eng/testing/tests.singlefile.targets
+++ b/eng/testing/tests.singlefile.targets
@@ -12,7 +12,7 @@
chmod +rwx $(AssemblyName) && ./$(AssemblyName)
-
+
true
true
true
@@ -20,6 +20,30 @@
$(SingleFileHostSourcePath).exe
+
+ $(CoreCLRILCompilerDir)
+ $(CoreCLRILCompilerDir)netstandard/ILCompiler.Build.Tasks.dll
+ $(CoreCLRAotSdkDir)
+ $(NetCoreAppCurrentTestHostSharedFrameworkPath)
+ $(NoWarn);IL3050;IL3052;IL3055;IL1005
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets
index 191d2c2295690f..bed571a3064021 100644
--- a/eng/testing/tests.wasm.targets
+++ b/eng/testing/tests.wasm.targets
@@ -29,13 +29,13 @@
See also eng\testing\WasmRunnerTemplate.sh
-->
-
+
-
+
diff --git a/eng/testing/xunit/xunit.props b/eng/testing/xunit/xunit.props
index 3f9c4b67141a2f..a2ed68f1ecbc96 100644
--- a/eng/testing/xunit/xunit.props
+++ b/eng/testing/xunit/xunit.props
@@ -10,6 +10,7 @@
+
diff --git a/global.json b/global.json
index f191cfdd2e3525..43ff763c74d864 100644
--- a/global.json
+++ b/global.json
@@ -12,12 +12,12 @@
"python3": "3.7.1"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.22056.6",
- "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22056.6",
- "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22056.6",
- "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22056.6",
+ "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.22075.6",
+ "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.22075.6",
+ "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22075.6",
+ "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22075.6",
"Microsoft.Build.NoTargets": "3.1.0",
"Microsoft.Build.Traversal": "3.0.23",
- "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.22059.2"
+ "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.22073.5"
}
}
diff --git a/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj b/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj
index db820d395a1256..685f9415101950 100644
--- a/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj
+++ b/src/coreclr/.nuget/Microsoft.ILVerification/Microsoft.ILVerification.pkgproj
@@ -15,7 +15,7 @@
lib\netstandard2.0\ILVerification.dll
- 1.8.1
+ $(SystemReflectionMetadataVersion)
netstandard2.0
Build,Analyzers
diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt
index 2440f6ca999cad..38e5488938b6d7 100644
--- a/src/coreclr/CMakeLists.txt
+++ b/src/coreclr/CMakeLists.txt
@@ -247,7 +247,6 @@ add_subdirectory(debug)
add_subdirectory(binder)
add_subdirectory(classlibnative)
add_subdirectory(dlls)
-add_subdirectory(ToolBox)
add_subdirectory(tools)
add_subdirectory(unwinder)
add_subdirectory(interop)
diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index e1230d59401d86..3d21bffd3d24f8 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -140,8 +140,6 @@
-
-
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/Math.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs
index c86aa1b2e62bfe..a619dc4b1ca795 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Math.CoreCLR.cs
@@ -16,14 +16,6 @@ namespace System
{
public static partial class Math
{
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern double Abs(double value);
-
- [Intrinsic]
- [MethodImpl(MethodImplOptions.InternalCall)]
- public static extern float Abs(float value);
-
[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern double Acos(double d);
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/ToolBox/CMakeLists.txt b/src/coreclr/ToolBox/CMakeLists.txt
deleted file mode 100644
index 4e7f4368681d1d..00000000000000
--- a/src/coreclr/ToolBox/CMakeLists.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-add_subdirectory(SOS)
-add_subdirectory(superpmi)
diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp
index 830c673ea06a63..7b48a0a90ce831 100644
--- a/src/coreclr/binder/assemblybindercommon.cpp
+++ b/src/coreclr/binder/assemblybindercommon.cpp
@@ -972,7 +972,7 @@ namespace BINDER_SPACE
{
// Search Assembly.ni.dll, then Assembly.dll
// The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies.
- SString candidates[] = { W(".ni.dll"), W(".dll") };
+ const WCHAR* const candidates[] = { W(".ni.dll"), W(".dll") };
// Loop through the binding paths looking for a matching assembly
for (int i = 0; i < 2; i++)
diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp
index 499e20d928887f..e349b99b3c14e0 100644
--- a/src/coreclr/binder/bindertracing.cpp
+++ b/src/coreclr/binder/bindertracing.cpp
@@ -176,8 +176,8 @@ namespace BinderTracing
{
static thread_local bool t_AssemblyLoadStartInProgress = false;
- AssemblyBindOperation::AssemblyBindOperation(AssemblySpec *assemblySpec, const WCHAR *assemblyPath)
- : m_bindRequest { assemblySpec, nullptr, assemblyPath }
+ AssemblyBindOperation::AssemblyBindOperation(AssemblySpec *assemblySpec, const SString& assemblyPath)
+ : m_bindRequest { assemblySpec, SString::Empty(), assemblyPath }
, m_populatedBindRequest { false }
, m_checkedIgnoreBind { false }
, m_ignoreBind { false }
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/bindertracing.h b/src/coreclr/binder/inc/bindertracing.h
index 75d8270b8eee51..ca28c045196388 100644
--- a/src/coreclr/binder/inc/bindertracing.h
+++ b/src/coreclr/binder/inc/bindertracing.h
@@ -27,7 +27,7 @@ namespace BinderTracing
{
public:
// This class assumes the assembly spec will have a longer lifetime than itself
- AssemblyBindOperation(AssemblySpec *assemblySpec, const WCHAR *assemblyPath = nullptr);
+ AssemblyBindOperation(AssemblySpec *assemblySpec, const SString& assemblyPath = SString::Empty());
~AssemblyBindOperation();
void SetResult(PEAssembly *assembly, bool cached = false);
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/build-runtime.cmd b/src/coreclr/build-runtime.cmd
index ed9d735a7d4285..30cd7d2785267a 100644
--- a/src/coreclr/build-runtime.cmd
+++ b/src/coreclr/build-runtime.cmd
@@ -345,6 +345,9 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do (
if not "!string:-nativeaot-=!"=="!string!" (
set __CMakeTarget=!__CMakeTarget! nativeaot
)
+ if not "!string:-spmi-=!"=="!string!" (
+ set __CMakeTarget=!__CMakeTarget! spmi
+ )
)
if [!__CMakeTarget!] == [] (
set __CMakeTarget=install
@@ -745,7 +748,7 @@ echo -all: Builds all configurations and platforms.
echo Build architecture: one of -x64, -x86, -arm, -arm64 ^(default: -x64^).
echo Build type: one of -Debug, -Checked, -Release ^(default: -Debug^).
echo -component ^ : specify this option one or more times to limit components built to those specified.
-echo Allowed ^: hosts jit alljits runtime paltests iltools
+echo Allowed ^: hosts jit alljits runtime paltests iltools nativeaot spmi
echo -enforcepgo: verify after the build that PGO was used for key DLLs, and fail the build if not
echo -pgoinstrument: generate instrumented code for profile guided optimization enabled binaries.
echo -cmakeargs: user-settable additional arguments passed to CMake.
diff --git a/src/coreclr/build-runtime.sh b/src/coreclr/build-runtime.sh
index 8d42b92ce95c0a..a1e03198ac6dff 100755
--- a/src/coreclr/build-runtime.sh
+++ b/src/coreclr/build-runtime.sh
@@ -22,7 +22,7 @@ usage_list+=("-pgodatapath: path to profile guided optimization data.")
usage_list+=("-pgoinstrument: generate instrumented code for profile guided optimization enabled binaries.")
usage_list+=("-skipcrossarchnative: Skip building cross-architecture native binaries.")
usage_list+=("-staticanalyzer: use scan_build static analyzer.")
-usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', and 'nativeaot'. Can be specified multiple times.")
+usage_list+=("-component: Build individual components instead of the full project. Available options are 'hosts', 'jit', 'runtime', 'paltests', 'alljits', 'iltools', 'nativeaot', and 'spmi'. Can be specified multiple times.")
setup_dirs_local()
{
diff --git a/src/coreclr/classlibnative/float/floatdouble.cpp b/src/coreclr/classlibnative/float/floatdouble.cpp
index 67aceb60ea13e6..d20b772eb2207c 100644
--- a/src/coreclr/classlibnative/float/floatdouble.cpp
+++ b/src/coreclr/classlibnative/float/floatdouble.cpp
@@ -42,15 +42,6 @@
#pragma float_control(precise, off)
#endif
-/*=====================================Abs======================================
-**
-==============================================================================*/
-FCIMPL1_V(double, COMDouble::Abs, double x)
- FCALL_CONTRACT;
-
- return fabs(x);
-FCIMPLEND
-
/*=====================================Acos=====================================
**
==============================================================================*/
diff --git a/src/coreclr/classlibnative/float/floatsingle.cpp b/src/coreclr/classlibnative/float/floatsingle.cpp
index 965998fbaa2ba3..1694fd78cb8467 100644
--- a/src/coreclr/classlibnative/float/floatsingle.cpp
+++ b/src/coreclr/classlibnative/float/floatsingle.cpp
@@ -8,18 +8,6 @@
#include "floatsingle.h"
-// Windows x86 and Windows ARM/ARM64 may not define _isnanf() or _copysignf() but they do
-// define _isnan() and _copysign(). We will redirect the macros to these other functions if
-// the macro is not defined for the platform. This has the side effect of a possible implicit
-// upcasting for arguments passed in and an explicit downcasting for the _copysign() call.
-#if (defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_ARM64)) && !defined(TARGET_UNIX)
-
-#if !defined(_copysignf)
-#define _copysignf (float)_copysign
-#endif
-
-#endif
-
// The default compilation mode is /fp:precise, which disables floating-point intrinsics. This
// default compilation mode has previously caused performance regressions in floating-point code.
// We enable /fp:fast semantics for the majority of the math functions, as it will speed up performance
@@ -40,15 +28,6 @@
#pragma float_control(precise, off)
#endif
-/*=====================================Abs=====================================
-**
-==============================================================================*/
-FCIMPL1_V(float, COMSingle::Abs, float x)
- FCALL_CONTRACT;
-
- return fabsf(x);
-FCIMPLEND
-
/*=====================================Acos=====================================
**
==============================================================================*/
diff --git a/src/coreclr/classlibnative/inc/floatdouble.h b/src/coreclr/classlibnative/inc/floatdouble.h
index 9163349127ca14..43fecbd47431f3 100644
--- a/src/coreclr/classlibnative/inc/floatdouble.h
+++ b/src/coreclr/classlibnative/inc/floatdouble.h
@@ -9,7 +9,6 @@
class COMDouble {
public:
- FCDECL1_V(static double, Abs, double x);
FCDECL1_V(static double, Acos, double x);
FCDECL1_V(static double, Acosh, double x);
FCDECL1_V(static double, Asin, double x);
diff --git a/src/coreclr/classlibnative/inc/floatsingle.h b/src/coreclr/classlibnative/inc/floatsingle.h
index 09a0512b230dbd..765032ce6371e4 100644
--- a/src/coreclr/classlibnative/inc/floatsingle.h
+++ b/src/coreclr/classlibnative/inc/floatsingle.h
@@ -9,7 +9,6 @@
class COMSingle {
public:
- FCDECL1_V(static float, Abs, float x);
FCDECL1_V(static float, Acos, float x);
FCDECL1_V(static float, Acosh, float x);
FCDECL1_V(static float, Asin, float x);
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/components.cmake b/src/coreclr/components.cmake
index c23a38539247e9..3eaa2c966bf32e 100644
--- a/src/coreclr/components.cmake
+++ b/src/coreclr/components.cmake
@@ -6,6 +6,7 @@ add_component(runtime)
add_component(paltests paltests_install)
add_component(iltools)
add_component(nativeaot)
+add_component(spmi)
# Define coreclr_all as the fallback component and make every component depend on this component.
# iltools and paltests should be minimal subsets, so don't add a dependency on coreclr_misc
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 ebb5d12c0ce3aa..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();
@@ -5428,6 +5416,16 @@ GENERICS_TYPE_TOKEN DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD
if (dwExactGenericArgsTokenIndex == 0)
{
+ // In a rare case of VS4Mac debugging VS4Mac ARM64 optimized code we get a null generics argument token. We aren't sure
+ // why the token is null, it may be a bug or it may be by design in the runtime. In the interest of time we are working
+ // around the issue rather than investigating the root cause. This workaround should only cause us to degrade generic
+ // types from exact type parameters to approximate or canonical type parameters. In the future if we discover this issue
+ // is happening more frequently than we expect or the workaround is more impactful than we expect we may need to remove
+ // this workaround and resolve the underlying issue.
+ if (rawToken == 0)
+ {
+ return rawToken;
+ }
// In this case the real generics type token is the MethodTable of the "this" object.
// Note that we want the target address here.
@@ -6058,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
@@ -7015,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;
@@ -7035,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/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src
index 2a529b2f4a779d..334d1b90c93082 100644
--- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src
+++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src
@@ -65,7 +65,6 @@ nativeStringResourceTable_mscorrc
#PAL_wcsrchr
#PAL_wcscmp
#PAL_wcschr
-#PAL_wcscspn
#PAL_wcscat
#PAL_wcsstr
#PAL__open
@@ -140,8 +139,6 @@ nativeStringResourceTable_mscorrc
#LoadLibraryA
#LoadLibraryW
#LoadLibraryExW
-#LocalAlloc
-#LocalFree
#MapViewOfFile
#MapViewOfFileEx
#MoveFileExW
diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc
index 0e78c99f38d5de..d2c7bff988cc87 100644
--- a/src/coreclr/dlls/mscorrc/mscorrc.rc
+++ b/src/coreclr/dlls/mscorrc/mscorrc.rc
@@ -194,6 +194,10 @@ BEGIN
IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL "Unable to find an entry point named '%1' in DLL."
IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO "Unable to find an entry point named '%1' in shared library."
IDS_EE_NDIRECT_GETPROCADDRESS_NONAME "A library name must be specified in a DllImport attribute applied to non-IJW methods."
+ IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR "Setting SetLastError to 'true' is not supported when runtime marshalling is disabled."
+ IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID "The LCIDConversionAttribute is not supported when runtime marshalling is disabled."
+ IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG "Setting PreserveSig to false for a P/Invoke is not supported when runtime marshalling is disabled."
+ IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS "Using a variable argument list in a P/Invoke is not supported when runtime marshalling is disabled."
IDS_EE_CLASS_CONSTRAINTS_VIOLATION "GenericArguments[%1], '%2', on '%3' violates the constraint of type parameter '%4'."
IDS_EE_METHOD_CONSTRAINTS_VIOLATION "Method %1.%2: type argument '%3' violates the constraint of type parameter '%4'."
IDS_EE_NOSYNCHRONIZED "Synchronized attribute cannot be used with this method type."
@@ -297,6 +301,7 @@ BEGIN
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled."
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."
+ IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled."
IDS_EE_BADMARSHALPARAM_STRINGBUILDER "Invalid managed/unmanaged type combination (StringBuilders must be paired with LPStr, LPWStr, or LPTStr)."
IDS_EE_BADMARSHALPARAM_NO_LPTSTR "Invalid managed/unmanaged type combination (Strings cannot be paired with LPTStr for parameters and return types of methods in interfaces exposed to COM)."
diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h
index 05b31799ec5c47..7a8f148456a831 100644
--- a/src/coreclr/dlls/mscorrc/resource.h
+++ b/src/coreclr/dlls/mscorrc/resource.h
@@ -588,3 +588,8 @@
#define IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE 0x2649
#define IDS_EE_THREAD_APARTMENT_NOT_SUPPORTED 0x264A
#define IDS_EE_NO_IINSPECTABLE 0x264B
+#define IDS_EE_BADMARSHAL_MARSHAL_DISABLED 0x264C
+#define IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR 0x264D
+#define IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID 0x264E
+#define IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG 0x264F
+#define IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS 0x2650
diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp
index 5a2a9c2c2c20e6..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;
@@ -9404,7 +9402,7 @@ void gc_heap::remove_ro_segment (heap_segment* seg)
enter_spin_lock (&gc_heap::gc_lock);
- seg_table->remove ((uint8_t*)seg);
+ seg_table->remove (heap_segment_mem (seg));
seg_mapping_table_remove_ro_segment (seg);
// Locate segment (and previous segment) in the list.
@@ -10892,7 +10890,7 @@ void gc_heap::seg_clear_mark_array_bits_soh (heap_segment* seg)
}
}
-void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
+void gc_heap::bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
{
if ((start < background_saved_highest_address) &&
(end > background_saved_lowest_address))
@@ -10916,8 +10914,15 @@ void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
if (startwrd == endwrd)
{
- unsigned int wrd = firstwrd | lastwrd;
- mark_array[startwrd] &= wrd;
+ if (startbit != endbit)
+ {
+ unsigned int wrd = firstwrd | lastwrd;
+ mark_array[startwrd] &= wrd;
+ }
+ else
+ {
+ assert (start == end);
+ }
return;
}
@@ -10940,18 +10945,6 @@ void gc_heap::clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
}
}
}
-
-void gc_heap::bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end)
-{
- if ((start < background_saved_highest_address) &&
- (end > background_saved_lowest_address))
- {
- start = max (start, background_saved_lowest_address);
- end = min (end, background_saved_highest_address);
-
- clear_batch_mark_array_bits (start, end);
- }
-}
#endif //BACKGROUND_GC
inline
@@ -11144,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);
@@ -11548,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))
@@ -11568,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)",
@@ -11606,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);
@@ -13568,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;
@@ -20428,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);
+ }
}
}
}
@@ -24364,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;
}
@@ -27453,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;
@@ -29741,7 +29752,7 @@ void gc_heap::thread_final_regions (bool compact_p)
}
}
- verify_regions (true);
+ verify_regions (true, false);
}
void gc_heap::thread_start_region (generation* gen, heap_segment* region)
@@ -29792,7 +29803,7 @@ heap_segment* gc_heap::get_new_region (int gen_number, size_t size)
heap_segment_next (generation_tail_region (gen)) = new_region;
generation_tail_region (gen) = new_region;
- verify_regions (gen_number, false);
+ verify_regions (gen_number, false, settings.concurrent);
}
return new_region;
@@ -29861,7 +29872,7 @@ void gc_heap::update_start_tail_regions (generation* gen,
(size_t)prev_region, heap_segment_mem (prev_region)));
}
- verify_regions (false);
+ verify_regions (false, settings.concurrent);
}
// There's one complication with deciding whether we can make a region SIP or not - if the plan_gen_num of
@@ -30130,12 +30141,19 @@ 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
void gc_heap::check_demotion_helper_sip (uint8_t** pval, int parent_gen_num, uint8_t* parent_loc)
{
uint8_t* child_object = *pval;
+ if (!is_in_heap_range (child_object))
+ return;
if (!child_object) return;
int child_object_plan_gen = get_region_plan_gen_num (child_object);
@@ -36653,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);
@@ -41401,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) ?
@@ -42157,7 +42175,7 @@ gc_heap::verify_free_lists ()
}
}
-void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num)
+void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail)
{
#ifdef USE_REGIONS
// For the given generation, verify that
@@ -42220,7 +42238,7 @@ void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num)
FATAL_GC_ERROR();
}
- if (tail_region != prev_region_in_gen)
+ if (can_verify_tail && (tail_region != prev_region_in_gen))
{
dprintf (REGIONS_LOG, ("h%d gen%d tail region is %Ix(%Ix), diff from last region %Ix(%Ix)!!",
heap_number, gen_number,
@@ -42231,12 +42249,18 @@ void gc_heap::verify_regions (int gen_number, bool can_verify_gen_num)
#endif //USE_REGIONS
}
-void gc_heap::verify_regions (bool can_verify_gen_num)
+inline bool is_user_alloc_gen (int gen_number)
+{
+ return ((gen_number == soh_gen0) || (gen_number == loh_generation) || (gen_number == poh_generation));
+}
+
+void gc_heap::verify_regions (bool can_verify_gen_num, bool concurrent_p)
{
#ifdef USE_REGIONS
for (int i = 0; i < total_generation_count; i++)
{
- verify_regions (i, can_verify_gen_num);
+ bool can_verify_tail = (concurrent_p ? !is_user_alloc_gen (i) : true);
+ verify_regions (i, can_verify_gen_num, can_verify_tail);
}
#endif //USE_REGIONS
}
@@ -42367,7 +42391,7 @@ void gc_heap::verify_heap (BOOL begin_gc_p)
//verify that the generation structures makes sense
{
#ifdef USE_REGIONS
- verify_regions (true);
+ verify_regions (true, settings.concurrent);
#else //USE_REGIONS
generation* gen = generation_of (max_generation);
@@ -43428,8 +43452,15 @@ void GCHeap::SetYieldProcessorScalingFactor (float scalingFactor)
unsigned int GCHeap::WhichGeneration (Object* object)
{
- gc_heap* hp = gc_heap::heap_of ((uint8_t*)object);
- unsigned int g = hp->object_gennum ((uint8_t*)object);
+ uint8_t* o = (uint8_t*)object;
+#ifdef FEATURE_BASICFREEZE
+ if (!((o < g_gc_highest_address) && (o >= g_gc_lowest_address)))
+ {
+ return max_generation;
+ }
+#endif //FEATURE_BASICFREEZE
+ gc_heap* hp = gc_heap::heap_of (o);
+ unsigned int g = hp->object_gennum (o);
dprintf (3, ("%Ix is in gen %d", (size_t)object, g));
return g;
}
@@ -44071,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/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h
index cfffcf1221a811..c7d72c7145baf4 100644
--- a/src/coreclr/gc/gcinterface.dac.h
+++ b/src/coreclr/gc/gcinterface.dac.h
@@ -111,7 +111,7 @@ enum oom_reason
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* If you modify failure_get_memory and */
/* oom_reason be sure to make the corresponding */
-/* changes in toolbox\sos\strike\strike.cpp. */
+/* changes in tools\sos\strike\strike.cpp. */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
enum failure_get_memory
{
diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h
index 14bf3ef2908895..567e7c1bd69caf 100644
--- a/src/coreclr/gc/gcpriv.h
+++ b/src/coreclr/gc/gcpriv.h
@@ -51,8 +51,8 @@ inline void FATAL_GC_ERROR()
//
// This means any empty regions can be freely used for any generation. For
// Server GC we will balance regions between heaps.
-// For now disable regions StandAlone GC builds
-#if defined (HOST_64BIT) && !defined (BUILD_AS_STANDALONE)
+// For now disable regions outside of StandAlone GC builds
+#if defined (HOST_64BIT) && defined (BUILD_AS_STANDALONE)
#define USE_REGIONS
#endif //HOST_64BIT && BUILD_AS_STANDALONE
@@ -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);
@@ -1286,9 +1287,9 @@ class gc_heap
PER_HEAP
void verify_free_lists();
PER_HEAP
- void verify_regions (int gen_number, bool can_verify_gen_num);
+ void verify_regions (int gen_number, bool can_verify_gen_num, bool can_verify_tail);
PER_HEAP
- void verify_regions (bool can_verify_gen_num);
+ void verify_regions (bool can_verify_gen_num, bool concurrent_p);
PER_HEAP_ISOLATED
void enter_gc_lock_for_verify_heap();
PER_HEAP_ISOLATED
@@ -2156,8 +2157,6 @@ class gc_heap
PER_HEAP
void seg_clear_mark_array_bits_soh (heap_segment* seg);
PER_HEAP
- void clear_batch_mark_array_bits (uint8_t* start, uint8_t* end);
- PER_HEAP
void bgc_clear_batch_mark_array_bits (uint8_t* start, uint8_t* end);
#ifdef VERIFY_HEAP
PER_HEAP
@@ -3596,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/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp
index 431421afc87e40..2d979c395610e9 100644
--- a/src/coreclr/gc/unix/gcenv.unix.cpp
+++ b/src/coreclr/gc/unix/gcenv.unix.cpp
@@ -28,6 +28,10 @@
#undef min
#undef max
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) (0)
+#endif
+
#if __has_cpp_attribute(fallthrough)
#define FALLTHROUGH [[fallthrough]]
#else
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 eda1e11d2f2e14..64855ed939ddd7 100644
--- a/src/coreclr/inc/bbsweep.h
+++ b/src/coreclr/inc/bbsweep.h
@@ -31,11 +31,9 @@
#pragma push_macro("SetEvent")
#pragma push_macro("ResetEvent")
#pragma push_macro("ReleaseSemaphore")
-#pragma push_macro("LocalFree")
#undef SetEvent
#undef ResetEvent
#undef ReleaseSemaphore
-#undef LocalFree
// MAX_COUNT is the maximal number of runtime processes that can run at a given time
#define MAX_COUNT 20
@@ -184,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);
@@ -293,15 +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 (pACL) LocalFree(pACL);
- if (buffer) delete [] ((char *) buffer);
-#endif
}
bInitialized = hSweepMutex &&
@@ -381,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")
@@ -416,7 +314,6 @@ class BBSweep
HANDLE hBBSweepThread; // a handle to the CLR sweeper thread (that calls watch for sweep events)
};
-#pragma pop_macro("LocalFree")
#pragma pop_macro("ReleaseSemaphore")
#pragma pop_macro("ResetEvent")
#pragma pop_macro("SetEvent")
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/dacvars.h b/src/coreclr/inc/dacvars.h
index fdae380a90cb4f..686c77217395ec 100644
--- a/src/coreclr/inc/dacvars.h
+++ b/src/coreclr/inc/dacvars.h
@@ -5,7 +5,7 @@
// 1. in daccess.h to build the table of DAC globals
// 2. in enummem.cpp to dump out the related memory of static and globals
// in a mini dump or heap dump
-// 3. in DacUpdateDll and toolbox\DacTablenGen\main.cs
+// 3. in DacUpdateDll and tools\DacTablenGen\main.cs
//
// To use this functionality for other tools or purposes, define the
// DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or
diff --git a/src/coreclr/inc/holder.h b/src/coreclr/inc/holder.h
index 448610634a6129..4ec7b106cc0e8a 100644
--- a/src/coreclr/inc/holder.h
+++ b/src/coreclr/inc/holder.h
@@ -1152,7 +1152,14 @@ FORCEINLINE void HolderFreeLibrary(HMODULE h) { FreeLibrary(h); }
typedef Wrapper, HolderFreeLibrary, NULL> HModuleHolder;
template FORCEINLINE
-void DoLocalFree(T* pMem) { (LocalFree)((HLOCAL)pMem); }
+void DoLocalFree(T* pMem)
+{
+#ifdef HOST_WINDOWS
+ (LocalFree)((void*)pMem);
+#else
+ (free)((void*)pMem);
+#endif
+}
template
using LocalAllocHolder = SpecializedWrapper<_TYPE, DoLocalFree<_TYPE>>;
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/sigparser.h b/src/coreclr/inc/sigparser.h
index 1e861c4cd3edf8..b9b79e951e40b8 100644
--- a/src/coreclr/inc/sigparser.h
+++ b/src/coreclr/inc/sigparser.h
@@ -864,6 +864,21 @@ class CorTypeInfo
return (GetGCType_NoThrow(type) == TYPE_GC_REF);
}
+ static BOOL IsByRef(CorElementType type)
+ {
+ WRAPPER_NO_CONTRACT;
+ SUPPORTS_DAC;
+
+ return (GetGCType(type) == TYPE_GC_BYREF);
+ }
+ static BOOL IsByRef_NoThrow(CorElementType type)
+ {
+ WRAPPER_NO_CONTRACT;
+ SUPPORTS_DAC;
+
+ return (GetGCType_NoThrow(type) == TYPE_GC_BYREF);
+ }
+
FORCEINLINE static BOOL IsGenericVariable(CorElementType type)
{
WRAPPER_NO_CONTRACT;
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 0fde8090d0699a..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)
@@ -85,9 +83,6 @@ VPTR_CLASS(ExternalMethodFrame)
#ifdef FEATURE_READYTORUN
VPTR_CLASS(DynamicHelperFrame)
#endif
-#if defined(TARGET_X86)
-VPTR_CLASS(UMThkCallFrame)
-#endif
#if defined(TARGET_X86) && !defined(UNIX_X86_ABI)
VPTR_CLASS(TailCallFrame)
#endif
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/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp
index 51fad24772b47c..4e0e708be326c6 100644
--- a/src/coreclr/jit/assertionprop.cpp
+++ b/src/coreclr/jit/assertionprop.cpp
@@ -2576,7 +2576,6 @@ void Compiler::optAssertionGen(GenTree* tree)
case GT_OBJ:
case GT_BLK:
- case GT_DYN_BLK:
case GT_IND:
// R-value indirections create non-null assertions, but not all indirections are R-values.
// Those under ADDR nodes or on the LHS of ASGs are "locations", and will not end up
@@ -4626,9 +4625,9 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree,
case GT_OBJ:
case GT_BLK:
- case GT_DYN_BLK:
case GT_IND:
case GT_NULLCHECK:
+ case GT_STORE_DYN_BLK:
return optAssertionProp_Ind(assertions, tree, stmt);
case GT_BOUNDS_CHECK:
diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h
index c5996ac8239d75..81a511f4bceed6 100644
--- a/src/coreclr/jit/block.h
+++ b/src/coreclr/jit/block.h
@@ -825,6 +825,17 @@ struct BasicBlock : private LIR::Range
BBswtDesc* bbJumpSwt; // switch descriptor
};
+ bool KindIs(BBjumpKinds kind) const
+ {
+ return bbJumpKind == kind;
+ }
+
+ template
+ bool KindIs(BBjumpKinds kind, T... rest) const
+ {
+ return KindIs(kind) || KindIs(rest...);
+ }
+
// NumSucc() gives the number of successors, and GetSucc() returns a given numbered successor.
//
// There are two versions of these functions: ones that take a Compiler* and ones that don't. You must
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 250a23904944ab..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
@@ -6922,9 +6922,12 @@ void CodeGen::genArm64EmitterUnitTests()
#ifdef ALL_ARM64_EMITTER_UNIT_TESTS
//
- // R_R fmov/fcmp/fcvt
+ // R_R cmeq/fmov/fcmp/fcvt
//
+ // cmeq scalar
+ theEmitter->emitIns_R_R(INS_cmeq, EA_8BYTE, REG_V0, REG_V1);
+
// fmov to vector to vector
theEmitter->emitIns_Mov(INS_fmov, EA_8BYTE, REG_V0, REG_V2, /* canSkip */ false);
theEmitter->emitIns_Mov(INS_fmov, EA_4BYTE, REG_V1, REG_V3, /* canSkip */ false);
diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp
index 227de58aedc970..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;
@@ -2840,8 +2840,8 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
// When both addresses are not 16-byte aligned the CopyBlock instruction sequence starts with padding
// str instruction. For example, when both addresses are 8-byte aligned the instruction sequence looks like
//
- // ldr D_simdReg1, [srcReg, #srcOffset]
- // str D_simdReg1, [dstReg, #dstOffset]
+ // ldr X_intReg1, [srcReg, #srcOffset]
+ // str X_intReg1, [dstReg, #dstOffset]
// ldp Q_simdReg1, Q_simdReg2, [srcReg, #srcOffset+8]
// stp Q_simdReg1, Q_simdReg2, [dstReg, #dstOffset+8]
// ldp Q_simdReg1, Q_simdReg2, [srcReg, #srcOffset+40]
@@ -2853,7 +2853,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
// be profitable).
const bool canUse16ByteWideInstrs = isSrcRegAddrAlignmentKnown && isDstRegAddrAlignmentKnown &&
- (size >= FP_REGSIZE_BYTES) && (srcRegAddrAlignment == dstRegAddrAlignment);
+ (size >= 2 * FP_REGSIZE_BYTES) && (srcRegAddrAlignment == dstRegAddrAlignment);
bool shouldUse16ByteWideInstrs = false;
@@ -2876,8 +2876,7 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
{
// In order to use 16-byte instructions the JIT needs to adjust either srcOffset or dstOffset.
// The JIT should use 16-byte loads and stores when the resulting sequence (incl. an additional add
- // instruction)
- // has fewer number of instructions.
+ // instruction) has fewer number of instructions.
if (helper.InstructionCount(FP_REGSIZE_BYTES) + 1 < helper.InstructionCount(REGSIZE_BYTES))
{
@@ -2937,51 +2936,31 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
const unsigned intRegCount = node->AvailableTempRegCount(RBM_ALLINT);
- switch (intRegCount)
+ if (intRegCount >= 2)
{
- case 1:
- intReg1 = node->GetSingleTempReg(RBM_ALLINT);
- break;
- case 2:
- intReg1 = node->ExtractTempReg(RBM_ALLINT);
- intReg2 = node->GetSingleTempReg(RBM_ALLINT);
- break;
- default:
- break;
+ intReg1 = node->ExtractTempReg(RBM_ALLINT);
+ intReg2 = node->ExtractTempReg(RBM_ALLINT);
}
-
- regNumber simdReg1 = REG_NA;
- regNumber simdReg2 = REG_NA;
-
- const unsigned simdRegCount = node->AvailableTempRegCount(RBM_ALLFLOAT);
-
- switch (simdRegCount)
+ else if (intRegCount == 1)
{
- case 1:
- simdReg1 = node->GetSingleTempReg(RBM_ALLFLOAT);
- break;
- case 2:
- simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT);
- simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT);
- break;
- default:
- break;
+ intReg1 = node->GetSingleTempReg(RBM_ALLINT);
+ intReg2 = rsGetRsvdReg();
+ }
+ else
+ {
+ intReg1 = rsGetRsvdReg();
}
if (shouldUse16ByteWideInstrs)
{
+ const regNumber simdReg1 = node->ExtractTempReg(RBM_ALLFLOAT);
+ const regNumber simdReg2 = node->GetSingleTempReg(RBM_ALLFLOAT);
+
helper.Unroll(FP_REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter());
}
else
{
- if (intReg2 == REG_NA)
- {
- helper.Unroll(REGSIZE_BYTES, intReg1, simdReg1, simdReg2, srcReg, dstReg, GetEmitter());
- }
- else
- {
- helper.UnrollBaseInstrs(intReg1, intReg2, srcReg, dstReg, GetEmitter());
- }
+ helper.UnrollBaseInstrs(intReg1, intReg2, srcReg, dstReg, GetEmitter());
}
#endif // TARGET_ARM64
diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp
index 7072e4fd66b0a5..fe8b2d82dcaec9 100644
--- a/src/coreclr/jit/codegencommon.cpp
+++ b/src/coreclr/jit/codegencommon.cpp
@@ -6236,15 +6236,9 @@ void CodeGen::genEnregisterOSRArgsAndLocals()
// This local was part of the live tier0 state and is enregistered in the
// OSR method. Initialize the register from the right frame slot.
//
- // We currently don't expect to see enregistered multi-reg args in OSR methods,
- // as struct promotion is disabled. So any struct arg just uses the location
- // on the tier0 frame.
- //
// If we ever enable promotion we'll need to generalize what follows to copy each
// field from the tier0 frame to its OSR home.
//
- assert(!varDsc->lvIsMultiRegArg);
-
if (!VarSetOps::IsMember(compiler, compiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex))
{
// This arg or local is not live at entry to the OSR method.
@@ -6391,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)
{
@@ -7543,6 +7552,16 @@ void CodeGen::genFnProlog()
#endif // PROFILING_SUPPORTED
+ // For OSR we may have a zero-length prolog. That's not supported
+ // when the method must report a generics context,/ so add a nop if so.
+ //
+ if (compiler->opts.IsOSR() && (GetEmitter()->emitGetPrologOffsetEstimate() == 0) &&
+ (compiler->lvaReportParamTypeArg() || compiler->lvaKeepAliveAndReportThis()))
+ {
+ JITDUMP("OSR: prolog was zero length and has generic context to report: adding nop to pad prolog.\n");
+ instGen(INS_nop);
+ }
+
if (!GetInterruptible())
{
// The 'real' prolog ends here for non-interruptible methods.
diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp
index 51e9afc0743987..009c0d9ad41dda 100644
--- a/src/coreclr/jit/codegenlinear.cpp
+++ b/src/coreclr/jit/codegenlinear.cpp
@@ -1657,7 +1657,7 @@ void CodeGen::genConsumeRegs(GenTree* tree)
#ifdef FEATURE_SIMD
// (In)Equality operation that produces bool result, when compared
// against Vector zero, marks its Vector Zero operand as contained.
- assert(tree->OperIsLeaf() || tree->IsSIMDZero());
+ assert(tree->OperIsLeaf() || tree->IsSIMDZero() || tree->IsVectorZero());
#else
assert(tree->OperIsLeaf());
#endif
@@ -1912,7 +1912,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg)
}
else
{
- GenTree* sizeNode = blkNode->AsDynBlk()->gtDynamicSize;
+ GenTree* sizeNode = blkNode->AsStoreDynBlk()->gtDynamicSize;
inst_Mov(sizeNode->TypeGet(), sizeReg, sizeNode->GetRegNum(), /* canSkip */ true);
}
}
@@ -2022,7 +2022,7 @@ void CodeGen::genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber
// in the case where the size is a constant (i.e. it is not GT_STORE_DYN_BLK).
if (blkNode->OperGet() == GT_STORE_DYN_BLK)
{
- genConsumeReg(blkNode->AsDynBlk()->gtDynamicSize);
+ genConsumeReg(blkNode->AsStoreDynBlk()->gtDynamicSize);
}
// Next, perform any necessary moves.
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 b8775857bb659a..cf87223f71760b 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -2644,15 +2644,19 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
verboseDump = (JitConfig.JitDumpTier0() > 0);
}
- // Optionally suppress dumping some OSR jit requests.
+ // Optionally suppress dumping except for a specific OSR jit request.
//
- if (verboseDump && jitFlags->IsSet(JitFlags::JIT_FLAG_OSR))
- {
- const int desiredOffset = JitConfig.JitDumpAtOSROffset();
+ const int dumpAtOSROffset = JitConfig.JitDumpAtOSROffset();
- if (desiredOffset != -1)
+ if (verboseDump && (dumpAtOSROffset != -1))
+ {
+ if (jitFlags->IsSet(JitFlags::JIT_FLAG_OSR))
+ {
+ verboseDump = (((IL_OFFSET)dumpAtOSROffset) == info.compILEntry);
+ }
+ else
{
- verboseDump = (((IL_OFFSET)desiredOffset) == info.compILEntry);
+ verboseDump = false;
}
}
@@ -4632,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);
@@ -4772,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
@@ -4905,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);
@@ -4962,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();
@@ -5017,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);
@@ -5626,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
@@ -6157,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 */
@@ -6397,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;
@@ -6407,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)
@@ -9385,7 +9381,6 @@ void cTreeFlags(Compiler* comp, GenTree* tree)
FALLTHROUGH;
case GT_BLK:
- case GT_DYN_BLK:
case GT_STORE_BLK:
case GT_STORE_DYN_BLK:
@@ -9738,7 +9733,7 @@ bool Compiler::lvaIsOSRLocal(unsigned varNum)
//
void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block)
{
- assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK));
+ assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK));
tree->ChangeOper(GT_NULLCHECK);
tree->ChangeType(TYP_INT);
block->bbFlags |= BBF_HAS_NULLCHECK;
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 5a16ac8a58bf8c..967d27eac4703b 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -1735,7 +1735,7 @@ struct fgArgTabEntry
// In this case, it must be removed by GenTreeCall::ResetArgInfo.
bool isNonStandardArgAddedLate() const
{
- switch (nonStandardArgKind)
+ switch (static_cast(nonStandardArgKind))
{
case NonStandardArgKind::None:
case NonStandardArgKind::PInvokeFrame:
@@ -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);
@@ -5432,7 +5432,7 @@ class Compiler
// Requires that "tree" is a GT_IND marked as an array index, and that its address argument
// has been parsed to yield the other input arguments. If evaluation of the address
- // can raise exceptions, those should be captured in the exception set "excVN."
+ // can raise exceptions, those should be captured in the exception set "addrXvnp".
// Assumes that "elemTypeEq" is the (equivalence class rep) of the array element type.
// Marks "tree" with the VN for H[elemTypeEq][arrVN][inx][fldSeq] (for the liberal VN; a new unique
// VN for the conservative VN.) Also marks the tree's argument as the address of an array element.
@@ -5443,14 +5443,14 @@ class Compiler
CORINFO_CLASS_HANDLE elemTypeEq,
ValueNum arrVN,
ValueNum inxVN,
- ValueNum excVN,
+ ValueNumPair addrXvnp,
FieldSeqNode* fldSeq);
- // Requires "funcApp" to be a VNF_PtrToArrElem, and "addrXvn" to represent the exception set thrown
+ // Requires "funcApp" to be a VNF_PtrToArrElem, and "addrXvnp" to represent the exception set thrown
// by evaluating the array index expression "tree". Returns the value number resulting from
// dereferencing the array in the current GcHeap state. If "tree" is non-null, it must be the
// "GT_IND" that does the dereference, and it is given the returned value number.
- ValueNum fgValueNumberArrIndexVal(GenTree* tree, struct VNFuncApp* funcApp, ValueNum addrXvn);
+ ValueNum fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* funcApp, ValueNumPair addrXvnp);
// Compute the value number for a byref-exposed load of the given type via the given pointerVN.
ValueNum fgValueNumberByrefExposedLoad(var_types type, ValueNum pointerVN);
@@ -5560,6 +5560,10 @@ class Compiler
// Adds the exception sets for the current tree node
void fgValueNumberAddExceptionSet(GenTree* tree);
+#ifdef DEBUG
+ void fgDebugCheckExceptionSets();
+#endif
+
// These are the current value number for the memory implicit variables while
// doing value numbering. These are the value numbers under the "liberal" interpretation
// of memory values; the "conservative" interpretation needs no VN, since every access of
@@ -5941,7 +5945,7 @@ class Compiler
bool fgReorderBlocks();
- void fgDetermineFirstColdBlock();
+ PhaseStatus fgDetermineFirstColdBlock();
bool fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc = nullptr);
@@ -6400,11 +6404,16 @@ class Compiler
GenTree* fgMorphGetStructAddr(GenTree** pTree, CORINFO_CLASS_HANDLE clsHnd, bool isRValue = false);
GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigned blockWidth, bool isBlkReqd);
GenTree* fgMorphCopyBlock(GenTree* tree);
+ GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree);
GenTree* fgMorphForRegisterFP(GenTree* tree);
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr);
GenTree* fgOptimizeCast(GenTreeCast* cast);
GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp);
GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp);
+ GenTree* fgOptimizeCommutativeArithmetic(GenTreeOp* tree);
+ GenTree* fgOptimizeAddition(GenTreeOp* add);
+ GenTree* fgOptimizeMultiply(GenTreeOp* mul);
+ GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp);
GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects);
GenTree* fgMorphRetInd(GenTreeUnOp* tree);
GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
@@ -6415,7 +6424,7 @@ class Compiler
bool fgMorphCanUseLclFldForCopy(unsigned lclNum1, unsigned lclNum2);
GenTreeLclVar* fgMorphTryFoldObjAsLclVar(GenTreeObj* obj);
- GenTree* fgMorphCommutative(GenTreeOp* tree);
+ GenTreeOp* fgMorphCommutative(GenTreeOp* tree);
GenTree* fgMorphCastedBitwiseOp(GenTreeOp* tree);
GenTree* fgMorphReduceAddOps(GenTree* tree);
@@ -6731,6 +6740,12 @@ class Compiler
CALLINT_ALL, // kills everything (normal method call)
};
+ enum class FieldKindForVN
+ {
+ SimpleStatic,
+ WithBaseAddr
+ };
+
public:
// A "LoopDsc" describes a ("natural") loop. We (currently) require the body of a loop to be a contiguous (in
// bbNext order) sequence of basic blocks. (At times, we may require the blocks in a loop to be "properly numbered"
@@ -6785,9 +6800,9 @@ class Compiler
int lpLoopVarFPCount; // The register count for the FP LclVars that are read/written inside this loop
int lpVarInOutFPCount; // The register count for the FP LclVars that are alive inside or across this loop
- typedef JitHashTable, bool> FieldHandleSet;
- FieldHandleSet* lpFieldsModified; // This has entries (mappings to "true") for all static field and object
- // instance fields modified
+ typedef JitHashTable, FieldKindForVN>
+ FieldHandleSet;
+ FieldHandleSet* lpFieldsModified; // This has entries for all static field and object instance fields modified
// in the loop.
typedef JitHashTable, bool> ClassHandleSet;
@@ -6798,7 +6813,7 @@ class Compiler
// Adds the variable liveness information for 'blk' to 'this' LoopDsc
void AddVariableLiveness(Compiler* comp, BasicBlock* blk);
- inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd);
+ inline void AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind);
// This doesn't *always* take a class handle -- it can also take primitive types, encoded as class handles
// (shifted left, with a low-order bit set to distinguish.)
// Use the {Encode/Decode}ElemType methods to construct/destruct these.
@@ -6916,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);
@@ -6977,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);
@@ -7045,7 +7062,7 @@ class Compiler
void AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock* blk);
// Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
- void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd);
+ void AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind);
// Adds "elemType" to the set of modified array element types of "lnum" and any parent loops.
void AddModifiedElemTypeAllContainingLoops(unsigned lnum, CORINFO_CLASS_HANDLE elemType);
@@ -7105,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.
@@ -7370,14 +7381,11 @@ class Compiler
typedef ArrayStack GenTreePtrStack;
typedef JitHashTable, GenTreePtrStack*> LclNumToGenTreePtrStack;
- // Kill set to track variables with intervening definitions.
- VARSET_TP optCopyPropKillSet;
-
// Copy propagation functions.
- void optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName);
+ void optCopyProp(Statement* stmt, GenTreeLclVarCommon* tree, unsigned lclNum, LclNumToGenTreePtrStack* curSsaName);
void optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName);
void optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curSsaName);
- unsigned optIsSsaLocal(GenTree* tree);
+ unsigned optIsSsaLocal(GenTreeLclVarCommon* lclNode);
int optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDsc, bool preferOp2);
void optVnCopyProp();
INDEBUG(void optDumpCopyPropStack(LclNumToGenTreePtrStack* curSsaName));
@@ -8070,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,
@@ -10701,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
@@ -11490,42 +11491,14 @@ class GenTreeVisitor
break;
}
- case GT_DYN_BLK:
- {
- GenTreeDynBlk* const dynBlock = node->AsDynBlk();
-
- GenTree** op1Use = &dynBlock->gtOp1;
- GenTree** op2Use = &dynBlock->gtDynamicSize;
-
- result = WalkTree(op1Use, dynBlock);
- if (result == fgWalkResult::WALK_ABORT)
- {
- return result;
- }
- result = WalkTree(op2Use, dynBlock);
- if (result == fgWalkResult::WALK_ABORT)
- {
- return result;
- }
- break;
- }
-
case GT_STORE_DYN_BLK:
{
- GenTreeDynBlk* const dynBlock = node->AsDynBlk();
+ GenTreeStoreDynBlk* const dynBlock = node->AsStoreDynBlk();
GenTree** op1Use = &dynBlock->gtOp1;
GenTree** op2Use = &dynBlock->gtOp2;
GenTree** op3Use = &dynBlock->gtDynamicSize;
- if (TVisitor::UseExecutionOrder)
- {
- if (dynBlock->IsReverseOp())
- {
- std::swap(op1Use, op2Use);
- }
- }
-
result = WalkTree(op1Use, dynBlock);
if (result == fgWalkResult::WALK_ABORT)
{
diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp
index b75828d4cc68a2..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);
}
@@ -3346,14 +3358,14 @@ inline void Compiler::optAssertionRemove(AssertionIndex index)
}
}
-inline void Compiler::LoopDsc::AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd)
+inline void Compiler::LoopDsc::AddModifiedField(Compiler* comp, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind)
{
if (lpFieldsModified == nullptr)
{
lpFieldsModified =
new (comp->getAllocatorLoopHoist()) Compiler::LoopDsc::FieldHandleSet(comp->getAllocatorLoopHoist());
}
- lpFieldsModified->Set(fldHnd, true, FieldHandleSet::Overwrite);
+ lpFieldsModified->Set(fldHnd, fieldKind, FieldHandleSet::Overwrite);
}
inline void Compiler::LoopDsc::AddModifiedElemType(Compiler* comp, CORINFO_CLASS_HANDLE structHnd)
@@ -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
@@ -4347,20 +4343,9 @@ void GenTree::VisitOperands(TVisitor visitor)
return;
}
- case GT_DYN_BLK:
- {
- GenTreeDynBlk* const dynBlock = this->AsDynBlk();
- if (visitor(dynBlock->gtOp1) == VisitResult::Abort)
- {
- return;
- }
- visitor(dynBlock->gtDynamicSize);
- return;
- }
-
case GT_STORE_DYN_BLK:
{
- GenTreeDynBlk* const dynBlock = this->AsDynBlk();
+ GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk();
if (visitor(dynBlock->gtOp1) == VisitResult::Abort)
{
return;
@@ -4516,11 +4501,12 @@ inline static bool StructHasNoPromotionFlagSet(DWORD attribs)
return ((attribs & CORINFO_FLG_DONT_PROMOTE) != 0);
}
-/*****************************************************************************
- * This node should not be referenced by anyone now. Set its values to garbage
- * to catch extra references
- */
-
+//------------------------------------------------------------------------------
+// DEBUG_DESTROY_NODE: sets value of tree to garbage to catch extra references
+//
+// Arguments:
+// tree: This node should not be referenced by anyone now
+//
inline void DEBUG_DESTROY_NODE(GenTree* tree)
{
#ifdef DEBUG
@@ -4541,6 +4527,19 @@ inline void DEBUG_DESTROY_NODE(GenTree* tree)
#endif
}
+//------------------------------------------------------------------------------
+// DEBUG_DESTROY_NODE: sets value of trees to garbage to catch extra references
+//
+// Arguments:
+// tree, ...rest: These nodes should not be referenced by anyone now
+//
+template
+void DEBUG_DESTROY_NODE(GenTree* tree, T... rest)
+{
+ DEBUG_DESTROY_NODE(tree);
+ DEBUG_DESTROY_NODE(rest...);
+}
+
//------------------------------------------------------------------------------
// lvRefCnt: access reference count for this local var
//
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/copyprop.cpp b/src/coreclr/jit/copyprop.cpp
index 1c80436902f90e..52c765a12dc41e 100644
--- a/src/coreclr/jit/copyprop.cpp
+++ b/src/coreclr/jit/copyprop.cpp
@@ -32,17 +32,16 @@ void Compiler::optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrSt
{
for (GenTree* const tree : stmt->TreeList())
{
- if (!tree->IsLocal())
- {
- continue;
- }
- const unsigned lclNum = optIsSsaLocal(tree);
- if (lclNum == BAD_VAR_NUM)
- {
- continue;
- }
- if (tree->gtFlags & GTF_VAR_DEF)
+ GenTreeLclVarCommon* lclDefNode = nullptr;
+ if (tree->OperIs(GT_ASG) && tree->DefinesLocal(this, &lclDefNode))
{
+ const unsigned lclNum = optIsSsaLocal(lclDefNode);
+
+ if (lclNum == BAD_VAR_NUM)
+ {
+ continue;
+ }
+
GenTreePtrStack* stack = nullptr;
curSsaName->Lookup(lclNum, &stack);
stack->Pop();
@@ -123,97 +122,67 @@ int Compiler::optCopyProp_LclVarScore(LclVarDsc* lclVarDsc, LclVarDsc* copyVarDs
// definitions share the same value number. If so, then we can make the replacement.
//
// Arguments:
-// block - Block the tree belongs to
// stmt - Statement the tree belongs to
-// tree - The tree to perform copy propagation on
+// tree - The local tree to perform copy propagation on
+// lclNum - The local number of said tree
// curSsaName - The map from lclNum to its recently live definitions as a stack
-void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, LclNumToGenTreePtrStack* curSsaName)
+void Compiler::optCopyProp(Statement* stmt,
+ GenTreeLclVarCommon* tree,
+ unsigned lclNum,
+ LclNumToGenTreePtrStack* curSsaName)
{
- // TODO-Review: EH successor/predecessor iteration seems broken.
- if (block->bbCatchTyp == BBCT_FINALLY || block->bbCatchTyp == BBCT_FAULT)
- {
- return;
- }
-
- // If not local nothing to do.
- if (!tree->IsLocal())
- {
- return;
- }
- if (tree->OperGet() == GT_PHI_ARG || tree->OperGet() == GT_LCL_FLD)
- {
- return;
- }
-
- // Propagate only on uses.
- if (tree->gtFlags & GTF_VAR_DEF)
- {
- return;
- }
- const unsigned lclNum = optIsSsaLocal(tree);
-
- // Skip non-SSA variables.
- if (lclNum == BAD_VAR_NUM)
- {
- return;
- }
-
+ assert((lclNum != BAD_VAR_NUM) && (optIsSsaLocal(tree) == lclNum) && ((tree->gtFlags & GTF_VAR_DEF) == 0));
assert(tree->gtVNPair.GetConservative() != ValueNumStore::NoVN);
for (LclNumToGenTreePtrStack::KeyIterator iter = curSsaName->Begin(); !iter.Equal(curSsaName->End()); ++iter)
{
unsigned newLclNum = iter.Get();
- GenTree* op = iter.GetValue()->Top();
-
// Nothing to do if same.
if (lclNum == newLclNum)
{
continue;
}
- // Skip variables with assignments embedded in the statement (i.e., with a comma). Because we
- // are not currently updating their SSA names as live in the copy-prop pass of the stmt.
- if (VarSetOps::IsMember(this, optCopyPropKillSet, lvaTable[newLclNum].lvVarIndex))
- {
- continue;
- }
+ LclVarDsc* varDsc = lvaGetDesc(lclNum);
+ LclVarDsc* newLclVarDsc = lvaGetDesc(newLclNum);
+ GenTree* newLclDefNode = iter.GetValue()->Top(); // Note that this "def" node can actually be a use (for
+ // parameters and other use-before-def locals).
// Do not copy propagate if the old and new lclVar have different 'doNotEnregister' settings.
// This is primarily to avoid copy propagating to IND(ADDR(LCL_VAR)) where the replacement lclVar
// is not marked 'lvDoNotEnregister'.
// However, in addition, it may not be profitable to propagate a 'doNotEnregister' lclVar to an
// existing use of an enregisterable lclVar.
-
- if (lvaTable[lclNum].lvDoNotEnregister != lvaTable[newLclNum].lvDoNotEnregister)
+ if (varDsc->lvDoNotEnregister != newLclVarDsc->lvDoNotEnregister)
{
continue;
}
- if (op->gtFlags & GTF_VAR_CAST)
+ if ((gsShadowVarInfo != nullptr) && newLclVarDsc->lvIsParam &&
+ (gsShadowVarInfo[newLclNum].shadowCopy == lclNum))
{
continue;
}
- if (gsShadowVarInfo != nullptr && lvaTable[newLclNum].lvIsParam &&
- gsShadowVarInfo[newLclNum].shadowCopy == lclNum)
- {
- continue;
- }
- ValueNum opVN = GetUseAsgDefVNOrTreeVN(op);
- if (opVN == ValueNumStore::NoVN)
+
+ ValueNum newLclDefVN = GetUseAsgDefVNOrTreeVN(newLclDefNode);
+ if (newLclDefVN == ValueNumStore::NoVN)
{
continue;
}
- if (op->TypeGet() != tree->TypeGet())
+
+ if (newLclDefNode->TypeGet() != tree->TypeGet())
{
continue;
}
- if (opVN != tree->gtVNPair.GetConservative())
+
+ if (newLclDefVN != tree->gtVNPair.GetConservative())
{
continue;
}
- if (optCopyProp_LclVarScore(lvaGetDesc(lclNum), lvaGetDesc(newLclNum), true) <= 0)
+
+ if (optCopyProp_LclVarScore(varDsc, newLclVarDsc, true) <= 0)
{
continue;
}
@@ -230,34 +199,25 @@ void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, Lc
// node x2 = phi(x0, x1) which can then be used to substitute 'c' with. But because of pruning
// there would be no such phi node. To solve this we'll check if 'x' is live, before replacing
// 'c' with 'x.'
- if (!lvaTable[newLclNum].lvVerTypeInfo.IsThisPtr())
- {
- if (lvaTable[newLclNum].IsAddressExposed())
- {
- continue;
- }
- // We compute liveness only on tracked variables. So skip untracked locals.
- if (!lvaTable[newLclNum].lvTracked)
- {
- continue;
- }
+ // We compute liveness only on tracked variables. And all SSA locals are tracked.
+ assert(lvaGetDesc(newLclNum)->lvTracked);
- // Because of this dependence on live variable analysis, CopyProp phase is immediately
- // after Liveness, SSA and VN.
- if (!VarSetOps::IsMember(this, compCurLife, lvaTable[newLclNum].lvVarIndex))
- {
- continue;
- }
+ // Because of this dependence on live variable analysis, CopyProp phase is immediately
+ // after Liveness, SSA and VN.
+ if ((newLclNum != info.compThisArg) && !VarSetOps::IsMember(this, compCurLife, newLclVarDsc->lvVarIndex))
+ {
+ continue;
}
+
unsigned newSsaNum = SsaConfig::RESERVED_SSA_NUM;
- if (op->gtFlags & GTF_VAR_DEF)
+ if (newLclDefNode->gtFlags & GTF_VAR_DEF)
{
- newSsaNum = GetSsaNumForLocalVarDef(op);
+ newSsaNum = GetSsaNumForLocalVarDef(newLclDefNode);
}
else // parameters, this pointer etc.
{
- newSsaNum = op->AsLclVarCommon()->GetSsaNum();
+ newSsaNum = newLclDefNode->AsLclVarCommon()->GetSsaNum();
}
if (newSsaNum == SsaConfig::RESERVED_SSA_NUM)
@@ -271,48 +231,42 @@ void Compiler::optCopyProp(BasicBlock* block, Statement* stmt, GenTree* tree, Lc
JITDUMP("VN based copy assertion for ");
printTreeID(tree);
printf(" V%02d " FMT_VN " by ", lclNum, tree->GetVN(VNK_Conservative));
- printTreeID(op);
- printf(" V%02d " FMT_VN ".\n", newLclNum, op->GetVN(VNK_Conservative));
- gtDispTree(tree, nullptr, nullptr, true);
+ printTreeID(newLclDefNode);
+ printf(" V%02d " FMT_VN ".\n", newLclNum, newLclDefNode->GetVN(VNK_Conservative));
+ DISPNODE(tree);
}
#endif
tree->AsLclVarCommon()->SetLclNum(newLclNum);
tree->AsLclVarCommon()->SetSsaNum(newSsaNum);
gtUpdateSideEffects(stmt, tree);
+
#ifdef DEBUG
if (verbose)
{
printf("copy propagated to:\n");
- gtDispTree(tree, nullptr, nullptr, true);
+ DISPNODE(tree);
}
#endif
break;
}
- return;
}
//------------------------------------------------------------------------------
// optIsSsaLocal : helper to check if the tree is a local that participates in SSA numbering.
//
// Arguments:
-// tree - The tree to perform the check on;
+// lclNode - The local tree to perform the check on;
//
// Returns:
// - lclNum if the local is participating in SSA;
// - fieldLclNum if the parent local can be replaced by its only field;
// - BAD_VAR_NUM otherwise.
//
-unsigned Compiler::optIsSsaLocal(GenTree* tree)
+unsigned Compiler::optIsSsaLocal(GenTreeLclVarCommon* lclNode)
{
- if (!tree->IsLocal())
- {
- return BAD_VAR_NUM;
- }
-
- GenTreeLclVarCommon* lclNode = tree->AsLclVarCommon();
- unsigned lclNum = lclNode->GetLclNum();
- LclVarDsc* varDsc = lvaGetDesc(lclNum);
+ unsigned lclNum = lclNode->GetLclNum();
+ LclVarDsc* varDsc = lvaGetDesc(lclNum);
if (!lvaInSsa(lclNum) && varDsc->CanBeReplacedWithItsField(this))
{
@@ -355,68 +309,63 @@ void Compiler::optBlockCopyProp(BasicBlock* block, LclNumToGenTreePtrStack* curS
VarSetOps::Assign(this, compCurLife, block->bbLiveIn);
for (Statement* const stmt : block->Statements())
{
- VarSetOps::ClearD(this, optCopyPropKillSet);
-
// Walk the tree to find if any local variable can be replaced with current live definitions.
+ // Simultaneously, push live definitions on the stack - that logic must be in sync with the
+ // SSA renaming process.
for (GenTree* const tree : stmt->TreeList())
{
treeLifeUpdater.UpdateLife(tree);
- optCopyProp(block, stmt, tree, curSsaName);
-
- // TODO-Review: Merge this loop with the following loop to correctly update the
- // live SSA num while also propagating copies.
- //
- // 1. This loop performs copy prop with currently live (on-top-of-stack) SSA num.
- // 2. The subsequent loop maintains a stack for each lclNum with
- // currently active SSA numbers when definitions are encountered.
- //
- // If there is an embedded definition using a "comma" in a stmt, then the currently
- // live SSA number will get updated only in the next loop (2). However, this new
- // definition is now supposed to be live (on tos). If we did not update the stacks
- // using (2), copy prop (1) will use a SSA num defined outside the stmt ignoring the
- // embedded update. Killing the variable is a simplification to produce 0 ASM diffs
- // for an update release.
- //
- const unsigned lclNum = optIsSsaLocal(tree);
- if ((lclNum != BAD_VAR_NUM) && (tree->gtFlags & GTF_VAR_DEF))
+ GenTreeLclVarCommon* lclDefNode = nullptr;
+ if (tree->OperIs(GT_ASG) && tree->DefinesLocal(this, &lclDefNode))
{
- VarSetOps::AddElemD(this, optCopyPropKillSet, lvaTable[lclNum].lvVarIndex);
- }
- }
+ const unsigned lclNum = optIsSsaLocal(lclDefNode);
- // This logic must be in sync with SSA renaming process.
- for (GenTree* const tree : stmt->TreeList())
- {
- const unsigned lclNum = optIsSsaLocal(tree);
- if (lclNum == BAD_VAR_NUM)
- {
- continue;
- }
+ if (lclNum == BAD_VAR_NUM)
+ {
+ continue;
+ }
- // As we encounter a definition add it to the stack as a live definition.
- if (tree->gtFlags & GTF_VAR_DEF)
- {
GenTreePtrStack* stack;
if (!curSsaName->Lookup(lclNum, &stack))
{
stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator());
}
- stack->Push(tree);
+ stack->Push(lclDefNode);
curSsaName->Set(lclNum, stack, LclNumToGenTreePtrStack::Overwrite);
}
- // If we encounter first use of a param or this pointer add it as a live definition.
- // Since they are always live, do it only once.
- else if ((tree->gtOper == GT_LCL_VAR) && !(tree->gtFlags & GTF_VAR_USEASG) &&
- (lvaTable[lclNum].lvIsParam || lvaTable[lclNum].lvVerTypeInfo.IsThisPtr()))
+ // TODO-CQ: propagate on LCL_FLDs too.
+ else if (tree->OperIs(GT_LCL_VAR) && ((tree->gtFlags & GTF_VAR_DEF) == 0))
{
- GenTreePtrStack* stack;
- if (!curSsaName->Lookup(lclNum, &stack))
+ const unsigned lclNum = optIsSsaLocal(tree->AsLclVarCommon());
+
+ if (lclNum == BAD_VAR_NUM)
{
- stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator());
- stack->Push(tree);
- curSsaName->Set(lclNum, stack);
+ continue;
+ }
+
+ // If we encounter first use of a param or this pointer add it as a live definition.
+ // Since they are always live, we'll do it only once.
+ if (lvaGetDesc(lclNum)->lvIsParam || (lclNum == info.compThisArg))
+ {
+ GenTreePtrStack* stack;
+ if (!curSsaName->Lookup(lclNum, &stack))
+ {
+ assert(tree->AsLclVarCommon()->GetSsaNum() == SsaConfig::FIRST_SSA_NUM);
+
+ stack = new (curSsaName->GetAllocator()) GenTreePtrStack(curSsaName->GetAllocator());
+ stack->Push(tree);
+ curSsaName->Set(lclNum, stack);
+ }
}
+
+ // TODO-Review: EH successor/predecessor iteration seems broken.
+ if ((block->bbCatchTyp == BBCT_FINALLY) || (block->bbCatchTyp == BBCT_FAULT))
+ {
+ continue;
+ }
+
+ optCopyProp(stmt, tree->AsLclVarCommon(), lclNum, curSsaName);
}
}
}
@@ -462,7 +411,6 @@ void Compiler::optVnCopyProp()
}
VarSetOps::AssignNoCopy(this, compCurLife, VarSetOps::MakeEmpty(this));
- VarSetOps::AssignNoCopy(this, optCopyPropKillSet, VarSetOps::MakeEmpty(this));
class CopyPropDomTreeVisitor : public DomTreeVisitor
{
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/emit.h b/src/coreclr/jit/emit.h
index 47daad7798fc20..66706ecaf488e2 100644
--- a/src/coreclr/jit/emit.h
+++ b/src/coreclr/jit/emit.h
@@ -614,6 +614,15 @@ class emitter
assert((ins != INS_invalid) && (ins < INS_count));
_idIns = ins;
}
+ bool idInsIs(instruction ins) const
+ {
+ return idIns() == ins;
+ }
+ template
+ bool idInsIs(instruction ins, T... rest) const
+ {
+ return idInsIs(ins) || idInsIs(rest...);
+ }
insFormat idInsFmt() const
{
@@ -2874,19 +2883,12 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id)
/* static */ emitAttr emitter::emitGetMemOpSize(instrDesc* id)
{
emitAttr defaultSize = id->idOpSize();
- emitAttr newSize = defaultSize;
+
switch (id->idIns())
{
- case INS_vextractf128:
- case INS_vextracti128:
- case INS_vinsertf128:
- case INS_vinserti128:
- {
- return EA_16BYTE;
- }
-
case INS_pextrb:
case INS_pinsrb:
+ case INS_vpbroadcastb:
{
return EA_1BYTE;
}
@@ -2894,27 +2896,142 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id)
case INS_pextrw:
case INS_pextrw_sse41:
case INS_pinsrw:
+ case INS_pmovsxbq:
+ case INS_pmovzxbq:
+ case INS_vpbroadcastw:
{
return EA_2BYTE;
}
+ case INS_addss:
+ case INS_cmpss:
+ case INS_comiss:
+ case INS_cvtss2sd:
+ case INS_cvtss2si:
+ case INS_cvttss2si:
+ case INS_divss:
case INS_extractps:
case INS_insertps:
+ case INS_maxss:
+ case INS_minss:
+ case INS_movss:
+ case INS_mulss:
case INS_pextrd:
case INS_pinsrd:
+ case INS_pmovsxbd:
+ case INS_pmovsxwq:
+ case INS_pmovzxbd:
+ case INS_pmovzxwq:
+ case INS_rcpss:
+ case INS_roundss:
+ case INS_rsqrtss:
+ case INS_sqrtss:
+ case INS_subss:
+ case INS_ucomiss:
+ case INS_vbroadcastss:
+ case INS_vfmadd132ss:
+ case INS_vfmadd213ss:
+ case INS_vfmadd231ss:
+ case INS_vfmsub132ss:
+ case INS_vfmsub213ss:
+ case INS_vfmsub231ss:
+ case INS_vfnmadd132ss:
+ case INS_vfnmadd213ss:
+ case INS_vfnmadd231ss:
+ case INS_vfnmsub132ss:
+ case INS_vfnmsub213ss:
+ case INS_vfnmsub231ss:
+ case INS_vpbroadcastd:
{
return EA_4BYTE;
}
+ case INS_addsd:
+ case INS_cmpsd:
+ case INS_comisd:
+ case INS_cvtsd2si:
+ case INS_cvtsd2ss:
+ case INS_cvttsd2si:
+ case INS_divsd:
+ case INS_maxsd:
+ case INS_minsd:
+ case INS_movhpd:
+ case INS_movhps:
+ case INS_movlpd:
+ case INS_movlps:
+ case INS_movq:
+ case INS_movsd:
+ case INS_mulsd:
case INS_pextrq:
case INS_pinsrq:
+ case INS_pmovsxbw:
+ case INS_pmovsxdq:
+ case INS_pmovsxwd:
+ case INS_pmovzxbw:
+ case INS_pmovzxdq:
+ case INS_pmovzxwd:
+ case INS_roundsd:
+ case INS_sqrtsd:
+ case INS_subsd:
+ case INS_ucomisd:
+ case INS_vbroadcastsd:
+ case INS_vfmadd132sd:
+ case INS_vfmadd213sd:
+ case INS_vfmadd231sd:
+ case INS_vfmsub132sd:
+ case INS_vfmsub213sd:
+ case INS_vfmsub231sd:
+ case INS_vfnmadd132sd:
+ case INS_vfnmadd213sd:
+ case INS_vfnmadd231sd:
+ case INS_vfnmsub132sd:
+ case INS_vfnmsub213sd:
+ case INS_vfnmsub231sd:
+ case INS_vpbroadcastq:
{
return EA_8BYTE;
}
+ case INS_cvtdq2pd:
+ case INS_cvtps2pd:
+ {
+ if (defaultSize == 32)
+ {
+ return EA_16BYTE;
+ }
+ else
+ {
+ assert(defaultSize == 16);
+ return EA_8BYTE;
+ }
+ }
+
+ case INS_vbroadcastf128:
+ case INS_vbroadcasti128:
+ case INS_vextractf128:
+ case INS_vextracti128:
+ case INS_vinsertf128:
+ case INS_vinserti128:
+ {
+ return EA_16BYTE;
+ }
+
+ case INS_movddup:
+ {
+ if (defaultSize == 32)
+ {
+ return EA_32BYTE;
+ }
+ else
+ {
+ assert(defaultSize == 16);
+ return EA_8BYTE;
+ }
+ }
+
default:
{
- return id->idOpSize();
+ return defaultSize;
}
}
}
diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp
index 51e02c5c268958..52f24d4524279d 100644
--- a/src/coreclr/jit/emitarm64.cpp
+++ b/src/coreclr/jit/emitarm64.cpp
@@ -4732,19 +4732,19 @@ void emitter::emitIns_R_R(
assert(isVectorRegister(reg1));
assert(isVectorRegister(reg2));
- if (isValidVectorDatasize(size))
+ if (insOptsAnyArrangement(opt))
{
// Vector operation
- assert(insOptsAnyArrangement(opt));
+ assert(isValidVectorDatasize(size));
assert(isValidArrangement(size, opt));
elemsize = optGetElemsize(opt);
fmt = IF_DV_2M;
}
else
{
- NYI("Untested");
// Scalar operation
- assert(size == EA_8BYTE); // Only Double supported
+ assert(size == EA_8BYTE);
+ assert(insOptsNone(opt));
fmt = IF_DV_2L;
}
break;
@@ -12971,6 +12971,11 @@ void emitter::emitDispIns(
emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
}
+ if (ins == INS_fcmeq)
+ {
+ printf(", ");
+ emitDispImm(0, false);
+ }
break;
case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
@@ -12990,6 +12995,11 @@ void emitter::emitDispIns(
emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
}
+ if (ins == INS_cmeq)
+ {
+ printf(", ");
+ emitDispImm(0, false);
+ }
break;
case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
@@ -13126,6 +13136,11 @@ void emitter::emitDispIns(
emitDispReg(id->idReg1(), size, true);
emitDispReg(id->idReg2(), size, false);
}
+ if (fmt == IF_DV_2L && ins == INS_cmeq)
+ {
+ printf(", ");
+ emitDispImm(0, false);
+ }
break;
case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
@@ -15614,6 +15629,11 @@ bool emitter::IsMovInstruction(instruction ins)
// mov Rx, Ry # <-- last instruction
// mov Ry, Rx # <-- current instruction can be omitted.
//
+// 4. Move that does zero extension while previous instruction already did it
+//
+// ldr Wx, [Ry] # <-- ldr will clear upper 4 byte of Wx
+// mov Wx, Wx # <-- clears upper 4 byte in Wx
+//
// Arguments:
// ins - The current instruction
// size - Operand size of current instruction
@@ -15640,6 +15660,8 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN
return false;
}
+ const bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0);
+
if (dst == src)
{
// A mov with a EA_4BYTE has the side-effect of clearing the upper bits
@@ -15655,10 +15677,18 @@ bool emitter::IsRedundantMov(instruction ins, emitAttr size, regNumber dst, regN
JITDUMP("\n -- suppressing mov because src and dst is same 16-byte register.\n");
return true;
}
+ else if (isGeneralRegisterOrSP(dst) && (size == EA_4BYTE))
+ {
+ // See if the previous instruction already cleared upper 4 bytes for us unintentionally
+ if (!isFirstInstrInBlock && (emitLastIns != nullptr) && (emitLastIns->idReg1() == dst) &&
+ (emitLastIns->idOpSize() == size) && emitLastIns->idInsIs(INS_ldr, INS_ldrh, INS_ldrb))
+ {
+ JITDUMP("\n -- suppressing mov because ldr already cleared upper 4 bytes\n");
+ return true;
+ }
+ }
}
- bool isFirstInstrInBlock = (emitCurIGinsCnt == 0) && ((emitCurIG->igFlags & IGF_EXTEND) == 0);
-
if (!isFirstInstrInBlock && // Don't optimize if instruction is not the first instruction in IG.
(emitLastIns != nullptr) &&
(emitLastIns->idIns() == INS_mov) && // Don't optimize if last instruction was not 'mov'.
diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp
index 1075c4ccd97d0e..d90c5771ce1a96 100644
--- a/src/coreclr/jit/emitxarch.cpp
+++ b/src/coreclr/jit/emitxarch.cpp
@@ -8965,9 +8965,8 @@ void emitter::emitDispIns(
}
else
{
- attr = emitGetMemOpSize(id);
-
- sstr = codeGen->genSizeStr(attr);
+ attr = id->idOpSize();
+ sstr = codeGen->genSizeStr(emitGetMemOpSize(id));
if (ins == INS_lea)
{
@@ -11743,17 +11742,6 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
#ifdef DEBUG
int byteSize = EA_SIZE_IN_BYTES(emitGetMemOpSize(id));
- // this instruction has a fixed size (4) src.
- if (ins == INS_cvttss2si || ins == INS_cvtss2sd || ins == INS_vbroadcastss)
- {
- byteSize = 4;
- }
- // This has a fixed size (8) source.
- if (ins == INS_vbroadcastsd)
- {
- byteSize = 8;
- }
-
// Check that the offset is properly aligned (i.e. the ddd in [ddd])
// When SMALL_CODE is set, we only expect 4-byte alignment, otherwise
// we expect the same alignment as the size of the constant.
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 73695932cb5439..7f8bd7b01c6d03 100644
--- a/src/coreclr/jit/fgbasic.cpp
+++ b/src/coreclr/jit/fgbasic.cpp
@@ -321,7 +321,7 @@ bool Compiler::fgFirstBBisScratch()
// Normally, the first scratch block is a fall-through block. However, if the block after it was an empty
// BBJ_ALWAYS block, it might get removed, and the code that removes it will make the first scratch block
// a BBJ_ALWAYS block.
- assert((fgFirstBBScratch->bbJumpKind == BBJ_NONE) || (fgFirstBBScratch->bbJumpKind == BBJ_ALWAYS));
+ assert(fgFirstBBScratch->KindIs(BBJ_NONE, BBJ_ALWAYS));
return true;
}
@@ -1113,12 +1113,12 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
{
ni = lookupNamedIntrinsic(methodHnd);
- bool foldableIntrinsc = false;
+ bool foldableIntrinsic = false;
if (IsMathIntrinsic(ni))
{
// Most Math(F) intrinsics have single arguments
- foldableIntrinsc = FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo);
+ foldableIntrinsic = FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo);
}
else
{
@@ -1131,7 +1131,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_System_GC_KeepAlive:
{
pushedStack.PushUnknown();
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
break;
}
@@ -1145,6 +1145,20 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
break;
}
+ case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant:
+ if (FgStack::IsConstArgument(pushedStack.Top(), impInlineInfo))
+ {
+ compInlineResult->Note(InlineObservation::CALLEE_CONST_ARG_FEEDS_ISCONST);
+ }
+ else
+ {
+ compInlineResult->Note(InlineObservation::CALLEE_ARG_FEEDS_ISCONST);
+ }
+ // RuntimeHelpers.IsKnownConstant is always folded into a const
+ pushedStack.PushConstant();
+ foldableIntrinsic = true;
+ break;
+
// These are foldable if the first argument is a constant
case NI_System_Type_get_IsValueType:
case NI_System_Type_GetTypeFromHandle:
@@ -1159,10 +1173,10 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_Vector128_Create:
#endif
{
- // Top() in order to keep it as is in case of foldableIntrinsc
+ // Top() in order to keep it as is in case of foldableIntrinsic
if (FgStack::IsConstantOrConstArg(pushedStack.Top(), impInlineInfo))
{
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
}
break;
}
@@ -1177,7 +1191,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
if (FgStack::IsConstantOrConstArg(pushedStack.Top(0), impInlineInfo) &&
FgStack::IsConstantOrConstArg(pushedStack.Top(1), impInlineInfo))
{
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushConstant();
}
break;
@@ -1186,31 +1200,31 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
case NI_IsSupported_True:
case NI_IsSupported_False:
{
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushConstant();
break;
}
#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS)
case NI_Vector128_get_Count:
case NI_Vector256_get_Count:
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushConstant();
// TODO: check if it's a loop condition - we unroll such loops.
break;
case NI_Vector256_get_Zero:
case NI_Vector256_get_AllBitsSet:
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushUnknown();
break;
#elif defined(TARGET_ARM64) && defined(FEATURE_HW_INTRINSICS)
case NI_Vector64_get_Count:
case NI_Vector128_get_Count:
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushConstant();
break;
case NI_Vector128_get_Zero:
case NI_Vector128_get_AllBitsSet:
- foldableIntrinsc = true;
+ foldableIntrinsic = true;
pushedStack.PushUnknown();
break;
#endif
@@ -1222,7 +1236,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
}
}
- if (foldableIntrinsc)
+ if (foldableIntrinsic)
{
compInlineResult->Note(InlineObservation::CALLSITE_FOLDABLE_INTRINSIC);
handled = true;
@@ -2215,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;
}
@@ -2407,7 +2421,7 @@ void Compiler::fgLinkBasicBlocks()
/* Is the next block reachable? */
- if (curBBdesc->bbJumpKind == BBJ_ALWAYS || curBBdesc->bbJumpKind == BBJ_LEAVE)
+ if (curBBdesc->KindIs(BBJ_ALWAYS, BBJ_LEAVE))
{
break;
}
@@ -3502,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);
@@ -3513,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();
@@ -4369,7 +4380,7 @@ BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
BasicBlock* Compiler::fgSplitEdge(BasicBlock* curr, BasicBlock* succ)
{
- assert(curr->bbJumpKind == BBJ_COND || curr->bbJumpKind == BBJ_SWITCH || curr->bbJumpKind == BBJ_ALWAYS);
+ assert(curr->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_ALWAYS));
if (fgComputePredsDone)
{
@@ -4538,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
@@ -4562,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)
@@ -4620,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);
@@ -4670,7 +4675,7 @@ void Compiler::fgRemoveBlock(BasicBlock* block, bool unreachable)
}
#endif // DEBUG
- noway_assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
+ noway_assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS));
/* Who is the "real" successor of this block? */
@@ -5182,7 +5187,7 @@ bool Compiler::fgIsForwardBranch(BasicBlock* bJump, BasicBlock* bSrc /* = NULL *
{
bool result = false;
- if ((bJump->bbJumpKind == BBJ_COND) || (bJump->bbJumpKind == BBJ_ALWAYS))
+ if (bJump->KindIs(BBJ_COND, BBJ_ALWAYS))
{
BasicBlock* bDest = bJump->bbJumpDest;
BasicBlock* bTemp = (bSrc == nullptr) ? bJump : bSrc;
@@ -5799,7 +5804,7 @@ bool Compiler::fgIsBetterFallThrough(BasicBlock* bCur, BasicBlock* bAlt)
noway_assert(bAlt != nullptr);
// We only handle the cases when bAlt is a BBJ_ALWAYS or a BBJ_COND
- if ((bAlt->bbJumpKind != BBJ_ALWAYS) && (bAlt->bbJumpKind != BBJ_COND))
+ if (!bAlt->KindIs(BBJ_ALWAYS, BBJ_COND))
{
return false;
}
diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp
index 7fd7b5d5625636..2df6d000419b9e 100644
--- a/src/coreclr/jit/fgdiagnostic.cpp
+++ b/src/coreclr/jit/fgdiagnostic.cpp
@@ -2151,11 +2151,11 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 *
{
if (block == fgEntryBB)
{
- printf("original-entry");
+ printf(" original-entry");
}
if (block == fgOSREntryBB)
{
- printf("osr-entry");
+ printf(" osr-entry");
}
}
@@ -2503,7 +2503,7 @@ bool BBPredsChecker::CheckEhTryDsc(BasicBlock* block, BasicBlock* blockPred, EHb
bool BBPredsChecker::CheckEhHndDsc(BasicBlock* block, BasicBlock* blockPred, EHblkDsc* ehHndlDsc)
{
// You can do a BBJ_EHFINALLYRET or BBJ_EHFILTERRET into a handler region
- if ((blockPred->bbJumpKind == BBJ_EHFINALLYRET) || (blockPred->bbJumpKind == BBJ_EHFILTERRET))
+ if (blockPred->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET))
{
return true;
}
@@ -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/fginline.cpp b/src/coreclr/jit/fginline.cpp
index aaf40cefbfd130..53566eb17de7bf 100644
--- a/src/coreclr/jit/fginline.cpp
+++ b/src/coreclr/jit/fginline.cpp
@@ -47,7 +47,9 @@ unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
// This inline candidate has the same IL code buffer as an already
// inlined method does.
inlineResult->NoteFatal(InlineObservation::CALLSITE_IS_RECURSIVE);
- break;
+
+ // No need to note CALLSITE_DEPTH we're already rejecting this candidate
+ return depth;
}
if (depth > InlineStrategy::IMPLEMENTATION_MAX_INLINE_DEPTH)
diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp
index 361ff92ee8099a..eebe8a8e8eff5c 100644
--- a/src/coreclr/jit/fgopt.cpp
+++ b/src/coreclr/jit/fgopt.cpp
@@ -145,16 +145,16 @@ bool Compiler::fgReachable(BasicBlock* b1, BasicBlock* b2)
if (b1->bbNum > fgDomBBcount)
{
- noway_assert(b1->bbJumpKind == BBJ_NONE || b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND);
+ noway_assert(b1->KindIs(BBJ_NONE, BBJ_ALWAYS, BBJ_COND));
- if (b1->bbFallsThrough() && fgReachable(b1->bbNext, b2))
+ if (b1->KindIs(BBJ_NONE, BBJ_COND) && fgReachable(b1->bbNext, b2))
{
return true;
}
- if (b1->bbJumpKind == BBJ_ALWAYS || b1->bbJumpKind == BBJ_COND)
+ if (b1->KindIs(BBJ_ALWAYS, BBJ_COND) && fgReachable(b1->bbJumpDest, b2))
{
- return fgReachable(b1->bbJumpDest, b2);
+ return true;
}
return false;
@@ -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:
@@ -3549,7 +3543,7 @@ bool Compiler::fgOptimizeUncondBranchToSimpleCond(BasicBlock* block, BasicBlock*
//
bool Compiler::fgOptimizeBranchToNext(BasicBlock* block, BasicBlock* bNext, BasicBlock* bPrev)
{
- assert(block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS);
+ assert(block->KindIs(BBJ_COND, BBJ_ALWAYS));
assert(block->bbJumpDest == bNext);
assert(block->bbNext == bNext);
assert(block->bbPrev == bPrev);
@@ -4604,7 +4598,7 @@ bool Compiler::fgReorderBlocks()
bool backwardBranch = false;
// Setup bDest
- if ((bPrev->bbJumpKind == BBJ_COND) || (bPrev->bbJumpKind == BBJ_ALWAYS))
+ if (bPrev->KindIs(BBJ_COND, BBJ_ALWAYS))
{
bDest = bPrev->bbJumpDest;
forwardBranch = fgIsForwardBranch(bPrev);
@@ -4854,8 +4848,7 @@ bool Compiler::fgReorderBlocks()
// to bTmp (which is a higher weighted block) then it is better to keep out current
// candidateBlock and have it fall into bTmp
//
- if ((candidateBlock == nullptr) ||
- ((candidateBlock->bbJumpKind != BBJ_COND) && (candidateBlock->bbJumpKind != BBJ_ALWAYS)) ||
+ if ((candidateBlock == nullptr) || !candidateBlock->KindIs(BBJ_COND, BBJ_ALWAYS) ||
(candidateBlock->bbJumpDest != bTmp))
{
// otherwise we have a new candidateBlock
@@ -5796,7 +5789,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
// Remove JUMPS to the following block
// and optimize any JUMPS to JUMPS
- if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_ALWAYS)
+ if (block->KindIs(BBJ_COND, BBJ_ALWAYS))
{
bDest = block->bbJumpDest;
if (bDest == bNext)
@@ -5935,7 +5928,7 @@ bool Compiler::fgUpdateFlowGraph(bool doTailDuplication)
// Add fall through fixup block, if needed.
//
- if ((bDest->bbJumpKind == BBJ_NONE) || (bDest->bbJumpKind == BBJ_COND))
+ if (bDest->KindIs(BBJ_NONE, BBJ_COND))
{
BasicBlock* const bFixup = fgNewBBafter(BBJ_ALWAYS, bDest, true);
bFixup->inheritWeight(bDestNext);
@@ -6109,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;
@@ -6127,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/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp
index f94cb8615be404..34ab390a9b899e 100644
--- a/src/coreclr/jit/fgprofile.cpp
+++ b/src/coreclr/jit/fgprofile.cpp
@@ -1721,12 +1721,23 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod()
// jitting on PGO. If we ever implement a broader pattern of deferral -- say deferring
// based on static PGO -- we will need to reconsider.
//
+ // Under OSR stress we may add patchpoints even without backedges. So we also
+ // need to change the PGO instrumetation approach if OSR stress is enabled.
+ //
CLANG_FORMAT_COMMENT_ANCHOR;
+#if defined(DEBUG)
+ const bool mayHaveStressPatchpoints =
+ (JitConfig.JitOffsetOnStackReplacement() >= 0) || (JitConfig.JitRandomOnStackReplacement() > 0);
+#else
+ const bool mayHaveStressPatchpoints = false;
+#endif
+
+ const bool mayHavePatchpoints =
+ (JitConfig.TC_OnStackReplacement() > 0) && (compHasBackwardJump || mayHaveStressPatchpoints);
const bool prejit = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT);
- const bool tier0WithPatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) &&
- (JitConfig.TC_OnStackReplacement() > 0) && compHasBackwardJump;
- const bool osrMethod = opts.IsOSR();
+ const bool tier0WithPatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && mayHavePatchpoints;
+ const bool osrMethod = opts.IsOSR();
const bool useEdgeProfiles = (JitConfig.JitEdgeProfiling() > 0) && !prejit && !tier0WithPatchpoints && !osrMethod;
if (useEdgeProfiles)
@@ -3417,7 +3428,7 @@ weight_t Compiler::fgComputeMissingBlockWeights()
// Sum up the weights of all of the return blocks and throw blocks
// This is used when we have a back-edge into block 1
//
- if (bDst->hasProfileWeight() && ((bDst->bbJumpKind == BBJ_RETURN) || (bDst->bbJumpKind == BBJ_THROW)))
+ if (bDst->hasProfileWeight() && bDst->KindIs(BBJ_RETURN, BBJ_THROW))
{
returnWeight += bDst->bbWeight;
}
@@ -3988,7 +3999,7 @@ void Compiler::fgDebugCheckProfileData()
// Exit blocks
//
- if ((block->bbJumpKind == BBJ_RETURN) || (block->bbJumpKind == BBJ_THROW))
+ if (block->KindIs(BBJ_RETURN, BBJ_THROW))
{
exitWeight += blockWeight;
exitProfiled = true;
@@ -4157,7 +4168,7 @@ bool Compiler::fgDebugCheckOutgoingProfileData(BasicBlock* block)
// We won't check finally or filter returns (for now).
//
- if ((block->bbJumpKind == BBJ_EHFINALLYRET) || (block->bbJumpKind == BBJ_EHFILTERRET))
+ if (block->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET))
{
return true;
}
diff --git a/src/coreclr/jit/fgstmt.cpp b/src/coreclr/jit/fgstmt.cpp
index 24140b3fc52b98..f5f07399a1d371 100644
--- a/src/coreclr/jit/fgstmt.cpp
+++ b/src/coreclr/jit/fgstmt.cpp
@@ -182,7 +182,7 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt)
// This routine can only be used when in tree order.
assert(fgOrder == FGOrderTree);
- if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
+ if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN))
{
Statement* firstStmt = block->firstStmt();
noway_assert(firstStmt != nullptr);
diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp
index 188e44ab7f7f68..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;
@@ -108,23 +107,8 @@ PhaseStatus Compiler::fgInsertGCPolls()
// the test.
// If we're doing GCPOLL_CALL, just insert a GT_CALL node before the last node in the block.
- CLANG_FORMAT_COMMENT_ANCHOR;
-#ifdef DEBUG
- switch (block->bbJumpKind)
- {
- case BBJ_RETURN:
- case BBJ_ALWAYS:
- case BBJ_COND:
- case BBJ_SWITCH:
- case BBJ_NONE:
- case BBJ_THROW:
- case BBJ_CALLFINALLY:
- break;
- default:
- assert(!"Unexpected block kind");
- }
-#endif // DEBUG
+ assert(block->KindIs(BBJ_RETURN, BBJ_ALWAYS, BBJ_COND, BBJ_SWITCH, BBJ_NONE, BBJ_THROW, BBJ_CALLFINALLY));
GCPollType pollType = GCPOLL_INLINE;
@@ -196,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;
}
@@ -245,10 +222,9 @@ BasicBlock* Compiler::fgCreateGCPoll(GCPollType pollType, BasicBlock* block)
createdPollBlocks = false;
Statement* newStmt = nullptr;
- if ((block->bbJumpKind == BBJ_ALWAYS) || (block->bbJumpKind == BBJ_CALLFINALLY) ||
- (block->bbJumpKind == BBJ_NONE))
+ if (block->KindIs(BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_NONE))
{
- // For BBJ_ALWAYS, BBJ_CALLFINALLY, and BBJ_NONE and we don't need to insert it before the condition.
+ // For BBJ_ALWAYS, BBJ_CALLFINALLY, and BBJ_NONE we don't need to insert it before the condition.
// Just append it.
newStmt = fgNewStmtAtEnd(block, call);
}
@@ -3109,6 +3085,9 @@ void Compiler::fgSimpleLowering()
fgDispHandlerTab();
printf("\n");
}
+
+ fgDebugCheckBBlist();
+ fgDebugCheckLinks();
#endif
}
@@ -3390,7 +3369,7 @@ void Compiler::fgCreateFunclets()
* or are rarely executed.
*/
-void Compiler::fgDetermineFirstColdBlock()
+PhaseStatus Compiler::fgDetermineFirstColdBlock()
{
#ifdef DEBUG
if (verbose)
@@ -3404,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
@@ -3427,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
@@ -3498,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
@@ -3594,14 +3573,12 @@ EXIT:;
{
printf("fgFirstColdBlock is NULL.\n");
}
-
- fgDispBasicBlocks();
}
-
- fgVerifyHandlerTab();
#endif // DEBUG
fgFirstColdBlock = firstColdBlock;
+
+ return PhaseStatus::MODIFIED_EVERYTHING;
}
/* static */
@@ -3926,33 +3903,6 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)
return;
}
- // Special handling for dynamic block ops.
- if (tree->OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK))
- {
- GenTreeDynBlk* dynBlk = tree->AsDynBlk();
- GenTree* sizeNode = dynBlk->gtDynamicSize;
- GenTree* dstAddr = dynBlk->Addr();
- GenTree* src = dynBlk->Data();
- bool isReverse = dynBlk->IsReverseOp();
-
- // We either have a DYN_BLK or a STORE_DYN_BLK. If the latter, we have a
- // src (the Data to be stored), and isReverse tells us whether to evaluate
- // that before dstAddr.
- if (isReverse && (src != nullptr))
- {
- fgSetTreeSeqHelper(src, isLIR);
- }
- fgSetTreeSeqHelper(dstAddr, isLIR);
- if (!isReverse && (src != nullptr))
- {
- fgSetTreeSeqHelper(src, isLIR);
- }
- fgSetTreeSeqHelper(sizeNode, isLIR);
-
- fgSetTreeSeqFinish(dynBlk, isLIR);
- return;
- }
-
/* Is it a 'simple' unary/binary operator? */
if (kind & GTK_SMPOP)
@@ -4124,8 +4074,9 @@ void Compiler::fgSetTreeSeqHelper(GenTree* tree, bool isLIR)
break;
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
- noway_assert(!"DYN_BLK nodes should be sequenced as a special case");
+ fgSetTreeSeqHelper(tree->AsStoreDynBlk()->Addr(), isLIR);
+ fgSetTreeSeqHelper(tree->AsStoreDynBlk()->Data(), isLIR);
+ fgSetTreeSeqHelper(tree->AsStoreDynBlk()->gtDynamicSize, isLIR);
break;
default:
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 280c2f70875902..35b9d2d829ca42 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -258,7 +258,6 @@ void GenTree::InitNodeSize()
GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_CMPXCHG] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_QMARK] = TREE_NODE_SZ_LARGE;
- GenTree::s_gtNodeSizes[GT_DYN_BLK] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_INTRINSIC] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_ALLOCOBJ] = TREE_NODE_SZ_LARGE;
@@ -320,7 +319,7 @@ void GenTree::InitNodeSize()
static_assert_no_msg(sizeof(GenTreeAddrMode) <= TREE_NODE_SZ_SMALL);
static_assert_no_msg(sizeof(GenTreeObj) <= TREE_NODE_SZ_SMALL);
static_assert_no_msg(sizeof(GenTreeBlk) <= TREE_NODE_SZ_SMALL);
- static_assert_no_msg(sizeof(GenTreeDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node
+ static_assert_no_msg(sizeof(GenTreeStoreDynBlk) <= TREE_NODE_SZ_LARGE); // *** large node
static_assert_no_msg(sizeof(GenTreeRetExpr) <= TREE_NODE_SZ_LARGE); // *** large node
static_assert_no_msg(sizeof(GenTreeILOffset) <= TREE_NODE_SZ_SMALL);
static_assert_no_msg(sizeof(GenTreeClsVar) <= TREE_NODE_SZ_SMALL);
@@ -1609,10 +1608,9 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)
Compare(op1->AsCmpXchg()->gtOpComparand, op2->AsCmpXchg()->gtOpComparand);
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
- return Compare(op1->AsDynBlk()->Addr(), op2->AsDynBlk()->Addr()) &&
- Compare(op1->AsDynBlk()->Data(), op2->AsDynBlk()->Data()) &&
- Compare(op1->AsDynBlk()->gtDynamicSize, op2->AsDynBlk()->gtDynamicSize);
+ return Compare(op1->AsStoreDynBlk()->Addr(), op2->AsStoreDynBlk()->Addr()) &&
+ Compare(op1->AsStoreDynBlk()->Data(), op2->AsStoreDynBlk()->Data()) &&
+ Compare(op1->AsStoreDynBlk()->gtDynamicSize, op2->AsStoreDynBlk()->gtDynamicSize);
default:
assert(!"unexpected operator");
@@ -2073,11 +2071,9 @@ unsigned Compiler::gtHashValue(GenTree* tree)
break;
case GT_STORE_DYN_BLK:
- hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->Data()));
- FALLTHROUGH;
- case GT_DYN_BLK:
- hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->Addr()));
- hash = genTreeHashAdd(hash, gtHashValue(tree->AsDynBlk()->gtDynamicSize));
+ hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Data()));
+ hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->Addr()));
+ hash = genTreeHashAdd(hash, gtHashValue(tree->AsStoreDynBlk()->gtDynamicSize));
break;
default:
@@ -4136,7 +4132,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
case GT_IND:
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
// In an indirection, the destination address is evaluated prior to the source.
// If we have any side effects on the target indirection,
@@ -4181,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;
@@ -4645,23 +4641,19 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
break;
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
- level = gtSetEvalOrder(tree->AsDynBlk()->Addr());
- costEx = tree->AsDynBlk()->Addr()->GetCostEx();
- costSz = tree->AsDynBlk()->Addr()->GetCostSz();
+ level = gtSetEvalOrder(tree->AsStoreDynBlk()->Addr());
+ costEx = tree->AsStoreDynBlk()->Addr()->GetCostEx();
+ costSz = tree->AsStoreDynBlk()->Addr()->GetCostSz();
- if (oper == GT_STORE_DYN_BLK)
- {
- lvl2 = gtSetEvalOrder(tree->AsDynBlk()->Data());
- level = max(level, lvl2);
- costEx += tree->AsDynBlk()->Data()->GetCostEx();
- costSz += tree->AsDynBlk()->Data()->GetCostSz();
- }
+ lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->Data());
+ level = max(level, lvl2);
+ costEx += tree->AsStoreDynBlk()->Data()->GetCostEx();
+ costSz += tree->AsStoreDynBlk()->Data()->GetCostSz();
- lvl2 = gtSetEvalOrder(tree->AsDynBlk()->gtDynamicSize);
+ lvl2 = gtSetEvalOrder(tree->AsStoreDynBlk()->gtDynamicSize);
level = max(level, lvl2);
- costEx += tree->AsDynBlk()->gtDynamicSize->GetCostEx();
- costSz += tree->AsDynBlk()->gtDynamicSize->GetCostSz();
+ costEx += tree->AsStoreDynBlk()->gtDynamicSize->GetCostEx();
+ costSz += tree->AsStoreDynBlk()->gtDynamicSize->GetCostSz();
break;
default:
@@ -4965,25 +4957,9 @@ bool GenTree::TryGetUse(GenTree* operand, GenTree*** pUse)
return false;
}
- case GT_DYN_BLK:
- {
- GenTreeDynBlk* const dynBlock = this->AsDynBlk();
- if (operand == dynBlock->gtOp1)
- {
- *pUse = &dynBlock->gtOp1;
- return true;
- }
- if (operand == dynBlock->gtDynamicSize)
- {
- *pUse = &dynBlock->gtDynamicSize;
- return true;
- }
- return false;
- }
-
case GT_STORE_DYN_BLK:
{
- GenTreeDynBlk* const dynBlock = this->AsDynBlk();
+ GenTreeStoreDynBlk* const dynBlock = this->AsStoreDynBlk();
if (operand == dynBlock->gtOp1)
{
*pUse = &dynBlock->gtOp1;
@@ -5184,7 +5160,8 @@ GenTree* GenTree::gtRetExprVal(BasicBlockFlags* pbbFlags /* = nullptr */)
bool GenTree::OperRequiresAsgFlag()
{
- if (OperIs(GT_ASG) || OperIs(GT_XADD, GT_XORR, GT_XAND, GT_XCHG, GT_LOCKADD, GT_CMPXCHG, GT_MEMORYBARRIER))
+ if (OperIs(GT_ASG, GT_STORE_DYN_BLK) ||
+ OperIs(GT_XADD, GT_XORR, GT_XAND, GT_XCHG, GT_LOCKADD, GT_CMPXCHG, GT_MEMORYBARRIER))
{
return true;
}
@@ -5250,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.
//
@@ -5266,7 +5243,6 @@ bool GenTree::OperIsImplicitIndir() const
case GT_CMPXCHG:
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
case GT_STORE_BLK:
case GT_STORE_OBJ:
case GT_STORE_DYN_BLK:
@@ -5275,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:
{
@@ -5331,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:
@@ -5353,9 +5321,9 @@ bool GenTree::OperMayThrow(Compiler* comp)
case GT_IND:
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
- case GT_STORE_BLK:
case GT_NULLCHECK:
+ case GT_STORE_BLK:
+ case GT_STORE_DYN_BLK:
return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsIndir()->Addr()));
case GT_ARR_LENGTH:
@@ -6827,24 +6795,19 @@ void Compiler::gtBlockOpInit(GenTree* result, GenTree* dst, GenTree* srcOrFillVa
// gtNewBlkOpNode: Creates a GenTree for a block (struct) assignment.
//
// Arguments:
-// dst - Destination or target to copy to / initialize the buffer.
-// srcOrFillVall - the size of the buffer to copy/initialize or zero, in the case of CpObj.
+// dst - The destination node: local var / block node.
+// srcOrFillVall - The value to assign for CopyBlk, the integer "fill" for InitBlk
// isVolatile - Whether this is a volatile memory operation or not.
// isCopyBlock - True if this is a block copy (rather than a block init).
//
// Return Value:
// Returns the newly constructed and initialized block operation.
//
-// Notes:
-// If size is zero, the dst must be a GT_OBJ with the class handle.
-// 'dst' must be a block node or lclVar.
-//
GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVolatile, bool isCopyBlock)
{
assert(dst->OperIsBlk() || dst->OperIsLocal());
if (isCopyBlock)
{
- srcOrFillVal->gtFlags |= GTF_DONT_CSE;
if (srcOrFillVal->OperIsIndir() && (srcOrFillVal->gtGetOp1()->gtOper == GT_ADDR))
{
srcOrFillVal = srcOrFillVal->gtGetOp1()->gtGetOp1();
@@ -7435,10 +7398,6 @@ GenTree* Compiler::gtCloneExpr(
GenTreeBlk(GT_BLK, tree->TypeGet(), tree->AsBlk()->Addr(), tree->AsBlk()->GetLayout());
break;
- case GT_DYN_BLK:
- copy = new (this, GT_DYN_BLK) GenTreeDynBlk(tree->AsOp()->gtGetOp1(), tree->AsDynBlk()->gtDynamicSize);
- break;
-
case GT_FIELD:
copy = new (this, GT_FIELD) GenTreeField(tree->TypeGet(), tree->AsField()->GetFldObj(),
tree->AsField()->gtFldHnd, tree->AsField()->gtFldOffset);
@@ -7666,10 +7625,10 @@ GenTree* Compiler::gtCloneExpr(
break;
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
copy = new (this, oper)
- GenTreeDynBlk(gtCloneExpr(tree->AsDynBlk()->Addr(), addFlags, deepVarNum, deepVarVal),
- gtCloneExpr(tree->AsDynBlk()->gtDynamicSize, addFlags, deepVarNum, deepVarVal));
+ GenTreeStoreDynBlk(gtCloneExpr(tree->AsStoreDynBlk()->Addr(), addFlags, deepVarNum, deepVarVal),
+ gtCloneExpr(tree->AsStoreDynBlk()->Data(), addFlags, deepVarNum, deepVarVal),
+ gtCloneExpr(tree->AsStoreDynBlk()->gtDynamicSize, addFlags, deepVarNum, deepVarVal));
break;
default:
@@ -8353,20 +8312,10 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
m_advance = &GenTreeUseEdgeIterator::AdvanceArrOffset;
return;
- case GT_DYN_BLK:
- m_edge = &m_node->AsDynBlk()->Addr();
- assert(*m_edge != nullptr);
- m_advance = &GenTreeUseEdgeIterator::AdvanceDynBlk;
- return;
-
case GT_STORE_DYN_BLK:
- {
- GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
- m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1;
+ m_edge = &m_node->AsStoreDynBlk()->Addr();
assert(*m_edge != nullptr);
-
m_advance = &GenTreeUseEdgeIterator::AdvanceStoreDynBlk;
- }
return;
case GT_CALL:
@@ -8444,28 +8393,16 @@ void GenTreeUseEdgeIterator::AdvanceArrOffset()
assert(*m_edge != nullptr);
}
-//------------------------------------------------------------------------
-// GenTreeUseEdgeIterator::AdvanceDynBlk: produces the next operand of a DynBlk node and advances the state.
-//
-void GenTreeUseEdgeIterator::AdvanceDynBlk()
-{
- GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
-
- m_edge = &dynBlock->gtDynamicSize;
- assert(*m_edge != nullptr);
- m_advance = &GenTreeUseEdgeIterator::Terminate;
-}
-
//------------------------------------------------------------------------
// GenTreeUseEdgeIterator::AdvanceStoreDynBlk: produces the next operand of a StoreDynBlk node and advances the state.
//
void GenTreeUseEdgeIterator::AdvanceStoreDynBlk()
{
- GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
+ GenTreeStoreDynBlk* const dynBlock = m_node->AsStoreDynBlk();
switch (m_state)
{
case 0:
- m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2;
+ m_edge = &dynBlock->Data();
m_state = 1;
break;
case 1:
@@ -9257,7 +9194,6 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_
case GT_LEA:
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
case GT_STORE_BLK:
case GT_STORE_OBJ:
case GT_STORE_DYN_BLK:
@@ -10824,6 +10760,9 @@ void Compiler::gtDispTree(GenTree* tree,
case NI_System_Object_GetType:
printf(" objGetType");
break;
+ case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant:
+ printf(" isKnownConst");
+ break;
default:
unreached();
@@ -11073,7 +11012,6 @@ void Compiler::gtDispTree(GenTree* tree,
break;
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
if (tree->OperIsCopyBlkOp())
{
printf(" (copy)");
@@ -11086,12 +11024,12 @@ void Compiler::gtDispTree(GenTree* tree,
if (!topOnly)
{
- if (tree->AsDynBlk()->Data() != nullptr)
+ gtDispChild(tree->AsStoreDynBlk()->Addr(), indentStack, IIArc, nullptr, topOnly);
+ if (tree->AsStoreDynBlk()->Data() != nullptr)
{
- gtDispChild(tree->AsDynBlk()->Data(), indentStack, IIArc, nullptr, topOnly);
+ gtDispChild(tree->AsStoreDynBlk()->Data(), indentStack, IIArc, nullptr, topOnly);
}
- gtDispChild(tree->AsDynBlk()->Addr(), indentStack, IIArc, nullptr, topOnly);
- gtDispChild(tree->AsDynBlk()->gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly);
+ gtDispChild(tree->AsStoreDynBlk()->gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly);
}
break;
@@ -11484,7 +11422,7 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr *
displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
}
}
- else if (node->OperIsDynBlkOp())
+ else if (node->OperIs(GT_STORE_DYN_BLK))
{
if (operand == node->AsBlk()->Addr())
{
@@ -11496,19 +11434,7 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr *
}
else
{
- assert(operand == node->AsDynBlk()->gtDynamicSize);
- displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
- }
- }
- else if (node->OperGet() == GT_DYN_BLK)
- {
- if (operand == node->AsBlk()->Addr())
- {
- displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
- }
- else
- {
- assert(operand == node->AsDynBlk()->gtDynamicSize);
+ assert(operand == node->AsStoreDynBlk()->gtDynamicSize);
displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
}
}
@@ -14541,14 +14467,14 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
{
if (flags & GTF_ASG)
{
- // TODO-Cleanup: This only checks for GT_ASG but according to OperRequiresAsgFlag there
- // are many more opers that are considered to have an assignment side effect: atomic ops
+ // TODO-Bug: This only checks for GT_ASG/GT_STORE_DYN_BLK but according to OperRequiresAsgFlag
+ // there are many more opers that are considered to have an assignment side effect: atomic ops
// (GT_CMPXCHG & co.), GT_MEMORYBARRIER (not classified as an atomic op) and HW intrinsic
// memory stores. Atomic ops have special handling in gtExtractSideEffList but the others
// will simply be dropped is they are ever subject to an "extract side effects" operation.
// It is possible that the reason no bugs have yet been observed in this area is that the
// other nodes are likely to always be tree roots.
- if (tree->OperIs(GT_ASG))
+ if (tree->OperIs(GT_ASG, GT_STORE_DYN_BLK))
{
return true;
}
@@ -15274,33 +15200,21 @@ bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bo
GenTree* destAddr = blkNode->Addr();
unsigned width = blkNode->Size();
// Do we care about whether this assigns the entire variable?
- if (pIsEntire != nullptr && blkNode->OperIs(GT_DYN_BLK))
+ if (pIsEntire != nullptr && blkNode->OperIs(GT_STORE_DYN_BLK))
{
- GenTree* blockWidth = blkNode->AsDynBlk()->gtDynamicSize;
+ GenTree* blockWidth = blkNode->AsStoreDynBlk()->gtDynamicSize;
if (blockWidth->IsCnsIntOrI())
{
- if (blockWidth->IsIconHandle())
- {
- // If it's a handle, it must be a class handle. We only create such block operations
- // for initialization of struct types, so the type of the argument(s) will match this
- // type, by construction, and be "entire".
- assert(blockWidth->IsIconHandle(GTF_ICON_CLASS_HDL));
- width = comp->info.compCompHnd->getClassSize(
- CORINFO_CLASS_HANDLE(blockWidth->AsIntConCommon()->IconValue()));
- }
- else
+ assert(blockWidth->AsIntConCommon()->FitsInI32());
+ width = static_cast(blockWidth->AsIntConCommon()->IconValue());
+
+ if (width == 0)
{
- ssize_t swidth = blockWidth->AsIntConCommon()->IconValue();
- assert(swidth >= 0);
- // cpblk of size zero exists in the wild (in yacc-generated code in SQL) and is valid IL.
- if (swidth == 0)
- {
- return false;
- }
- width = unsigned(swidth);
+ return false;
}
}
}
+
return destAddr->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
}
// Otherwise...
@@ -15930,26 +15844,26 @@ bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp)
// this: ADD(CONST FldSeq, baseAddr)
//
// Arguments:
-// comp - the Compiler object
-// pObj - [out] parameter for instance fields, the object reference
-// pStatic - [out] parameter for static fields, the base address
-// pFldSeq - [out] parameter for the field sequence
+// comp - the Compiler object
+// pBaseAddr - [out] parameter for "the base address"
+// pFldSeq - [out] parameter for the field sequence
//
// Return Value:
// If "this" matches patterns denoted above, and the FldSeq found is "full",
// i. e. starts with a class field or a static field, and includes all the
// struct fields that this tree represents the address of, this method will
-// return "true" and set either "pObj" or "pStatic" to some value, which must
-// be used by the caller as the key into the "first field map" to obtain the
-// actual value for the field.
+// return "true" and set either "pBaseAddr" to some value, which must be used
+// by the caller as the key into the "first field map" to obtain the actual
+// value for the field. For instance fields, "base address" will be the object
+// reference, for statics - the address to which the field offset with the
+// field sequence is added, see "impImportStaticFieldAccess" and "fgMorphField".
//
-bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq)
+bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeqNode** pFldSeq)
{
assert(TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF));
- *pObj = nullptr;
- *pStatic = nullptr;
- *pFldSeq = FieldSeqStore::NotAField();
+ *pBaseAddr = nullptr;
+ *pFldSeq = FieldSeqStore::NotAField();
GenTree* baseAddr = nullptr;
FieldSeqNode* fldSeq = nullptr;
@@ -16006,8 +15920,8 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, Fie
// TODO-VNTypes: we will always return the "baseAddr" here for now, but strictly speaking,
// we only need to do that if we have a shared field, to encode the logical "instantiation"
// argument. In all other cases, this serves no purpose and just leads to redundant maps.
- *pStatic = baseAddr;
- *pFldSeq = fldSeq;
+ *pBaseAddr = baseAddr;
+ *pFldSeq = fldSeq;
return true;
}
@@ -16015,8 +15929,8 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, Fie
{
assert(!comp->eeIsValueClass(comp->info.compCompHnd->getFieldClass(fldSeq->GetFieldHandle())));
- *pObj = baseAddr;
- *pFldSeq = fldSeq;
+ *pBaseAddr = baseAddr;
+ *pFldSeq = fldSeq;
return true;
}
@@ -17732,6 +17646,20 @@ bool GenTree::isContainableHWIntrinsic() const
return true;
}
+ default:
+ {
+ return false;
+ }
+ }
+#elif TARGET_ARM64
+ switch (AsHWIntrinsic()->GetHWIntrinsicId())
+ {
+ case NI_Vector64_get_Zero:
+ case NI_Vector128_get_Zero:
+ {
+ return true;
+ }
+
default:
{
return false;
@@ -17931,7 +17859,7 @@ GenTree* Compiler::gtNewSimdAbsNode(
if ((simdBaseType != TYP_LONG) && ((simdSize == 32) || compOpportunisticallyDependsOn(InstructionSet_SSSE3)))
{
NamedIntrinsic intrinsic = (simdSize == 32) ? NI_AVX2_Abs : NI_SSSE3_Abs;
- return gtNewSimdAsHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize);
+ return gtNewSimdHWIntrinsicNode(type, op1, intrinsic, simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
}
else
{
@@ -19359,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;
}
@@ -19388,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;
}
@@ -19397,7 +19333,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op,
getAllBitsSet = NI_Vector128_get_AllBitsSet;
}
- op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize,
+ op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
if (simdBaseType == TYP_FLOAT)
@@ -19411,7 +19347,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op,
simdBaseJitType = CORINFO_TYPE_LONG;
}
- op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize);
+ op2 = gtNewSimdHWIntrinsicNode(simdType, getAllBitsSet, simdBaseJitType, simdSize);
break;
}
#elif defined(TARGET_ARM64)
@@ -19442,7 +19378,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op,
getAllBitsSet = NI_Vector128_get_AllBitsSet;
}
- op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize,
+ op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
if (simdBaseType == TYP_FLOAT)
@@ -19456,7 +19392,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode(genTreeOps op,
simdBaseJitType = CORINFO_TYPE_LONG;
}
- op2 = gtNewSimdHWIntrinsicNode(simdBaseType, getAllBitsSet, simdBaseJitType, simdSize);
+ op2 = gtNewSimdHWIntrinsicNode(simdType, getAllBitsSet, simdBaseJitType, simdSize);
break;
}
#else
@@ -19498,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)
@@ -19518,9 +19446,22 @@ 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, simdBaseType, op1, op2, simdBaseJitType, simdSize,
+ op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
if (simdBaseType == TYP_FLOAT)
@@ -19534,13 +19475,23 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op,
simdBaseJitType = CORINFO_TYPE_LONG;
}
- op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
+ op2 = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
break;
}
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)
@@ -19555,7 +19506,7 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op,
intrinsic = (simdSize == 8) ? NI_Vector64_op_Inequality : NI_Vector128_op_Inequality;
- op1 = gtNewSimdCmpOpNode(op, simdBaseType, op1, op2, simdBaseJitType, simdSize,
+ op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
if (simdBaseType == TYP_FLOAT)
@@ -19569,7 +19520,7 @@ GenTree* Compiler::gtNewSimdCmpOpAnyNode(genTreeOps op,
simdBaseJitType = CORINFO_TYPE_LONG;
}
- op2 = gtNewSimdZeroNode(simdBaseType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
+ op2 = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
break;
}
@@ -19642,7 +19593,8 @@ GenTree* Compiler::gtNewSimdCndSelNode(var_types type,
// result = op2 | op3
return gtNewSimdBinOpNode(GT_OR, type, op2, op3, simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
#elif defined(TARGET_ARM64)
- return gtNewSimdAsHWIntrinsicNode(type, op1, op2, op3, NI_AdvSimd_BitwiseSelect, simdBaseJitType, simdSize);
+ return gtNewSimdHWIntrinsicNode(type, op1, op2, op3, NI_AdvSimd_BitwiseSelect, simdBaseJitType, simdSize,
+ isSimdAsHWIntrinsic);
#else
#error Unsupported platform
#endif // !TARGET_XARCH && !TARGET_ARM64
@@ -19701,7 +19653,7 @@ GenTree* Compiler::gtNewSimdDotProdNode(var_types type,
assert(op2->TypeIs(simdType));
var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType);
- assert(genActualType(simdBaseType) == type);
+ assert(JITtype2varType(simdBaseJitType) == type);
NamedIntrinsic intrinsic = NI_Illegal;
@@ -20734,7 +20686,7 @@ GenTree* Compiler::gtNewSimdSumNode(
for (int i = 0; i < haddCount; i++)
{
op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for vector sum"));
- op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, intrinsic, simdBaseJitType, simdSize);
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, intrinsic, simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
}
if (simdSize == 32)
@@ -20742,14 +20694,15 @@ GenTree* Compiler::gtNewSimdSumNode(
intrinsic = (simdBaseType == TYP_FLOAT) ? NI_SSE_Add : NI_SSE2_Add;
op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL, nullptr DEBUGARG("Clone op1 for vector sum"));
- op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD16, op1, gtNewIconNode(0x01, TYP_INT), NI_AVX_ExtractVector128,
- simdBaseJitType, simdSize);
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, gtNewIconNode(0x01, TYP_INT), NI_AVX_ExtractVector128,
+ simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
- tmp = gtNewSimdAsHWIntrinsicNode(simdType, tmp, NI_Vector256_GetLower, simdBaseJitType, simdSize);
- op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD16, op1, tmp, intrinsic, simdBaseJitType, 16);
+ tmp = gtNewSimdHWIntrinsicNode(simdType, tmp, NI_Vector256_GetLower, simdBaseJitType, simdSize,
+ isSimdAsHWIntrinsic);
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, tmp, intrinsic, simdBaseJitType, 16, isSimdAsHWIntrinsic);
}
- return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize);
+ return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize, isSimdAsHWIntrinsic);
#elif defined(TARGET_ARM64)
switch (simdBaseType)
{
@@ -20757,34 +20710,64 @@ GenTree* Compiler::gtNewSimdSumNode(
case TYP_UBYTE:
case TYP_SHORT:
case TYP_USHORT:
+ {
+ tmp = gtNewSimdHWIntrinsicNode(simdType, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize,
+ isSimdAsHWIntrinsic);
+ return gtNewSimdHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic);
+ }
+
case TYP_INT:
case TYP_UINT:
{
- tmp = gtNewSimdAsHWIntrinsicNode(simdType, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize);
- return gtNewSimdAsHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8);
+ if (simdSize == 8)
+ {
+ op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("Clone op1 for vector sum"));
+ tmp = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_AddPairwise, simdBaseJitType, simdSize,
+ isSimdAsHWIntrinsic);
+ }
+ else
+ {
+ tmp = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, 16,
+ isSimdAsHWIntrinsic);
+ }
+ return gtNewSimdHWIntrinsicNode(type, tmp, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic);
}
+
case TYP_FLOAT:
{
- unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType);
- int haddCount = genLog2(vectorLength);
-
- for (int i = 0; i < haddCount; i++)
+ if (simdSize == 8)
{
- op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL,
- nullptr DEBUGARG("Clone op1 for vector sum"));
- op1 = gtNewSimdAsHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType,
- simdSize);
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType,
+ simdSize, isSimdAsHWIntrinsic);
}
+ else
+ {
+ unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType);
+ int haddCount = genLog2(vectorLength);
- return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize);
+ for (int i = 0; i < haddCount; i++)
+ {
+ op1 = impCloneExpr(op1, &tmp, clsHnd, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("Clone op1 for vector sum"));
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, tmp, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType,
+ simdSize, isSimdAsHWIntrinsic);
+ }
+ }
+ return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector128_ToScalar, simdBaseJitType, simdSize,
+ isSimdAsHWIntrinsic);
}
+
case TYP_DOUBLE:
case TYP_LONG:
case TYP_ULONG:
{
- op1 = gtNewSimdAsHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType,
- simdSize);
- return gtNewSimdAsHWIntrinsicNode(type, op1, NI_Vector64_ToScalar, simdBaseJitType, 8);
+ if (simdSize == 16)
+ {
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddPairwiseScalar, simdBaseJitType,
+ simdSize, isSimdAsHWIntrinsic);
+ }
+ return gtNewSimdHWIntrinsicNode(type, op1, NI_Vector64_ToScalar, simdBaseJitType, 8, isSimdAsHWIntrinsic);
}
default:
{
@@ -21397,7 +21380,9 @@ GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(
bool GenTreeHWIntrinsic::OperIsMemoryLoad() const
{
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
- HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(GetHWIntrinsicId());
+ NamedIntrinsic intrinsicId = GetHWIntrinsicId();
+ HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId);
+
if (category == HW_Category_MemoryLoad)
{
return true;
@@ -21406,17 +21391,42 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad() const
else if (HWIntrinsicInfo::MaybeMemoryLoad(GetHWIntrinsicId()))
{
// Some intrinsics (without HW_Category_MemoryLoad) also have MemoryLoad semantics
+ // This is generally because they have both vector and pointer overloads, e.g.,
+ // * Vector128 BroadcastScalarToVector128(Vector128 value)
+ // * Vector128 BroadcastScalarToVector128(byte* source)
+ // So, we need to check the argument's type is memory-reference or Vector128
- if (category == HW_Category_SIMDScalar)
+ if ((category == HW_Category_SimpleSIMD) || (category == HW_Category_SIMDScalar))
{
- // Avx2.BroadcastScalarToVector128/256 have vector and pointer overloads both, e.g.,
- // Vector128 BroadcastScalarToVector128(Vector128 value)
- // Vector128 BroadcastScalarToVector128(byte* source)
- // So, we need to check the argument's type is memory-reference or Vector128
assert(GetOperandCount() == 1);
- return (GetHWIntrinsicId() == NI_AVX2_BroadcastScalarToVector128 ||
- GetHWIntrinsicId() == NI_AVX2_BroadcastScalarToVector256) &&
- !Op(1)->TypeIs(TYP_SIMD16);
+
+ switch (intrinsicId)
+ {
+ case NI_SSE41_ConvertToVector128Int16:
+ case NI_SSE41_ConvertToVector128Int32:
+ case NI_SSE41_ConvertToVector128Int64:
+ case NI_AVX2_BroadcastScalarToVector128:
+ case NI_AVX2_BroadcastScalarToVector256:
+ case NI_AVX2_ConvertToVector256Int16:
+ case NI_AVX2_ConvertToVector256Int32:
+ case NI_AVX2_ConvertToVector256Int64:
+ {
+ CorInfoType auxiliaryType = GetAuxiliaryJitType();
+
+ if (auxiliaryType == CORINFO_TYPE_PTR)
+ {
+ return true;
+ }
+
+ assert(auxiliaryType == CORINFO_TYPE_UNDEF);
+ return false;
+ }
+
+ default:
+ {
+ unreached();
+ }
+ }
}
else if (category == HW_Category_IMM)
{
@@ -22015,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/gentree.h b/src/coreclr/jit/gentree.h
index 3c5fff088cef14..085bc17a1e5107 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -1235,12 +1235,10 @@ struct GenTree
bool OperIsBlkOp();
bool OperIsCopyBlkOp();
bool OperIsInitBlkOp();
- bool OperIsDynBlkOp();
static bool OperIsBlk(genTreeOps gtOper)
{
- return ((gtOper == GT_BLK) || (gtOper == GT_OBJ) || (gtOper == GT_DYN_BLK) || (gtOper == GT_STORE_BLK) ||
- (gtOper == GT_STORE_OBJ) || (gtOper == GT_STORE_DYN_BLK));
+ return (gtOper == GT_BLK) || (gtOper == GT_OBJ) || OperIsStoreBlk(gtOper);
}
bool OperIsBlk() const
@@ -1248,19 +1246,9 @@ struct GenTree
return OperIsBlk(OperGet());
}
- static bool OperIsDynBlk(genTreeOps gtOper)
- {
- return ((gtOper == GT_DYN_BLK) || (gtOper == GT_STORE_DYN_BLK));
- }
-
- bool OperIsDynBlk() const
- {
- return OperIsDynBlk(OperGet());
- }
-
static bool OperIsStoreBlk(genTreeOps gtOper)
{
- return ((gtOper == GT_STORE_BLK) || (gtOper == GT_STORE_OBJ) || (gtOper == GT_STORE_DYN_BLK));
+ return StaticOperIs(gtOper, GT_STORE_BLK, GT_STORE_OBJ, GT_STORE_DYN_BLK);
}
bool OperIsStoreBlk() const
@@ -1704,6 +1692,8 @@ struct GenTree
inline bool IsIntegralConst(ssize_t constVal) const;
inline bool IsIntegralConstVector(ssize_t constVal) const;
inline bool IsSIMDZero() const;
+ inline bool IsFloatPositiveZero() const;
+ inline bool IsVectorZero() const;
inline bool IsBoxedValue();
@@ -1917,7 +1907,7 @@ struct GenTree
// where Y is an arbitrary tree, and X is a lclVar.
unsigned IsLclVarUpdateTree(GenTree** otherTree, genTreeOps* updateOper);
- bool IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq);
+ bool IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeqNode** pFldSeq);
// Requires "this" to be the address of an array (the child of a GT_IND labeled with GTF_IND_ARR_INDEX).
// Sets "pArr" to the node representing the array (either an array object pointer, or perhaps a byref to the some
@@ -2076,9 +2066,14 @@ struct GenTree
SetAllEffectsFlags(source->gtFlags & GTF_ALL_EFFECT);
}
- void SetAllEffectsFlags(GenTree* source, GenTree* otherSource)
+ void SetAllEffectsFlags(GenTree* firstSource, GenTree* secondSource)
+ {
+ SetAllEffectsFlags((firstSource->gtFlags | secondSource->gtFlags) & GTF_ALL_EFFECT);
+ }
+
+ void SetAllEffectsFlags(GenTree* firstSource, GenTree* secondSource, GenTree* thirdSouce)
{
- SetAllEffectsFlags((source->gtFlags | otherSource->gtFlags) & GTF_ALL_EFFECT);
+ SetAllEffectsFlags((firstSource->gtFlags | secondSource->gtFlags | thirdSouce->gtFlags) & GTF_ALL_EFFECT);
}
void SetAllEffectsFlags(GenTreeFlags sourceFlags)
@@ -2097,7 +2092,7 @@ struct GenTree
inline bool IsCnsFltOrDbl() const;
- inline bool IsCnsNonZeroFltOrDbl();
+ inline bool IsCnsNonZeroFltOrDbl() const;
bool IsIconHandle() const
{
@@ -2743,7 +2738,6 @@ class GenTreeUseEdgeIterator final
void AdvanceCmpXchg();
void AdvanceArrElem();
void AdvanceArrOffset();
- void AdvanceDynBlk();
void AdvanceStoreDynBlk();
void AdvanceFieldList();
void AdvancePhi();
@@ -5983,8 +5977,6 @@ struct GenTreeAddrMode : public GenTreeOp
struct GenTreeIndir : public GenTreeOp
{
// The address for the indirection.
- // Since GenTreeDynBlk derives from this, but is an "EXOP" (i.e. it has extra fields),
- // we can't access Op1 and Op2 in the normal manner if we may have a DynBlk.
GenTree*& Addr()
{
return gtOp1;
@@ -6051,7 +6043,7 @@ struct GenTreeBlk : public GenTreeIndir
void SetLayout(ClassLayout* layout)
{
- assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK));
+ assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK));
m_layout = layout;
}
@@ -6068,7 +6060,7 @@ struct GenTreeBlk : public GenTreeIndir
// The size of the buffer to be copied.
unsigned Size() const
{
- assert((m_layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK));
+ assert((m_layout != nullptr) || OperIs(GT_STORE_DYN_BLK));
return (m_layout != nullptr) ? m_layout->GetSize() : 0;
}
@@ -6106,7 +6098,7 @@ struct GenTreeBlk : public GenTreeIndir
#endif
{
assert(OperIsBlk(oper));
- assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK));
+ assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK));
gtFlags |= (addr->gtFlags & GTF_ALL_EFFECT);
}
@@ -6119,7 +6111,7 @@ struct GenTreeBlk : public GenTreeIndir
#endif
{
assert(OperIsBlk(oper));
- assert((layout != nullptr) || OperIs(GT_DYN_BLK, GT_STORE_DYN_BLK));
+ assert((layout != nullptr) || OperIs(GT_STORE_DYN_BLK));
gtFlags |= (addr->gtFlags & GTF_ALL_EFFECT);
gtFlags |= (data->gtFlags & GTF_ALL_EFFECT);
}
@@ -6168,28 +6160,33 @@ struct GenTreeObj : public GenTreeBlk
#endif
};
-// gtDynBlk -- 'dynamic block' (GT_DYN_BLK).
+// GenTreeStoreDynBlk -- 'dynamic block store' (GT_STORE_DYN_BLK).
//
-// This node is used for block values that have a dynamic size.
-// Note that such a value can never have GC pointers.
-
-struct GenTreeDynBlk : public GenTreeBlk
+// This node is used to represent stores that have a dynamic size - the "cpblk" and "initblk"
+// IL instructions are implemented with it. Note that such stores assume the input has no GC
+// pointers in it, and as such do not ever use write barriers.
+//
+// The "Data()" member of this node will either be a "dummy" IND(struct) node, for "cpblk", or
+// the zero constant/INIT_VAL for "initblk".
+//
+struct GenTreeStoreDynBlk : public GenTreeBlk
{
public:
GenTree* gtDynamicSize;
- GenTreeDynBlk(GenTree* addr, GenTree* dynamicSize)
- : GenTreeBlk(GT_DYN_BLK, TYP_STRUCT, addr, nullptr), gtDynamicSize(dynamicSize)
+ GenTreeStoreDynBlk(GenTree* dstAddr, GenTree* data, GenTree* dynamicSize)
+ : GenTreeBlk(GT_STORE_DYN_BLK, TYP_VOID, dstAddr, data, nullptr), gtDynamicSize(dynamicSize)
{
- // Conservatively the 'addr' could be null or point into the global heap.
- gtFlags |= GTF_EXCEPT | GTF_GLOB_REF;
+ // Conservatively the 'dstAddr' could be null or point into the global heap.
+ // Likewise, this is a store and so must be marked with the GTF_ASG flag.
+ gtFlags |= (GTF_ASG | GTF_EXCEPT | GTF_GLOB_REF);
gtFlags |= (dynamicSize->gtFlags & GTF_ALL_EFFECT);
}
#if DEBUGGABLE_GENTREE
protected:
friend GenTree;
- GenTreeDynBlk() : GenTreeBlk()
+ GenTreeStoreDynBlk() : GenTreeBlk()
{
}
#endif // DEBUGGABLE_GENTREE
@@ -7488,20 +7485,7 @@ struct GenTreeCC final : public GenTree
inline bool GenTree::OperIsBlkOp()
{
- return ((gtOper == GT_ASG) && varTypeIsStruct(AsOp()->gtOp1)) || (OperIsBlk() && (AsBlk()->Data() != nullptr));
-}
-
-inline bool GenTree::OperIsDynBlkOp()
-{
- if (gtOper == GT_ASG)
- {
- return gtGetOp1()->OperGet() == GT_DYN_BLK;
- }
- else if (gtOper == GT_STORE_DYN_BLK)
- {
- return true;
- }
- return false;
+ return ((gtOper == GT_ASG) && varTypeIsStruct(AsOp()->gtOp1)) || OperIsStoreBlk();
}
inline bool GenTree::OperIsInitBlkOp()
@@ -7650,6 +7634,79 @@ inline bool GenTree::IsSIMDZero() const
return false;
}
+//-------------------------------------------------------------------
+// IsFloatPositiveZero: returns true if this is exactly a const float value of postive zero (+0.0)
+//
+// Returns:
+// True if this represents a const floating-point value of exactly positive zero (+0.0).
+// Will return false if the value is negative zero (-0.0).
+//
+inline bool GenTree::IsFloatPositiveZero() const
+{
+ return IsCnsFltOrDbl() && !IsCnsNonZeroFltOrDbl();
+}
+
+//-------------------------------------------------------------------
+// IsVectorZero: returns true if this is an integral or floating-point (SIMD or HW intrinsic) vector
+// with all its elements equal to zero.
+//
+// Returns:
+// True if this represents an integral or floating-point const (SIMD or HW intrinsic) vector with all its elements
+// equal to zero.
+//
+// TODO: We already have IsSIMDZero() and IsIntegralConstVector(0),
+// however, IsSIMDZero() does not cover hardware intrinsics, and IsIntegralConstVector(0) does not cover floating
+// point. In order to not risk adverse behaviour by modifying those, this function 'IsVectorZero' was introduced.
+// At some point, it makes sense to normalize this logic to be a single function call rather than have several
+// separate ones; preferably this one.
+inline bool GenTree::IsVectorZero() const
+{
+#ifdef FEATURE_SIMD
+ if (gtOper == GT_SIMD)
+ {
+ const GenTreeSIMD* node = AsSIMD();
+
+ if (node->GetSIMDIntrinsicId() == SIMDIntrinsicInit)
+ {
+ return (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero());
+ }
+ }
+#endif
+
+#ifdef FEATURE_HW_INTRINSICS
+ if (gtOper == GT_HWINTRINSIC)
+ {
+ const GenTreeHWIntrinsic* node = AsHWIntrinsic();
+ const var_types simdBaseType = node->GetSimdBaseType();
+
+ if (varTypeIsIntegral(simdBaseType) || varTypeIsFloating(simdBaseType))
+ {
+ const NamedIntrinsic intrinsicId = node->GetHWIntrinsicId();
+
+ if (node->GetOperandCount() == 0)
+ {
+#if defined(TARGET_XARCH)
+ return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero);
+#elif defined(TARGET_ARM64)
+ return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero);
+#endif // !TARGET_XARCH && !TARGET_ARM64
+ }
+ else if ((node->GetOperandCount() == 1) &&
+ (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero()))
+ {
+#if defined(TARGET_XARCH)
+ return (intrinsicId == NI_Vector128_Create) || (intrinsicId == NI_Vector256_Create);
+#elif defined(TARGET_ARM64)
+ return (intrinsicId == NI_Vector64_Create) || (intrinsicId == NI_Vector128_Create);
+#endif // !TARGET_XARCH && !TARGET_ARM64
+ }
+ }
+ }
+#endif // FEATURE_HW_INTRINSICS
+
+ return false;
+}
+
inline bool GenTree::IsBoxedValue()
{
assert(gtOper != GT_BOX || AsBox()->BoxOp() != nullptr);
@@ -8328,7 +8385,7 @@ inline bool GenTree::IsCnsFltOrDbl() const
return OperGet() == GT_CNS_DBL;
}
-inline bool GenTree::IsCnsNonZeroFltOrDbl()
+inline bool GenTree::IsCnsNonZeroFltOrDbl() const
{
if (OperGet() == GT_CNS_DBL)
{
diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h
index 5a5afe6aad0504..9b40861fef0fd0 100644
--- a/src/coreclr/jit/gtlist.h
+++ b/src/coreclr/jit/gtlist.h
@@ -90,8 +90,7 @@ GTNODE(OBJ , GenTreeObj ,0,(GTK_UNOP|GTK_EXOP))
GTNODE(STORE_OBJ , GenTreeObj ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Object that MAY have gc pointers, and thus includes the relevant gc layout info.
GTNODE(BLK , GenTreeBlk ,0,(GTK_UNOP|GTK_EXOP)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields)
GTNODE(STORE_BLK , GenTreeBlk ,0,(GTK_BINOP|GTK_EXOP|GTK_NOVALUE)) // Block/object with no gc pointers, and with a known size (e.g. a struct with no gc fields)
-GTNODE(DYN_BLK , GenTreeDynBlk ,0,GTK_SPECIAL) // Dynamically sized block object
-GTNODE(STORE_DYN_BLK , GenTreeDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block object
+GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,(GTK_SPECIAL|GTK_NOVALUE)) // Dynamically sized block store
GTNODE(BOX , GenTreeBox ,0,(GTK_UNOP|GTK_EXOP|GTK_NOTLIR))
GTNODE(FIELD , GenTreeField ,0,(GTK_UNOP|GTK_EXOP)) // Member-field
diff --git a/src/coreclr/jit/gtstructs.h b/src/coreclr/jit/gtstructs.h
index 591753837fe892..63730117790201 100644
--- a/src/coreclr/jit/gtstructs.h
+++ b/src/coreclr/jit/gtstructs.h
@@ -92,14 +92,14 @@ GTSTRUCT_2(ClsVar , GT_CLS_VAR, GT_CLS_VAR_ADDR)
GTSTRUCT_1(ArgPlace , GT_ARGPLACE)
GTSTRUCT_1(CmpXchg , GT_CMPXCHG)
GTSTRUCT_1(AddrMode , GT_LEA)
-GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_DYN_BLK, GT_STORE_DYN_BLK)
+GTSTRUCT_N(Blk , GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK)
GTSTRUCT_2(Obj , GT_OBJ, GT_STORE_OBJ)
-GTSTRUCT_2(DynBlk , GT_DYN_BLK, GT_STORE_DYN_BLK)
+GTSTRUCT_1(StoreDynBlk , GT_STORE_DYN_BLK)
GTSTRUCT_1(Qmark , GT_QMARK)
GTSTRUCT_1(PhiArg , GT_PHI_ARG)
GTSTRUCT_1(Phi , GT_PHI)
GTSTRUCT_1(StoreInd , GT_STOREIND)
-GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_DYN_BLK, GT_STORE_DYN_BLK)
+GTSTRUCT_N(Indir , GT_STOREIND, GT_IND, GT_NULLCHECK, GT_BLK, GT_STORE_BLK, GT_OBJ, GT_STORE_OBJ, GT_STORE_DYN_BLK)
#if FEATURE_ARG_SPLIT
GTSTRUCT_2_SPECIAL(PutArgStk, GT_PUTARG_STK, GT_PUTARG_SPLIT)
GTSTRUCT_1(PutArgSplit , GT_PUTARG_SPLIT)
diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp
index dfde343fe52cb6..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;
@@ -1007,6 +1026,41 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
retNode = isScalar ? gtNewScalarHWIntrinsicNode(retType, op1, intrinsic)
: gtNewSimdHWIntrinsicNode(retType, op1, intrinsic, simdBaseJitType, simdSize);
+
+#if defined(TARGET_XARCH)
+ switch (intrinsic)
+ {
+ case NI_SSE41_ConvertToVector128Int16:
+ case NI_SSE41_ConvertToVector128Int32:
+ case NI_SSE41_ConvertToVector128Int64:
+ case NI_AVX2_BroadcastScalarToVector128:
+ case NI_AVX2_BroadcastScalarToVector256:
+ case NI_AVX2_ConvertToVector256Int16:
+ case NI_AVX2_ConvertToVector256Int32:
+ case NI_AVX2_ConvertToVector256Int64:
+ {
+ // These intrinsics have both pointer and vector overloads
+ // We want to be able to differentiate between them so lets
+ // just track the aux type as a ptr or undefined, depending
+
+ CorInfoType auxiliaryType = CORINFO_TYPE_UNDEF;
+
+ if (!varTypeIsSIMD(op1->TypeGet()))
+ {
+ auxiliaryType = CORINFO_TYPE_PTR;
+ }
+
+ retNode->AsHWIntrinsic()->SetAuxiliaryJitType(auxiliaryType);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+#endif // TARGET_XARCH
+
break;
case 2:
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/hwintrinsicarm64.cpp b/src/coreclr/jit/hwintrinsicarm64.cpp
index 0c1b01e64ed931..3e5c612236050a 100644
--- a/src/coreclr/jit/hwintrinsicarm64.cpp
+++ b/src/coreclr/jit/hwintrinsicarm64.cpp
@@ -339,6 +339,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
GenTree* op1 = nullptr;
GenTree* op2 = nullptr;
GenTree* op3 = nullptr;
+ GenTree* op4 = nullptr;
switch (intrinsic)
{
@@ -601,11 +602,16 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
{
assert(sig->numArgs == 2);
- op2 = impSIMDPopStack(retType);
- op1 = impSIMDPopStack(retType);
+ if (!varTypeIsLong(simdBaseType))
+ {
+ var_types simdType = getSIMDTypeForSize(simdSize);
- retNode =
- gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
+ op2 = impSIMDPopStack(simdType);
+ op1 = impSIMDPopStack(simdType);
+
+ retNode = gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize,
+ /* isSimdAsHWIntrinsic */ false);
+ }
break;
}
@@ -681,6 +687,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case TYP_UBYTE:
{
op2 = gtNewIconNode(0x80);
+ simdBaseType = TYP_UBYTE;
+ simdBaseJitType = CORINFO_TYPE_UBYTE;
vectorCreateOp1 = gtNewLconNode(0x00FFFEFDFCFBFAF9);
if (simdSize == 16)
@@ -705,30 +713,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case TYP_INT:
case TYP_UINT:
- {
- op2 = gtNewIconNode(0x80000000);
- vectorCreateOp1 = gtNewLconNode(0xFFFFFFE2FFFFFFE1);
-
- if (simdSize == 16)
- {
- vectorCreateOp2 = gtNewLconNode(0xFFFFFFE4FFFFFFE3);
- }
- break;
- }
-
- case TYP_LONG:
- case TYP_ULONG:
- {
- op2 = gtNewLconNode(0x8000000000000000);
- vectorCreateOp1 = gtNewLconNode(0xFFFFFFFFFFFFFFC1);
-
- if (simdSize == 16)
- {
- vectorCreateOp2 = gtNewLconNode(0xFFFFFFFFFFFFFFC2);
- }
- break;
- }
-
case TYP_FLOAT:
{
op2 = gtNewIconNode(0x80000000);
@@ -743,6 +727,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
break;
}
+ case TYP_LONG:
+ case TYP_ULONG:
case TYP_DOUBLE:
{
op2 = gtNewLconNode(0x8000000000000000);
@@ -774,17 +760,27 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
gtNewSimdHWIntrinsicNode(simdType, vectorCreateOp1, NI_Vector64_Create, vectorCreateType, simdSize);
}
+ op2 =
+ gtNewSimdCreateBroadcastNode(simdType, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
+
op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op2, NI_AdvSimd_And, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
- op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op3, NI_AdvSimd_ShiftLogical, simdBaseJitType, simdSize,
+ NamedIntrinsic shiftIntrinsic = NI_AdvSimd_ShiftLogical;
+
+ if ((simdSize == 8) && varTypeIsLong(simdBaseType))
+ {
+ shiftIntrinsic = NI_AdvSimd_ShiftLogicalScalar;
+ }
+
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op3, shiftIntrinsic, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
if (varTypeIsByte(simdBaseType) && (simdSize == 16))
{
- CORINFO_CLASS_HANDLE clsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType);
+ CORINFO_CLASS_HANDLE simdClsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType);
- op1 = impCloneExpr(op1, &op2, clsHnd, (unsigned)CHECK_SPILL_ALL,
+ op1 = impCloneExpr(op1, &op2, simdClsHnd, (unsigned)CHECK_SPILL_ALL,
nullptr DEBUGARG("Clone op1 for vector extractmostsignificantbits"));
op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_Vector128_GetLower, simdBaseJitType, simdSize,
@@ -793,9 +789,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
/* isSimdAsHWIntrinsic */ false);
op1 = gtNewSimdHWIntrinsicNode(simdBaseType, op1, NI_Vector64_ToScalar, simdBaseJitType, 8,
/* isSimdAsHWIntrinsic */ false);
- op1 = gtNewCastNode(TYP_INT, op1, /* isUnsigned */ true, simdBaseType);
+ op1 = gtNewCastNode(TYP_INT, op1, /* isUnsigned */ true, TYP_INT);
- GenTree* zero = gtNewSimdHWIntrinsicNode(retType, NI_Vector128_get_Zero, simdBaseJitType, simdSize);
+ GenTree* zero = gtNewSimdZeroNode(simdType, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
ssize_t index = 8 / genTypeSize(simdBaseType);
op2 = gtNewSimdHWIntrinsicNode(simdType, op2, zero, gtNewIconNode(index), NI_AdvSimd_ExtractVector128,
@@ -806,7 +802,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
/* isSimdAsHWIntrinsic */ false);
op2 = gtNewSimdHWIntrinsicNode(simdBaseType, op2, NI_Vector64_ToScalar, simdBaseJitType, 8,
/* isSimdAsHWIntrinsic */ false);
- op2 = gtNewCastNode(TYP_INT, op2, /* isUnsigned */ true, simdBaseType);
+ op2 = gtNewCastNode(TYP_INT, op2, /* isUnsigned */ true, TYP_INT);
op2 = gtNewOperNode(GT_LSH, TYP_INT, op2, gtNewIconNode(8));
retNode = gtNewOperNode(GT_OR, TYP_INT, op1, op2);
@@ -815,8 +811,20 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
{
if (!varTypeIsLong(simdBaseType))
{
- op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType,
- simdSize, /* isSimdAsHWIntrinsic */ false);
+ if ((simdSize == 8) && ((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)))
+ {
+ CORINFO_CLASS_HANDLE simdClsHnd = gtGetStructHandleForSIMD(simdType, simdBaseJitType);
+
+ op1 = impCloneExpr(op1, &op2, simdClsHnd, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("Clone op1 for vector extractmostsignificantbits"));
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, op2, NI_AdvSimd_AddPairwise, simdBaseJitType,
+ simdSize, /* isSimdAsHWIntrinsic */ false);
+ }
+ else
+ {
+ op1 = gtNewSimdHWIntrinsicNode(TYP_SIMD8, op1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType,
+ simdSize, /* isSimdAsHWIntrinsic */ false);
+ }
}
else if (simdSize == 16)
{
@@ -829,7 +837,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
if ((simdBaseType != TYP_INT) && (simdBaseType != TYP_UINT))
{
- retNode = gtNewCastNode(TYP_INT, retNode, /* isUnsigned */ true, simdBaseType);
+ retNode = gtNewCastNode(TYP_INT, retNode, /* isUnsigned */ true, TYP_INT);
}
}
break;
@@ -1398,9 +1406,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector128_Store:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize);
break;
@@ -1410,6 +1419,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector128_StoreAligned:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
if (!opts.MinOpts())
{
@@ -1419,7 +1429,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize);
break;
@@ -1429,6 +1439,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector128_StoreAlignedNonTemporal:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
if (!opts.MinOpts())
{
@@ -1438,7 +1449,7 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
// ARM64 has non-temporal stores (STNP) but we don't currently support them
@@ -1449,6 +1460,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector64_StoreUnsafe:
case NI_Vector128_StoreUnsafe:
{
+ var_types simdType = getSIMDTypeForSize(simdSize);
+
if (sig->numArgs == 3)
{
op3 = impPopStack().val;
@@ -1459,13 +1472,13 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
if (sig->numArgs == 3)
{
- op3 = gtNewIconNode(genTypeSize(simdBaseType), op2->TypeGet());
- op2 = gtNewOperNode(GT_MUL, op2->TypeGet(), op2, op3);
- op2 = gtNewOperNode(GT_ADD, op1->TypeGet(), op1, op2);
+ op4 = gtNewIconNode(genTypeSize(simdBaseType), op3->TypeGet());
+ op3 = gtNewOperNode(GT_MUL, op3->TypeGet(), op3, op4);
+ op2 = gtNewOperNode(GT_ADD, op2->TypeGet(), op2, op3);
}
retNode = gtNewSimdHWIntrinsicNode(retType, op2, op1, NI_AdvSimd_Store, simdBaseJitType, simdSize);
@@ -1476,8 +1489,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector128_Sum:
{
assert(sig->numArgs == 1);
+ var_types simdType = getSIMDTypeForSize(simdSize);
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
break;
}
diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp
index 706b988f049e51..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;
@@ -496,6 +499,29 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt);
break;
+ case NI_AdvSimd_CompareEqual:
+ case NI_AdvSimd_Arm64_CompareEqual:
+ case NI_AdvSimd_Arm64_CompareEqualScalar:
+ if (intrin.op1->isContained())
+ {
+ assert(HWIntrinsicInfo::SupportsContainment(intrin.id));
+ assert(intrin.op1->IsVectorZero());
+
+ GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt);
+ }
+ else if (intrin.op2->isContained())
+ {
+ assert(HWIntrinsicInfo::SupportsContainment(intrin.id));
+ assert(intrin.op2->IsVectorZero());
+
+ GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt);
+ }
+ else
+ {
+ GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt);
+ }
+ break;
+
case NI_AdvSimd_AbsoluteCompareLessThan:
case NI_AdvSimd_AbsoluteCompareLessThanOrEqual:
case NI_AdvSimd_CompareLessThan:
diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
index cd9e0f8f8fc3d5..10c8dcaedb197a 100644
--- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
+++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp
@@ -27,11 +27,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// assertIsContainableHWIntrinsicOp: Asserts that op is containable by node
//
// Arguments:
-// lowering - The lowering phase from the compiler
-// node - The HWIntrinsic node that has the contained node
-// op - The op that is contained
+// lowering - The lowering phase from the compiler
+// containingNode - The HWIntrinsic node that has the contained node
+// containedNode - The node that is contained
//
-static void assertIsContainableHWIntrinsicOp(Lowering* lowering, GenTreeHWIntrinsic* node, GenTree* op)
+static void assertIsContainableHWIntrinsicOp(Lowering* lowering,
+ GenTreeHWIntrinsic* containingNode,
+ GenTree* containedNode)
{
#if DEBUG
// The Lowering::IsContainableHWIntrinsicOp call is not quite right, since it follows pre-register allocation
@@ -39,14 +41,15 @@ static void assertIsContainableHWIntrinsicOp(Lowering* lowering, GenTreeHWIntrin
//
// We use isContainable to track the special HWIntrinsic node containment rules (for things like LoadAligned and
// LoadUnaligned) and we use the supportsRegOptional check to support general-purpose loads (both from stack
- // spillage
- // and for isUsedFromMemory contained nodes, in the case where the register allocator decided to not allocate a
- // register
- // in the first place).
+ // spillage and for isUsedFromMemory contained nodes, in the case where the register allocator decided to not
+ // allocate a register in the first place).
+
+ GenTree* node = containedNode;
+ bool supportsRegOptional = false;
+ bool isContainable = lowering->TryGetContainableHWIntrinsicOp(containingNode, &node, &supportsRegOptional);
- bool supportsRegOptional = false;
- bool isContainable = lowering->IsContainableHWIntrinsicOp(node, op, &supportsRegOptional);
assert(isContainable || supportsRegOptional);
+ assert(node == containedNode);
#endif // DEBUG
}
@@ -83,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));
@@ -521,6 +527,14 @@ void CodeGen::genHWIntrinsic_R_RM(
break;
}
+ case GT_CNS_DBL:
+ {
+ GenTreeDblCon* cns = rmOp->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_R_C(ins, attr, reg, hnd, 0);
+ return;
+ }
+
default:
{
unreached();
@@ -737,6 +751,14 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins,
break;
}
+ case GT_CNS_DBL:
+ {
+ GenTreeDblCon* cns = op2->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_SIMD_R_R_C_I(ins, simdSize, targetReg, op1Reg, hnd, 0, ival);
+ return;
+ }
+
default:
unreached();
break;
@@ -886,6 +908,14 @@ void CodeGen::genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins,
break;
}
+ case GT_CNS_DBL:
+ {
+ GenTreeDblCon* cns = op2->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_SIMD_R_R_C_R(ins, simdSize, targetReg, op1Reg, op3Reg, hnd, 0);
+ return;
+ }
+
default:
unreached();
break;
@@ -1012,6 +1042,14 @@ void CodeGen::genHWIntrinsic_R_R_R_RM(
break;
}
+ case GT_CNS_DBL:
+ {
+ GenTreeDblCon* cns = op3->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_SIMD_R_R_R_C(ins, attr, targetReg, op1Reg, op2Reg, hnd, 0);
+ return;
+ }
+
default:
unreached();
break;
diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h
index 4b2e3fa132ad7f..7d4582db97616a 100644
--- a/src/coreclr/jit/hwintrinsiclistarm64.h
+++ b/src/coreclr/jit/hwintrinsiclistarm64.h
@@ -42,28 +42,28 @@ HARDWARE_INTRINSIC(Vector64, ConvertToUInt64,
HARDWARE_INTRINSIC(Vector64, Create, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_invalid, INS_invalid, INS_fmov, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Vector64, Divide, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector64, get_Count, 8, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector64, get_Zero, 8, 0, {INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi, INS_movi}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector64, GetElement, 8, 2, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector64, GreaterThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, GreaterThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, GreaterThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, GreaterThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, LessThan, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, LessThanAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, LessThanAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, LessThanOrEqual, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, LessThanOrEqualAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Load, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, LoadAligned, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, LoadAlignedNonTemporal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
@@ -90,12 +90,12 @@ HARDWARE_INTRINSIC(Vector64, ShiftLeft,
HARDWARE_INTRINSIC(Vector64, ShiftRightArithmetic, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, ShiftRightLogical, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, Store, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, Store, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, Subtract, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(Vector64, ToVector128, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(Vector64, ToVector128Unsafe, 8, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen)
@@ -140,11 +140,11 @@ HARDWARE_INTRINSIC(Vector128, ConvertToUInt64,
HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_fmov, INS_fmov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni, INS_mvni}, HW_Category_Helper, HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoCodeGen|HW_Flag_SpecialImport)
@@ -153,17 +153,17 @@ HARDWARE_INTRINSIC(Vector128, GetElement,
HARDWARE_INTRINSIC(Vector128, GetLower, 16, 1, {INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov, INS_mov}, HW_Category_SIMD, HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(Vector128, GetUpper, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport)
HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Load, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
@@ -190,12 +190,12 @@ HARDWARE_INTRINSIC(Vector128, ShiftLeft,
HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_smov, INS_umov, INS_smov, INS_umov, INS_smov, INS_umov, INS_umov, INS_umov, INS_dup, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(Vector128, WidenLower, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, WidenUpper, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
@@ -240,7 +240,7 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear,
HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar)
-HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative)
+HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen)
@@ -492,8 +492,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar,
HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics)
HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen)
HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag)
-HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
+HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_NoFlag)
HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar)
diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h
index 95ab714ae6334a..7c80de358cf4ef 100644
--- a/src/coreclr/jit/hwintrinsiclistxarch.h
+++ b/src/coreclr/jit/hwintrinsiclistxarch.h
@@ -59,28 +59,28 @@ HARDWARE_INTRINSIC(Vector128, ConvertToUInt64,
HARDWARE_INTRINSIC(Vector128, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, get_Count, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, get_Zero, 16, 0, {INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps, INS_xorps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, GetElement, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector128, GreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, GreaterThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, LessThanOrEqualAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Load, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LoadAligned, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, LoadAlignedNonTemporal, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
@@ -107,12 +107,12 @@ HARDWARE_INTRINSIC(Vector128, ShiftLeft,
HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, ToVector256, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector128, ToVector256Unsafe, 16, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
@@ -155,11 +155,11 @@ HARDWARE_INTRINSIC(Vector256, ConvertToUInt64,
HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movd, INS_movss, INS_movsdsse2}, HW_Category_SIMDScalar, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector256, Divide, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_pcmpeqd, INS_cmpps, INS_cmpps}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector256, get_Count, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
@@ -167,17 +167,17 @@ HARDWARE_INTRINSIC(Vector256, get_Zero,
HARDWARE_INTRINSIC(Vector256, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movdqu, INS_movups, INS_movupd}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector256, GreaterThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, GreaterThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, GreaterThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, GreaterThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, LessThan, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, LessThanAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, LessThanAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, LessThanOrEqual, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, LessThanOrEqualAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Load, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, LoadAligned, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, LoadAlignedNonTemporal, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
@@ -204,12 +204,12 @@ HARDWARE_INTRINSIC(Vector256, ShiftLeft,
HARDWARE_INTRINSIC(Vector256, ShiftRightArithmetic, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, ShiftRightLogical, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, Store, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, Store, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, Subtract, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
-HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen)
+HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen)
HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movss, INS_movsdsse2}, HW_Category_SimpleSIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(Vector256, WidenLower, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
HARDWARE_INTRINSIC(Vector256, WidenUpper, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg)
@@ -494,9 +494,9 @@ HARDWARE_INTRINSIC(SSE41, BlendVariable,
HARDWARE_INTRINSIC(SSE41, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41, CeilingScalar, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundss, INS_roundsd}, HW_Category_SIMDScalar, HW_Flag_CopyUpperBits)
HARDWARE_INTRINSIC(SSE41, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pcmpeqq, INS_pcmpeqq, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_Commutative)
-HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int16, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int32, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int64, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics)
+HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int16, 16, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad)
+HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int32, 16, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad)
+HARDWARE_INTRINSIC(SSE41, ConvertToVector128Int64, 16, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_MaybeMemoryLoad)
HARDWARE_INTRINSIC(SSE41, DotProduct, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dpps, INS_dppd}, HW_Category_IMM, HW_Flag_FullRangeIMM)
HARDWARE_INTRINSIC(SSE41, Extract, 16, 2, {INS_pextrb, INS_pextrb, INS_invalid, INS_invalid, INS_pextrd, INS_pextrd, INS_invalid, INS_invalid, INS_extractps, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiIns|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(SSE41, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_roundps, INS_roundpd}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics)
@@ -649,9 +649,9 @@ HARDWARE_INTRINSIC(AVX2, CompareLessThan,
HARDWARE_INTRINSIC(AVX2, ExtractVector128, 32, 2, {INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_vextracti128, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM)
HARDWARE_INTRINSIC(AVX2, ConvertToInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(AVX2, ConvertToUInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics)
-HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int16, 32, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
-HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg)
+HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int16, 32, 1, {INS_pmovsxbw, INS_pmovzxbw, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad)
+HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 1, {INS_pmovsxbd, INS_pmovzxbd, INS_pmovsxwd, INS_pmovzxwd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad)
+HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 1, {INS_pmovsxbq, INS_pmovzxbq, INS_pmovsxwq, INS_pmovzxwq, INS_pmovsxdq, INS_pmovzxdq, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_MaybeMemoryLoad)
HARDWARE_INTRINSIC(AVX2, GatherVector128, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AVX2, GatherVector256, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment)
HARDWARE_INTRINSIC(AVX2, GatherMaskVector128, 16, 5, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment)
diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp
index e6f499588c5285..aec1be705f3db8 100644
--- a/src/coreclr/jit/hwintrinsicxarch.cpp
+++ b/src/coreclr/jit/hwintrinsicxarch.cpp
@@ -535,6 +535,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
GenTree* op1 = nullptr;
GenTree* op2 = nullptr;
GenTree* op3 = nullptr;
+ GenTree* op4 = nullptr;
if (!featureSIMD || !IsBaselineSimdIsaSupported())
{
@@ -947,6 +948,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector256_Dot:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
if (varTypeIsByte(simdBaseType) || varTypeIsLong(simdBaseType))
{
@@ -973,8 +975,8 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
}
}
- op2 = impSIMDPopStack(retType);
- op1 = impSIMDPopStack(retType);
+ op2 = impSIMDPopStack(simdType);
+ op1 = impSIMDPopStack(simdType);
retNode =
gtNewSimdDotProdNode(retType, op1, op2, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
@@ -1022,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);
@@ -1044,24 +1046,137 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
{
var_types simdType = getSIMDTypeForSize(simdSize);
- op1 = impSIMDPopStack(simdType);
-
NamedIntrinsic moveMaskIntrinsic = NI_Illegal;
+ NamedIntrinsic shuffleIntrinsic = NI_Illegal;
+ NamedIntrinsic createIntrinsic = NI_Illegal;
- if (simdBaseType == TYP_FLOAT)
- {
- moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE_MoveMask;
- }
- else if (simdBaseType == TYP_DOUBLE)
- {
- moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE2_MoveMask;
- }
- else
+ switch (simdBaseType)
{
- moveMaskIntrinsic = (simdSize == 32) ? NI_AVX2_MoveMask : NI_SSE2_MoveMask;
- simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE;
+ case TYP_BYTE:
+ case TYP_UBYTE:
+ {
+ op1 = impSIMDPopStack(simdType);
+ moveMaskIntrinsic = (simdSize == 32) ? NI_AVX2_MoveMask : NI_SSE2_MoveMask;
+ break;
+ }
+
+ case TYP_SHORT:
+ case TYP_USHORT:
+ {
+ simdBaseJitType = varTypeIsUnsigned(simdBaseType) ? CORINFO_TYPE_UBYTE : CORINFO_TYPE_BYTE;
+
+ assert((simdSize == 16) || (simdSize == 32));
+ IntrinsicNodeBuilder nodeBuilder(getAllocator(CMK_ASTNode), simdSize);
+
+ // We want to tightly pack the most significant byte of each short/ushort
+ // and then zero the tightly packed least significant bytes
+
+ nodeBuilder.AddOperand(0x00, gtNewIconNode(0x01));
+ nodeBuilder.AddOperand(0x01, gtNewIconNode(0x03));
+ nodeBuilder.AddOperand(0x02, gtNewIconNode(0x05));
+ nodeBuilder.AddOperand(0x03, gtNewIconNode(0x07));
+ nodeBuilder.AddOperand(0x04, gtNewIconNode(0x09));
+ nodeBuilder.AddOperand(0x05, gtNewIconNode(0x0B));
+ nodeBuilder.AddOperand(0x06, gtNewIconNode(0x0D));
+ nodeBuilder.AddOperand(0x07, gtNewIconNode(0x0F));
+
+ for (unsigned i = 0x08; i < 0x10; i++)
+ {
+ // The most significant bit being set means zero the value
+ nodeBuilder.AddOperand(i, gtNewIconNode(0x80));
+ }
+
+ if (simdSize == 32)
+ {
+ // Vector256 works on 2x128-bit lanes, so repeat the same indices for the upper lane
+
+ nodeBuilder.AddOperand(0x10, gtNewIconNode(0x01));
+ nodeBuilder.AddOperand(0x11, gtNewIconNode(0x03));
+ nodeBuilder.AddOperand(0x12, gtNewIconNode(0x05));
+ nodeBuilder.AddOperand(0x13, gtNewIconNode(0x07));
+ nodeBuilder.AddOperand(0x14, gtNewIconNode(0x09));
+ nodeBuilder.AddOperand(0x15, gtNewIconNode(0x0B));
+ nodeBuilder.AddOperand(0x16, gtNewIconNode(0x0D));
+ nodeBuilder.AddOperand(0x17, gtNewIconNode(0x0F));
+
+ for (unsigned i = 0x18; i < 0x20; i++)
+ {
+ // The most significant bit being set means zero the value
+ nodeBuilder.AddOperand(i, gtNewIconNode(0x80));
+ }
+
+ createIntrinsic = NI_Vector256_Create;
+ shuffleIntrinsic = NI_AVX2_Shuffle;
+ moveMaskIntrinsic = NI_AVX2_MoveMask;
+ }
+ else if (compOpportunisticallyDependsOn(InstructionSet_SSSE3))
+ {
+ createIntrinsic = NI_Vector128_Create;
+ shuffleIntrinsic = NI_SSSE3_Shuffle;
+ moveMaskIntrinsic = NI_SSE2_MoveMask;
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ op2 = gtNewSimdHWIntrinsicNode(simdType, std::move(nodeBuilder), createIntrinsic,
+ simdBaseJitType, simdSize);
+
+ op1 = impSIMDPopStack(simdType);
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, op2, shuffleIntrinsic, simdBaseJitType, simdSize);
+
+ if (simdSize == 32)
+ {
+ CorInfoType simdOtherJitType;
+
+ // Since Vector256 is 2x128-bit lanes we need a full width permutation so we get the lower
+ // 64-bits of each lane next to eachother. The upper bits should be zero, but also don't
+ // matter so we can also then simplify down to a 128-bit move mask.
+
+ simdOtherJitType = (simdBaseType == TYP_UBYTE) ? CORINFO_TYPE_ULONG : CORINFO_TYPE_LONG;
+
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, gtNewIconNode(0xD8), NI_AVX2_Permute4x64,
+ simdOtherJitType, simdSize);
+
+ simdSize = 16;
+ simdType = TYP_SIMD16;
+
+ op1 = gtNewSimdHWIntrinsicNode(simdType, op1, NI_Vector256_GetLower, simdBaseJitType,
+ simdSize);
+ }
+ break;
+ }
+
+ case TYP_INT:
+ case TYP_UINT:
+ case TYP_FLOAT:
+ {
+ simdBaseJitType = CORINFO_TYPE_FLOAT;
+ op1 = impSIMDPopStack(simdType);
+ moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE_MoveMask;
+ break;
+ }
+
+ case TYP_LONG:
+ case TYP_ULONG:
+ case TYP_DOUBLE:
+ {
+ simdBaseJitType = CORINFO_TYPE_DOUBLE;
+ op1 = impSIMDPopStack(simdType);
+ moveMaskIntrinsic = (simdSize == 32) ? NI_AVX_MoveMask : NI_SSE2_MoveMask;
+ break;
+ }
+
+ default:
+ {
+ unreached();
+ }
}
+ assert(moveMaskIntrinsic != NI_Illegal);
+ assert(op1 != nullptr);
+
retNode = gtNewSimdHWIntrinsicNode(retType, op1, moveMaskIntrinsic, simdBaseJitType, simdSize,
/* isSimdAsHWIntrinsic */ false);
}
@@ -1172,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);
@@ -1190,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);
@@ -1224,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);
@@ -1242,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);
@@ -1276,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);
@@ -1294,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);
@@ -1328,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);
@@ -1346,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);
@@ -1780,9 +1895,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector256_Store:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
NamedIntrinsic storeIntrinsic = NI_Illegal;
@@ -1807,9 +1923,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector256_StoreAligned:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
NamedIntrinsic storeIntrinsic = NI_Illegal;
@@ -1834,9 +1951,10 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector256_StoreAlignedNonTemporal:
{
assert(sig->numArgs == 2);
+ var_types simdType = getSIMDTypeForSize(simdSize);
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
NamedIntrinsic storeIntrinsic = NI_Illegal;
@@ -1860,6 +1978,8 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector128_StoreUnsafe:
case NI_Vector256_StoreUnsafe:
{
+ var_types simdType = getSIMDTypeForSize(simdSize);
+
if (sig->numArgs == 3)
{
op3 = impPopStack().val;
@@ -1870,13 +1990,13 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
}
op2 = impPopStack().val;
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
if (sig->numArgs == 3)
{
- op3 = gtNewIconNode(genTypeSize(simdBaseType), op2->TypeGet());
- op2 = gtNewOperNode(GT_MUL, op2->TypeGet(), op2, op3);
- op2 = gtNewOperNode(GT_ADD, op1->TypeGet(), op1, op2);
+ op4 = gtNewIconNode(genTypeSize(simdBaseType), op3->TypeGet());
+ op3 = gtNewOperNode(GT_MUL, op3->TypeGet(), op3, op4);
+ op2 = gtNewOperNode(GT_ADD, op2->TypeGet(), op2, op3);
}
NamedIntrinsic storeIntrinsic = NI_Illegal;
@@ -1902,8 +2022,14 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
case NI_Vector256_Sum:
{
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))
{
@@ -1922,7 +2048,7 @@ GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic,
break;
}
- op1 = impSIMDPopStack(retType);
+ op1 = impSIMDPopStack(simdType);
retNode = gtNewSimdSumNode(retType, op1, simdBaseJitType, simdSize, /* isSimdAsHWIntrinsic */ false);
break;
}
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index aab024d3ac30d4..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;
@@ -1864,7 +1808,6 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal,
case GT_OBJ:
case GT_BLK:
- case GT_DYN_BLK:
case GT_ASG:
// These should already have the appropriate type.
assert(structVal->gtType == structType);
@@ -2488,21 +2431,9 @@ bool Compiler::impSpillStackEntry(unsigned level,
/* Allocate a temp if we haven't been asked to use a particular one */
- if (tiVerificationNeeded)
- {
- // 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))
{
- if (tnum != BAD_VAR_NUM && (tnum >= lvaCount))
- {
- return false;
- }
+ return false;
}
bool isNewTemp = false;
@@ -2512,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);
@@ -2647,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.
{
@@ -3879,19 +3787,25 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
return new (this, GT_LABEL) GenTree(GT_LABEL, TYP_I_IMPL);
}
- if (((ni == NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan) ||
- (ni == NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray)) &&
- IsTargetAbi(CORINFO_CORERT_ABI))
+ switch (ni)
{
// CreateSpan must be expanded for NativeAOT
- mustExpand = true;
- }
+ case NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan:
+ case NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray:
+ mustExpand |= IsTargetAbi(CORINFO_CORERT_ABI);
+ break;
- if ((ni == NI_System_ByReference_ctor) || (ni == NI_System_ByReference_get_Value) ||
- (ni == NI_System_Activator_AllocatorOf) || (ni == NI_System_Activator_DefaultConstructorOf) ||
- (ni == NI_System_Object_MethodTableOf) || (ni == NI_System_EETypePtr_EETypePtrOf))
- {
- mustExpand = true;
+ case NI_System_ByReference_ctor:
+ case NI_System_ByReference_get_Value:
+ case NI_System_Activator_AllocatorOf:
+ case NI_System_Activator_DefaultConstructorOf:
+ case NI_System_Object_MethodTableOf:
+ case NI_System_EETypePtr_EETypePtrOf:
+ mustExpand = true;
+ break;
+
+ default:
+ break;
}
GenTree* retNode = nullptr;
@@ -3935,29 +3849,19 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_String_get_Length:
{
GenTree* op1 = impPopStack().val;
- if (opts.OptimizationEnabled())
+ if (op1->OperIs(GT_CNS_STR))
{
- if (op1->OperIs(GT_CNS_STR))
+ // Optimize `ldstr + String::get_Length()` to CNS_INT
+ // e.g. "Hello".Length => 5
+ GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon());
+ if (iconNode != nullptr)
{
- // Optimize `ldstr + String::get_Length()` to CNS_INT
- // e.g. "Hello".Length => 5
- GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon());
- if (iconNode != nullptr)
- {
- retNode = iconNode;
- break;
- }
+ retNode = iconNode;
+ break;
}
- GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB);
- op1 = arrLen;
- }
- else
- {
- /* Create the expression "*(str_addr + stringLengthOffset)" */
- op1 = gtNewOperNode(GT_ADD, TYP_BYREF, op1,
- gtNewIconNode(OFFSETOF__CORINFO_String__stringLen, TYP_I_IMPL));
- op1 = gtNewOperNode(GT_IND, TYP_INT, op1);
}
+ GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB);
+ op1 = arrLen;
// Getting the length of a null string should throw
op1->gtFlags |= GTF_EXCEPT;
@@ -4007,6 +3911,26 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
}
+ case NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant:
+ {
+ GenTree* op1 = impPopStack().val;
+ if (op1->OperIsConst())
+ {
+ // op1 is a known constant, replace with 'true'.
+ retNode = gtNewIconNode(1);
+ JITDUMP("\nExpanding RuntimeHelpers.IsKnownConstant to true early\n");
+ // We can also consider FTN_ADDR and typeof(T) here
+ }
+ else
+ {
+ // op1 is not a known constant, we'll do the expansion in morph
+ retNode = new (this, GT_INTRINSIC) GenTreeIntrinsic(TYP_INT, op1, ni, method);
+ JITDUMP("\nConverting RuntimeHelpers.IsKnownConstant to:\n");
+ DISPTREE(retNode);
+ }
+ break;
+ }
+
case NI_System_Activator_AllocatorOf:
case NI_System_Activator_DefaultConstructorOf:
case NI_System_Object_MethodTableOf:
@@ -4283,7 +4207,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Threading_Thread_get_ManagedThreadId:
{
- if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_RET_EXPR))
+ if (impStackTop().val->OperIs(GT_RET_EXPR))
{
GenTreeCall* call = impStackTop().val->AsRetExpr()->gtInlineCandidate->AsCall();
if (call->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC)
@@ -4306,7 +4230,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
case NI_System_Threading_Interlocked_Or:
case NI_System_Threading_Interlocked_And:
{
- if (opts.OptimizationEnabled() && compOpportunisticallyDependsOn(InstructionSet_Atomics))
+ if (compOpportunisticallyDependsOn(InstructionSet_Atomics))
{
assert(sig->numArgs == 2);
GenTree* op2 = impPopStack().val;
@@ -5352,6 +5276,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray;
}
+ else if (strcmp(methodName, "IsKnownConstant") == 0)
+ {
+ result = NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant;
+ }
}
else if (strncmp(namespaceName, "System.Runtime.Intrinsics", 25) == 0)
{
@@ -6341,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,
@@ -9523,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))
@@ -9594,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;
}
@@ -9905,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();
@@ -9923,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)
@@ -10766,7 +10676,7 @@ void Compiler::impImportLeave(BasicBlock* block)
* scope */
exitBlock = fgNewBBinRegion(BBJ_EHCATCHRET, 0, XTnum + 1, step);
- assert(step->bbJumpKind == BBJ_ALWAYS || step->bbJumpKind == BBJ_EHCATCHRET);
+ assert(step->KindIs(BBJ_ALWAYS, BBJ_EHCATCHRET));
step->bbJumpDest = exitBlock; // the previous step (maybe a call to a nested finally, or a nested catch
// exit) returns to this block
step->bbJumpDest->bbRefs++;
@@ -10874,7 +10784,7 @@ void Compiler::impImportLeave(BasicBlock* block)
// never returns to the call-to-finally call, and the finally-protected 'try' region doesn't appear on
// stack walks.)
- assert(step->bbJumpKind == BBJ_ALWAYS || step->bbJumpKind == BBJ_EHCATCHRET);
+ assert(step->KindIs(BBJ_ALWAYS, BBJ_EHCATCHRET));
#if FEATURE_EH_CALLFINALLY_THUNKS
if (step->bbJumpKind == BBJ_EHCATCHRET)
@@ -11773,41 +11683,48 @@ 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
- // Are there any places in the method where we might add a patchpoint?
+ bool enablePatchpoints = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0);
+
+#ifdef DEBUG
+
+ // Optionally suppress patchpoints by method hash
//
- if (compHasBackwardJump)
+ 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)
{
- // Is OSR enabled?
+ // We don't inline at Tier0, if we do, we may need rethink our approach.
+ // Could probably support inlines that don't introduce flow.
+ //
+ assert(!compIsForInlining());
+
+ // OSR is not yet supported for methods with explicit tail calls.
//
- if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && (JitConfig.TC_OnStackReplacement() > 0))
+ // But we also do not have to switch these methods to be optimized as we should be
+ // able to avoid getting trapped in Tier0 code by normal call counting.
+ // So instead, just suppress adding patchpoints.
+ //
+ if (!compTailPrefixSeen)
{
- // OSR is not yet supported for methods with explicit tail calls.
- //
- // But we also may not switch methods to be optimized as we should be
- // able to avoid getting trapped in Tier0 code by normal call counting.
- // So instead, just suppress adding patchpoints.
+ // The normaly policy is only to add patchpoints to the targets of lexically
+ // backwards branches.
//
- if (!compTailPrefixSeen)
+ if (compHasBackwardJump)
{
assert(compCanHavePatchpoints());
- // We don't inline at Tier0, if we do, we may need rethink our approach.
- // Could probably support inlines that don't introduce flow.
- assert(!compIsForInlining());
-
// Is the start of this block a suitable patchpoint?
//
if (((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) != 0) && (verCurrentState.esStackDepth == 0))
@@ -11820,12 +11737,64 @@ void Compiler::impImportBlockCode(BasicBlock* block)
setMethodHasPatchpoint();
}
}
+ else
+ {
+ // Should not see backward branch targets w/o backwards branches
+ assert((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) == 0);
+ }
}
- }
- else
- {
- // Should not see backward branch targets w/o backwards branches
- assert((block->bbFlags & BBF_BACKWARD_JUMP_TARGET) == 0);
+
+#ifdef DEBUG
+ // As a stress test, we can place patchpoints at the start of any block
+ // that is a stack empty point and is not within a handler.
+ //
+ // Todo: enable for mid-block stack empty points too.
+ //
+ const int offsetOSR = JitConfig.JitOffsetOnStackReplacement();
+ const int randomOSR = JitConfig.JitRandomOnStackReplacement();
+ const bool tryOffsetOSR = offsetOSR >= 0;
+ const bool tryRandomOSR = randomOSR > 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.
+ //
+ bool addPatchpoint = false;
+
+ // Specific offset?
+ //
+ if (tryOffsetOSR)
+ {
+ if (impCurOpcOffs == (unsigned)offsetOSR)
+ {
+ addPatchpoint = true;
+ }
+ }
+ // Random?
+ //
+ else
+ {
+ // Reuse the random inliner's random state.
+ // Note m_inlineStrategy is always created, even if we're not inlining.
+ //
+ CLRRandom* const random = impInlineRoot()->m_inlineStrategy->GetRandom(randomOSR);
+ const int randomValue = (int)random->Next(100);
+
+ addPatchpoint = (randomValue < randomOSR);
+ }
+
+ if (addPatchpoint)
+ {
+ block->bbFlags |= BBF_PATCHPOINT;
+ setMethodHasPatchpoint();
+ }
+
+ JITDUMP("\n** %s patchpoint%s added to " FMT_BB " (il offset %u)\n", tryOffsetOSR ? "offset" : "random",
+ addPatchpoint ? "" : " not", block->bbNum, impCurOpcOffs);
+ }
+
+#endif // DEBUG
}
// Mark stack-empty rare blocks to be considered for partial compilation.
@@ -12259,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;
@@ -12319,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);
@@ -12344,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:
@@ -12379,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;
@@ -12404,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");
}
@@ -12446,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
@@ -12560,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())
{
@@ -12641,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;
@@ -12669,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
@@ -12724,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))
@@ -12767,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. */
@@ -12828,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))
{
@@ -12902,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))
@@ -12971,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 */
@@ -13106,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))
{
@@ -13136,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())
@@ -13193,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
@@ -13382,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;
@@ -13513,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);
@@ -13531,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());
@@ -13544,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);
@@ -13605,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();
@@ -13733,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;
@@ -13841,15 +13552,9 @@ 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;
+ /* Pull two values */
+ op2 = impPopStack().val;
+ op1 = impPopStack().val;
#ifdef TARGET_64BIT
if ((op1->TypeGet() == TYP_I_IMPL) && (genActualType(op2->TypeGet()) == TYP_INT))
@@ -13934,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()));
@@ -14088,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
@@ -14237,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);
@@ -14331,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);
@@ -14397,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:
@@ -14438,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);
}
}
@@ -14540,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:
@@ -14568,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
@@ -14638,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)
@@ -14650,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);
@@ -14693,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
@@ -14718,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);
@@ -14864,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())
{
@@ -14899,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);
@@ -15103,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
@@ -15247,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())
@@ -15373,45 +14944,10 @@ void Compiler::impImportBlockCode(BasicBlock* block)
// SkipVerification.
impHandleAccessAllowed(fieldInfo.accessAllowed, &fieldInfo.accessCalloutHelper);
- if (tiVerificationNeeded)
+ // Raise InvalidProgramException if static load accesses non-static field
+ if (isLoadStatic && ((fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC) == 0))
{
- // 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
- {
- // 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.
@@ -15726,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.
@@ -16004,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 =
@@ -16096,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())
{
@@ -16226,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);
@@ -16303,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);
@@ -16322,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;
@@ -16451,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;
@@ -16468,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);
@@ -16649,7 +16119,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
}
assert(op1->gtType == TYP_BYREF);
- assert(!tiVerificationNeeded || tiRetVal.IsByRef());
}
else
{
@@ -16694,7 +16163,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
oper = GT_OBJ;
assert(op1->gtType == TYP_BYREF);
- assert(!tiVerificationNeeded || tiRetVal.IsByRef());
goto OBJ;
}
@@ -16723,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);
@@ -16786,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;
@@ -16814,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);
@@ -16887,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();
@@ -16924,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);
@@ -16954,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
@@ -16989,59 +16384,66 @@ 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; // Dest
+ op1 = impPopStack().val; // Dst addr
if (op3->IsCnsIntOrI())
{
size = (unsigned)op3->AsIntConCommon()->IconValue();
op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size));
+ op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false);
}
else
{
- op1 = new (this, GT_DYN_BLK) GenTreeDynBlk(op1, op3);
+ if (!op2->IsIntegralConst(0))
+ {
+ op2 = gtNewOperNode(GT_INIT_VAL, TYP_INT, op2);
+ }
+
+ op1 = new (this, GT_STORE_DYN_BLK) GenTreeStoreDynBlk(op1, op2, op3);
size = 0;
+
+ if ((prefixFlags & PREFIX_VOLATILE) != 0)
+ {
+ op1->gtFlags |= GTF_BLK_VOLATILE;
+ }
}
- op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false);
goto SPILL_APPEND;
case CEE_CPBLK:
- if (tiVerificationNeeded)
- {
- Verify(false, "bad opcode");
- }
op3 = impPopStack().val; // Size
- op2 = impPopStack().val; // Src
- op1 = impPopStack().val; // Dest
+ op2 = impPopStack().val; // Src addr
+ op1 = impPopStack().val; // Dst addr
- if (op3->IsCnsIntOrI())
+ if (op2->OperGet() == GT_ADDR)
{
- size = (unsigned)op3->AsIntConCommon()->IconValue();
- op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size));
+ op2 = op2->AsOp()->gtOp1;
}
else
{
- op1 = new (this, GT_DYN_BLK) GenTreeDynBlk(op1, op3);
- size = 0;
+ op2 = gtNewOperNode(GT_IND, TYP_STRUCT, op2);
}
- if (op2->OperGet() == GT_ADDR)
+
+ if (op3->IsCnsIntOrI())
{
- op2 = op2->AsOp()->gtOp1;
+ size = (unsigned)op3->AsIntConCommon()->IconValue();
+ op1 = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, op1, typGetBlkLayout(size));
+ op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, true);
}
else
{
- op2 = gtNewOperNode(GT_IND, TYP_STRUCT, op2);
+ op1 = new (this, GT_STORE_DYN_BLK) GenTreeStoreDynBlk(op1, op2, op3);
+ size = 0;
+
+ if ((prefixFlags & PREFIX_VOLATILE) != 0)
+ {
+ op1->gtFlags |= GTF_BLK_VOLATILE;
+ }
}
- op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, true);
goto SPILL_APPEND;
case CEE_CPOBJ:
@@ -17052,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
@@ -17107,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)
{
@@ -17190,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);
@@ -17229,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))
{
@@ -17295,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())
{
@@ -17455,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)
@@ -17583,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
@@ -18470,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;
@@ -18511,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)
@@ -18710,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;
@@ -19180,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;
@@ -19370,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
{
@@ -19395,7 +18620,7 @@ void Compiler::impImport()
{
return;
}
- if (compIsForImportOnly() && !tiVerificationNeeded)
+ if (compIsForImportOnly())
{
return;
}
@@ -19416,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.
@@ -19466,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
@@ -22134,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/inline.def b/src/coreclr/jit/inline.def
index a28daf4e980fdc..a519471a3caec2 100644
--- a/src/coreclr/jit/inline.def
+++ b/src/coreclr/jit/inline.def
@@ -70,6 +70,8 @@ INLINE_OBSERVATION(ARG_FEEDS_CONSTANT_TEST, bool, "argument feeds constant t
INLINE_OBSERVATION(ARG_FEEDS_TEST, bool, "argument feeds test", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_CAST, int, "argument feeds castclass or isinst", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_RANGE_CHECK, bool, "argument feeds range check", INFORMATION, CALLEE)
+INLINE_OBSERVATION(ARG_FEEDS_ISCONST, bool, "argument feeds IsKnownConstant", INFORMATION, CALLEE)
+INLINE_OBSERVATION(CONST_ARG_FEEDS_ISCONST, bool, "const argument feeds IsKnownConstant", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_STRUCT, int, "arg is a struct passed by value", INFORMATION, CALLEE)
INLINE_OBSERVATION(RETURNS_STRUCT, bool, "returns a struct by value", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_STRUCT_FIELD_ACCESS, int, "ldfld/stfld over arg (struct)", INFORMATION, CALLEE)
diff --git a/src/coreclr/jit/inlinepolicy.cpp b/src/coreclr/jit/inlinepolicy.cpp
index 1ec47378872d54..0ea9135b82c249 100644
--- a/src/coreclr/jit/inlinepolicy.cpp
+++ b/src/coreclr/jit/inlinepolicy.cpp
@@ -326,6 +326,14 @@ void DefaultPolicy::NoteBool(InlineObservation obs, bool value)
m_ArgFeedsRangeCheck++;
break;
+ case InlineObservation::CALLEE_CONST_ARG_FEEDS_ISCONST:
+ m_ConstArgFeedsIsKnownConst = true;
+ break;
+
+ case InlineObservation::CALLEE_ARG_FEEDS_ISCONST:
+ m_ArgFeedsIsKnownConst = true;
+ break;
+
case InlineObservation::CALLEE_UNSUPPORTED_OPCODE:
propagate = true;
break;
@@ -727,6 +735,15 @@ double DefaultPolicy::DetermineMultiplier()
JITDUMP("\nInline candidate has arg that feeds range check. Multiplier increased to %g.", multiplier);
}
+ if (m_ConstArgFeedsIsKnownConst || (m_ArgFeedsIsKnownConst && m_IsPrejitRoot))
+ {
+ // if we use RuntimeHelpers.IsKnownConstant we most likely expect our function to be always inlined
+ // at least in the case of constant arguments. In IsPrejitRoot we don't have callsite info so let's
+ // assume we have a constant here in order to avoid "baked" noinline
+ multiplier += 20;
+ JITDUMP("\nConstant argument feeds RuntimeHelpers.IsKnownConstant. Multiplier increased to %g.", multiplier);
+ }
+
if (m_ConstantArgFeedsConstantTest > 0)
{
multiplier += 3.0;
@@ -1371,7 +1388,7 @@ void ExtendedDefaultPolicy::NoteInt(InlineObservation obs, int value)
{
SetNever(InlineObservation::CALLEE_DOES_NOT_RETURN);
}
- else if (!m_IsForceInline && !m_HasProfile)
+ else if (!m_IsForceInline && !m_HasProfile && !m_ConstArgFeedsIsKnownConst && !m_ArgFeedsIsKnownConst)
{
unsigned bbLimit = (unsigned)JitConfig.JitExtDefaultPolicyMaxBB();
if (m_IsPrejitRoot)
@@ -1381,6 +1398,7 @@ void ExtendedDefaultPolicy::NoteInt(InlineObservation obs, int value)
bbLimit += 5 + m_Switch * 10;
}
bbLimit += m_FoldableBranch + m_FoldableSwitch * 10;
+
if ((unsigned)value > bbLimit)
{
SetNever(InlineObservation::CALLEE_TOO_MANY_BASIC_BLOCKS);
@@ -2638,6 +2656,8 @@ void DiscretionaryPolicy::DumpData(FILE* file) const
fprintf(file, ",%u", m_ArgFeedsConstantTest);
fprintf(file, ",%u", m_MethodIsMostlyLoadStore ? 1 : 0);
fprintf(file, ",%u", m_ArgFeedsRangeCheck);
+ fprintf(file, ",%u", m_ConstArgFeedsIsKnownConst ? 1 : 0);
+ fprintf(file, ",%u", m_ArgFeedsIsKnownConst ? 1 : 0);
fprintf(file, ",%u", m_ConstantArgFeedsConstantTest);
fprintf(file, ",%d", m_CalleeNativeSizeEstimate);
fprintf(file, ",%d", m_CallsiteNativeSizeEstimate);
diff --git a/src/coreclr/jit/inlinepolicy.h b/src/coreclr/jit/inlinepolicy.h
index f5f200e9f5bd71..05e8539982ee88 100644
--- a/src/coreclr/jit/inlinepolicy.h
+++ b/src/coreclr/jit/inlinepolicy.h
@@ -110,6 +110,8 @@ class DefaultPolicy : public LegalPolicy
, m_CallsiteIsInLoop(false)
, m_IsNoReturn(false)
, m_IsNoReturnKnown(false)
+ , m_ConstArgFeedsIsKnownConst(false)
+ , m_ArgFeedsIsKnownConst(false)
{
// empty
}
@@ -178,6 +180,8 @@ class DefaultPolicy : public LegalPolicy
bool m_CallsiteIsInLoop : 1;
bool m_IsNoReturn : 1;
bool m_IsNoReturnKnown : 1;
+ bool m_ConstArgFeedsIsKnownConst : 1;
+ bool m_ArgFeedsIsKnownConst : 1;
};
// ExtendedDefaultPolicy is a slightly more aggressive variant of
diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp
index bbf204c74caa82..1cbe07cb69b1c3 100644
--- a/src/coreclr/jit/instr.cpp
+++ b/src/coreclr/jit/instr.cpp
@@ -1017,7 +1017,8 @@ void CodeGen::inst_RV_RV_IV(instruction ins, emitAttr size, regNumber reg1, regN
//
void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival)
{
- noway_assert(GetEmitter()->emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
+ emitter* emit = GetEmitter();
+ noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
if (rmOp->isContained() || rmOp->isUsedFromSpillTemp())
{
@@ -1069,7 +1070,7 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT
case GT_CLS_VAR_ADDR:
{
- GetEmitter()->emitIns_R_C_I(ins, attr, reg1, addr->AsClsVar()->gtClsVarHnd, 0, ival);
+ emit->emitIns_R_C_I(ins, attr, reg1, addr->AsClsVar()->gtClsVarHnd, 0, ival);
return;
}
@@ -1084,7 +1085,7 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT
// temporary GT_IND to generate code with.
memIndir = &load;
}
- GetEmitter()->emitIns_R_A_I(ins, attr, reg1, memIndir, ival);
+ emit->emitIns_R_A_I(ins, attr, reg1, memIndir, ival);
return;
}
}
@@ -1106,6 +1107,14 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT
break;
}
+ case GT_CNS_DBL:
+ {
+ GenTreeDblCon* cns = rmOp->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_R_C_I(ins, attr, reg1, hnd, 0, ival);
+ return;
+ }
+
default:
unreached();
}
@@ -1117,12 +1126,12 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT
assert((varNum != BAD_VAR_NUM) || (tmpDsc != nullptr));
assert(offset != (unsigned)-1);
- GetEmitter()->emitIns_R_S_I(ins, attr, reg1, varNum, offset, ival);
+ emit->emitIns_R_S_I(ins, attr, reg1, varNum, offset, ival);
}
else
{
regNumber rmOpReg = rmOp->GetRegNum();
- GetEmitter()->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpReg, ival);
+ emit->emitIns_SIMD_R_R_I(ins, attr, reg1, rmOpReg, ival);
}
}
@@ -1142,7 +1151,8 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT
void CodeGen::inst_RV_RV_TT(
instruction ins, emitAttr size, regNumber targetReg, regNumber op1Reg, GenTree* op2, bool isRMW)
{
- noway_assert(GetEmitter()->emitVerifyEncodable(ins, EA_SIZE(size), targetReg));
+ emitter* emit = GetEmitter();
+ noway_assert(emit->emitVerifyEncodable(ins, EA_SIZE(size), targetReg));
// TODO-XArch-CQ: Commutative operations can have op1 be contained
// TODO-XArch-CQ: Non-VEX encoded instructions can have both ops contained
@@ -1197,7 +1207,7 @@ void CodeGen::inst_RV_RV_TT(
case GT_CLS_VAR_ADDR:
{
- GetEmitter()->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, addr->AsClsVar()->gtClsVarHnd, 0);
+ emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, addr->AsClsVar()->gtClsVarHnd, 0);
return;
}
@@ -1212,7 +1222,7 @@ void CodeGen::inst_RV_RV_TT(
// temporary GT_IND to generate code with.
memIndir = &load;
}
- GetEmitter()->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, memIndir);
+ emit->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, memIndir);
return;
}
}
@@ -1238,10 +1248,9 @@ void CodeGen::inst_RV_RV_TT(
case GT_CNS_DBL:
{
- GenTreeDblCon* dblCns = op2->AsDblCon();
- CORINFO_FIELD_HANDLE cnsDblHnd =
- GetEmitter()->emitFltOrDblConst(dblCns->gtDconVal, emitTypeSize(dblCns));
- GetEmitter()->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, cnsDblHnd, 0);
+ GenTreeDblCon* cns = op2->AsDblCon();
+ CORINFO_FIELD_HANDLE hnd = emit->emitFltOrDblConst(cns->gtDconVal, emitTypeSize(cns));
+ emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, hnd, 0);
return;
}
@@ -1258,7 +1267,7 @@ void CodeGen::inst_RV_RV_TT(
assert((varNum != BAD_VAR_NUM) || (tmpDsc != nullptr));
assert(offset != (unsigned)-1);
- GetEmitter()->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, varNum, offset);
+ emit->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, varNum, offset);
}
else
{
@@ -1277,7 +1286,7 @@ void CodeGen::inst_RV_RV_TT(
op1Reg = targetReg;
}
- GetEmitter()->emitIns_SIMD_R_R_R(ins, size, targetReg, op1Reg, op2Reg);
+ emit->emitIns_SIMD_R_R_R(ins, size, targetReg, op1Reg, op2Reg);
}
}
#endif // TARGET_XARCH
diff --git a/src/coreclr/jit/instrsarm64.h b/src/coreclr/jit/instrsarm64.h
index c89b006a418970..d4e7ef5b10c8d6 100644
--- a/src/coreclr/jit/instrsarm64.h
+++ b/src/coreclr/jit/instrsarm64.h
@@ -312,8 +312,8 @@ INST4(neg, "neg", 0, IF_EN4G, 0x4B0003E0, 0x4B0003E0,
INST4(cmeq, "cmeq", 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, 0x5E209800, 0x0E209800)
// cmeq Vd,Vn,Vm DV_3E 01111110111mmmmm 100011nnnnnddddd 7EE0 8C00 Vd,Vn,Vm (scalar)
// cmeq Vd,Vn,Vm DV_3A 0Q101110XX1mmmmm 100011nnnnnddddd 2E20 8C00 Vd,Vn,Vm (vector)
- // cmeq Vd,Vn DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn (scalar)
- // cmeq Vd,Vn DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn (vector)
+ // cmeq Vd,Vn,#0 DV_2L 01011110XX100000 100110nnnnnddddd 5E20 9800 Vd,Vn,#0 (scalar - with zero)
+ // cmeq Vd,Vn,#0 DV_2M 0Q001110XX100000 100110nnnnnddddd 0E20 9800 Vd,Vn,#0 (vector - with zero)
INST4(cmge, "cmge", 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800)
// cmge Vd,Vn,Vm DV_3E 01011110111mmmmm 001111nnnnnddddd 5EE0 3C00 Vd,Vn,Vm (scalar)
@@ -331,8 +331,8 @@ INST4(cmgt, "cmgt", 0, IF_EN4H, 0x5EE03400, 0x0E203400,
INST4(fcmeq, "fcmeq", 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800)
// fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd Vn Vm (scalar)
// fcmeq Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111001nnnnnddddd 0E20 E400 Vd,Vn,Vm (vector)
- // fcmeq Vd,Vn DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn (scalar)
- // fcmeq Vd,Vn DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn (vector)
+ // fcmeq Vd,Vn,#0 DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn,#0 (scalar - with zero)
+ // fcmeq Vd,Vn,#0 DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn,#0 (vector - with zero)
INST4(fcmge, "fcmge", 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800)
// fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd Vn Vm (scalar)
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 1c8da276c3dc58..1346c2069da170 100644
--- a/src/coreclr/jit/jitconfigvalues.h
+++ b/src/coreclr/jit/jitconfigvalues.h
@@ -463,10 +463,24 @@ CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 0)
CONFIG_INTEGER(TC_OnStackReplacement_InitialCounter, W("TC_OnStackReplacement_InitialCounter"), 1000)
// Enable partial compilation for Tier0 methods
CONFIG_INTEGER(TC_PartialCompilation, W("TC_PartialCompilation"), 0)
+#if defined(DEBUG)
+// Randomly sprinkle patchpoints. Value is the likelyhood any given stack-empty point becomes a patchpoint.
+CONFIG_INTEGER(JitRandomOnStackReplacement, W("JitRandomOnStackReplacement"), 0)
+// Place patchpoint at the specified IL offset, if possible. Overrides random placement.
+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/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp
index 84d7965d395bf5..66684e38e1a3bb 100644
--- a/src/coreclr/jit/lclmorph.cpp
+++ b/src/coreclr/jit/lclmorph.cpp
@@ -567,26 +567,6 @@ class LocalAddressVisitor final : public GenTreeVisitor
PopValue();
break;
- case GT_DYN_BLK:
- assert(TopValue(2).Node() == node);
- assert(TopValue(1).Node() == node->AsDynBlk()->Addr());
- assert(TopValue(0).Node() == node->AsDynBlk()->gtDynamicSize);
-
- // The block size may be the result of an indirection so we need
- // to escape the location that may be associated with it.
- EscapeValue(TopValue(0), node);
-
- if (!TopValue(2).Indir(TopValue(1)))
- {
- // If the address comes from another indirection (e.g. DYN_BLK(IND(...))
- // then we need to escape the location.
- EscapeLocation(TopValue(1), node);
- }
-
- PopValue();
- PopValue();
- break;
-
case GT_RETURN:
if (TopValue(0).Node() != node)
{
@@ -829,14 +809,13 @@ class LocalAddressVisitor final : public GenTreeVisitor
// user - the node that uses the indirection
//
// Notes:
- // This returns 0 for indirection of unknown size, typically GT_DYN_BLK.
- // GT_IND nodes that have type TYP_STRUCT are expected to only appears
- // on the RHS of an assignment, in which case the LHS size will be used instead.
- // Otherwise 0 is returned as well.
+ // This returns 0 for indirection of unknown size. GT_IND nodes that have type
+ // TYP_STRUCT are expected to only appears on the RHS of an assignment, in which
+ // case the LHS size will be used instead. Otherwise 0 is returned as well.
//
unsigned GetIndirSize(GenTree* indir, GenTree* user)
{
- assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK, GT_FIELD));
+ assert(indir->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_FIELD));
if (indir->TypeGet() != TYP_STRUCT)
{
@@ -883,7 +862,7 @@ class LocalAddressVisitor final : public GenTreeVisitor
case GT_OBJ:
return indir->AsBlk()->GetLayout()->GetSize();
default:
- assert(indir->OperIs(GT_IND, GT_DYN_BLK));
+ assert(indir->OperIs(GT_IND));
return 0;
}
}
diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp
index 7b329e0a86a461..a1cfc61822216f 100644
--- a/src/coreclr/jit/lclvars.cpp
+++ b/src/coreclr/jit/lclvars.cpp
@@ -305,7 +305,9 @@ void Compiler::lvaInitTypeRef()
JITDUMP("-- V%02u is OSR exposed\n", varNum);
varDsc->lvHasLdAddrOp = 1;
- if (varDsc->lvType != TYP_STRUCT) // Why does it apply only to non-structs?
+ // todo: Why does it apply only to non-structs?
+ //
+ if (!varTypeIsStruct(varDsc) && !varTypeIsSIMD(varDsc))
{
lvaSetVarAddrExposed(varNum DEBUGARG(AddressExposedReason::OSR_EXPOSED));
}
@@ -485,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();
@@ -1321,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);
@@ -1371,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);
@@ -1393,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);
@@ -4111,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/lir.cpp b/src/coreclr/jit/lir.cpp
index 97f9e4f4807d2b..81d03b93f7b347 100644
--- a/src/coreclr/jit/lir.cpp
+++ b/src/coreclr/jit/lir.cpp
@@ -1636,7 +1636,7 @@ void LIR::InsertBeforeTerminator(BasicBlock* block, LIR::Range&& range)
LIR::Range& blockRange = LIR::AsRange(block);
GenTree* insertionPoint = nullptr;
- if ((block->bbJumpKind == BBJ_COND) || (block->bbJumpKind == BBJ_SWITCH) || (block->bbJumpKind == BBJ_RETURN))
+ if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN))
{
insertionPoint = blockRange.LastNode();
assert(insertionPoint != nullptr);
diff --git a/src/coreclr/jit/liveness.cpp b/src/coreclr/jit/liveness.cpp
index 4f8d9334249cf0..d9592683db7981 100644
--- a/src/coreclr/jit/liveness.cpp
+++ b/src/coreclr/jit/liveness.cpp
@@ -2090,7 +2090,6 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
{
bool removed = fgTryRemoveNonLocal(node, &blockRange);
if (!removed && node->IsUnusedValue())
diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp
index c206249a437400..bdd8d763aa4c7e 100644
--- a/src/coreclr/jit/loopcloning.cpp
+++ b/src/coreclr/jit/loopcloning.cpp
@@ -767,7 +767,7 @@ BasicBlock* LoopCloneContext::CondToStmtInBlock(Compiler*
{
noway_assert(conds.Size() > 0);
assert(slowHead != nullptr);
- assert((insertAfter->bbJumpKind == BBJ_NONE) || (insertAfter->bbJumpKind == BBJ_COND));
+ assert(insertAfter->KindIs(BBJ_NONE, BBJ_COND));
// Choose how to generate the conditions
const bool generateOneConditionPerBlock = true;
@@ -1847,7 +1847,7 @@ void Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context)
// X
BasicBlock* h = loop.lpHead;
- if (h->bbJumpKind != BBJ_NONE && h->bbJumpKind != BBJ_ALWAYS)
+ if (!h->KindIs(BBJ_NONE, BBJ_ALWAYS))
{
// Make a new block to be the unique entry to the loop.
JITDUMP("Create new unique single-successor entry to loop\n");
diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index 06d42a37f986f6..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();
@@ -3792,32 +3798,29 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call)
assert(thisArgNode != nullptr);
assert(thisArgNode->gtOper == GT_PUTARG_REG);
- GenTree* originalThisExpr = thisArgNode->AsOp()->gtOp1;
- GenTree* thisExpr = originalThisExpr;
+ GenTree* thisExpr = thisArgNode->AsOp()->gtOp1;
// We're going to use the 'this' expression multiple times, so make a local to copy it.
- unsigned lclNum;
-
- if (call->IsTailCallViaJitHelper() && originalThisExpr->IsLocal())
+ GenTree* base;
+ if (thisExpr->OperIs(GT_LCL_VAR))
+ {
+ base = comp->gtNewLclvNode(thisExpr->AsLclVar()->GetLclNum(), thisExpr->TypeGet());
+ }
+ else if (thisExpr->OperIs(GT_LCL_FLD))
{
- // For ordering purposes for the special tailcall arguments on x86, we forced the
- // 'this' pointer in this case to a local in Compiler::fgMorphTailCall().
- // We could possibly use this case to remove copies for all architectures and non-tailcall
- // calls by creating a new lcl var or lcl field reference, as is done in the
- // LowerVirtualVtableCall() code.
- assert(originalThisExpr->OperGet() == GT_LCL_VAR);
- lclNum = originalThisExpr->AsLclVarCommon()->GetLclNum();
+ base = comp->gtNewLclFldNode(thisExpr->AsLclFld()->GetLclNum(), thisExpr->TypeGet(),
+ thisExpr->AsLclFld()->GetLclOffs());
}
else
{
unsigned delegateInvokeTmp = comp->lvaGrabTemp(true DEBUGARG("delegate invoke call"));
+ base = comp->gtNewLclvNode(delegateInvokeTmp, thisExpr->TypeGet());
LIR::Use thisExprUse(BlockRange(), &thisArgNode->AsOp()->gtOp1, thisArgNode);
ReplaceWithLclVar(thisExprUse, delegateInvokeTmp);
thisExpr = thisExprUse.Def(); // it's changed; reload it.
- lclNum = delegateInvokeTmp;
}
// replace original expression feeding into thisPtr with
@@ -3836,8 +3839,6 @@ GenTree* Lowering::LowerDelegateInvoke(GenTreeCall* call)
// the control target is
// [originalThis + firstTgtOffs]
- GenTree* base = new (comp, GT_LCL_VAR) GenTreeLclVar(GT_LCL_VAR, originalThisExpr->TypeGet(), lclNum);
-
unsigned targetOffs = comp->eeGetEEInfo()->offsetOfDelegateFirstTarget;
GenTree* result = new (comp, GT_LEA) GenTreeAddrMode(TYP_REF, base, nullptr, 0, targetOffs);
GenTree* callTarget = Ind(result);
@@ -4606,7 +4607,7 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call)
// If what we are passing as the thisptr is not already a local, make a new local to place it in
// because we will be creating expressions based on it.
unsigned lclNum;
- if (thisPtr->IsLocal())
+ if (thisPtr->OperIsLocal())
{
lclNum = thisPtr->AsLclVarCommon()->GetLclNum();
}
@@ -4890,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;
@@ -4919,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.
//
@@ -5108,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
@@ -5122,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.
@@ -5133,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);
}
//------------------------------------------------------------------------
@@ -6779,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())
@@ -6847,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())
@@ -6860,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);
}
}
@@ -6922,6 +6932,14 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas
void Lowering::LowerBlockStoreCommon(GenTreeBlk* blkNode)
{
assert(blkNode->OperIs(GT_STORE_BLK, GT_STORE_DYN_BLK, GT_STORE_OBJ));
+
+ // Lose the type information stored in the source - we no longer need it.
+ if (blkNode->Data()->OperIs(GT_OBJ, GT_BLK))
+ {
+ blkNode->Data()->SetOper(GT_IND);
+ LowerIndir(blkNode->Data()->AsIndir());
+ }
+
if (TryTransformStoreObjAsStoreInd(blkNode))
{
return;
@@ -6996,7 +7014,7 @@ bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode)
return false;
}
- JITDUMP("Replacing STORE_OBJ with STOREIND for [06%u]", blkNode->gtTreeID);
+ JITDUMP("Replacing STORE_OBJ with STOREIND for [%06u]\n", blkNode->gtTreeID);
blkNode->ChangeOper(GT_STOREIND);
blkNode->ChangeType(regType);
diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h
index ed0ecc56619708..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);
@@ -564,8 +566,8 @@ class Lowering final : public Phase
}
#ifdef FEATURE_HW_INTRINSICS
- // Return true if 'node' is a containable HWIntrinsic op.
- bool IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree* node, bool* supportsRegOptional);
+ // Tries to get a containable node for a given HWIntrinsic
+ bool TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree** pNode, bool* supportsRegOptional);
#endif // FEATURE_HW_INTRINSICS
static void TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, BasicBlock* block);
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index e4ba37cffb1d52..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
//
@@ -293,6 +309,8 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
GenTree* src = blkNode->Data();
unsigned size = blkNode->Size();
+ const bool isDstAddrLocal = dstAddr->OperIsLocalAddr();
+
if (blkNode->OperIsInitBlkOp())
{
if (src->OperIs(GT_INIT_VAL))
@@ -306,7 +324,18 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
blkNode->SetOper(GT_STORE_BLK);
}
- if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= INITBLK_UNROLL_LIMIT) && src->OperIs(GT_CNS_INT))
+ unsigned initBlockUnrollLimit = INITBLK_UNROLL_LIMIT;
+
+#ifdef TARGET_ARM64
+ if (isDstAddrLocal)
+ {
+ // Since dstAddr points to the stack CodeGen can use more optimal
+ // quad-word store SIMD instructions for InitBlock.
+ initBlockUnrollLimit = INITBLK_LCL_UNROLL_LIMIT;
+ }
+#endif
+
+ if (!blkNode->OperIs(GT_STORE_DYN_BLK) && (size <= initBlockUnrollLimit) && src->OperIs(GT_CNS_INT))
{
blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll;
@@ -353,19 +382,39 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
assert(src->OperIs(GT_IND, GT_LCL_VAR, GT_LCL_FLD));
src->SetContained();
+ bool isSrcAddrLocal = false;
+
if (src->OperIs(GT_IND))
{
+ GenTree* srcAddr = src->AsIndir()->Addr();
// TODO-Cleanup: Make sure that GT_IND lowering didn't mark the source address as contained.
// Sometimes the GT_IND type is a non-struct type and then GT_IND lowering may contain the
// address, not knowing that GT_IND is part of a block op that has containment restrictions.
- src->AsIndir()->Addr()->ClearContained();
+ srcAddr->ClearContained();
+ isSrcAddrLocal = srcAddr->OperIsLocalAddr();
+ }
+ else
+ {
+ isSrcAddrLocal = true;
+
+ if (src->OperIs(GT_LCL_VAR))
+ {
+ // TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register.
+ const unsigned srcLclNum = src->AsLclVar()->GetLclNum();
+ comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(DoNotEnregisterReason::BlockOp));
+ }
}
- else if (src->OperIs(GT_LCL_VAR))
+
+ unsigned copyBlockUnrollLimit = CPBLK_UNROLL_LIMIT;
+
+#ifdef TARGET_ARM64
+ if (isSrcAddrLocal && isDstAddrLocal)
{
- // TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register.
- const unsigned srcLclNum = src->AsLclVar()->GetLclNum();
- comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(DoNotEnregisterReason::BlockOp));
+ // Since both srcAddr and dstAddr point to the stack CodeGen can use more optimal
+ // quad-word load and store SIMD instructions for CopyBlock.
+ copyBlockUnrollLimit = CPBLK_LCL_UNROLL_LIMIT;
}
+#endif
if (blkNode->OperIs(GT_STORE_OBJ))
{
@@ -373,7 +422,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
{
blkNode->SetOper(GT_STORE_BLK);
}
- else if (dstAddr->OperIsLocalAddr() && (size <= CPBLK_UNROLL_LIMIT))
+ else if (isDstAddrLocal && (size <= copyBlockUnrollLimit))
{
// If the size is small enough to unroll then we need to mark the block as non-interruptible
// to actually allow unrolling. The generated code does not report GC references loaded in the
@@ -389,7 +438,7 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll;
}
- else if (blkNode->OperIs(GT_STORE_BLK) && (size <= CPBLK_UNROLL_LIMIT))
+ else if (blkNode->OperIs(GT_STORE_BLK) && (size <= copyBlockUnrollLimit))
{
blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindUnroll;
@@ -490,7 +539,6 @@ void Lowering::LowerCast(GenTree* tree)
GenTree* op1 = tree->AsOp()->gtOp1;
var_types dstType = tree->CastToType();
var_types srcType = genActualType(op1->TypeGet());
- var_types tmpType = TYP_UNDEF;
if (varTypeIsFloating(srcType))
{
@@ -501,16 +549,6 @@ void Lowering::LowerCast(GenTree* tree)
assert(!varTypeIsSmall(srcType));
- if (tmpType != TYP_UNDEF)
- {
- GenTree* tmp = comp->gtNewCastNode(tmpType, op1, tree->IsUnsigned(), tmpType);
- tmp->gtFlags |= (tree->gtFlags & (GTF_OVERFLOW | GTF_EXCEPT));
-
- tree->gtFlags &= ~GTF_UNSIGNED;
- tree->AsOp()->gtOp1 = tmp;
- BlockRange().InsertAfter(op1, tmp);
- }
-
// Now determine if we have operands that should be contained.
ContainCheckCast(tree->AsCast());
}
@@ -852,8 +890,8 @@ void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp)
GenTree* insCns = comp->gtNewIconNode(-1, TYP_INT);
BlockRange().InsertAfter(idxCns, insCns);
- GenTree* tmp = comp->gtNewSimdAsHWIntrinsicNode(simdType, cmp, idxCns, insCns, NI_AdvSimd_Insert,
- CORINFO_TYPE_INT, simdSize);
+ GenTree* tmp = comp->gtNewSimdHWIntrinsicNode(simdType, cmp, idxCns, insCns, NI_AdvSimd_Insert,
+ CORINFO_TYPE_INT, simdSize);
BlockRange().InsertAfter(insCns, tmp);
LowerNode(tmp);
@@ -869,7 +907,7 @@ void Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp)
BlockRange().InsertAfter(msk, zroCns);
GenTree* val =
- comp->gtNewSimdAsHWIntrinsicNode(TYP_UBYTE, msk, zroCns, NI_AdvSimd_Extract, CORINFO_TYPE_UBYTE, simdSize);
+ comp->gtNewSimdHWIntrinsicNode(TYP_UBYTE, msk, zroCns, NI_AdvSimd_Extract, CORINFO_TYPE_UBYTE, simdSize);
BlockRange().InsertAfter(zroCns, val);
LowerNode(val);
@@ -1147,7 +1185,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
BlockRange().InsertAfter(idx, tmp1);
LowerNode(tmp1);
- op1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op1, idx, tmp1, NI_AdvSimd_Insert, simdBaseJitType, simdSize);
+ op1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, idx, tmp1, NI_AdvSimd_Insert, simdBaseJitType, simdSize);
BlockRange().InsertAfter(tmp1, op1);
LowerNode(op1);
@@ -1158,7 +1196,7 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
BlockRange().InsertAfter(idx, tmp2);
LowerNode(tmp2);
- op2 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op2, idx, tmp2, NI_AdvSimd_Insert, simdBaseJitType, simdSize);
+ op2 = comp->gtNewSimdHWIntrinsicNode(simdType, op2, idx, tmp2, NI_AdvSimd_Insert, simdBaseJitType, simdSize);
BlockRange().InsertAfter(tmp2, op2);
LowerNode(op2);
}
@@ -1183,32 +1221,35 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
}
assert(!varTypeIsLong(simdBaseType));
- tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, op1, op2, multiply, simdBaseJitType, simdSize);
+ tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, op1, op2, multiply, simdBaseJitType, simdSize);
BlockRange().InsertBefore(node, tmp1);
LowerNode(tmp1);
if (varTypeIsFloating(simdBaseType))
{
- // We will be constructing the following parts:
- // ...
- // /--* tmp1 simd16
- // * STORE_LCL_VAR simd16
- // tmp1 = LCL_VAR simd16
- // tmp2 = LCL_VAR simd16
- // ...
+ if ((simdSize != 8) || (simdBaseType == TYP_FLOAT))
+ {
+ // We will be constructing the following parts:
+ // ...
+ // /--* tmp1 simd16
+ // * STORE_LCL_VAR simd16
+ // tmp1 = LCL_VAR simd16
+ // tmp2 = LCL_VAR simd16
+ // ...
- // This is roughly the following managed code:
- // ...
- // var tmp2 = tmp1;
- // ...
+ // This is roughly the following managed code:
+ // ...
+ // var tmp2 = tmp1;
+ // ...
- node->Op(1) = tmp1;
- LIR::Use tmp1Use(BlockRange(), &node->Op(1), node);
- ReplaceWithLclVar(tmp1Use);
- tmp1 = node->Op(1);
+ node->Op(1) = tmp1;
+ LIR::Use tmp1Use(BlockRange(), &node->Op(1), node);
+ ReplaceWithLclVar(tmp1Use);
+ tmp1 = node->Op(1);
- tmp2 = comp->gtClone(tmp1);
- BlockRange().InsertAfter(tmp1, tmp2);
+ tmp2 = comp->gtClone(tmp1);
+ BlockRange().InsertAfter(tmp1, tmp2);
+ }
if (simdSize == 8)
{
@@ -1226,8 +1267,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
// var tmp1 = AdvSimd.AddPairwise(tmp1, tmp2);
// ...
- tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType,
- simdSize);
+ tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType,
+ simdSize);
BlockRange().InsertAfter(tmp2, tmp1);
LowerNode(tmp1);
}
@@ -1252,8 +1293,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
// var tmp1 = AdvSimd.Arm64.AddPairwise(tmp1, tmp2);
// ...
- tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType,
- simdSize);
+ tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise, simdBaseJitType,
+ simdSize);
BlockRange().InsertAfter(tmp2, tmp1);
LowerNode(tmp1);
@@ -1291,8 +1332,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
tmp2 = comp->gtClone(tmp1);
BlockRange().InsertAfter(tmp1, tmp2);
- tmp1 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise,
- simdBaseJitType, simdSize);
+ tmp1 = comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_Arm64_AddPairwise,
+ simdBaseJitType, simdSize);
BlockRange().InsertAfter(tmp2, tmp1);
LowerNode(tmp1);
}
@@ -1304,20 +1345,66 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
{
assert(varTypeIsIntegral(simdBaseType));
- // We will be constructing the following parts:
- // ...
- // /--* tmp1 simd16
- // tmp2 = * HWINTRINSIC simd16 T AddAcross
- // ...
+ if ((simdSize == 8) && ((simdBaseType == TYP_INT) || (simdBaseType == TYP_UINT)))
+ {
+ // We will be constructing the following parts:
+ // ...
+ // /--* tmp1 simd16
+ // * STORE_LCL_VAR simd16
+ // tmp1 = LCL_VAR simd16
+ // tmp2 = LCL_VAR simd16
+ // ...
- // This is roughly the following managed code:
- // ...
- // var tmp2 = AdvSimd.Arm64.AddAcross(tmp1);
- // ...
+ // This is roughly the following managed code:
+ // ...
+ // var tmp2 = tmp1;
+ // ...
- tmp2 = comp->gtNewSimdAsHWIntrinsicNode(simdType, tmp1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize);
- BlockRange().InsertAfter(tmp1, tmp2);
- LowerNode(tmp2);
+ node->Op(1) = tmp1;
+ LIR::Use tmp1Use(BlockRange(), &node->Op(1), node);
+ ReplaceWithLclVar(tmp1Use);
+ tmp1 = node->Op(1);
+
+ tmp2 = comp->gtClone(tmp1);
+ BlockRange().InsertAfter(tmp1, tmp2);
+
+ // We will be constructing the following parts:
+ // ...
+ // /--* tmp1 simd16
+ // /--* tmp2 simd16
+ // tmp2 = * HWINTRINSIC simd8 T AddPairwise
+ // ...
+
+ // This is roughly the following managed code:
+ // ...
+ // var tmp2 = AdvSimd.AddPairwise(tmp1, tmp2);
+ // ...
+
+ tmp1 =
+ comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, tmp2, NI_AdvSimd_AddPairwise, simdBaseJitType, simdSize);
+ BlockRange().InsertAfter(tmp2, tmp1);
+ LowerNode(tmp1);
+
+ tmp2 = tmp1;
+ }
+ else
+ {
+ // We will be constructing the following parts:
+ // ...
+ // /--* tmp1 simd16
+ // tmp2 = * HWINTRINSIC simd16 T AddAcross
+ // ...
+
+ // This is roughly the following managed code:
+ // ...
+ // var tmp2 = AdvSimd.Arm64.AddAcross(tmp1);
+ // ...
+
+ tmp2 =
+ comp->gtNewSimdHWIntrinsicNode(simdType, tmp1, NI_AdvSimd_Arm64_AddAcross, simdBaseJitType, simdSize);
+ BlockRange().InsertAfter(tmp1, tmp2);
+ LowerNode(tmp2);
+ }
}
// We will be constructing the following parts:
@@ -1853,6 +1940,21 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
MakeSrcContained(node, intrin.op4);
break;
+ case NI_AdvSimd_CompareEqual:
+ case NI_AdvSimd_Arm64_CompareEqual:
+ case NI_AdvSimd_Arm64_CompareEqualScalar:
+ {
+ if (intrin.op1->IsVectorZero())
+ {
+ MakeSrcContained(node, intrin.op1);
+ }
+ else if (intrin.op2->IsVectorZero())
+ {
+ MakeSrcContained(node, intrin.op2);
+ }
+ break;
+ }
+
case NI_Vector64_CreateScalarUnsafe:
case NI_Vector128_CreateScalarUnsafe:
case NI_AdvSimd_DuplicateToVector64:
diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp
index c8076c4525f2df..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;
}
@@ -832,8 +859,8 @@ void Lowering::LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIn
bool op1SupportsRegOptional = false;
bool op2SupportsRegOptional = false;
- if (!IsContainableHWIntrinsicOp(node, node->Op(2), &op2SupportsRegOptional) &&
- IsContainableHWIntrinsicOp(node, node->Op(1), &op1SupportsRegOptional))
+ if (!TryGetContainableHWIntrinsicOp(node, &node->Op(2), &op2SupportsRegOptional) &&
+ TryGetContainableHWIntrinsicOp(node, &node->Op(1), &op1SupportsRegOptional))
{
// Swap operands if op2 cannot be contained but op1 can.
swapOperands = true;
@@ -3047,8 +3074,6 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
if (simdSize == 32)
{
- assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX2));
-
switch (simdBaseType)
{
case TYP_SHORT:
@@ -3056,6 +3081,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
case TYP_INT:
case TYP_UINT:
{
+ assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX2));
+
multiply = NI_AVX2_MultiplyLow;
horizontalAdd = NI_AVX2_HorizontalAdd;
add = NI_AVX2_Add;
@@ -3064,6 +3091,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
case TYP_FLOAT:
{
+ assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX));
+
// We will be constructing the following parts:
// idx = CNS_INT int 0xF1
// /--* op1 simd16
@@ -3127,6 +3156,8 @@ void Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node)
case TYP_DOUBLE:
{
+ assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX));
+
multiply = NI_AVX_Multiply;
horizontalAdd = NI_AVX_HorizontalAdd;
add = NI_AVX_Add;
@@ -3425,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;
}
@@ -3693,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
//----------------------------------------------------------------------------------------------
@@ -5158,21 +5267,34 @@ void Lowering::ContainCheckSIMD(GenTreeSIMD* simdNode)
#ifdef FEATURE_HW_INTRINSICS
//----------------------------------------------------------------------------------------------
-// IsContainableHWIntrinsicOp: Return true if 'node' is a containable HWIntrinsic op.
+// TryGetContainableHWIntrinsicOp: Tries to get a containable node for a given HWIntrinsic
//
// Arguments:
-// containingNode - The hardware intrinsic node which contains 'node'
-// node - The node to check
-// [Out] supportsRegOptional - On return, this will be true if 'containingNode' supports regOptional operands;
+// [In] containingNode - The hardware intrinsic node which contains 'node'
+// [In/Out] pNode - The node to check and potentially replace with the containable node
+// [Out] supportsRegOptional - On return, this will be true if 'containingNode' supports regOptional operands
// otherwise, false.
//
// Return Value:
-// true if 'node' is a containable hardware intrinsic node; otherwise, false.
+// true if 'node' is a containable by containingNode; otherwise, false.
+//
+// When true is returned 'node' (and by extension the relevant op of 'containingNode') may be modified
+// to handle special scenarios such as CreateScalarUnsafe which exist to bridge the type system with
+// the actual registers.
//
-bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, GenTree* node, bool* supportsRegOptional)
+// When false is returned 'node' is not modified.
+//
+bool Lowering::TryGetContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode,
+ GenTree** pNode,
+ bool* supportsRegOptional)
{
+ assert(containingNode != nullptr);
+ assert((pNode != nullptr) && (*pNode != nullptr));
+ assert(supportsRegOptional != nullptr);
+
NamedIntrinsic containingIntrinsicId = containingNode->GetHWIntrinsicId();
HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(containingIntrinsicId);
+ GenTree*& node = *pNode;
// We shouldn't have called in here if containingNode doesn't support containment
assert(HWIntrinsicInfo::SupportsContainment(containingIntrinsicId));
@@ -5213,8 +5335,10 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
switch (category)
{
case HW_Category_MemoryLoad:
- supportsGeneralLoads = (!node->OperIsHWIntrinsic());
+ {
+ supportsGeneralLoads = !node->OperIsHWIntrinsic();
break;
+ }
case HW_Category_SimpleSIMD:
{
@@ -5227,26 +5351,90 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_AVX2_ConvertToVector256Int32:
case NI_AVX2_ConvertToVector256Int64:
{
- supportsGeneralLoads = (!node->OperIsHWIntrinsic());
+ assert(!supportsSIMDScalarLoads);
+
+ if (!containingNode->OperIsMemoryLoad())
+ {
+ // The containable form is the one that takes a SIMD value, that may be in memory.
+
+ if (!comp->canUseVexEncoding())
+ {
+ supportsAlignedSIMDLoads = true;
+ supportsUnalignedSIMDLoads = !supportsAlignedSIMDLoads;
+ }
+ else
+ {
+ supportsAlignedSIMDLoads = !comp->opts.MinOpts();
+ supportsUnalignedSIMDLoads = true;
+ }
+
+ // General loads are a bit special where we need at least `sizeof(simdType) / (sizeof(baseType)
+ // * 2)` elements
+ // For example:
+ // * ConvertToVector128Int16 - sizeof(simdType) = 16; sizeof(baseType) = 1; expectedSize = 8
+ // * ConvertToVector128Int32 - sizeof(simdType) = 16; sizeof(baseType) = 1 | 2;
+ // expectedSize = 8 | 4
+ // * ConvertToVector128Int64 - sizeof(simdType) = 16; sizeof(baseType) = 1 | 2 | 4;
+ // expectedSize = 8 | 4 | 2
+ // * ConvertToVector256Int16 - sizeof(simdType) = 32; sizeof(baseType) = 1; expectedSize = 16
+ // * ConvertToVector256Int32 - sizeof(simdType) = 32; sizeof(baseType) = 1 | 2;
+ // expectedSize = 16 | 8
+ // * ConvertToVector256Int64 - sizeof(simdType) = 32; sizeof(baseType) = 1 | 2 | 4;
+ // expectedSize = 16 | 8 | 4
+
+ const unsigned sizeof_simdType = genTypeSize(containingNode->TypeGet());
+ const unsigned sizeof_baseType = genTypeSize(containingNode->GetSimdBaseType());
+
+ assert((sizeof_simdType == 16) || (sizeof_simdType == 32));
+ assert((sizeof_baseType == 1) || (sizeof_baseType == 2) || (sizeof_baseType == 4));
+
+ const unsigned expectedSize = sizeof_simdType / (sizeof_baseType * 2);
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ assert((sizeof_simdType != 16) || (expectedSize == 8) || (expectedSize == 4) ||
+ (expectedSize == 2));
+ assert((sizeof_simdType != 32) || (expectedSize == 16) || (expectedSize == 8) ||
+ (expectedSize == 4));
+
+ supportsGeneralLoads = (operandSize >= expectedSize);
+ }
+ else
+ {
+ // The memory form of this already takes a pointer and should be treated like a MemoryLoad
+ supportsGeneralLoads = !node->OperIsHWIntrinsic();
+ }
+ break;
+ }
+
+ case NI_SSE2_ConvertToVector128Double:
+ case NI_SSE3_MoveAndDuplicate:
+ case NI_AVX_ConvertToVector256Double:
+ {
+ assert(!supportsSIMDScalarLoads);
+
+ // Most instructions under the non-VEX encoding require aligned operands.
+ // Those used for Sse2.ConvertToVector128Double (CVTDQ2PD and CVTPS2PD)
+ // and Sse3.MoveAndDuplicate (MOVDDUP) are exceptions and don't fail for
+ // unaligned inputs as they read mem64 (half the vector width) instead
+
+ supportsAlignedSIMDLoads = !comp->opts.MinOpts();
+ supportsUnalignedSIMDLoads = true;
+
+ const unsigned expectedSize = genTypeSize(containingNode->TypeGet()) / 2;
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize);
break;
}
default:
{
- if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32))
- {
- // These intrinsics only expect 16 or 32-byte nodes for containment
- break;
- }
+ assert(!supportsSIMDScalarLoads);
if (!comp->canUseVexEncoding())
{
- // Most instructions under the non-VEX encoding require aligned operands.
- // Those used for Sse2.ConvertToVector128Double (CVTDQ2PD and CVTPS2PD)
- // are exceptions and don't fail for unaligned inputs.
-
- supportsAlignedSIMDLoads = (containingIntrinsicId != NI_SSE2_ConvertToVector128Double);
- supportsUnalignedSIMDLoads = !supportsAlignedSIMDLoads;
+ assert(!supportsUnalignedSIMDLoads);
+ supportsAlignedSIMDLoads = true;
}
else
{
@@ -5254,7 +5442,10 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
supportsUnalignedSIMDLoads = true;
}
- supportsGeneralLoads = supportsUnalignedSIMDLoads;
+ const unsigned expectedSize = genTypeSize(containingNode->TypeGet());
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize);
break;
}
}
@@ -5283,11 +5474,9 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_AVX_Blend:
case NI_AVX_Compare:
case NI_AVX_DotProduct:
- case NI_AVX_InsertVector128:
case NI_AVX_Permute:
case NI_AVX_Permute2x128:
case NI_AVX2_Blend:
- case NI_AVX2_InsertVector128:
case NI_AVX2_MultipleSumAbsoluteDifferences:
case NI_AVX2_Permute2x128:
case NI_AVX2_Permute4x64:
@@ -5297,17 +5486,29 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_AVX2_ShuffleHigh:
case NI_AVX2_ShuffleLow:
{
- if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32))
- {
- // These intrinsics only expect 16 or 32-byte nodes for containment
- break;
- }
assert(!supportsSIMDScalarLoads);
+ const unsigned expectedSize = genTypeSize(containingNode->GetSimdBaseType());
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
supportsAlignedSIMDLoads = !comp->canUseVexEncoding() || !comp->opts.MinOpts();
supportsUnalignedSIMDLoads = comp->canUseVexEncoding();
- supportsGeneralLoads = supportsUnalignedSIMDLoads;
+ supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize);
+ break;
+ }
+ case NI_AVX_InsertVector128:
+ case NI_AVX2_InsertVector128:
+ {
+ // InsertVector128 is special in that that it returns a TYP_SIMD32 but takes a TYP_SIMD16
+ assert(!supportsSIMDScalarLoads);
+
+ const unsigned expectedSize = 16;
+ const unsigned operandSize = genTypeSize(node->TypeGet());
+
+ supportsAlignedSIMDLoads = !comp->canUseVexEncoding() || !comp->opts.MinOpts();
+ supportsUnalignedSIMDLoads = comp->canUseVexEncoding();
+ supportsGeneralLoads = supportsUnalignedSIMDLoads && (operandSize >= expectedSize);
break;
}
@@ -5315,16 +5516,13 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_SSE41_Insert:
case NI_SSE41_X64_Insert:
{
+ assert(supportsAlignedSIMDLoads == false);
+ assert(supportsUnalignedSIMDLoads == false);
+
if (containingNode->GetSimdBaseType() == TYP_FLOAT)
{
assert(containingIntrinsicId == NI_SSE41_Insert);
- if (genTypeSize(node->TypeGet()) != 16)
- {
- // These intrinsics only expect 16-byte nodes for containment
- break;
- }
-
// Sse41.Insert(V128, V128, byte) is a bit special
// in that it has different behavior depending on whether the
// second operand is coming from a register or memory. When coming
@@ -5333,8 +5531,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
// from memory, it only works with the lowest element and is effectively
// a `SIMDScalar`.
- assert(supportsAlignedSIMDLoads == false);
- assert(supportsUnalignedSIMDLoads == false);
assert(supportsGeneralLoads == false);
assert(supportsSIMDScalarLoads == false);
@@ -5342,8 +5538,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
GenTree* op2 = containingNode->Op(2);
GenTree* op3 = containingNode->Op(3);
- assert(node == op2);
-
// The upper two bits of the immediate value are ignored if
// op2 comes from memory. In order to support using the upper
// bits, we need to disable containment support if op3 is not
@@ -5363,9 +5557,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
// We should only get here for integral nodes.
assert(varTypeIsIntegral(node->TypeGet()));
-
- assert(supportsAlignedSIMDLoads == false);
- assert(supportsUnalignedSIMDLoads == false);
assert(supportsSIMDScalarLoads == false);
const unsigned expectedSize = genTypeSize(containingNode->GetSimdBaseType());
@@ -5377,12 +5568,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_AVX_CompareScalar:
{
- if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32))
- {
- // These intrinsics only expect 16 or 32-byte nodes for containment
- break;
- }
-
assert(supportsAlignedSIMDLoads == false);
assert(supportsUnalignedSIMDLoads == false);
@@ -5413,21 +5598,38 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
case NI_Vector128_CreateScalarUnsafe:
case NI_Vector256_CreateScalarUnsafe:
{
+ if (!varTypeIsIntegral(node->TypeGet()))
+ {
+ // The floating-point overload doesn't require any special semantics
+ supportsSIMDScalarLoads = true;
+ supportsGeneralLoads = supportsSIMDScalarLoads;
+ break;
+ }
+
+ // The integral overloads only take GPR/mem
assert(supportsSIMDScalarLoads == false);
const unsigned expectedSize = genTypeSize(genActualType(containingNode->GetSimdBaseType()));
const unsigned operandSize = genTypeSize(node->TypeGet());
- supportsGeneralLoads = (operandSize == expectedSize);
+ supportsGeneralLoads = (operandSize >= expectedSize);
break;
}
case NI_AVX2_BroadcastScalarToVector128:
case NI_AVX2_BroadcastScalarToVector256:
{
- // The memory form of this already takes a pointer, and cannot be further contained.
- // The containable form is the one that takes a SIMD value, that may be in memory.
- supportsGeneralLoads = (node->TypeGet() == TYP_SIMD16);
+ if (!containingNode->OperIsMemoryLoad())
+ {
+ // The containable form is the one that takes a SIMD value, that may be in memory.
+ supportsSIMDScalarLoads = true;
+ supportsGeneralLoads = supportsSIMDScalarLoads;
+ }
+ else
+ {
+ // The memory form of this already takes a pointer and should be treated like a MemoryLoad
+ supportsGeneralLoads = !node->OperIsHWIntrinsic();
+ }
break;
}
@@ -5449,23 +5651,18 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
break;
}
+ // The integral overloads only take GPR/mem
assert(supportsSIMDScalarLoads == false);
const unsigned expectedSize = genTypeSize(genActualType(containingNode->GetSimdBaseType()));
const unsigned operandSize = genTypeSize(node->TypeGet());
- supportsGeneralLoads = (operandSize == expectedSize);
+ supportsGeneralLoads = (operandSize >= expectedSize);
break;
}
default:
{
- if ((genTypeSize(node->TypeGet()) != 16) && (genTypeSize(node->TypeGet()) != 32))
- {
- // These intrinsics only expect 16 or 32-byte nodes for containment
- break;
- }
-
supportsSIMDScalarLoads = true;
supportsGeneralLoads = supportsSIMDScalarLoads;
break;
@@ -5508,20 +5705,55 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
}
}
- noway_assert(supportsRegOptional != nullptr);
*supportsRegOptional = supportsGeneralLoads;
if (!node->OperIsHWIntrinsic())
{
- return supportsGeneralLoads && IsContainableMemoryOp(node);
+ return supportsGeneralLoads && (IsContainableMemoryOp(node) || node->IsCnsNonZeroFltOrDbl());
}
// TODO-XArch: Update this to be table driven, if possible.
- NamedIntrinsic intrinsicId = node->AsHWIntrinsic()->GetHWIntrinsicId();
+ GenTreeHWIntrinsic* hwintrinsic = node->AsHWIntrinsic();
+ NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId();
switch (intrinsicId)
{
+ case NI_Vector128_CreateScalarUnsafe:
+ case NI_Vector256_CreateScalarUnsafe:
+ {
+ if (!supportsSIMDScalarLoads)
+ {
+ return false;
+ }
+
+ GenTree* op1 = hwintrinsic->Op(1);
+ bool op1SupportsRegOptional = false;
+
+ if (!TryGetContainableHWIntrinsicOp(containingNode, &op1, &op1SupportsRegOptional))
+ {
+ return false;
+ }
+
+ LIR::Use use;
+ if (!BlockRange().TryGetUse(node, &use) || (use.User() != containingNode))
+ {
+ return false;
+ }
+
+ // We have CreateScalarUnsafe where the underlying scalar is directly containable
+ // by containingNode. As such, we'll just remove CreateScalarUnsafe and consume
+ // the value directly.
+
+ use.ReplaceWith(op1);
+ BlockRange().Remove(node);
+
+ node = op1;
+ node->ClearContained();
+
+ return true;
+ }
+
case NI_SSE_LoadAlignedVector128:
case NI_SSE2_LoadAlignedVector128:
case NI_AVX_LoadAlignedVector256:
@@ -5567,7 +5799,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* containingNode, Ge
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))
@@ -5709,7 +5941,22 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
bool supportsRegOptional = false;
- if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ if (node->OperIsMemoryLoad())
+ {
+ // We have a few cases that can be potential memory loads
+
+ assert((intrinsicId == NI_SSE41_ConvertToVector128Int16) ||
+ (intrinsicId == NI_SSE41_ConvertToVector128Int32) ||
+ (intrinsicId == NI_SSE41_ConvertToVector128Int64) ||
+ (intrinsicId == NI_AVX2_BroadcastScalarToVector128) ||
+ (intrinsicId == NI_AVX2_BroadcastScalarToVector256) ||
+ (intrinsicId == NI_AVX2_ConvertToVector256Int16) ||
+ (intrinsicId == NI_AVX2_ConvertToVector256Int32) ||
+ (intrinsicId == NI_AVX2_ConvertToVector256Int64));
+
+ ContainCheckHWIntrinsicAddr(node, op1);
+ }
+ else if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
}
@@ -5765,13 +6012,13 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
{
bool supportsRegOptional = false;
- if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
else if ((isCommutative || (intrinsicId == NI_BMI2_MultiplyNoFlags) ||
(intrinsicId == NI_BMI2_X64_MultiplyNoFlags)) &&
- IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
@@ -5817,7 +6064,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
if (!HWIntrinsicInfo::isImmOp(intrinsicId, op2))
{
- if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
@@ -5839,7 +6086,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
{
// These intrinsics have op2 as an imm and op1 as a reg/mem
- if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
}
@@ -5866,7 +6113,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
if (HWIntrinsicInfo::isImmOp(intrinsicId, op2))
{
- if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
}
@@ -5875,7 +6122,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
op1->SetRegOptional();
}
}
- else if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ else if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
@@ -5888,7 +6135,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AES_KeygenAssist:
{
- if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
}
@@ -6016,18 +6263,19 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
// Set op regOptional only if none of them is containable.
// Prefer to make op3 contained,
- if (resultOpNum != 3 && IsContainableHWIntrinsicOp(node, op3, &supportsOp3RegOptional))
+ if (resultOpNum != 3 && TryGetContainableHWIntrinsicOp(node, &op3, &supportsOp3RegOptional))
{
// result = (op1 * op2) + [op3]
MakeSrcContained(node, op3);
}
- else if (resultOpNum != 2 && IsContainableHWIntrinsicOp(node, op2, &supportsOp2RegOptional))
+ else if (resultOpNum != 2 &&
+ TryGetContainableHWIntrinsicOp(node, &op2, &supportsOp2RegOptional))
{
// result = (op1 * [op2]) + op3
MakeSrcContained(node, op2);
}
else if (resultOpNum != 1 && !HWIntrinsicInfo::CopiesUpperBits(intrinsicId) &&
- IsContainableHWIntrinsicOp(node, op1, &supportsOp1RegOptional))
+ TryGetContainableHWIntrinsicOp(node, &op1, &supportsOp1RegOptional))
{
// result = ([op1] * op2) + op3
MakeSrcContained(node, op1);
@@ -6057,7 +6305,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AVX_BlendVariable:
case NI_AVX2_BlendVariable:
{
- if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
@@ -6070,7 +6318,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AVXVNNI_MultiplyWideningAndAdd:
case NI_AVXVNNI_MultiplyWideningAndAddSaturate:
{
- if (IsContainableHWIntrinsicOp(node, op3, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op3, &supportsRegOptional))
{
MakeSrcContained(node, op3);
}
@@ -6083,11 +6331,11 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_BMI2_MultiplyNoFlags:
case NI_BMI2_X64_MultiplyNoFlags:
{
- if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
- else if (IsContainableHWIntrinsicOp(node, op1, &supportsRegOptional))
+ else if (TryGetContainableHWIntrinsicOp(node, &op1, &supportsRegOptional))
{
MakeSrcContained(node, op1);
// MultiplyNoFlags is a Commutative operation, so swap the first two operands here
@@ -6141,7 +6389,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AVX2_Permute2x128:
case NI_PCLMULQDQ_CarrylessMultiply:
{
- if (IsContainableHWIntrinsicOp(node, op2, &supportsRegOptional))
+ if (TryGetContainableHWIntrinsicOp(node, &op2, &supportsRegOptional))
{
MakeSrcContained(node, op2);
}
diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp
index 9308836ff78fcb..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;
}
@@ -2808,7 +2812,7 @@ regNumber LinearScan::allocateReg(Interval* currentInterval,
bool wasAssigned = regSelector->foundUnassignedReg() && (assignedInterval != nullptr) &&
(assignedInterval->physReg == foundReg);
unassignPhysReg(availablePhysRegRecord ARM_ARG(currentInterval->registerType));
- if (regSelector->isMatchingConstant())
+ if (regSelector->isMatchingConstant() && compiler->opts.OptimizationEnabled())
{
assert(assignedInterval->isConstant);
refPosition->treeNode->SetReuseRegVal();
@@ -6415,7 +6419,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
else
{
JITDUMP("at end of " FMT_BB ":\n", block->bbNum);
- if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH)
+ if (block->KindIs(BBJ_COND, BBJ_SWITCH))
{
noway_assert(!blockRange.IsEmpty());
@@ -6427,7 +6431,7 @@ void LinearScan::insertUpperVectorRestore(GenTree* tree,
}
else
{
- assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
+ assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS));
blockRange.InsertAtEnd(LIR::SeqTree(compiler, simdNode));
}
}
@@ -7291,7 +7295,7 @@ void LinearScan::insertMove(
{
// Put the copy at the bottom
GenTree* lastNode = blockRange.LastNode();
- if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH)
+ if (block->KindIs(BBJ_COND, BBJ_SWITCH))
{
noway_assert(!blockRange.IsEmpty());
@@ -7359,7 +7363,7 @@ void LinearScan::insertSwap(
{
// Put the copy at the bottom
// If there's a branch, make an embedded statement that executes just prior to the branch
- if (block->bbJumpKind == BBJ_COND || block->bbJumpKind == BBJ_SWITCH)
+ if (block->KindIs(BBJ_COND, BBJ_SWITCH))
{
noway_assert(!blockRange.IsEmpty());
@@ -7371,7 +7375,7 @@ void LinearScan::insertSwap(
}
else
{
- assert(block->bbJumpKind == BBJ_NONE || block->bbJumpKind == BBJ_ALWAYS);
+ assert(block->KindIs(BBJ_NONE, BBJ_ALWAYS));
blockRange.InsertAtEnd(std::move(swapRange));
}
}
diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h
index 1b549424f0fc44..052c3f93999a3c 100644
--- a/src/coreclr/jit/lsra.h
+++ b/src/coreclr/jit/lsra.h
@@ -1772,7 +1772,7 @@ class LinearScan : public LinearScanInterface
// The following keep track of information about internal (temporary register) intervals
// during the building of a single node.
- static const int MaxInternalCount = 4;
+ static const int MaxInternalCount = 5;
RefPosition* internalDefs[MaxInternalCount];
int internalCount = 0;
bool setInternalRegsDelayFree;
diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp
index 73b971ec5932fa..f18099f4f573e5 100644
--- a/src/coreclr/jit/lsraarm64.cpp
+++ b/src/coreclr/jit/lsraarm64.cpp
@@ -522,7 +522,6 @@ int LinearScan::BuildNode(GenTree* tree)
break;
case GT_BLK:
- case GT_DYN_BLK:
// These should all be eliminated prior to Lowering.
assert(!"Non-store block node in Lowering");
srcCount = 0;
@@ -1091,55 +1090,52 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree)
}
}
}
- else
+ else if (intrin.op2 != nullptr)
{
- if (intrin.op2 != nullptr)
- {
- // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg
- // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use.
+ // RMW intrinsic operands doesn't have to be delayFree when they can be assigned the same register as op1Reg
+ // (i.e. a register that corresponds to read-modify-write operand) and one of them is the last use.
- assert(intrin.op1 != nullptr);
+ assert(intrin.op1 != nullptr);
- bool forceOp2DelayFree = false;
- if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement))
+ bool forceOp2DelayFree = false;
+ if ((intrin.id == NI_Vector64_GetElement) || (intrin.id == NI_Vector128_GetElement))
+ {
+ if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal()))
{
- if (!intrin.op2->IsCnsIntOrI() && (!intrin.op1->isContained() || intrin.op1->OperIsLocal()))
- {
- // If the index is not a constant and the object is not contained or is a local
- // we will need a general purpose register to calculate the address
- // internal register must not clobber input index
- // TODO-Cleanup: An internal register will never clobber a source; this code actually
- // ensures that the index (op2) doesn't interfere with the target.
- buildInternalIntRegisterDefForNode(intrinsicTree);
- forceOp2DelayFree = true;
- }
-
- if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained())
- {
- // If the index is not a constant or op1 is in register,
- // we will use the SIMD temp location to store the vector.
- var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16;
- compiler->getSIMDInitTempVarNum(requiredSimdTempType);
- }
+ // If the index is not a constant and the object is not contained or is a local
+ // we will need a general purpose register to calculate the address
+ // internal register must not clobber input index
+ // TODO-Cleanup: An internal register will never clobber a source; this code actually
+ // ensures that the index (op2) doesn't interfere with the target.
+ buildInternalIntRegisterDefForNode(intrinsicTree);
+ forceOp2DelayFree = true;
}
- if (forceOp2DelayFree)
- {
- srcCount += BuildDelayFreeUses(intrin.op2);
- }
- else
+ if (!intrin.op2->IsCnsIntOrI() && !intrin.op1->isContained())
{
- srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2);
+ // If the index is not a constant or op1 is in register,
+ // we will use the SIMD temp location to store the vector.
+ var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16;
+ compiler->getSIMDInitTempVarNum(requiredSimdTempType);
}
+ }
- if (intrin.op3 != nullptr)
- {
- srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3);
+ if (forceOp2DelayFree)
+ {
+ srcCount += BuildDelayFreeUses(intrin.op2);
+ }
+ else
+ {
+ srcCount += isRMW ? BuildDelayFreeUses(intrin.op2, intrin.op1) : BuildOperandUses(intrin.op2);
+ }
- if (intrin.op4 != nullptr)
- {
- srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4);
- }
+ if (intrin.op3 != nullptr)
+ {
+ srcCount += isRMW ? BuildDelayFreeUses(intrin.op3, intrin.op1) : BuildOperandUses(intrin.op3);
+
+ if (intrin.op4 != nullptr)
+ {
+ srcCount += isRMW ? BuildDelayFreeUses(intrin.op4, intrin.op1) : BuildOperandUses(intrin.op4);
}
}
}
diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp
index ef7a2d0440aa49..a8db1264b64af1 100644
--- a/src/coreclr/jit/lsraarmarch.cpp
+++ b/src/coreclr/jit/lsraarmarch.cpp
@@ -694,36 +694,40 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode)
{
buildInternalIntRegisterDefForNode(blkNode);
#ifdef TARGET_ARM64
- const bool dstAddrMayNeedReg = dstAddr->isContained();
- const bool srcAddrMayNeedReg = src->OperIs(GT_LCL_VAR, GT_LCL_FLD) ||
- ((srcAddrOrFill != nullptr) && srcAddrOrFill->isContained());
+ const bool canUseLoadStorePairIntRegsInstrs = (size >= 2 * REGSIZE_BYTES);
- if (srcAddrMayNeedReg && dstAddrMayNeedReg)
+ if (canUseLoadStorePairIntRegsInstrs)
{
- // The following allocates an additional integer register in a case
- // when a load instruction and a store instruction cannot be encoded.
+ // CodeGen can use ldp/stp instructions sequence.
buildInternalIntRegisterDefForNode(blkNode);
- // In this case, CodeGen will use a SIMD register for copying.
- buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
- // And in case of a larger block size, two SIMD registers.
- if (size >= 2 * REGSIZE_BYTES)
- {
- buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
- }
}
- else if (srcAddrMayNeedReg || dstAddrMayNeedReg)
+
+ const bool isSrcAddrLocal = src->OperIs(GT_LCL_VAR, GT_LCL_FLD) ||
+ ((srcAddrOrFill != nullptr) && srcAddrOrFill->OperIsLocalAddr());
+ const bool isDstAddrLocal = dstAddr->OperIsLocalAddr();
+
+ // CodeGen can use 16-byte SIMD ldp/stp for larger block sizes
+ // only when both source and destination base address registers have known alignment.
+ // This is the case, when both registers are either sp or fp.
+ bool canUse16ByteWideInstrs = isSrcAddrLocal && isDstAddrLocal && (size >= 2 * FP_REGSIZE_BYTES);
+
+ // Note that the SIMD registers allocation is speculative - LSRA doesn't know at this point
+ // whether CodeGen will use SIMD registers (i.e. if such instruction sequence will be more optimal).
+ // Therefore, it must allocate an additional integer register anyway.
+ if (canUse16ByteWideInstrs)
{
- if (size >= 2 * REGSIZE_BYTES)
- {
- buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
- buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
- }
- else
- {
- buildInternalIntRegisterDefForNode(blkNode);
- }
+ buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
+ buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates());
}
- else if (size >= 2 * REGSIZE_BYTES)
+
+ const bool srcAddrMayNeedReg =
+ isSrcAddrLocal || ((srcAddrOrFill != nullptr) && srcAddrOrFill->isContained());
+ const bool dstAddrMayNeedReg = isDstAddrLocal || dstAddr->isContained();
+
+ // The following allocates an additional integer register in a case
+ // when a load instruction and a store instruction cannot be encoded using offset
+ // from a corresponding base register.
+ if (srcAddrMayNeedReg && dstAddrMayNeedReg)
{
buildInternalIntRegisterDefForNode(blkNode);
}
@@ -781,7 +785,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode)
if (blkNode->OperIs(GT_STORE_DYN_BLK))
{
useCount++;
- BuildUse(blkNode->AsDynBlk()->gtDynamicSize, sizeRegMask);
+ BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask);
}
buildInternalRegisterUses();
diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp
index a48d7e7bdee574..d58f1996091fae 100644
--- a/src/coreclr/jit/lsrabuild.cpp
+++ b/src/coreclr/jit/lsrabuild.cpp
@@ -3078,6 +3078,15 @@ int LinearScan::BuildOperandUses(GenTree* node, regMaskTP candidates)
return 1;
}
+#ifdef TARGET_ARM64
+ // Must happen before OperIsHWIntrinsic case,
+ // but this occurs when a vector zero node is marked as contained.
+ if (node->IsVectorZero())
+ {
+ return 0;
+ }
+#endif
+
#if !defined(TARGET_64BIT)
if (node->OperIs(GT_LONG))
{
@@ -3164,6 +3173,14 @@ int LinearScan::BuildDelayFreeUses(GenTree* node, GenTree* rmwNode, regMaskTP ca
{
use = BuildUse(node, candidates);
}
+#ifdef TARGET_ARM64
+ // Must happen before OperIsHWIntrinsic case,
+ // but this occurs when a vector zero node is marked as contained.
+ else if (node->IsVectorZero())
+ {
+ return 0;
+ }
+#endif
#ifdef FEATURE_HW_INTRINSICS
else if (node->OperIsHWIntrinsic())
{
diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp
index ce1de0b6f4fde1..e679f00b3bca33 100644
--- a/src/coreclr/jit/lsraxarch.cpp
+++ b/src/coreclr/jit/lsraxarch.cpp
@@ -496,7 +496,6 @@ int LinearScan::BuildNode(GenTree* tree)
case GT_OBJ:
#endif
case GT_BLK:
- case GT_DYN_BLK:
// These should all be eliminated prior to Lowering.
assert(!"Non-store block node in Lowering");
srcCount = 0;
@@ -1438,7 +1437,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode)
if (blkNode->OperIs(GT_STORE_DYN_BLK))
{
useCount++;
- BuildUse(blkNode->AsDynBlk()->gtDynamicSize, sizeRegMask);
+ BuildUse(blkNode->AsStoreDynBlk()->gtDynamicSize, sizeRegMask);
}
#ifdef TARGET_X86
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 972cecf7cd2eef..f07fe3ca9ed02b 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -4866,10 +4866,6 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, GenTreeCall::Use*
argx->gtFlags &= ~(GTF_ALL_EFFECT) | (argx->AsBlk()->Addr()->gtFlags & GTF_ALL_EFFECT);
argx->SetIndirExceptionFlags(this);
}
- else
- {
- argx->gtFlags |= GTF_DONT_CSE;
- }
// Copy the valuetype to the temp
GenTree* copyBlk = gtNewBlkOpNode(dest, argx, false /* not volatile */, true /* copyBlock */);
@@ -5198,7 +5194,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
asIndex->Arr()->AsStrCon()->gtSconCPX, &length);
if ((cnsIndex < length) && (str != nullptr))
{
- GenTree* cnsCharNode = gtNewIconNode(str[cnsIndex], elemTyp);
+ GenTree* cnsCharNode = gtNewIconNode(str[cnsIndex], TYP_INT);
INDEBUG(cnsCharNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
return cnsCharNode;
}
@@ -10431,15 +10427,8 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigne
{
if (indirTree != nullptr)
{
- if (indirTree->OperIsBlk() && !isBlkReqd)
- {
- effectiveVal->SetOper(GT_IND);
- }
- else
- {
- // If we have an indirection and a block is required, it should already be a block.
- assert(indirTree->OperIsBlk() || !isBlkReqd);
- }
+ // If we have an indirection and a block is required, it should already be a block.
+ assert(indirTree->OperIsBlk() || !isBlkReqd);
effectiveVal->gtType = asgType;
}
else
@@ -10778,7 +10767,7 @@ GenTree* Compiler::fgMorphFieldAssignToSimdSetElement(GenTree* tree)
// A folded GenTree* instance or nullptr if something prevents folding.
//
-GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree)
+GenTreeOp* Compiler::fgMorphCommutative(GenTreeOp* tree)
{
assert(varTypeIsIntegralOrI(tree->TypeGet()));
assert(tree->OperIs(GT_ADD, GT_MUL, GT_OR, GT_AND, GT_XOR));
@@ -10850,7 +10839,7 @@ GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree)
DEBUG_DESTROY_NODE(foldedCns);
INDEBUG(cns1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
- return op1;
+ return op1->AsOp();
}
//------------------------------------------------------------------------------
@@ -10863,6 +10852,8 @@ GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree)
// A folded GenTree* instance, or nullptr if it couldn't be folded
GenTree* Compiler::fgMorphCastedBitwiseOp(GenTreeOp* tree)
{
+ // This transform does not preserve VNs and deletes a node.
+ assert(fgGlobalMorph);
assert(varTypeIsIntegralOrI(tree));
assert(tree->OperIs(GT_OR, GT_AND, GT_XOR));
@@ -11610,7 +11601,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
break;
case GT_OBJ:
case GT_BLK:
- case GT_DYN_BLK:
case GT_IND:
// A non-null mac here implies this node is part of an address computation (the tree parent is
// GT_ADDR).
@@ -11849,7 +11839,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
}
} // if (op2)
+#ifndef TARGET_64BIT
DONE_MORPHING_CHILDREN:
+#endif // !TARGET_64BIT
if (tree->OperIsIndirOrArrLength())
{
@@ -11984,8 +11976,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
*/
GenTree* temp;
- GenTree* cns1;
- GenTree* cns2;
size_t ival1;
GenTree* lclVarTree;
GenTree* effectiveOp1;
@@ -12236,335 +12226,15 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
case GT_OR:
case GT_XOR:
case GT_AND:
-
- /* Commute any non-REF constants to the right */
-
- noway_assert(op1);
- if (op1->OperIsConst() && (op1->gtType != TYP_REF))
- {
- // TODO-Review: We used to assert here that
- // noway_assert(!op2->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD));
- // With modifications to AddrTaken==>AddrExposed, we did more assertion propagation,
- // and would sometimes hit this assertion. This may indicate a missed "remorph".
- // Task is to re-enable this assertion and investigate.
-
- /* Swap the operands */
- tree->AsOp()->gtOp1 = op2;
- tree->AsOp()->gtOp2 = op1;
-
- op1 = op2;
- op2 = tree->AsOp()->gtOp2;
- }
-
- // Fold "cmp & 1" to just "cmp"
- if (tree->OperIs(GT_AND) && tree->TypeIs(TYP_INT) && op1->OperIsCompare() && op2->IsIntegralConst(1) &&
- !gtIsActiveCSE_Candidate(tree) && !gtIsActiveCSE_Candidate(op2))
- {
- DEBUG_DESTROY_NODE(op2);
- DEBUG_DESTROY_NODE(tree);
- return op1;
- }
-
- // See if we can fold floating point operations (can regress minopts mode)
- if (opts.OptimizationEnabled() && varTypeIsFloating(tree->TypeGet()) && !optValnumCSE_phase)
- {
- if ((oper == GT_MUL) && !op1->IsCnsFltOrDbl() && op2->IsCnsFltOrDbl())
- {
- if (op2->AsDblCon()->gtDconVal == 2.0)
- {
- bool needsComma = !op1->OperIsLeaf() && !op1->IsLocal();
- // if op1 is not a leaf/local we have to introduce a temp via GT_COMMA.
- // Unfortunately, it's not optHoistLoopCode-friendly yet so let's do it later.
- if (!needsComma || (fgOrder == FGOrderLinear))
- {
- // Fold "x*2.0" to "x+x"
- op2 = fgMakeMultiUse(&tree->AsOp()->gtOp1);
- op1 = tree->AsOp()->gtOp1;
- oper = GT_ADD;
- tree = gtNewOperNode(oper, tree->TypeGet(), op1, op2);
- INDEBUG(tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
- }
- }
- else if (op2->AsDblCon()->gtDconVal == 1.0)
- {
- // Fold "x*1.0" to "x"
- DEBUG_DESTROY_NODE(op2);
- DEBUG_DESTROY_NODE(tree);
- return op1;
- }
- }
- }
-
- /* See if we can fold GT_ADD nodes. */
-
- if (oper == GT_ADD)
- {
- /* Fold "((x+icon1)+(y+icon2)) to ((x+y)+(icon1+icon2))" */
-
- if (op1->gtOper == GT_ADD && op2->gtOper == GT_ADD && !gtIsActiveCSE_Candidate(op2) &&
- op1->AsOp()->gtOp2->gtOper == GT_CNS_INT && op2->AsOp()->gtOp2->gtOper == GT_CNS_INT &&
- !op1->gtOverflow() && !op2->gtOverflow())
- {
- // Don't create a byref pointer that may point outside of the ref object.
- // If a GC happens, the byref won't get updated. This can happen if one
- // of the int components is negative. It also requires the address generation
- // be in a fully-interruptible code region.
- if (!varTypeIsGC(op1->AsOp()->gtOp1->TypeGet()) && !varTypeIsGC(op2->AsOp()->gtOp1->TypeGet()))
- {
- cns1 = op1->AsOp()->gtOp2;
- cns2 = op2->AsOp()->gtOp2;
-
- ssize_t value = cns1->AsIntCon()->IconValue() + cns2->AsIntCon()->IconValue();
- cns1->AsIntCon()->SetValueTruncating(value);
-
- tree->AsOp()->gtOp2 = cns1;
- DEBUG_DESTROY_NODE(cns2);
-
- op1->AsOp()->gtOp2 = op2->AsOp()->gtOp1;
- op1->gtFlags |= (op1->AsOp()->gtOp2->gtFlags & GTF_ALL_EFFECT);
- DEBUG_DESTROY_NODE(op2);
- op2 = tree->AsOp()->gtOp2;
- }
- }
-
- if (op2->IsCnsIntOrI() && varTypeIsIntegralOrI(typ))
- {
- // Fold (x + 0).
- if ((op2->AsIntConCommon()->IconValue() == 0) && !gtIsActiveCSE_Candidate(tree))
- {
- // Remove the addition iff it won't change the tree type
- // to TYP_REF.
-
- if (!gtIsActiveCSE_Candidate(op2) &&
- ((op1->TypeGet() == tree->TypeGet()) || (op1->TypeGet() != TYP_REF)))
- {
- if (fgGlobalMorph && (op2->OperGet() == GT_CNS_INT) &&
- (op2->AsIntCon()->gtFieldSeq != nullptr) &&
- (op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField()))
- {
- fgAddFieldSeqForZeroOffset(op1, op2->AsIntCon()->gtFieldSeq);
- }
-
- DEBUG_DESTROY_NODE(op2);
- DEBUG_DESTROY_NODE(tree);
-
- return op1;
- }
- }
- }
-
- if (opts.OptimizationEnabled() && fgGlobalMorph)
- {
- // - a + b = > b - a
- // ADD((NEG(a), b) => SUB(b, a)
-
- // Skip optimization if non-NEG operand is constant.
- if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && !op2->IsIntegralConst() &&
- gtCanSwapOrder(op1, op2))
- {
- // tree: ADD
- // op1: NEG
- // op2: b
- // op1Child: a
-
- GenTree* op1Child = op1->AsOp()->gtOp1; // a
- oper = GT_SUB;
- tree->SetOper(oper, GenTree::PRESERVE_VN);
- tree->AsOp()->gtOp1 = op2;
- tree->AsOp()->gtOp2 = op1Child;
-
- DEBUG_DESTROY_NODE(op1);
-
- op1 = op2;
- op2 = op1Child;
- }
- // a + -b = > a - b
- // ADD(a, (NEG(b)) => SUB(a, b)
- else if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG))
- {
- // a is non constant because it was already canonicalized to have
- // variable on the left and constant on the right.
-
- // tree: ADD
- // op1: a
- // op2: NEG
- // op2Child: b
-
- GenTree* op2Child = op2->AsOp()->gtOp1; // a
- oper = GT_SUB;
- tree->SetOper(oper, GenTree::PRESERVE_VN);
- tree->AsOp()->gtOp2 = op2Child;
-
- DEBUG_DESTROY_NODE(op2);
-
- op2 = op2Child;
- }
- }
- }
- /* See if we can fold GT_MUL by const nodes */
- else if (oper == GT_MUL && op2->IsCnsIntOrI() && !optValnumCSE_phase)
- {
-#ifndef TARGET_64BIT
- noway_assert(typ <= TYP_UINT);
-#endif // TARGET_64BIT
- noway_assert(!tree->gtOverflow());
-
- ssize_t mult = op2->AsIntConCommon()->IconValue();
- bool op2IsConstIndex = op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr &&
- op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq();
-
- assert(!op2IsConstIndex || op2->AsIntCon()->gtFieldSeq->m_next == nullptr);
-
- if (mult == 0)
- {
- // We may be able to throw away op1 (unless it has side-effects)
-
- if ((op1->gtFlags & GTF_SIDE_EFFECT) == 0)
- {
- DEBUG_DESTROY_NODE(op1);
- DEBUG_DESTROY_NODE(tree);
- return op2; // Just return the "0" node
- }
-
- // We need to keep op1 for the side-effects. Hang it off
- // a GT_COMMA node
-
- tree->ChangeOper(GT_COMMA);
- return tree;
- }
-
- size_t abs_mult = (mult >= 0) ? mult : -mult;
- size_t lowestBit = genFindLowestBit(abs_mult);
- bool changeToShift = false;
-
- // is it a power of two? (positive or negative)
- if (abs_mult == lowestBit)
- {
- // if negative negate (min-int does not need negation)
- if (mult < 0 && mult != SSIZE_T_MIN)
- {
- // The type of the new GT_NEG node cannot just be op1->TypeGet().
- // Otherwise we may sign-extend incorrectly in cases where the GT_NEG
- // node ends up feeding directly a cast, for example in
- // GT_CAST(GT_MUL(-1, s_1.ubyte))
- tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_NEG, genActualType(op1->TypeGet()), op1);
- fgMorphTreeDone(op1);
- }
-
- // If "op2" is a constant array index, the other multiplicand must be a constant.
- // Transfer the annotation to the other one.
- if (op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr &&
- op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq())
- {
- assert(op2->AsIntCon()->gtFieldSeq->m_next == nullptr);
- GenTree* otherOp = op1;
- if (otherOp->OperGet() == GT_NEG)
- {
- otherOp = otherOp->AsOp()->gtOp1;
- }
- assert(otherOp->OperGet() == GT_CNS_INT);
- assert(otherOp->AsIntCon()->gtFieldSeq == FieldSeqStore::NotAField());
- otherOp->AsIntCon()->gtFieldSeq = op2->AsIntCon()->gtFieldSeq;
- }
-
- if (abs_mult == 1)
- {
- DEBUG_DESTROY_NODE(op2);
- DEBUG_DESTROY_NODE(tree);
- return op1;
- }
-
- /* Change the multiplication into a shift by log2(val) bits */
- op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult));
- changeToShift = true;
- }
- else if ((lowestBit > 1) && jitIsScaleIndexMul(lowestBit) && optAvoidIntMult())
- {
- int shift = genLog2(lowestBit);
- ssize_t factor = abs_mult >> shift;
-
- if (factor == 3 || factor == 5 || factor == 9)
- {
- // if negative negate (min-int does not need negation)
- if (mult < 0 && mult != SSIZE_T_MIN)
- {
- tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_NEG, genActualType(op1->TypeGet()), op1);
- fgMorphTreeDone(op1);
- }
-
- GenTree* factorIcon = gtNewIconNode(factor, TYP_I_IMPL);
- if (op2IsConstIndex)
- {
- factorIcon->AsIntCon()->gtFieldSeq =
- GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField);
- }
-
- // change the multiplication into a smaller multiplication (by 3, 5 or 9) and a shift
- tree->AsOp()->gtOp1 = op1 = gtNewOperNode(GT_MUL, tree->gtType, op1, factorIcon);
- fgMorphTreeDone(op1);
-
- op2->AsIntConCommon()->SetIconValue(shift);
- changeToShift = true;
- }
- }
- if (changeToShift)
- {
- // vnStore is null before the ValueNumber phase has run
- if (vnStore != nullptr)
- {
- // Update the ValueNumber for 'op2', as we just changed the constant
- fgValueNumberTreeConst(op2);
- }
- oper = GT_LSH;
- // Keep the old ValueNumber for 'tree' as the new expr
- // will still compute the same value as before
- tree->ChangeOper(oper, GenTree::PRESERVE_VN);
-
- goto DONE_MORPHING_CHILDREN;
- }
- }
- else if (fgOperIsBitwiseRotationRoot(oper))
- {
- tree = fgRecognizeAndMorphBitwiseRotation(tree);
-
- // fgRecognizeAndMorphBitwiseRotation may return a new tree
- oper = tree->OperGet();
- typ = tree->TypeGet();
- op1 = tree->AsOp()->gtOp1;
- op2 = tree->AsOp()->gtOp2;
- }
-
- if (fgGlobalMorph && varTypeIsIntegralOrI(tree) && tree->OperIs(GT_AND, GT_OR, GT_XOR))
- {
- GenTree* result = fgMorphCastedBitwiseOp(tree->AsOp());
- if (result != nullptr)
- {
- assert(result->OperIs(GT_CAST));
- assert(result->AsOp()->gtOp2 == nullptr);
- // tree got folded to a unary (cast) op
- tree = result;
- oper = tree->OperGet();
- typ = tree->TypeGet();
- op1 = tree->AsOp()->gtGetOp1();
- op2 = nullptr;
- }
- }
-
- if (varTypeIsIntegralOrI(tree->TypeGet()) && tree->OperIs(GT_ADD, GT_MUL, GT_AND, GT_OR, GT_XOR))
+ tree = fgOptimizeCommutativeArithmetic(tree->AsOp());
+ if (!tree->OperIsSimple())
{
- GenTree* foldedTree = fgMorphCommutative(tree->AsOp());
- if (foldedTree != nullptr)
- {
- tree = foldedTree;
- op1 = tree->gtGetOp1();
- op2 = tree->gtGetOp2();
- if (!tree->OperIs(oper))
- {
- return tree;
- }
- }
+ return tree;
}
-
+ typ = tree->TypeGet();
+ oper = tree->OperGet();
+ op1 = tree->gtGetOp1();
+ op2 = tree->gtGetOp2IfPresent();
break;
case GT_NOT:
@@ -13224,6 +12894,45 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
}
break;
+ case GT_INTRINSIC:
+ if (tree->AsIntrinsic()->gtIntrinsicName ==
+ NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant)
+ {
+ // Should be expanded by the time it reaches CSE phase
+ assert(!optValnumCSE_phase);
+
+ JITDUMP("\nExpanding RuntimeHelpers.IsKnownConstant to ");
+ if (op1->OperIsConst())
+ {
+ // We're lucky to catch a constant here while importer was not
+ JITDUMP("true\n");
+ DEBUG_DESTROY_NODE(tree, op1);
+ tree = gtNewIconNode(1);
+ }
+ else
+ {
+ GenTree* op1SideEffects = nullptr;
+ gtExtractSideEffList(op1, &op1SideEffects, GTF_ALL_EFFECT);
+ if (op1SideEffects != nullptr)
+ {
+ DEBUG_DESTROY_NODE(tree);
+ // Keep side-effects of op1
+ tree = gtNewOperNode(GT_COMMA, TYP_INT, op1SideEffects, gtNewIconNode(0));
+ JITDUMP("false with side effects:\n")
+ DISPTREE(tree);
+ }
+ else
+ {
+ JITDUMP("false\n");
+ DEBUG_DESTROY_NODE(tree, op1);
+ tree = gtNewIconNode(0);
+ }
+ }
+ INDEBUG(tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
+ return tree;
+ }
+ break;
+
default:
break;
}
@@ -13704,11 +13413,381 @@ GenTree* Compiler::fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp)
return cmp;
}
+//------------------------------------------------------------------------
+// fgOptimizeCommutativeArithmetic: Optimizes commutative operations.
+//
+// Arguments:
+// tree - the unchecked GT_ADD/GT_MUL/GT_OR/GT_XOR/GT_AND tree to optimize.
+//
+// Return Value:
+// The optimized tree that can have any shape.
+//
+GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree)
+{
+ assert(tree->OperIs(GT_ADD, GT_MUL, GT_OR, GT_XOR, GT_AND));
+ assert(!tree->gtOverflowEx());
+
+ // Commute constants to the right.
+ if (tree->gtGetOp1()->OperIsConst() && !tree->gtGetOp1()->TypeIs(TYP_REF))
+ {
+ // TODO-Review: We used to assert here that "(!op2->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD))".
+ // This may indicate a missed "remorph". Task is to re-enable this assertion and investigate.
+ std::swap(tree->gtOp1, tree->gtOp2);
+ }
+
+ if (fgOperIsBitwiseRotationRoot(tree->OperGet()))
+ {
+ GenTree* rotationTree = fgRecognizeAndMorphBitwiseRotation(tree);
+ if (rotationTree != nullptr)
+ {
+ return rotationTree;
+ }
+ }
+
+ if (fgGlobalMorph && tree->OperIs(GT_AND, GT_OR, GT_XOR))
+ {
+ GenTree* castTree = fgMorphCastedBitwiseOp(tree->AsOp());
+ if (castTree != nullptr)
+ {
+ return castTree;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ return tree;
+}
+
+//------------------------------------------------------------------------
+// fgOptimizeAddition: optimizes addition.
+//
+// Arguments:
+// add - the unchecked GT_ADD tree to optimize.
+//
+// Return Value:
+// The optimized tree, that can have any shape, in case any transformations
+// were performed. Otherwise, "nullptr", guaranteeing no state change.
+//
+GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add)
+{
+ assert(add->OperIs(GT_ADD) && !add->gtOverflow());
+ assert(!optValnumCSE_phase);
+
+ GenTree* op1 = add->gtGetOp1();
+ GenTree* op2 = add->gtGetOp2();
+
+ // Fold "((x + icon1) + (y + icon2))" to ((x + y) + (icon1 + icon2))".
+ // Be careful not to create a byref pointer that may point outside of the ref object.
+ // Only do this in global morph as we don't recompute the VN for "(x + y)", the new "op2".
+ if (op1->OperIs(GT_ADD) && op2->OperIs(GT_ADD) && !op1->gtOverflow() && !op2->gtOverflow() &&
+ op1->AsOp()->gtGetOp2()->IsCnsIntOrI() && op2->AsOp()->gtGetOp2()->IsCnsIntOrI() &&
+ !varTypeIsGC(op1->AsOp()->gtGetOp1()) && !varTypeIsGC(op2->AsOp()->gtGetOp1()) && fgGlobalMorph)
+ {
+ GenTreeOp* addOne = op1->AsOp();
+ GenTreeOp* addTwo = op2->AsOp();
+ GenTreeIntCon* constOne = addOne->gtGetOp2()->AsIntCon();
+ GenTreeIntCon* constTwo = addTwo->gtGetOp2()->AsIntCon();
+
+ addOne->gtOp2 = addTwo->gtGetOp1();
+ addOne->SetAllEffectsFlags(addOne->gtGetOp1(), addOne->gtGetOp2());
+ DEBUG_DESTROY_NODE(addTwo);
+
+ constOne->SetValueTruncating(constOne->IconValue() + constTwo->IconValue());
+ op2 = constOne;
+ add->gtOp2 = constOne;
+ DEBUG_DESTROY_NODE(constTwo);
+ }
+
+ // 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->IsIntegralConst(0) && ((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF)))
+ {
+ if (op2->IsCnsIntOrI() && (op2->AsIntCon()->gtFieldSeq != nullptr) &&
+ (op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField()))
+ {
+ fgAddFieldSeqForZeroOffset(op1, op2->AsIntCon()->gtFieldSeq);
+ }
+
+ DEBUG_DESTROY_NODE(op2);
+ DEBUG_DESTROY_NODE(add);
+
+ return op1;
+ }
+
+ // Note that these transformations are legal for floating-point ADDs as well.
+ if (opts.OptimizationEnabled())
+ {
+ // - a + b = > b - a
+ // ADD((NEG(a), b) => SUB(b, a)
+
+ // Do not do this if "op2" is constant for canonicalization purposes.
+ if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && !op2->IsIntegralConst() && gtCanSwapOrder(op1, op2))
+ {
+ add->SetOper(GT_SUB);
+ add->gtOp1 = op2;
+ add->gtOp2 = op1->AsOp()->gtGetOp1();
+
+ DEBUG_DESTROY_NODE(op1);
+
+ return add;
+ }
+
+ // a + -b = > a - b
+ // ADD(a, (NEG(b)) => SUB(a, b)
+ if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG))
+ {
+ add->SetOper(GT_SUB);
+ add->gtOp2 = op2->AsOp()->gtGetOp1();
+
+ DEBUG_DESTROY_NODE(op2);
+
+ return add;
+ }
+ }
+
+ return nullptr;
+}
+
+//------------------------------------------------------------------------
+// fgOptimizeMultiply: optimizes multiplication.
+//
+// Arguments:
+// mul - the unchecked TYP_I_IMPL/TYP_INT GT_MUL tree to optimize.
+//
+// Return Value:
+// The optimized tree, that can have any shape, in case any transformations
+// were performed. Otherwise, "nullptr", guaranteeing no state change.
+//
+GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul)
+{
+ assert(mul->OperIs(GT_MUL));
+ assert(varTypeIsIntOrI(mul) || varTypeIsFloating(mul));
+ assert(!mul->gtOverflow());
+ assert(!optValnumCSE_phase);
+
+ GenTree* op1 = mul->gtGetOp1();
+ GenTree* op2 = mul->gtGetOp2();
+
+ assert(mul->TypeGet() == genActualType(op1));
+ assert(mul->TypeGet() == genActualType(op2));
+
+ if (opts.OptimizationEnabled() && op2->IsCnsFltOrDbl())
+ {
+ double multiplierValue = op2->AsDblCon()->gtDconVal;
+
+ if (multiplierValue == 1.0)
+ {
+ // Fold "x * 1.0" to "x".
+ DEBUG_DESTROY_NODE(op2);
+ DEBUG_DESTROY_NODE(mul);
+
+ return op1;
+ }
+
+ // Fold "x * 2.0" to "x + x".
+ // If op1 is not a local we will have to introduce a temporary via GT_COMMA.
+ // Unfortunately, it's not optHoistLoopCode-friendly (yet), so we'll only do
+ // this for locals / after hoisting has run (when rationalization remorphs
+ // math INTRINSICSs into calls...).
+ if ((multiplierValue == 2.0) && (op1->IsLocal() || (fgOrder == FGOrderLinear)))
+ {
+ op2 = fgMakeMultiUse(&op1);
+ GenTree* add = gtNewOperNode(GT_ADD, mul->TypeGet(), op1, op2);
+ INDEBUG(add->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
+
+ return add;
+ }
+ }
+
+ if (op2->IsIntegralConst())
+ {
+ ssize_t mult = op2->AsIntConCommon()->IconValue();
+ bool op2IsConstIndex = op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr &&
+ op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq();
+
+ assert(!op2IsConstIndex || op2->AsIntCon()->gtFieldSeq->m_next == nullptr);
+
+ if (mult == 0)
+ {
+ // We may be able to throw away op1 (unless it has side-effects)
+
+ if ((op1->gtFlags & GTF_SIDE_EFFECT) == 0)
+ {
+ DEBUG_DESTROY_NODE(op1);
+ DEBUG_DESTROY_NODE(mul);
+
+ return op2; // Just return the "0" node
+ }
+
+ // We need to keep op1 for the side-effects. Hang it off a GT_COMMA node.
+ mul->ChangeOper(GT_COMMA, GenTree::PRESERVE_VN);
+ 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;
+
+ // is it a power of two? (positive or negative)
+ if (abs_mult == lowestBit)
+ {
+ // if negative negate (min-int does not need negation)
+ if (mult < 0 && mult != SSIZE_T_MIN)
+ {
+ op1 = gtNewOperNode(GT_NEG, genActualType(op1), op1);
+ mul->gtOp1 = op1;
+ fgMorphTreeDone(op1);
+ }
+
+ // If "op2" is a constant array index, the other multiplicand must be a constant.
+ // Transfer the annotation to the other one.
+ if (op2->OperGet() == GT_CNS_INT && op2->AsIntCon()->gtFieldSeq != nullptr &&
+ op2->AsIntCon()->gtFieldSeq->IsConstantIndexFieldSeq())
+ {
+ assert(op2->AsIntCon()->gtFieldSeq->m_next == nullptr);
+ GenTree* otherOp = op1;
+ if (otherOp->OperGet() == GT_NEG)
+ {
+ otherOp = otherOp->AsOp()->gtOp1;
+ }
+ assert(otherOp->OperGet() == GT_CNS_INT);
+ assert(otherOp->AsIntCon()->gtFieldSeq == FieldSeqStore::NotAField());
+ otherOp->AsIntCon()->gtFieldSeq = op2->AsIntCon()->gtFieldSeq;
+ }
+
+ if (abs_mult == 1)
+ {
+ DEBUG_DESTROY_NODE(op2);
+ DEBUG_DESTROY_NODE(mul);
+ return op1;
+ }
+
+ // Change the multiplication into a shift by log2(val) bits.
+ op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult));
+ changeToShift = true;
+ }
+ else if (mulShiftOpt && (lowestBit > 1) && jitIsScaleIndexMul(lowestBit))
+ {
+ int shift = genLog2(lowestBit);
+ ssize_t factor = abs_mult >> shift;
+
+ if (factor == 3 || factor == 5 || factor == 9)
+ {
+ // if negative negate (min-int does not need negation)
+ if (mult < 0 && mult != SSIZE_T_MIN)
+ {
+ op1 = gtNewOperNode(GT_NEG, genActualType(op1), op1);
+ mul->gtOp1 = op1;
+ fgMorphTreeDone(op1);
+ }
+
+ GenTree* factorIcon = gtNewIconNode(factor, mul->TypeGet());
+ if (op2IsConstIndex)
+ {
+ factorIcon->AsIntCon()->gtFieldSeq =
+ GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField);
+ }
+
+ // change the multiplication into a smaller multiplication (by 3, 5 or 9) and a shift
+ op1 = gtNewOperNode(GT_MUL, mul->TypeGet(), op1, factorIcon);
+ mul->gtOp1 = op1;
+ fgMorphTreeDone(op1);
+
+ op2->AsIntConCommon()->SetIconValue(shift);
+ changeToShift = true;
+ }
+ }
+
+ if (changeToShift)
+ {
+ fgUpdateConstTreeValueNumber(op2);
+ mul->ChangeOper(GT_LSH, GenTree::PRESERVE_VN);
+
+ return mul;
+ }
+ }
+
+ return nullptr;
+}
+
+//------------------------------------------------------------------------
+// fgOptimizeBitwiseAnd: optimizes the "and" operation.
+//
+// Arguments:
+// andOp - the GT_AND tree to optimize.
+//
+// Return Value:
+// The optimized tree, currently always a relop, in case any transformations
+// were performed. Otherwise, "nullptr", guaranteeing no state change.
+//
+GenTree* Compiler::fgOptimizeBitwiseAnd(GenTreeOp* andOp)
+{
+ assert(andOp->OperIs(GT_AND));
+ assert(!optValnumCSE_phase);
+
+ GenTree* op1 = andOp->gtGetOp1();
+ GenTree* op2 = andOp->gtGetOp2();
+
+ // Fold "cmp & 1" to just "cmp".
+ if (andOp->TypeIs(TYP_INT) && op1->OperIsCompare() && op2->IsIntegralConst(1))
+ {
+ DEBUG_DESTROY_NODE(op2);
+ DEBUG_DESTROY_NODE(andOp);
+
+ return op1;
+ }
+
+ return nullptr;
+}
+
//------------------------------------------------------------------------
// fgPropagateCommaThrow: propagate a "comma throw" up the tree.
//
// "Comma throws" in the compiler represent the canonical form of an always
-// throwing expression. They have the shape of COMMA(THROW, ZERO), to satsify
+// throwing expression. They have the shape of COMMA(THROW, ZERO), to satisfy
// the semantic that the original expression produced some value and are
// generated by "gtFoldExprConst" when it encounters checked arithmetic that
// will determinably overflow.
@@ -14347,7 +14426,7 @@ bool Compiler::fgOperIsBitwiseRotationRoot(genTreeOps oper)
// tree - tree to check for a rotation pattern
//
// Return Value:
-// An equivalent GT_ROL or GT_ROR tree if a pattern is found; original tree otherwise.
+// An equivalent GT_ROL or GT_ROR tree if a pattern is found; "nullptr" otherwise.
//
// Assumption:
// The input is a GT_OR or a GT_XOR tree.
@@ -14397,7 +14476,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
// We can't do anything if the tree has assignments, calls, or volatile
// reads. Note that we allow GTF_EXCEPT side effect since any exceptions
// thrown by the original tree will be thrown by the transformed tree as well.
- return tree;
+ return nullptr;
}
genTreeOps oper = tree->OperGet();
@@ -14420,7 +14499,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
}
else
{
- return tree;
+ return nullptr;
}
// Check if the trees representing the value to shift are identical.
@@ -14452,7 +14531,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
}
else
{
- return tree;
+ return nullptr;
}
}
@@ -14465,7 +14544,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
}
else
{
- return tree;
+ return nullptr;
}
}
@@ -14475,7 +14554,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
// something like (x << y & 15) or
// (x >> (32 - y) & 15 with 32 bit x.
// The transformation is not valid.
- return tree;
+ return nullptr;
}
GenTree* shiftIndexWithAdd = nullptr;
@@ -14521,7 +14600,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
// TODO-X86-CQ: we need to handle variable-sized long shifts specially on x86.
// GT_LSH, GT_RSH, and GT_RSZ have helpers for this case. We may need
// to add helpers for GT_ROL and GT_ROR.
- return tree;
+ return nullptr;
}
#endif
@@ -14575,7 +14654,8 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree)
return tree;
}
}
- return tree;
+
+ return nullptr;
}
#if !defined(TARGET_64BIT)
@@ -14902,23 +14982,7 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac)
break;
case GT_STORE_DYN_BLK:
- case GT_DYN_BLK:
- if (tree->OperGet() == GT_STORE_DYN_BLK)
- {
- tree->AsDynBlk()->Data() = fgMorphTree(tree->AsDynBlk()->Data());
- }
- tree->AsDynBlk()->Addr() = fgMorphTree(tree->AsDynBlk()->Addr());
- tree->AsDynBlk()->gtDynamicSize = fgMorphTree(tree->AsDynBlk()->gtDynamicSize);
-
- tree->gtFlags &= ~GTF_CALL;
- tree->SetIndirExceptionFlags(this);
-
- if (tree->OperGet() == GT_STORE_DYN_BLK)
- {
- tree->gtFlags |= tree->AsDynBlk()->Data()->gtFlags & GTF_ALL_EFFECT;
- }
- tree->gtFlags |= tree->AsDynBlk()->Addr()->gtFlags & GTF_ALL_EFFECT;
- tree->gtFlags |= tree->AsDynBlk()->gtDynamicSize->gtFlags & GTF_ALL_EFFECT;
+ tree = fgMorphStoreDynBlock(tree->AsStoreDynBlk());
break;
default:
diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp
index 233f72ef8f1102..d725923478433e 100644
--- a/src/coreclr/jit/morphblock.cpp
+++ b/src/coreclr/jit/morphblock.cpp
@@ -26,7 +26,6 @@ class MorphInitBlockHelper
static GenTree* MorphBlock(Compiler* comp, GenTree* tree, bool isDest);
static GenTree* MorphCommaBlock(Compiler* comp, GenTreeOp* firstComma);
- static GenTreeBlk* MorphDynamicBlock(Compiler* comp, GenTreeDynBlk* dynBlock);
protected:
Compiler* m_comp;
@@ -36,9 +35,7 @@ class MorphInitBlockHelper
GenTree* m_dst = nullptr;
GenTree* m_src = nullptr;
- unsigned m_blockSize = 0;
- bool m_blockSizeIsConst = false;
-
+ unsigned m_blockSize = 0;
unsigned m_dstLclNum = BAD_VAR_NUM;
GenTreeLclVarCommon* m_dstLclNode = nullptr;
LclVarDsc* m_dstVarDsc = nullptr;
@@ -212,9 +209,8 @@ void MorphInitBlockHelper::PrepareDst()
if (m_dst->IsLocal())
{
- m_dstLclNode = m_dst->AsLclVarCommon();
- m_dstVarDsc = m_comp->lvaGetDesc(m_dstLclNode);
- m_blockSizeIsConst = true;
+ m_dstLclNode = m_dst->AsLclVarCommon();
+ m_dstVarDsc = m_comp->lvaGetDesc(m_dstLclNode);
if (m_dst->OperIs(GT_LCL_VAR))
{
@@ -248,21 +244,19 @@ void MorphInitBlockHelper::PrepareDst()
else
{
assert(m_dst == m_dst->gtEffectiveVal() && "the commas were skipped in MorphBlock");
- assert(m_dst->OperIs(GT_IND, GT_BLK, GT_OBJ, GT_DYN_BLK));
+ assert(m_dst->OperIs(GT_IND, GT_BLK, GT_OBJ));
GenTree* dstAddr = m_dst->AsIndir()->Addr();
if (m_dst->OperGet() == GT_IND)
{
assert(m_dst->TypeGet() != TYP_STRUCT);
- m_blockSize = genTypeSize(m_dst);
- m_blockSizeIsConst = true;
+ m_blockSize = genTypeSize(m_dst);
}
else
{
assert(m_dst->OperIsBlk());
- GenTreeBlk* blk = m_dst->AsBlk();
- m_blockSize = blk->Size();
- m_blockSizeIsConst = !blk->OperIs(GT_DYN_BLK);
+ GenTreeBlk* blk = m_dst->AsBlk();
+ m_blockSize = blk->Size();
}
noway_assert(dstAddr->TypeIs(TYP_BYREF, TYP_I_IMPL));
@@ -444,22 +438,10 @@ GenTree* MorphInitBlockHelper::MorphBlock(Compiler* comp, GenTree* tree, bool is
return tree;
}
- GenTreeBlk* blkNode = tree->AsBlk();
- if (blkNode->OperIs(GT_DYN_BLK))
- {
- blkNode = MorphDynamicBlock(comp, blkNode->AsDynBlk());
- if (blkNode->OperIs(GT_DYN_BLK))
- {
- JITDUMP("MorphBlock after:\n");
- DISPTREE(blkNode);
- return blkNode;
- }
- }
-
- GenTree* blkAddr = blkNode->Addr();
+ GenTree* blkAddr = tree->AsBlk()->Addr();
assert(blkAddr != nullptr);
assert(blkAddr->TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF));
- // GT_ADDR, GT_LCL_VAR/FLD, GT_ADD, GT_COMMA, GT_CALL, GT_CNST_INT, GT_LCL_VAR/FLD_ADDR
+ // GT_ADDR, GT_LCL_VAR/FLD, GT_ADD, GT_COMMA, GT_CALL, GT_CNS_INT, GT_LCL_VAR/FLD_ADDR
JITDUMP("MorphBlock after:\n");
DISPTREE(tree);
@@ -539,41 +521,6 @@ GenTree* MorphInitBlockHelper::MorphCommaBlock(Compiler* comp, GenTreeOp* firstC
return res;
}
-//------------------------------------------------------------------------
-// MorphDynamicBlock: tries to transform a dynamic block as a const block.
-//
-// static
-GenTreeBlk* MorphInitBlockHelper::MorphDynamicBlock(Compiler* comp, GenTreeDynBlk* dynBlock)
-{
- if (dynBlock->gtDynamicSize->IsCnsIntOrI())
- {
- GenTreeIntCon* dynSize = dynBlock->gtDynamicSize->AsIntCon();
- assert(dynSize->FitsInI32());
- unsigned size = static_cast(dynSize->IconValue());
- // A GT_BLK with size of zero is not supported,
- // so if we encounter such a thing we just leave it as a GT_DYN_BLK
- if (size != 0)
- {
- dynBlock->gtDynamicSize = nullptr;
- GenTreeBlk* blkNode = dynBlock;
- blkNode->ChangeOper(GT_BLK);
- blkNode->SetLayout(comp->typGetBlkLayout(size));
- JITDUMP("MorphDynamicBlock: DYN_BLK was morphed into BLK:\n");
- return blkNode;
- }
- else
- {
- JITDUMP("MorphDynamicBlock: DYN_BLK with zero size can't be morphed:\n");
- return dynBlock;
- }
- }
- else
- {
- JITDUMP("MorphDynamicBlock: DYN_BLK with non-const size can't be morphed:\n");
- return dynBlock;
- }
-}
-
class MorphCopyBlockHelper : public MorphInitBlockHelper
{
public:
@@ -745,7 +692,7 @@ void MorphCopyBlockHelper::MorphStructCases()
if (m_dstVarDsc != nullptr)
{
- if (m_dstVarDsc->lvPromoted && m_blockSizeIsConst)
+ if (m_dstVarDsc->lvPromoted)
{
noway_assert(varTypeIsStruct(m_dstVarDsc));
noway_assert(!m_comp->opts.MinOpts());
@@ -765,7 +712,7 @@ void MorphCopyBlockHelper::MorphStructCases()
if (m_srcVarDsc != nullptr)
{
- if (m_srcVarDsc->lvPromoted && m_blockSizeIsConst)
+ if (m_srcVarDsc->lvPromoted)
{
noway_assert(varTypeIsStruct(m_srcVarDsc));
noway_assert(!m_comp->opts.MinOpts());
@@ -912,7 +859,7 @@ void MorphCopyBlockHelper::MorphStructCases()
// [000085] -A---------- = long
// [000083] D------N---- lclVar long V17 tmp9
//
- if (m_blockSizeIsConst && (m_dstVarDsc->lvFieldCnt == 1) && (m_srcVarDsc != nullptr) &&
+ if ((m_dstVarDsc->lvFieldCnt == 1) && (m_srcVarDsc != nullptr) &&
(m_blockSize == genTypeSize(m_srcVarDsc->TypeGet())))
{
// Reject the following tree:
@@ -950,7 +897,7 @@ void MorphCopyBlockHelper::MorphStructCases()
// [000243] -----+------ \--* addr byref
// [000242] D----+-N---- \--* lclVar byref V28 tmp19
//
- if (m_blockSizeIsConst && (m_srcVarDsc->lvFieldCnt == 1) && (m_dstVarDsc != nullptr) &&
+ if ((m_srcVarDsc->lvFieldCnt == 1) && (m_dstVarDsc != nullptr) &&
(m_blockSize == genTypeSize(m_dstVarDsc->TypeGet())))
{
// Check for type agreement
@@ -1048,9 +995,9 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
{
GenTreeOp* asgFields = nullptr;
- GenTree* addrSpill = nullptr;
- unsigned addrSpillTemp = BAD_VAR_NUM;
- bool addrSpillIsStackDest = false; // true if 'addrSpill' represents the address in our local stack frame
+ GenTree* addrSpill = nullptr;
+ unsigned addrSpillSrcLclNum = BAD_VAR_NUM;
+ unsigned addrSpillTemp = BAD_VAR_NUM;
GenTree* addrSpillAsg = nullptr;
@@ -1095,7 +1042,8 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
// We will spill m_srcAddr (i.e. assign to a temp "BlockOp address local")
// no need to clone a new copy as it is only used once
//
- addrSpill = m_srcAddr; // addrSpill represents the 'm_srcAddr'
+ addrSpill = m_srcAddr; // addrSpill represents the 'm_srcAddr'
+ addrSpillSrcLclNum = m_srcLclNum;
}
}
}
@@ -1144,28 +1092,13 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
// We will spill m_dstAddr (i.e. assign to a temp "BlockOp address local")
// no need to clone a new copy as it is only used once
//
- addrSpill = m_dstAddr; // addrSpill represents the 'm_dstAddr'
+ addrSpill = m_dstAddr; // addrSpill represents the 'm_dstAddr'
+ addrSpillSrcLclNum = m_dstLclNum;
}
}
}
}
- // TODO-CQ: this should be based on a more general
- // "BaseAddress" method, that handles fields of structs, before or after
- // morphing.
- if ((addrSpill != nullptr) && addrSpill->OperIs(GT_ADDR))
- {
- GenTree* addrSpillOp = addrSpill->AsOp()->gtGetOp1();
- if (addrSpillOp->IsLocal())
- {
- // We will *not* consider this to define the local, but rather have each individual field assign
- // be a definition.
- addrSpillOp->gtFlags &= ~(GTF_LIVENESS_MASK);
- addrSpillIsStackDest = true; // addrSpill represents the address of LclVar[varNum] in our
- // local stack frame
- }
- }
-
if (addrSpill != nullptr)
{
// 'addrSpill' is already morphed
@@ -1178,30 +1111,26 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
addrSpillDsc->lvType = TYP_BYREF;
- if (addrSpillIsStackDest)
+ if (addrSpillSrcLclNum != BAD_VAR_NUM)
{
+ // addrSpill represents the address of LclVar[varNum] in our local stack frame.
addrSpillDsc->lvStackByref = true;
}
GenTreeLclVar* addrSpillNode = m_comp->gtNewLclvNode(addrSpillTemp, TYP_BYREF);
addrSpillAsg = m_comp->gtNewAssignNode(addrSpillNode, addrSpill);
- // If we are assigning the address of a LclVar here
- // liveness does not account for this kind of address taken use.
+ // If we are assigning the address of a LclVar here liveness will not
+ // account for this kind of address taken use. Mark the local as
+ // address-exposed so that we don't do illegal optimizations with it.
//
- // We have to mark this local as address exposed so
- // that we don't delete the definition for this LclVar
- // as a dead store later on.
+ // TODO-CQ: usage of "addrSpill" for local addresses is a workaround
+ // for cases where we fail to use LCL_FLD nodes instead. Fix them and
+ // delete this code.
//
- if (addrSpill->OperGet() == GT_ADDR)
+ if (addrSpillSrcLclNum != BAD_VAR_NUM)
{
- GenTree* addrOp = addrSpill->AsOp()->gtOp1;
- if (addrOp->IsLocal())
- {
- unsigned lclVarNum = addrOp->AsLclVarCommon()->GetLclNum();
- m_comp->lvaGetDesc(lclVarNum)->SetAddressExposed(true DEBUGARG(AddressExposedReason::COPY_FLD_BY_FLD));
- m_comp->lvaSetVarDoNotEnregister(lclVarNum DEBUGARG(DoNotEnregisterReason::AddrExposed));
- }
+ m_comp->lvaSetVarAddrExposed(addrSpillSrcLclNum DEBUGARG(AddressExposedReason::COPY_FLD_BY_FLD));
}
}
@@ -1209,7 +1138,6 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
// So, beyond this point we cannot rely on the old values of 'm_srcVarDsc' and 'm_dstVarDsc'.
for (unsigned i = 0; i < fieldCnt; ++i)
{
-
GenTree* dstFld;
if (m_dstDoFldAsg)
{
@@ -1278,7 +1206,7 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField()
// Is the address of a local?
GenTreeLclVarCommon* lclVarTree = nullptr;
bool isEntire = false;
- bool* pIsEntire = (m_blockSizeIsConst ? &isEntire : nullptr);
+ bool* pIsEntire = &isEntire;
if (dstAddrClone->DefinesLocalAddr(m_comp, m_blockSize, &lclVarTree, pIsEntire))
{
lclVarTree->gtFlags |= GTF_VAR_DEF;
@@ -1551,3 +1479,50 @@ GenTree* Compiler::fgMorphInitBlock(GenTree* tree)
{
return MorphInitBlockHelper::MorphInitBlock(this, tree);
}
+
+//------------------------------------------------------------------------
+// fgMorphStoreDynBlock: Morph a dynamic block store (GT_STORE_DYN_BLK).
+//
+// Performs full (pre-order and post-order) morphing for a STORE_DYN_BLK.
+//
+// Arguments:
+// tree - The GT_STORE_DYN_BLK tree to morph.
+//
+// Return Value:
+// In case the size turns into a constant - the store, transformed
+// into an "ordinary" ASG(BLK, Data()) one, and further morphed by
+// "fgMorphInitBlock"/"fgMorphCopyBlock". Otherwise, the original
+// tree (fully morphed).
+//
+GenTree* Compiler::fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree)
+{
+ tree->Addr() = fgMorphTree(tree->Addr());
+ tree->Data() = fgMorphTree(tree->Data());
+ tree->gtDynamicSize = fgMorphTree(tree->gtDynamicSize);
+
+ if (tree->gtDynamicSize->IsIntegralConst())
+ {
+ int64_t size = tree->gtDynamicSize->AsIntConCommon()->IntegralValue();
+ assert(FitsIn(size));
+
+ if (size != 0)
+ {
+ GenTree* lhs = gtNewBlockVal(tree->Addr(), static_cast(size));
+ lhs->SetIndirExceptionFlags(this);
+
+ GenTree* asg = gtNewAssignNode(lhs, tree->Data());
+ asg->gtFlags |= (tree->gtFlags & (GTF_ALL_EFFECT | GTF_BLK_VOLATILE | GTF_BLK_UNALIGNED));
+ INDEBUG(asg->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
+
+ JITDUMP("MorphStoreDynBlock: trasformed STORE_DYN_BLK into ASG(BLK, Data())\n");
+
+ return tree->OperIsCopyBlkOp() ? fgMorphCopyBlock(asg) : fgMorphInitBlock(asg);
+ }
+ }
+
+ tree->SetAllEffectsFlags(tree->Addr(), tree->Data(), tree->gtDynamicSize);
+ tree->SetIndirExceptionFlags(this);
+ tree->gtFlags |= GTF_ASG;
+
+ return tree;
+}
diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h
index 25733a41a9c9ed..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
{
@@ -78,6 +81,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan,
NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray,
+ NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant,
NI_System_String_get_Chars,
NI_System_String_get_Length,
diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp
index f16fb917a589d4..108fde7e984976 100644
--- a/src/coreclr/jit/optcse.cpp
+++ b/src/coreclr/jit/optcse.cpp
@@ -829,7 +829,8 @@ bool Compiler::optValnumCSE_Locate()
continue;
}
- if (ValueNumStore::isReservedVN(tree->GetVN(VNK_Liberal)))
+ ValueNum valueVN = vnStore->VNNormalValue(tree->GetVN(VNK_Liberal));
+ if (ValueNumStore::isReservedVN(valueVN) && (valueVN != ValueNumStore::VNForNull()))
{
continue;
}
@@ -2598,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 2d3aedc94ba0a2..dd2f3a8246ede1 100644
--- a/src/coreclr/jit/optimizer.cpp
+++ b/src/coreclr/jit/optimizer.cpp
@@ -302,7 +302,7 @@ void Compiler::optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk)
}
// We only consider back-edges that are BBJ_COND or BBJ_ALWAYS for loops.
- if ((predBlock->bbJumpKind != BBJ_COND) && (predBlock->bbJumpKind != BBJ_ALWAYS))
+ if (!predBlock->KindIs(BBJ_COND, BBJ_ALWAYS))
{
continue;
}
@@ -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;
@@ -580,18 +573,39 @@ void Compiler::optUpdateLoopsBeforeRemoveBlock(BasicBlock* block, bool skipUnmar
reportAfter();
}
- if ((skipUnmarkLoop == false) && //
- ((block->bbJumpKind == BBJ_ALWAYS) || (block->bbJumpKind == BBJ_COND)) && //
- block->bbJumpDest->isLoopHead() && //
- (block->bbJumpDest->bbNum <= block->bbNum) && //
- fgDomsComputed && //
- (fgCurBBEpochSize == fgDomBBcount + 1) && //
+ if ((skipUnmarkLoop == false) && //
+ block->KindIs(BBJ_ALWAYS, BBJ_COND) && //
+ block->bbJumpDest->isLoopHead() && //
+ (block->bbJumpDest->bbNum <= block->bbNum) && //
+ fgDomsComputed && //
+ (fgCurBBEpochSize == fgDomBBcount + 1) && //
fgReachable(block->bbJumpDest, block))
{
optUnmarkLoopBlocks(block->bbJumpDest, block);
}
}
+//------------------------------------------------------------------------
+// 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
/*****************************************************************************
@@ -1685,9 +1699,7 @@ class LoopSearch
return false;
}
- if ((bottom->bbJumpKind == BBJ_EHFINALLYRET) || (bottom->bbJumpKind == BBJ_EHFILTERRET) ||
- (bottom->bbJumpKind == BBJ_EHCATCHRET) || (bottom->bbJumpKind == BBJ_CALLFINALLY) ||
- (bottom->bbJumpKind == BBJ_SWITCH))
+ if (bottom->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, BBJ_CALLFINALLY, BBJ_SWITCH))
{
// BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, and BBJ_CALLFINALLY can never form a loop.
// BBJ_SWITCH that has a backward jump appears only for labeled break.
@@ -1829,7 +1841,7 @@ class LoopSearch
}
}
// Can we fall through into the loop?
- else if (head->bbJumpKind == BBJ_NONE || head->bbJumpKind == BBJ_COND)
+ else if (head->KindIs(BBJ_NONE, BBJ_COND))
{
// The ENTRY is at the TOP (a do-while loop)
return top;
@@ -2139,7 +2151,7 @@ class LoopSearch
return nullptr;
}
- if ((newMoveAfter->bbJumpKind == BBJ_ALWAYS) || (newMoveAfter->bbJumpKind == BBJ_COND))
+ if (newMoveAfter->KindIs(BBJ_ALWAYS, BBJ_COND))
{
unsigned int destNum = newMoveAfter->bbJumpDest->bbNum;
if ((destNum >= top->bbNum) && (destNum <= bottom->bbNum) && !loopBlocks.IsMember(destNum))
@@ -2329,8 +2341,8 @@ class LoopSearch
}
// Make sure we don't leave around a goto-next unless it's marked KEEP_BBJ_ALWAYS.
- assert(((block->bbJumpKind != BBJ_COND) && (block->bbJumpKind != BBJ_ALWAYS)) ||
- (block->bbJumpDest != newNext) || ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0));
+ assert(!block->KindIs(BBJ_COND, BBJ_ALWAYS) || (block->bbJumpDest != newNext) ||
+ ((block->bbFlags & BBF_KEEP_BBJ_ALWAYS) != 0));
return newBlock;
}
@@ -7574,6 +7586,8 @@ void Compiler::fgCreateLoopPreHeader(unsigned lnum)
fgAddRefPred(preHead, predBlock);
}
} while (++jumpTab, --jumpCnt);
+
+ UpdateSwitchTableTarget(predBlock, entry, preHead);
break;
default:
@@ -7850,24 +7864,16 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
}
else
{
- // We are only interested in IsFieldAddr()'s fldSeq out parameter.
- //
- GenTree* obj = nullptr; // unused
- GenTree* staticOffset = nullptr; // unused
- FieldSeqNode* fldSeq = nullptr;
-
- if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq) &&
- (fldSeq != FieldSeqStore::NotAField()))
+ GenTree* baseAddr = nullptr;
+ FieldSeqNode* fldSeq = nullptr;
+ if (arg->IsFieldAddr(this, &baseAddr, &fldSeq))
{
- // Get the first (object) field from field seq. GcHeap[field] will yield the "field map".
- assert(fldSeq != nullptr);
- if (fldSeq->IsFirstElemFieldSeq())
- {
- fldSeq = fldSeq->m_next;
- assert(fldSeq != nullptr);
- }
+ assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) &&
+ !fldSeq->IsPseudoField());
- AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->m_fieldHnd);
+ FieldKindForVN fieldKind =
+ (baseAddr != nullptr) ? FieldKindForVN::WithBaseAddr : FieldKindForVN::SimpleStatic;
+ AddModifiedFieldAllContainingLoops(mostNestedLoop, fldSeq->GetFieldHandle(), fieldKind);
// Conservatively assume byrefs may alias this object.
memoryHavoc |= memoryKindSet(ByrefExposed);
}
@@ -7893,7 +7899,8 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
}
else if (lhs->OperGet() == GT_CLS_VAR)
{
- AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->AsClsVar()->gtClsVarHnd);
+ AddModifiedFieldAllContainingLoops(mostNestedLoop, lhs->AsClsVar()->gtClsVarHnd,
+ FieldKindForVN::SimpleStatic);
// Conservatively assume byrefs may alias this static field
memoryHavoc |= memoryKindSet(ByrefExposed);
}
@@ -7972,6 +7979,7 @@ bool Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
case GT_XCHG:
case GT_CMPXCHG:
case GT_MEMORYBARRIER:
+ case GT_STORE_DYN_BLK:
{
memoryHavoc |= memoryKindSet(GcHeap, ByrefExposed);
}
@@ -8073,12 +8081,12 @@ void Compiler::AddVariableLivenessAllContainingLoops(unsigned lnum, BasicBlock*
}
// Adds "fldHnd" to the set of modified fields of "lnum" and any parent loops.
-void Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd)
+void Compiler::AddModifiedFieldAllContainingLoops(unsigned lnum, CORINFO_FIELD_HANDLE fldHnd, FieldKindForVN fieldKind)
{
assert(0 <= lnum && lnum < optLoopCount);
while (lnum != BasicBlock::NOT_IN_LOOP)
{
- optLoopTable[lnum].AddModifiedField(this, fldHnd);
+ optLoopTable[lnum].AddModifiedField(this, fldHnd, fieldKind);
lnum = optLoopTable[lnum].lpParent;
}
}
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/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp
index 4a475806148b7e..56ad0323fd6de2 100644
--- a/src/coreclr/jit/rangecheck.cpp
+++ b/src/coreclr/jit/rangecheck.cpp
@@ -869,7 +869,7 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE
JITDUMP("Merge assertions from pred " FMT_BB " edge: ", pred->bbNum);
Compiler::optDumpAssertionIndices(assertions, "\n");
}
- else if ((pred->bbJumpKind == BBJ_COND || pred->bbJumpKind == BBJ_ALWAYS) && pred->bbJumpDest == block)
+ else if (pred->KindIs(BBJ_COND, BBJ_ALWAYS) && (pred->bbJumpDest == block))
{
if (m_pCompiler->bbJtrueAssertionOut != nullptr)
{
diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp
index 5e54ca8bd94d46..72c1591c6d4251 100644
--- a/src/coreclr/jit/rationalize.cpp
+++ b/src/coreclr/jit/rationalize.cpp
@@ -416,13 +416,10 @@ void Rationalizer::RewriteAssignment(LIR::Use& use)
}
GenTreeSIMD* simdTree =
comp->gtNewSIMDNode(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType));
- assignment->AsOp()->gtOp2 = simdTree;
- value = simdTree;
- initVal->gtNext = simdTree;
- simdTree->gtPrev = initVal;
+ assignment->gtOp2 = simdTree;
+ value = simdTree;
- simdTree->gtNext = location;
- location->gtPrev = simdTree;
+ BlockRange().InsertAfter(initVal, simdTree);
}
}
#endif // FEATURE_SIMD
@@ -468,7 +465,6 @@ void Rationalizer::RewriteAssignment(LIR::Use& use)
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
{
assert(varTypeIsStruct(location));
GenTreeBlk* storeBlk = location->AsBlk();
@@ -481,9 +477,6 @@ void Rationalizer::RewriteAssignment(LIR::Use& use)
case GT_OBJ:
storeOper = GT_STORE_OBJ;
break;
- case GT_DYN_BLK:
- storeOper = GT_STORE_DYN_BLK;
- break;
default:
unreached();
}
diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp
index 4646769263d376..48fe4d84d9aecb 100644
--- a/src/coreclr/jit/ssabuilder.cpp
+++ b/src/coreclr/jit/ssabuilder.cpp
@@ -732,7 +732,7 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block)
// This is perhaps temporary -- maybe should be done elsewhere. Label GT_INDs on LHS of assignments, so we
// can skip these during (at least) value numbering.
GenTree* lhs = asgNode->gtGetOp1()->gtEffectiveVal(/*commaOnly*/ true);
- if (lhs->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_DYN_BLK))
+ if (lhs->OperIs(GT_IND, GT_OBJ, GT_BLK))
{
lhs->gtFlags |= GTF_IND_ASG_LHS;
}
diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h
index cdab21582ffced..4cc6b63f73009f 100644
--- a/src/coreclr/jit/targetarm64.h
+++ b/src/coreclr/jit/targetarm64.h
@@ -11,8 +11,10 @@
#define ROUND_FLOAT 0 // Do not round intermed float expression results
#define CPU_HAS_BYTE_REGS 0
- #define CPBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll CpBlk.
- #define INITBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll InitBlk.
+ #define CPBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll CpBlk
+ #define CPBLK_LCL_UNROLL_LIMIT 128 // Upper bound to let the code generator to loop unroll CpBlk (when both srcAddr and dstAddr point to the stack)
+ #define INITBLK_UNROLL_LIMIT 64 // Upper bound to let the code generator to loop unroll InitBlk
+ #define INITBLK_LCL_UNROLL_LIMIT 128 // Upper bound to let the code generator to loop unroll InitBlk (when dstAddr points to the stack)
#ifdef FEATURE_SIMD
#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned
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 1c4341e147009a..947f774fbdac05 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -1266,6 +1266,17 @@ bool ValueNumStore::VNExcIsSubset(ValueNum vnFullSet, ValueNum vnCandidateSet)
}
}
+//----------------------------------------------------------------------------------------
+// VNPExcIsSubset - Given two exception sets, returns true when both the liberal and
+// conservative value numbers of vnpCandidateSet represent subsets of
+// the corresponding numbers in vnpFullSet (see VNExcIsSubset).
+//
+bool ValueNumStore::VNPExcIsSubset(ValueNumPair vnpFullSet, ValueNumPair vnpCandidateSet)
+{
+ return VNExcIsSubset(vnpFullSet.GetLiberal(), vnpCandidateSet.GetLiberal()) &&
+ VNExcIsSubset(vnpFullSet.GetConservative(), vnpCandidateSet.GetConservative());
+}
+
//-------------------------------------------------------------------------------------
// VNUnpackExc: - Given a ValueNum 'vnWx, return via write back parameters both
// the normal and the exception set components.
@@ -1423,6 +1434,64 @@ ValueNumPair ValueNumStore::VNPMakeNormalUniquePair(ValueNumPair vnp)
return ValueNumPair(VNMakeNormalUnique(vnp.GetLiberal()), VNMakeNormalUnique(vnp.GetConservative()));
}
+//------------------------------------------------------------------------------------
+// VNUniqueWithExc:
+//
+// Arguments:
+// type - The type for the unique Value Number
+// vnExcSet - The Value Number for the exception set.
+//
+// Return Value:
+// - VN representing a "new, unique" value, with
+// the exceptions contained in "vnExcSet".
+//
+ValueNum ValueNumStore::VNUniqueWithExc(var_types type, ValueNum vnExcSet)
+{
+ ValueNum normVN = VNForExpr(m_pComp->compCurBB, type);
+
+ if (vnExcSet == VNForEmptyExcSet())
+ {
+ return normVN;
+ }
+
+#ifdef DEBUG
+ VNFuncApp excSetFunc;
+ assert(GetVNFunc(vnExcSet, &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons));
+#endif // DEBUG
+
+ return VNWithExc(normVN, vnExcSet);
+}
+
+//------------------------------------------------------------------------------------
+// VNPUniqueWithExc:
+//
+// Arguments:
+// type - The type for the unique Value Numbers
+// vnExcSet - The Value Number Pair for the exception set.
+//
+// Return Value:
+// - VN Pair representing a "new, unique" value (liberal and conservative
+// values will be equal), with the exceptions contained in "vnpExcSet".
+//
+// Notes: - We use the same unique value number both for liberal and conservative
+// portions of the pair to save memory (it would not be useful to make
+// them different).
+//
+ValueNumPair ValueNumStore::VNPUniqueWithExc(var_types type, ValueNumPair vnpExcSet)
+{
+#ifdef DEBUG
+ VNFuncApp excSetFunc;
+ assert((GetVNFunc(vnpExcSet.GetLiberal(), &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons)) ||
+ (vnpExcSet.GetLiberal() == VNForEmptyExcSet()));
+ assert((GetVNFunc(vnpExcSet.GetConservative(), &excSetFunc) && (excSetFunc.m_func == VNF_ExcSetCons)) ||
+ (vnpExcSet.GetConservative() == VNForEmptyExcSet()));
+#endif // DEBUG
+
+ ValueNum normVN = VNForExpr(m_pComp->compCurBB, type);
+
+ return VNPWithExc(ValueNumPair(normVN, normVN), vnpExcSet);
+}
+
//--------------------------------------------------------------------------------
// VNNormalValue: - Returns a Value Number that represents the result for the
// normal (non-exceptional) evaluation for the expression.
@@ -4338,21 +4407,21 @@ ValueNum Compiler::fgValueNumberArrIndexAssign(CORINFO_CLASS_HANDLE elemTypeEq,
return vnStore->VNForMapStore(fgCurMemoryVN[GcHeap], elemTypeEqVN, newValAtArrType);
}
-ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* pFuncApp, ValueNum addrXvn)
+ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, VNFuncApp* pFuncApp, ValueNumPair addrXvnp)
{
assert(vnStore->IsVNHandle(pFuncApp->m_args[0]));
CORINFO_CLASS_HANDLE arrElemTypeEQ = CORINFO_CLASS_HANDLE(vnStore->ConstantValue(pFuncApp->m_args[0]));
ValueNum arrVN = pFuncApp->m_args[1];
ValueNum inxVN = pFuncApp->m_args[2];
FieldSeqNode* fldSeq = vnStore->FieldSeqVNToFieldSeq(pFuncApp->m_args[3]);
- return fgValueNumberArrIndexVal(tree, arrElemTypeEQ, arrVN, inxVN, addrXvn, fldSeq);
+ return fgValueNumberArrIndexVal(tree, arrElemTypeEQ, arrVN, inxVN, addrXvnp, fldSeq);
}
ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
CORINFO_CLASS_HANDLE elemTypeEq,
ValueNum arrVN,
ValueNum inxVN,
- ValueNum excVN,
+ ValueNumPair addrXvnp,
FieldSeqNode* fldSeq)
{
assert(tree == nullptr || tree->OperIsIndir());
@@ -4372,7 +4441,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
JITDUMP(" *** Not a proper arrray access encountered in fgValueNumberArrIndexVal\n");
// a new unique value number
- selectedElem = vnStore->VNForExpr(compCurBB, elemTyp);
+ selectedElem = vnStore->VNForExpr(compCurBB, indType);
#ifdef DEBUG
if (verbose)
@@ -4383,7 +4452,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
if (tree != nullptr)
{
- tree->gtVNPair.SetBoth(selectedElem);
+ tree->gtVNPair = vnStore->VNPWithExc(ValueNumPair(selectedElem, selectedElem), addrXvnp);
}
}
else
@@ -4422,7 +4491,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
elemTyp = vnStore->TypeOfVN(selectedElem);
}
selectedElem = vnStore->VNApplySelectorsTypeCheck(selectedElem, indType, elemStructSize);
- selectedElem = vnStore->VNWithExc(selectedElem, excVN);
+ selectedElem = vnStore->VNWithExc(selectedElem, addrXvnp.GetLiberal());
#ifdef DEBUG
if (verbose && (selectedElem != wholeElem))
@@ -4434,10 +4503,7 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree,
if (tree != nullptr)
{
tree->gtVNPair.SetLiberal(selectedElem);
-
- // TODO-CQ: what to do here about exceptions? We don't have the array and ind conservative
- // values, so we don't have their exceptions. Maybe we should.
- tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
+ tree->gtVNPair.SetConservative(vnStore->VNUniqueWithExc(tree->TypeGet(), addrXvnp.GetConservative()));
}
}
@@ -5952,8 +6018,7 @@ void ValueNumStore::vnDumpValWithExc(Compiler* comp, VNFuncApp* valWithExc)
GetVNFunc(excVN, &excSeq);
printf("norm=");
- printf(FMT_VN, normVN);
- vnDump(comp, normVN);
+ comp->vnPrint(normVN, 1);
printf(", exc=");
printf(FMT_VN, excVN);
vnDumpExcSeq(comp, &excSeq, true);
@@ -6143,7 +6208,7 @@ void ValueNumStore::vnDumpZeroObj(Compiler* comp, VNFuncApp* zeroObj)
static UINT8 vnfOpAttribs[VNF_COUNT];
static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memory.
GT_NULLCHECK, GT_QMARK, GT_COLON, GT_LOCKADD, GT_XADD, GT_XCHG,
- GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND,
+ GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_DYN_BLK,
// These need special semantics:
GT_COMMA, // == second argument (but with exception(s) from first).
@@ -6793,6 +6858,7 @@ void Compiler::fgValueNumber()
#ifdef DEBUG
JitTestCheckVN();
+ fgDebugCheckExceptionSets();
#endif // DEBUG
fgVNPassesCompleted++;
@@ -6812,10 +6878,11 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk)
assert(asg->OperIs(GT_ASG));
GenTreeLclVar* newSsaDef = asg->AsOp()->gtGetOp1()->AsLclVar();
+ GenTreePhi* phiNode = asg->AsOp()->gtGetOp2()->AsPhi();
ValueNumPair phiVNP;
ValueNumPair sameVNP;
- for (GenTreePhi::Use& use : asg->AsOp()->gtGetOp2()->AsPhi()->Uses())
+ for (GenTreePhi::Use& use : phiNode->Uses())
{
GenTreePhiArg* phiArg = use.GetNode()->AsPhiArg();
ValueNum phiArgSsaNumVN = vnStore->VNForIntCon(phiArg->GetSsaNum());
@@ -6880,6 +6947,10 @@ void Compiler::fgValueNumberBlock(BasicBlock* blk)
printf(" %s.\n", sameVNP.BothDefined() ? "(all same)" : "");
}
#endif // DEBUG
+
+ newSsaDef->gtVNPair = vnStore->VNPForVoid();
+ phiNode->gtVNPair = newSsaDefVNP;
+ asg->gtVNPair = vnStore->VNPForVoid();
}
// Now do the same for each MemoryKind.
@@ -7128,8 +7199,9 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
for (Compiler::LoopDsc::FieldHandleSet::KeyIterator ki = fieldsMod->Begin(); !ki.Equal(fieldsMod->End());
++ki)
{
- CORINFO_FIELD_HANDLE fldHnd = ki.Get();
- ValueNum fldHndVN = vnStore->VNForHandle(ssize_t(fldHnd), GTF_ICON_FIELD_HDL);
+ CORINFO_FIELD_HANDLE fldHnd = ki.Get();
+ FieldKindForVN fieldKind = ki.GetValue();
+ ValueNum fldHndVN = vnStore->VNForHandle(ssize_t(fldHnd), GTF_ICON_FIELD_HDL);
#ifdef DEBUG
if (verbose)
@@ -7140,9 +7212,9 @@ ValueNum Compiler::fgMemoryVNForLoopSideEffects(MemoryKind memoryKind,
}
#endif // DEBUG
- // Instance field maps get a placeholder type - they do not represent "singular"
- // values. Static field maps, on the other hand, do, and so must be given proper types.
- var_types fldMapType = eeIsFieldStatic(fldHnd) ? eeGetFieldType(fldHnd) : TYP_MEM;
+ // Instance fields and "complex" statics select "first field maps"
+ // with a placeholder type. "Simple" statics select their own types.
+ var_types fldMapType = (fieldKind == FieldKindForVN::WithBaseAddr) ? TYP_MEM : eeGetFieldType(fldHnd);
newMemoryVN = vnStore->VNForMapStore(newMemoryVN, fldHndVN, vnStore->VNForExpr(entryBlock, fldMapType));
}
@@ -7464,13 +7536,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
}
// We have to handle the case where the LHS is a comma. In that case, we don't evaluate the comma,
- // so we give it VNForVoid, and we're really interested in the effective value.
- GenTree* lhsCommaIter = lhs;
- while (lhsCommaIter->OperGet() == GT_COMMA)
- {
- lhsCommaIter->gtVNPair.SetBoth(vnStore->VNForVoid());
- lhsCommaIter = lhsCommaIter->AsOp()->gtOp2;
- }
+ // and we're really just interested in the effective value.
lhs = lhs->gtEffectiveVal();
// Now, record the new VN for an assignment (performing the indicated "state update").
@@ -7627,8 +7693,6 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
// Indicates whether the argument of the IND is the address of a local.
bool wasLocal = false;
- lhs->gtVNPair = rhsVNPair;
-
VNFuncApp funcApp;
ValueNum argVN = arg->gtVNPair.GetLiberal();
@@ -7735,9 +7799,8 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
// Was the argument of the GT_IND the address of a local, handled above?
if (!wasLocal)
{
- GenTree* obj = nullptr;
- GenTree* staticOffset = nullptr;
- FieldSeqNode* fldSeq = nullptr;
+ GenTree* baseAddr = nullptr;
+ FieldSeqNode* fldSeq = nullptr;
// Is the LHS an array index expression?
if (argIsVNFunc && funcApp.m_func == VNF_PtrToArrElem)
@@ -7796,7 +7859,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
rhsVNPair.GetLiberal(), lhs->TypeGet());
recordGcHeapStore(tree, heapVN DEBUGARG("ArrIndexAssign (case 2)"));
}
- else if (arg->IsFieldAddr(this, &obj, &staticOffset, &fldSeq))
+ else if (arg->IsFieldAddr(this, &baseAddr, &fldSeq))
{
assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) && !fldSeq->IsPseudoField());
@@ -7807,11 +7870,10 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
// We will check that the final field in the sequence matches 'indType'.
var_types indType = lhs->TypeGet();
- // when (obj != nullptr) we have an instance field, otherwise a static field
- // when (staticOffset != nullptr) it represents a offset into a static or the call to
- // Shared Static Base
- if ((obj != nullptr) || (staticOffset != nullptr))
+ if (baseAddr != nullptr)
{
+ // Instance field / "complex" static: heap[field][baseAddr][struct fields...] = storeVal.
+
var_types firstFieldType;
ValueNum firstFieldSelectorVN =
vnStore->VNForFieldSelector(fldSeq->GetFieldHandle(), &firstFieldType);
@@ -7821,15 +7883,7 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
ValueNum fldMapVN =
vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
- ValueNum firstFieldValueSelectorVN = ValueNumStore::NoVN;
- if (obj != nullptr)
- {
- firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(obj->gtVNPair);
- }
- else // (staticOffset != nullptr)
- {
- firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(staticOffset->gtVNPair);
- }
+ ValueNum firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(baseAddr->gtVNPair);
ValueNum newFirstFieldValueVN = ValueNumStore::NoVN;
// Optimization: avoid traversting the maps for the value of the first field if
@@ -7840,12 +7894,12 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
}
else
{
- // Construct the ValueNumber for fldMap[obj/offset]. This (struct)
+ // Construct the ValueNumber for fldMap[baseAddr]. This (struct)
// map represents the specific field we're looking to store to.
ValueNum firstFieldValueVN = vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN,
firstFieldValueSelectorVN);
- // Construct the maps updating the rest of the fields in the sequence.
+ // Construct the maps updating the struct fields in the sequence.
newFirstFieldValueVN = vnStore->VNApplySelectorsAssign(VNK_Liberal, firstFieldValueVN,
fldSeq->m_next, storeVal, indType);
}
@@ -7859,15 +7913,11 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
}
else
{
- // Plain static field.
+ // "Simple" static: heap[field][struct fields...] = storeVal.
newHeapVN = vnStore->VNApplySelectorsAssign(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq,
storeVal, indType);
}
- // It is not strictly necessary to set the lhs value number,
- // but the dumps read better with it set to the 'storeVal' that we just computed
- lhs->gtVNPair.SetBoth(storeVal);
-
// Update the GcHeap value.
recordGcHeapStore(tree, newHeapVN DEBUGARG("StoreField"));
}
@@ -8165,7 +8215,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
else if (srcAddrFuncApp.m_func == VNF_PtrToArrElem)
{
ValueNum elemLib =
- fgValueNumberArrIndexVal(nullptr, &srcAddrFuncApp, vnStore->VNForEmptyExcSet());
+ fgValueNumberArrIndexVal(nullptr, &srcAddrFuncApp, vnStore->VNPForEmptyExcSet());
rhsVNPair.SetLiberal(elemLib);
rhsVNPair.SetConservative(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
}
@@ -8321,43 +8371,8 @@ bool Compiler::fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLcl
void Compiler::fgValueNumberTree(GenTree* tree)
{
genTreeOps oper = tree->OperGet();
+ var_types typ = tree->TypeGet();
-#ifdef FEATURE_SIMD
- if ((JitConfig.JitDisableSimdVN() & 1) == 1)
- {
- // This Jit Config forces the previous behavior of value numbering for SIMD nodes
- if (oper == GT_SIMD)
- {
- tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_UNKNOWN));
- return;
- }
- }
-#endif // FEATURE_SIMD
-
-#ifdef FEATURE_HW_INTRINSICS
- if ((JitConfig.JitDisableSimdVN() & 2) == 2)
- {
- // This Jit Config forces the previous behavior of value numbering for HW Intrinsic nodes
- if (oper == GT_HWINTRINSIC)
- {
- tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, TYP_UNKNOWN));
-
- GenTreeHWIntrinsic* hwIntrinsicNode = tree->AsHWIntrinsic();
- assert(hwIntrinsicNode != nullptr);
-
- // For safety/correctness we must mutate the global heap valuenumber
- // for any HW intrinsic that performs a memory store operation
- if (hwIntrinsicNode->OperIsMemoryStore())
- {
- fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore"));
- }
-
- return;
- }
- }
-#endif // FEATURE_HW_INTRINSICS
-
- var_types typ = tree->TypeGet();
if (GenTree::OperIsConst(oper))
{
// If this is a struct assignment, with a constant rhs, (i,.e. an initBlk),
@@ -8514,19 +8529,18 @@ void Compiler::fgValueNumberTree(GenTree* tree)
{
// We have a Def (write) of the LclVar
- // TODO-Review: For the short term, we have a workaround for copyblk/initblk. Those that use
- // addrSpillTemp will have a statement like "addrSpillTemp = addr(local)." If we previously decided
- // that this block operation defines the local, we will have labeled the "local" node as a DEF
- // This flag propagates to the "local" on the RHS. So we'll assume that this is correct,
- // and treat it as a def (to a new, unique VN).
- //
+ // The below block ensures we give VNs to the fields of
+ // "CanBeReplacedWithItsField" struct locals. To the numbering
+ // of block assignments, those appear as untracked locals, but
+ // we need to give the SSA defs they represent a VN.
if (lcl->GetSsaNum() != SsaConfig::RESERVED_SSA_NUM)
{
ValueNum uniqVN = vnStore->VNForExpr(compCurBB, lcl->TypeGet());
varDsc->GetPerSsaData(lcl->GetSsaNum())->m_vnPair.SetBoth(uniqVN);
}
- lcl->gtVNPair = ValueNumPair(); // Avoid confusion -- we don't set the VN of a lcl being defined.
+ // Location nodes get VNForVoid (no exceptions needed).
+ lcl->gtVNPair = vnStore->VNPForVoid();
}
}
break;
@@ -8568,6 +8582,11 @@ void Compiler::fgValueNumberTree(GenTree* tree)
tree->gtVNPair = vnStore->VNPairApplySelectors(lclVNPair, lclFld->GetFieldSeq(), indType);
}
}
+ else
+ {
+ // A location node (LHS).
+ lclFld->gtVNPair = vnStore->VNPForVoid();
+ }
}
break;
@@ -8652,6 +8671,11 @@ void Compiler::fgValueNumberTree(GenTree* tree)
}
tree->gtVNPair = clsVarVNPair;
}
+ else
+ {
+ // Location nodes get the "Void" VN.
+ tree->gtVNPair = vnStore->VNPForVoid();
+ }
break;
case GT_MEMORYBARRIER: // Leaf
@@ -8731,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))
@@ -8771,12 +8799,11 @@ void Compiler::fgValueNumberTree(GenTree* tree)
// a pointer to an object field or array element. Other cases become uses of
// the current ByrefExposed value and the pointer value, so that at least we
// can recognize redundant loads with no stores between them.
- GenTree* addr = tree->AsIndir()->Addr();
- GenTreeLclVarCommon* lclVarTree = nullptr;
- FieldSeqNode* fldSeq2 = nullptr;
- GenTree* obj = nullptr;
- GenTree* staticOffset = nullptr;
- bool isVolatile = (tree->gtFlags & GTF_IND_VOLATILE) != 0;
+ GenTree* addr = tree->AsIndir()->Addr();
+ GenTreeLclVarCommon* lclVarTree = nullptr;
+ FieldSeqNode* fldSeq = nullptr;
+ GenTree* baseAddr = nullptr;
+ bool isVolatile = (tree->gtFlags & GTF_IND_VOLATILE) != 0;
// See if the addr has any exceptional part.
ValueNumPair addrNvnp;
@@ -8849,61 +8876,65 @@ void Compiler::fgValueNumberTree(GenTree* tree)
// Try to parse it.
GenTree* arr = nullptr;
addr->ParseArrayAddress(this, &arrInfo, &arr, &inxVN, &fldSeq);
- if (arr == nullptr)
- {
- tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
- return;
- }
- assert(fldSeq != FieldSeqStore::NotAField());
-
- // Otherwise...
- // Need to form H[arrType][arr][ind][fldSeq]
- // Get the array element type equivalence class rep.
- CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
- ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL);
- JITDUMP(" VNForHandle(arrElemType: %s) is " FMT_VN "\n",
- (arrInfo.m_elemType == TYP_STRUCT) ? eeGetClassName(arrInfo.m_elemStructType)
- : varTypeName(arrInfo.m_elemType),
- elemTypeEqVN)
-
- // We take the "VNNormalValue"s here, because if either has exceptional outcomes, they will be captured
- // as part of the value of the composite "addr" operation...
- ValueNum arrVN = vnStore->VNLiberalNormalValue(arr->gtVNPair);
- inxVN = vnStore->VNNormalValue(inxVN);
-
- // Additionally, relabel the address with a PtrToArrElem value number.
- ValueNum fldSeqVN = vnStore->VNForFieldSeq(fldSeq);
- ValueNum elemAddr =
- vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem, elemTypeEqVN, arrVN, inxVN, fldSeqVN);
-
- // The aggregate "addr" VN should have had all the exceptions bubble up...
- elemAddr = vnStore->VNWithExc(elemAddr, addrXvnp.GetLiberal());
- addr->gtVNPair.SetBoth(elemAddr);
+ if (arr != nullptr)
+ {
+ assert(fldSeq != FieldSeqStore::NotAField());
+
+ // Need to form H[arrType][arr][ind][fldSeq]
+ // Get the array element type equivalence class rep.
+ CORINFO_CLASS_HANDLE elemTypeEq = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
+ ValueNum elemTypeEqVN = vnStore->VNForHandle(ssize_t(elemTypeEq), GTF_ICON_CLASS_HDL);
+ JITDUMP(" VNForHandle(arrElemType: %s) is " FMT_VN "\n",
+ (arrInfo.m_elemType == TYP_STRUCT) ? eeGetClassName(arrInfo.m_elemStructType)
+ : varTypeName(arrInfo.m_elemType),
+ elemTypeEqVN);
+
+ // We take the "VNNormalValue"s here, because if either has exceptional outcomes, they will
+ // be captured as part of the value of the composite "addr" operation...
+ ValueNum arrVN = vnStore->VNLiberalNormalValue(arr->gtVNPair);
+ inxVN = vnStore->VNNormalValue(inxVN);
+
+ // Additionally, relabel the address with a PtrToArrElem value number.
+ ValueNum fldSeqVN = vnStore->VNForFieldSeq(fldSeq);
+ ValueNum elemAddr =
+ vnStore->VNForFunc(TYP_BYREF, VNF_PtrToArrElem, elemTypeEqVN, arrVN, inxVN, fldSeqVN);
+
+ // The aggregate "addr" VN should have had all the exceptions bubble up...
+ addr->gtVNPair = vnStore->VNPWithExc(ValueNumPair(elemAddr, elemAddr), addrXvnp);
#ifdef DEBUG
- if (verbose)
- {
- printf(" Relabeled IND_ARR_INDEX address node ");
- Compiler::printTreeID(addr);
- printf(" with l:" FMT_VN ": ", elemAddr);
- vnStore->vnDump(this, elemAddr);
- printf("\n");
- if (vnStore->VNNormalValue(elemAddr) != elemAddr)
+ ValueNum elemAddrWithExc = addr->gtVNPair.GetLiberal();
+ if (verbose)
{
- printf(" [" FMT_VN " is: ", vnStore->VNNormalValue(elemAddr));
- vnStore->vnDump(this, vnStore->VNNormalValue(elemAddr));
- printf("]\n");
+ printf(" Relabeled IND_ARR_INDEX address node ");
+ Compiler::printTreeID(addr);
+ printf(" with l:" FMT_VN ": ", elemAddrWithExc);
+ vnStore->vnDump(this, elemAddrWithExc);
+ printf("\n");
+ if (elemAddrWithExc != elemAddr)
+ {
+ printf(" [" FMT_VN " is: ", elemAddr);
+ vnStore->vnDump(this, elemAddr);
+ printf("]\n");
+ }
}
- }
#endif // DEBUG
- // We now need to retrieve the value number for the array element value
- // and give this value number to the GT_IND node 'tree'
- // We do this whenever we have an rvalue, but we don't do it for a
- // normal LHS assignment into an array element.
- //
- if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0)
+ // We now need to retrieve the value number for the array element value
+ // and give this value number to the GT_IND node 'tree'
+ // We do this whenever we have an rvalue, but we don't do it for a
+ // normal LHS assignment into an array element.
+ //
+ if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0)
+ {
+ fgValueNumberArrIndexVal(tree, elemTypeEq, arrVN, inxVN, addrXvnp, fldSeq);
+ }
+ }
+ else // An unparseable array expression.
{
- fgValueNumberArrIndexVal(tree, elemTypeEq, arrVN, inxVN, addrXvnp.GetLiberal(), fldSeq);
+ if ((tree->gtFlags & GTF_IND_ASG_LHS) == 0)
+ {
+ tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), addrXvnp);
+ }
}
}
// In general we skip GT_IND nodes on that are the LHS of an assignment. (We labeled these earlier.)
@@ -8962,43 +8993,44 @@ void Compiler::fgValueNumberTree(GenTree* tree)
}
else if (vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToArrElem))
{
- fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp.GetLiberal());
+ fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp);
}
- else if (addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2))
+ else if (addr->IsFieldAddr(this, &baseAddr, &fldSeq))
{
- assert((fldSeq2 != nullptr) && (fldSeq2 != FieldSeqStore::NotAField()) &&
- !fldSeq2->IsPseudoField());
+ assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField()) && !fldSeq->IsPseudoField());
// The size of the ultimate value we will select, if it is of a struct type.
- size_t structSize = 0;
+ size_t structSize = 0;
+ ValueNum valueVN = ValueNumStore::NoVN;
- // Get the selector for the first field.
- var_types firstFieldType;
- ValueNum firstFieldSelectorVN =
- vnStore->VNForFieldSelector(fldSeq2->GetFieldHandle(), &firstFieldType, &structSize);
+ if (baseAddr != nullptr)
+ {
+ // Instance field / "complex" static: heap[field][baseAddr][struct fields...].
- ValueNum fldMapVN =
- vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
+ // Get the selector for the first field.
+ var_types firstFieldType;
+ ValueNum firstFieldSelectorVN =
+ vnStore->VNForFieldSelector(fldSeq->GetFieldHandle(), &firstFieldType, &structSize);
- ValueNum firstFieldValueSelectorVN;
- if (obj != nullptr)
- {
- firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(obj->gtVNPair);
+ ValueNum fldMapVN =
+ vnStore->VNForMapSelect(VNK_Liberal, TYP_MEM, fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
+
+ ValueNum firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(baseAddr->gtVNPair);
+
+ // Construct the value number for fldMap[baseAddr].
+ ValueNum firstFieldValueVN =
+ vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN, firstFieldValueSelectorVN);
+
+ // Finally, account for the rest of the fields in the sequence.
+ valueVN =
+ vnStore->VNApplySelectors(VNK_Liberal, firstFieldValueVN, fldSeq->m_next, &structSize);
}
else
{
- assert(staticOffset != nullptr);
- firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue(staticOffset->gtVNPair);
+ // "Simple" static: heap[static][struct fields...].
+ valueVN = vnStore->VNApplySelectors(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq, &structSize);
}
- // Construct the value number for fldMap[obj/offset].
- ValueNum firstFieldValueVN =
- vnStore->VNForMapSelect(VNK_Liberal, firstFieldType, fldMapVN, firstFieldValueSelectorVN);
-
- // Finally, account for the rest of the fields in the sequence.
- ValueNum valueVN =
- vnStore->VNApplySelectors(VNK_Liberal, firstFieldValueVN, fldSeq2->m_next, &structSize);
-
valueVN = vnStore->VNApplySelectorsTypeCheck(valueVN, tree->TypeGet(), structSize);
tree->gtVNPair.SetLiberal(valueVN);
@@ -9015,6 +9047,12 @@ void Compiler::fgValueNumberTree(GenTree* tree)
tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
}
}
+
+ // To be able to propagate exception sets, we give location nodes the "Void" VN.
+ if ((tree->gtFlags & GTF_IND_ASG_LHS) != 0)
+ {
+ tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), addrXvnp);
+ }
}
else if (tree->OperGet() == GT_CAST)
{
@@ -9111,8 +9149,7 @@ void Compiler::fgValueNumberTree(GenTree* tree)
if (newVN != ValueNumStore::NoVN)
{
// We don't care about differences between liberal and conservative for pointer values.
- newVN = vnStore->VNWithExc(newVN, excSetPair.GetLiberal());
- tree->gtVNPair.SetBoth(newVN);
+ tree->gtVNPair = vnStore->VNPWithExc(ValueNumPair(newVN, newVN), excSetPair);
}
else
{
@@ -9131,28 +9168,8 @@ void Compiler::fgValueNumberTree(GenTree* tree)
{
case GT_COMMA:
{
- ValueNumPair op1vnp;
- ValueNumPair op1Xvnp;
- vnStore->VNPUnpackExc(tree->AsOp()->gtOp1->gtVNPair, &op1vnp, &op1Xvnp);
- ValueNumPair op2vnp;
- ValueNumPair op2Xvnp = ValueNumStore::VNPForEmptyExcSet();
- GenTree* op2 = tree->gtGetOp2();
-
- if (op2->OperIsIndir() && ((op2->gtFlags & GTF_IND_ASG_LHS) != 0))
- {
- // If op2 represents the lhs of an assignment then we give a VNForVoid for the lhs
- op2vnp = ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid());
- }
- else if ((op2->OperGet() == GT_CLS_VAR) && (op2->gtFlags & GTF_CLS_VAR_ASG_LHS))
- {
- // If op2 represents the lhs of an assignment then we give a VNForVoid for the lhs
- op2vnp = ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid());
- }
- else
- {
- vnStore->VNPUnpackExc(op2->gtVNPair, &op2vnp, &op2Xvnp);
- }
- tree->gtVNPair = vnStore->VNPWithExc(op2vnp, vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp));
+ ValueNumPair op1Xvnp = vnStore->VNPExceptionSet(tree->AsOp()->gtOp1->gtVNPair);
+ tree->gtVNPair = vnStore->VNPWithExc(tree->AsOp()->gtOp2->gtVNPair, op1Xvnp);
}
break;
@@ -9183,18 +9200,6 @@ void Compiler::fgValueNumberTree(GenTree* tree)
}
break;
- case GT_NULLCHECK:
- {
- // An Explicit null check, produces no value
- // But we do persist any execeptions produced by op1
- //
- tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(),
- vnStore->VNPExceptionSet(tree->AsOp()->gtOp1->gtVNPair));
- // The exception set with VNF_NullPtrExc will be added below
- // by fgValueNumberAddExceptionSet
- }
- break;
-
case GT_LOCKADD: // Binop
noway_assert("LOCKADD should not appear before lowering");
break;
@@ -9229,20 +9234,41 @@ void Compiler::fgValueNumberTree(GenTree* tree)
break;
}
+ // These unary nodes do not produce values. Note that for NULLCHECK the
+ // additional exception will be added below by "fgValueNumberAddExceptionSet".
case GT_JTRUE:
- // These nodes never need to have a ValueNumber
- tree->gtVNPair.SetBoth(ValueNumStore::NoVN);
+ case GT_SWITCH:
+ case GT_RETURN:
+ case GT_RETFILT:
+ case GT_NULLCHECK:
+ if (tree->gtGetOp1() != nullptr)
+ {
+ tree->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(),
+ vnStore->VNPExceptionSet(tree->gtGetOp1()->gtVNPair));
+ }
+ else
+ {
+ tree->gtVNPair = vnStore->VNPForVoid();
+ }
break;
+ // BOX and CKFINITE are passthrough nodes (like NOP). We'll add the exception for the latter later.
case GT_BOX:
- // BOX doesn't do anything at this point, the actual object allocation
- // and initialization happens separately (and not numbering BOX correctly
- // prevents seeing allocation related assertions through it)
+ case GT_CKFINITE:
tree->gtVNPair = tree->gtGetOp1()->gtVNPair;
break;
+ // These unary nodes will receive a unique VN.
+ // TODO-CQ: model INIT_VAL properly.
+ case GT_LCLHEAP:
+ case GT_INIT_VAL:
+ tree->gtVNPair =
+ vnStore->VNPUniqueWithExc(tree->TypeGet(),
+ vnStore->VNPExceptionSet(tree->gtGetOp1()->gtVNPair));
+ break;
+
default:
- // The default action is to give the node a new, unique VN.
+ assert(!"Unhandled node in fgValueNumberTree");
tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
break;
}
@@ -9275,6 +9301,30 @@ void Compiler::fgValueNumberTree(GenTree* tree)
break;
#endif // FEATURE_HW_INTRINSICS
+ case GT_STORE_DYN_BLK:
+ {
+ // Conservatively, mutate the heaps - we don't analyze these rare stores.
+ // Likewise, any locals possibly defined by them we mark as address-exposed.
+ fgMutateGcHeap(tree DEBUGARG("dynamic block store"));
+
+ GenTreeStoreDynBlk* store = tree->AsStoreDynBlk();
+ ValueNumPair vnpExcSet = ValueNumStore::VNPForEmptyExcSet();
+
+ // Propagate the exceptions...
+ vnpExcSet = vnStore->VNPUnionExcSet(store->Addr()->gtVNPair, vnpExcSet);
+ vnpExcSet = vnStore->VNPUnionExcSet(store->Data()->gtVNPair, vnpExcSet);
+ vnpExcSet = vnStore->VNPUnionExcSet(store->gtDynamicSize->gtVNPair, vnpExcSet);
+
+ // This is a store, it produces no value. Thus we use VNPForVoid().
+ store->gtVNPair = vnStore->VNPWithExc(vnStore->VNPForVoid(), vnpExcSet);
+
+ // Note that we are only adding the exception for the destination address.
+ // Currently, "Data()" is an explicit indirection in case this is a "cpblk".
+ assert(store->Data()->gtEffectiveVal()->OperIsIndir() || store->OperIsInitBlkOp());
+ fgValueNumberAddExceptionSetForIndirection(store, store->Addr());
+ break;
+ }
+
case GT_CMPXCHG: // Specialop
{
// For CMPXCHG and other intrinsics add an arbitrary side effect on GcHeap/ByrefExposed.
@@ -9309,8 +9359,38 @@ void Compiler::fgValueNumberTree(GenTree* tree)
break;
}
+ // ARR_ELEM is a bounds-checked address. TODO-CQ: model it precisely.
+ case GT_ARR_ELEM:
+ {
+ GenTreeArrElem* arrElem = tree->AsArrElem();
+
+ ValueNumPair vnpExcSet = vnStore->VNPExceptionSet(arrElem->gtArrObj->gtVNPair);
+ for (size_t i = 0; i < arrElem->gtArrRank; i++)
+ {
+ vnpExcSet = vnStore->VNPUnionExcSet(arrElem->gtArrInds[i]->gtVNPair, vnpExcSet);
+ }
+
+ arrElem->gtVNPair = vnStore->VNPUniqueWithExc(arrElem->TypeGet(), vnpExcSet);
+
+ // TODO: model the IndexOutOfRangeException for this node.
+ fgValueNumberAddExceptionSetForIndirection(arrElem, arrElem->gtArrObj);
+ }
+ break;
+
+ // FIELD_LIST is an R-value that we currently don't model.
+ case GT_FIELD_LIST:
+ tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
+ for (GenTreeFieldList::Use& use : tree->AsFieldList()->Uses())
+ {
+ tree->gtVNPair =
+ vnStore->VNPWithExc(tree->gtVNPair, vnStore->VNPExceptionSet(use.GetNode()->gtVNPair));
+ }
+ break;
+
default:
+ assert(!"Unhandled special node in fgValueNumberTree");
tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
+ break;
}
}
#ifdef DEBUG
@@ -9384,19 +9464,25 @@ void Compiler::fgValueNumberSimd(GenTreeSIMD* tree)
ValueNumPair excSetPair;
ValueNumPair normalPair;
+ if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 1) == 1))
+ {
+ // We have a SIMD node with 3 or more args. To retain the
+ // previous behavior, we will generate a unique VN for this case.
+ excSetPair = ValueNumStore::VNPForEmptyExcSet();
+ for (GenTree* operand : tree->Operands())
+ {
+ excSetPair = vnStore->VNPUnionExcSet(operand->gtVNPair, excSetPair);
+ }
+ tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), excSetPair);
+ return;
+ }
+
// There are some SIMD operations that have zero args, i.e. NI_Vector128_Zero
if (tree->GetOperandCount() == 0)
{
excSetPair = ValueNumStore::VNPForEmptyExcSet();
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), simdFunc);
}
- else if (tree->GetOperandCount() > 2)
- {
- // We have a SIMD node with 3 or more args. To retain the
- // previous behavior, we will generate a unique VN for this case.
- tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
- return;
- }
else // SIMD unary or binary operator.
{
ValueNumPair resvnp = ValueNumPair();
@@ -9521,12 +9607,17 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore"));
}
- if (tree->GetOperandCount() > 2)
+ if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 2) == 2))
{
// TODO-CQ: allow intrinsics with > 2 operands to be properly VN'ed, it will
// allow use to process things like Vector128.Create(1,2,3,4) etc.
- // Generate unique VN for now to retaing previois behavior.
- tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
+ // Generate unique VN for now to retaing previous behavior.
+ ValueNumPair vnpExcSet = vnStore->VNPForEmptyExcSet();
+ for (GenTree* operand : tree->Operands())
+ {
+ vnpExcSet = vnStore->VNPUnionExcSet(operand->gtVNPair, vnpExcSet);
+ }
+ tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), vnpExcSet);
return;
}
@@ -9538,15 +9629,13 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
//
if (isMemoryLoad)
{
- ValueNumPair op1vnp;
- ValueNumPair op1Xvnp;
- vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp);
+ ValueNumPair op1vnp = vnStore->VNPNormalPair(tree->Op(1)->gtVNPair);
// The addrVN incorporates both op1's ValueNumber and the func operation
// The func is used because operations such as LoadLow and LoadHigh perform
// different operations, thus need to compute different ValueNumbers
// We don't need to encode the result type as it will be encoded by the opcode in 'func'
- //
+ // TODO-Bug: some HWI loads have more than one operand, we need to encode the rest.
ValueNum addrVN = vnStore->VNForFunc(TYP_BYREF, func, op1vnp.GetLiberal());
// The address could point anywhere, so it is an ByrefExposed load.
@@ -9554,7 +9643,11 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
ValueNum loadVN = fgValueNumberByrefExposedLoad(tree->TypeGet(), addrVN);
tree->gtVNPair.SetLiberal(loadVN);
tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
- tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, op1Xvnp);
+
+ for (GenTree* operand : tree->Operands())
+ {
+ tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, vnStore->VNPExceptionSet(operand->gtVNPair));
+ }
fgValueNumberAddExceptionSetForIndirection(tree, tree->Op(1));
return;
}
@@ -9941,14 +10034,12 @@ void Compiler::fgValueNumberCall(GenTreeCall* call)
{
// First: do value numbering of any argument placeholder nodes in the argument list
// (by transferring from the VN of the late arg that they are standing in for...)
- unsigned i = 0;
- for (GenTreeCall::Use& use : call->Args())
- {
- GenTree* arg = use.GetNode();
+
+ auto updateArgVN = [=](GenTree* arg, unsigned argIndex) {
if (arg->OperGet() == GT_ARGPLACE)
{
// Find the corresponding late arg.
- GenTree* lateArg = call->fgArgInfo->GetArgNode(i);
+ GenTree* lateArg = call->fgArgInfo->GetArgNode(argIndex);
assert(lateArg->gtVNPair.BothDefined());
arg->gtVNPair = lateArg->gtVNPair;
#ifdef DEBUG
@@ -9962,7 +10053,19 @@ void Compiler::fgValueNumberCall(GenTreeCall* call)
}
#endif
}
- i++;
+ };
+
+ unsigned argIndex = 0;
+ if (call->gtCallThisArg != nullptr)
+ {
+ updateArgVN(call->gtCallThisArg->GetNode(), argIndex);
+ argIndex++;
+ }
+
+ for (GenTreeCall::Use& use : call->Args())
+ {
+ updateArgVN(use.GetNode(), argIndex);
+ argIndex++;
}
if (call->gtCallType == CT_HELPER)
@@ -10506,27 +10609,16 @@ void Compiler::fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree
// Create baseVNP, from the values we just computed,
baseVNP = ValueNumPair(baseLVN, baseCVN);
- // Unpack, Norm,Exc for the tree's op1 VN
- ValueNumPair vnpBaseNorm;
- ValueNumPair vnpBaseExc;
- vnStore->VNPUnpackExc(baseVNP, &vnpBaseNorm, &vnpBaseExc);
+ // The exceptions in "baseVNP" should have been added to the "tree"'s set already.
+ assert(vnStore->VNPExcIsSubset(vnStore->VNPExceptionSet(tree->gtVNPair), vnStore->VNPExceptionSet(baseVNP)));
- // The Norm VN for op1 is used to create the NullPtrExc
- ValueNumPair excChkSet = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm));
-
- // Combine the excChkSet with exception set of op1
- ValueNumPair excSetBoth = vnStore->VNPExcSetUnion(excChkSet, vnpBaseExc);
+ // The normal VN for base address is used to create the NullPtrExc
+ ValueNumPair vnpBaseNorm = vnStore->VNPNormalPair(baseVNP);
- // Retrieve the Normal VN for tree, note that it may be NoVN, so we handle that case
- ValueNumPair vnpNorm = vnStore->VNPNormalPair(tree->gtVNPair);
+ ValueNumPair excChkSet = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm));
- // For as GT_IND on the lhs of an assignment we will get a NoVN value
- if (vnpNorm.GetLiberal() == ValueNumStore::NoVN)
- {
- // Use the special Void VN value instead.
- vnpNorm = vnStore->VNPForVoid();
- }
- tree->gtVNPair = vnStore->VNPWithExc(vnpNorm, excSetBoth);
+ // Add the NullPtrExc to "tree"'s value numbers.
+ tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, excChkSet);
}
//--------------------------------------------------------------------------------
@@ -10904,20 +10996,13 @@ 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: // Implicit null check.
- if ((tree->gtFlags & GTF_IND_ASG_LHS) != 0)
- {
- // Don't add exception set on LHS of assignment
- break;
- }
- FALLTHROUGH;
-
+ case GT_IND:
case GT_BLK:
case GT_OBJ:
- case GT_DYN_BLK:
case GT_NULLCHECK:
fgValueNumberAddExceptionSetForIndirection(tree, tree->AsIndir()->Addr());
break;
@@ -10956,6 +11041,61 @@ void Compiler::fgValueNumberAddExceptionSet(GenTree* tree)
}
#ifdef DEBUG
+//------------------------------------------------------------------------
+// fgDebugCheckExceptionSets: Verify the exception sets on trees.
+//
+// This function checks that the node's exception set is a superset of
+// the exception sets of its operands.
+//
+void Compiler::fgDebugCheckExceptionSets()
+{
+ struct ExceptionSetsChecker
+ {
+ static void CheckTree(GenTree* tree, ValueNumStore* vnStore)
+ {
+ // We will fail to VN some PHI_ARGs - their values may not
+ // be known at the point we number them because of loops.
+ assert(tree->gtVNPair.BothDefined() || tree->OperIs(GT_PHI_ARG));
+
+ ValueNumPair operandsExcSet = vnStore->VNPForEmptyExcSet();
+ tree->VisitOperands([&](GenTree* operand) -> GenTree::VisitResult {
+
+ CheckTree(operand, vnStore);
+
+ ValueNumPair operandVNP = operand->gtVNPair.BothDefined() ? operand->gtVNPair : vnStore->VNPForVoid();
+ operandsExcSet = vnStore->VNPUnionExcSet(operandVNP, operandsExcSet);
+
+ return GenTree::VisitResult::Continue;
+ });
+
+ // Currently, we fail to properly maintain the exception sets for trees with user
+ // calls or assignments.
+ if ((tree->gtFlags & (GTF_ASG | GTF_CALL)) != 0)
+ {
+ return;
+ }
+
+ ValueNumPair nodeExcSet = vnStore->VNPExceptionSet(tree->gtVNPair);
+ assert(vnStore->VNExcIsSubset(nodeExcSet.GetLiberal(), operandsExcSet.GetLiberal()));
+ assert(vnStore->VNExcIsSubset(nodeExcSet.GetConservative(), operandsExcSet.GetConservative()));
+ }
+ };
+
+ for (BasicBlock* const block : Blocks())
+ {
+ for (Statement* const stmt : block->Statements())
+ {
+ // Exclude statements VN hasn't visited for whichever reason...
+ if (stmt->GetRootNode()->GetVN(VNK_Liberal) == ValueNumStore::NoVN)
+ {
+ continue;
+ }
+
+ ExceptionSetsChecker::CheckTree(stmt->GetRootNode(), vnStore);
+ }
+ }
+}
+
// This method asserts that SSA name constraints specified are satisfied.
// Until we figure out otherwise, all VN's are assumed to be liberal.
// TODO-Cleanup: new JitTestLabels for lib vs cons vs both VN classes?
diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h
index 289e09fb688b13..6c19327c800375 100644
--- a/src/coreclr/jit/valuenum.h
+++ b/src/coreclr/jit/valuenum.h
@@ -494,6 +494,8 @@ class ValueNumStore
// Both arguments must be either VNForEmptyExcSet() or applications of VNF_ExcSetCons.
bool VNExcIsSubset(ValueNum vnFullSet, ValueNum vnCandidateSet);
+ bool VNPExcIsSubset(ValueNumPair vnpFullSet, ValueNumPair vnpCandidateSet);
+
// Returns "true" iff "vn" is an application of "VNF_ValWithExc".
bool VNHasExc(ValueNum vn)
{
@@ -528,6 +530,12 @@ class ValueNumStore
// Keeps any Exception set values
ValueNumPair VNPMakeNormalUniquePair(ValueNumPair vnp);
+ // A new unique value with the given exception set.
+ ValueNum VNUniqueWithExc(var_types type, ValueNum vnExcSet);
+
+ // A new unique VN pair with the given exception set pair.
+ ValueNumPair VNPUniqueWithExc(var_types type, ValueNumPair vnpExcSet);
+
// If "vn" is a "VNF_ValWithExc(norm, excSet)" value, returns the "norm" argument; otherwise,
// just returns "vn".
// The Normal value is the value number of the expression when no exceptions occurred
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 67efba61efde98..ae6229a0a7afe6 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
@@ -48,12 +48,14 @@
-
+
+
+
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
index 501384a4c0c6ca..529de6be54f554 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -31,6 +31,7 @@ The .NET Foundation licenses this file to you under the MIT license.
false
true
+ false
@@ -39,8 +40,6 @@ The .NET Foundation licenses this file to you under the MIT license.
true
true
- true
- copyused
@@ -131,13 +130,6 @@ The .NET Foundation licenses this file to you under the MIT license.
-
-
-
- true
-
-
-
@@ -199,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'" />
@@ -246,6 +209,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
@@ -278,6 +242,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
@@ -285,9 +250,6 @@ The .NET Foundation licenses this file to you under the MIT license.
-
-
-
@@ -304,8 +266,8 @@ 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/Math.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs
index 8a53e1588b83d2..15b629dbee219f 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Math.CoreRT.cs
@@ -16,18 +16,6 @@ namespace System
{
public static partial class Math
{
- [Intrinsic]
- public static float Abs(float value)
- {
- return RuntimeImports.fabsf(value);
- }
-
- [Intrinsic]
- public static double Abs(double value)
- {
- return RuntimeImports.fabs(value);
- }
-
[Intrinsic]
public static double Acos(double d)
{
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.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
index 304f7073e7ec3c..a7edbf10d819af 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
@@ -679,18 +679,6 @@ internal struct ConservativelyReportedRegionDesc
[RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")]
internal static extern void MemoryBarrier();
- [Intrinsic]
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- [RuntimeImport(RuntimeLibrary, "fabs")]
- internal static extern double fabs(double x);
-
- [Intrinsic]
- internal static float fabsf(float x)
- {
- // fabsf is not a real export for some architectures
- return (float)fabs(x);
- }
-
[Intrinsic]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "acos")]
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/pal.h b/src/coreclr/pal/inc/pal.h
index 237b75275cec96..db22c68fde053a 100644
--- a/src/coreclr/pal/inc/pal.h
+++ b/src/coreclr/pal/inc/pal.h
@@ -345,6 +345,7 @@ typedef __int64 time_t;
#define PAL_INITIALIZE_DEBUGGER_EXCEPTIONS 0x10
#define PAL_INITIALIZE_ENSURE_STACK_SIZE 0x20
#define PAL_INITIALIZE_REGISTER_SIGNALS 0x40
+#define PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL 0x80
// PAL_Initialize() flags
#define PAL_INITIALIZE (PAL_INITIALIZE_SYNC_THREAD | \
@@ -359,7 +360,8 @@ typedef __int64 time_t;
PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER | \
PAL_INITIALIZE_DEBUGGER_EXCEPTIONS | \
PAL_INITIALIZE_ENSURE_STACK_SIZE | \
- PAL_INITIALIZE_REGISTER_SIGNALS)
+ PAL_INITIALIZE_REGISTER_SIGNALS | \
+ PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL)
typedef DWORD (PALAPI_NOEXPORT *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
@@ -2842,24 +2844,6 @@ VirtualQuery(
#define FillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))
#define ZeroMemory(Destination,Length) memset((Destination),0,(Length))
-#define LMEM_FIXED 0x0000
-#define LMEM_MOVEABLE 0x0002
-#define LMEM_ZEROINIT 0x0040
-#define LPTR (LMEM_FIXED | LMEM_ZEROINIT)
-
-PALIMPORT
-HLOCAL
-PALAPI
-LocalAlloc(
- IN UINT uFlags,
- IN SIZE_T uBytes);
-
-PALIMPORT
-HLOCAL
-PALAPI
-LocalFree(
- IN HLOCAL hMem);
-
PALIMPORT
BOOL
PALAPI
@@ -3261,8 +3245,8 @@ FORCEINLINE void PAL_ArmInterlockedOperationBarrier()
Function:
InterlockedAdd
-The InterlockedAdd function adds the value of the specified variable
-with another specified value. The function prevents more than one thread
+The InterlockedAdd function adds the value of the specified variable
+with another specified value. The function prevents more than one thread
from using the same variable simultaneously.
Parameters
@@ -3934,8 +3918,6 @@ PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data);
#define wcspbrk PAL_wcspbrk
#define wcscmp PAL_wcscmp
#define wcsncpy PAL_wcsncpy
-#define wcstok PAL_wcstok
-#define wcscspn PAL_wcscspn
#define realloc PAL_realloc
#define fopen PAL_fopen
#define strtok PAL_strtok
@@ -4125,8 +4107,6 @@ PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcschr(const WCHAR *, WCHAR);
PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcsrchr(const WCHAR *, WCHAR);
PALIMPORT WCHAR _WConst_return * __cdecl PAL_wcspbrk(const WCHAR *, const WCHAR *);
PALIMPORT DLLEXPORT WCHAR _WConst_return * __cdecl PAL_wcsstr(const WCHAR *, const WCHAR *);
-PALIMPORT WCHAR * __cdecl PAL_wcstok(WCHAR *, const WCHAR *);
-PALIMPORT DLLEXPORT size_t __cdecl PAL_wcscspn(const WCHAR *, const WCHAR *);
PALIMPORT int __cdecl PAL_swprintf(WCHAR *, const WCHAR *, ...);
PALIMPORT int __cdecl PAL_vswprintf(WCHAR *, const WCHAR *, va_list);
PALIMPORT int __cdecl PAL_swscanf(const WCHAR *, const WCHAR *, ...);
diff --git a/src/coreclr/pal/inc/palprivate.h b/src/coreclr/pal/inc/palprivate.h
index 097229eb64ef4a..f90352b32355e8 100644
--- a/src/coreclr/pal/inc/palprivate.h
+++ b/src/coreclr/pal/inc/palprivate.h
@@ -203,8 +203,6 @@ CompareFileTime(
IN CONST FILETIME *lpFileTime1,
IN CONST FILETIME *lpFileTime2);
-PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t);
-
/* These are from the file in windows.
They are needed for _open_osfhandle.*/
#define _O_RDONLY 0x0000
diff --git a/src/coreclr/pal/inc/rt/sal.h b/src/coreclr/pal/inc/rt/sal.h
index 198b46d4a4e06e..ef976be402fdc5 100644
--- a/src/coreclr/pal/inc/rt/sal.h
+++ b/src/coreclr/pal/inc/rt/sal.h
@@ -2862,6 +2862,10 @@ of each annotation, see the advanced annotations section.
#define __useHeader _Use_decl_anno_impl_
#define __on_failure(annotes) _On_failure_impl_(annotes _SAL_nop_impl_)
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(x) (0)
+#endif
+
#ifndef __fallthrough // [
#if __has_cpp_attribute(fallthrough)
#define __fallthrough [[fallthrough]]
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 4f071b21046b07..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)
@@ -123,7 +126,6 @@ set(SOURCES
cruntime/malloc.cpp
cruntime/math.cpp
cruntime/misc.cpp
- cruntime/path.cpp
cruntime/printf.cpp
cruntime/printfcpp.cpp
cruntime/silent_printf.cpp
@@ -131,7 +133,6 @@ set(SOURCES
cruntime/stringtls.cpp
cruntime/thread.cpp
cruntime/wchar.cpp
- cruntime/wchartls.cpp
debug/debug.cpp
exception/seh.cpp
exception/signal.cpp
@@ -145,14 +146,12 @@ set(SOURCES
init/pal.cpp
init/sxs.cpp
loader/module.cpp
- loader/modulename.cpp
locale/unicode.cpp
locale/unicodedata.cpp
locale/utf8.cpp
map/common.cpp
map/map.cpp
map/virtual.cpp
- memory/local.cpp
misc/cgroup.cpp
misc/dbgmsg.cpp
misc/environ.cpp
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/path.cpp b/src/coreclr/pal/src/cruntime/path.cpp
deleted file mode 100644
index c25636771bc616..00000000000000
--- a/src/coreclr/pal/src/cruntime/path.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*++
-
-
-
-Module Name:
-
- path.c
-
-Abstract:
-
- Implementation of path functions part of Windows runtime library.
-
-Revision History:
-
-
-
---*/
-
-#include "pal/palinternal.h"
-#include "pal/dbgmsg.h"
-#include "pal/file.h"
-#include "pal/printfcpp.hpp"
-
-#include
-#include
-#include
-#include
-#include
-
-SET_DEFAULT_DEBUG_CHANNEL(CRT);
-
-/*++
-Function:
- _fullpath
-
-See MSDN doc.
-
---*/
-char *
-__cdecl
-_fullpath(
- char *absPath,
- const char *relPath,
- size_t maxLength)
-{
- char realpath_buf[PATH_MAX+1];
- char path_copy[PATH_MAX+1];
- char *retval = NULL;
- DWORD cPathCopy = sizeof(path_copy)/sizeof(path_copy[0]);
- size_t min_length;
- BOOL fBufAllocated = FALSE;
-
- PERF_ENTRY(_fullpath);
- ENTRY("_fullpath (absPath=%p, relPath=%p (%s), maxLength = %lu)\n",
- absPath, relPath ? relPath:"NULL", relPath ? relPath:"NULL", maxLength);
-
- if (strncpy_s(path_copy, sizeof(path_copy), relPath ? relPath : ".", cPathCopy) != SAFECRT_SUCCESS)
- {
- TRACE("_fullpath: strncpy_s failed!\n");
- goto fullpathExit;
- }
-
- FILEDosToUnixPathA(path_copy);
-
- if(NULL == realpath(path_copy, realpath_buf))
- {
- ERROR("realpath() failed; problem path is '%s'. errno is %d (%s)\n",
- realpath_buf, errno, strerror(errno));
- goto fullpathExit;
- }
-
- TRACE("real path is %s\n", realpath_buf);
- min_length = strlen(realpath_buf)+1; // +1 for the NULL terminator
-
- if(NULL == absPath)
- {
- absPath = static_cast(
- PAL_malloc(_MAX_PATH * sizeof(char)));
- if (!absPath)
- {
- ERROR("PAL_malloc failed with error %d\n", errno);
- goto fullpathExit;
- }
- maxLength = _MAX_PATH;
- fBufAllocated = TRUE;
- }
-
- if(min_length > maxLength)
- {
- ERROR("maxLength is %lu, we need at least %lu\n",
- maxLength, min_length);
- if (fBufAllocated)
- {
- PAL_free(absPath);
- fBufAllocated = FALSE;
- }
- goto fullpathExit;
- }
-
- strcpy_s(absPath, maxLength, realpath_buf);
- retval = absPath;
-
-fullpathExit:
- LOGEXIT("_fullpath returns char * %p\n", retval);
- PERF_EXIT(_fullpath);
- return retval;
-}
-
-
-
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/cruntime/wchar.cpp b/src/coreclr/pal/src/cruntime/wchar.cpp
index 5c21d7bd015335..3d887aecdb8835 100644
--- a/src/coreclr/pal/src/cruntime/wchar.cpp
+++ b/src/coreclr/pal/src/cruntime/wchar.cpp
@@ -3,8 +3,6 @@
/*++
-
-
Module Name:
wchar.c
@@ -13,11 +11,8 @@ Module Name:
Implementation of wide char string functions.
-
-
--*/
-
#include "pal/palinternal.h"
#include "pal/cruntime.h"
#include "pal/dbgmsg.h"
@@ -25,7 +20,6 @@ Module Name:
#include "pal/thread.hpp"
#include "pal/threadsusp.hpp"
-
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -950,46 +944,3 @@ PAL_wcstod( const wchar_16 * nptr, wchar_16 **endptr )
PERF_EXIT(wcstod);
return RetVal;
}
-
-/*++
-Function:
- PAL_wcscspn
-
-Finds the number of consecutive characters from the start of the string
-that are not in the set.
-
-Return value:
-
-The number of characters from the start of the string that are not in
-the set.
-
-Parameters:
-string String
-strCharSet Set of delimiter characters
-
---*/
-size_t
-__cdecl
-PAL_wcscspn(const wchar_16 *string, const wchar_16 *strCharSet)
-{
- const wchar_16 *temp;
- size_t count = 0;
-
- PERF_ENTRY(wcscspn);
-
- while(*string != 0)
- {
- for(temp = strCharSet; *temp != 0; temp++)
- {
- if (*string == *temp)
- {
- PERF_EXIT(wcscspn);
- return count;
- }
- }
- count++;
- string++;
- }
- PERF_EXIT(wcscspn);
- return count;
-}
diff --git a/src/coreclr/pal/src/cruntime/wchartls.cpp b/src/coreclr/pal/src/cruntime/wchartls.cpp
deleted file mode 100644
index 35b73359889a56..00000000000000
--- a/src/coreclr/pal/src/cruntime/wchartls.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*++
-
-
-
-Module Name:
-
- wchartls.c
-
-Abstract:
-
- Implementation of wide char string functions that depend on per-thread data
-
-
-
---*/
-
-#include "pal/palinternal.h"
-#include "pal/thread.hpp"
-#include "pal/dbgmsg.h"
-
-using namespace CorUnix;
-
-
-SET_DEFAULT_DEBUG_CHANNEL(CRT);
-
-/*++
-Function:
- PAL_wcstok
-
-Finds the next token in a wide character string.
-
-Return value:
-
-A pointer to the next token found in strToken. Returns NULL when no more
-tokens are found. Each call modifies strToken by substituting a NULL
-character for each delimiter that is encountered.
-
-Parameters:
-strToken String containing token(s)
-strDelimit Set of delimiter characters
-
---*/
-WCHAR *
-__cdecl
-PAL_wcstok(WCHAR *strToken, const WCHAR *strDelimit)
-{
- CPalThread *pThread = NULL;
- WCHAR *retval = NULL;
- WCHAR *delim_ptr;
- WCHAR *next_context; /* string to save in TLS for future calls */
-
- PERF_ENTRY(wcstok);
- ENTRY("PAL_wcstok (strToken=%p (%S), strDelimit=%p (%S))\n",
- strToken?strToken:W16_NULLSTRING,
- strToken?strToken:W16_NULLSTRING,
- strDelimit?strDelimit:W16_NULLSTRING,
- strDelimit?strDelimit:W16_NULLSTRING);
-
- /* Get the per-thread buffer from the thread structure. */
- pThread = InternalGetCurrentThread();
-
- if(NULL == strDelimit)
- {
- ERROR("delimiter string is NULL\n");
- goto done;
- }
-
- /* get token string from TLS if none is provided */
- if(NULL == strToken)
- {
- TRACE("wcstok() called with NULL string, using previous string\n");
- strToken = pThread->crtInfo.wcstokContext;
- if(NULL == strToken)
- {
- ERROR("wcstok called with NULL string without a previous call\n");
- goto done;
- }
- }
-
- /* first, skip all leading delimiters */
- while ((*strToken != '\0') && (PAL_wcschr(strDelimit,*strToken)))
- {
- strToken++;
- }
-
- /* if there were only delimiters, there's no string */
- if('\0' == strToken[0])
- {
- TRACE("end of string already reached, returning NULL\n");
- goto done;
- }
-
- /* we're now at the beginning of the token; look for the first delimiter */
- delim_ptr = PAL_wcspbrk(strToken,strDelimit);
- if(NULL == delim_ptr)
- {
- TRACE("no delimiters found, this is the last token\n");
- /* place the next context at the end of the string, so that subsequent
- calls will return NULL */
- next_context = strToken+PAL_wcslen(strToken);
- retval = strToken;
- }
- else
- {
- /* null-terminate current token */
- *delim_ptr=0;
-
- /* place the next context right after the delimiter */
- next_context = delim_ptr+1;
- retval = strToken;
-
- TRACE("found delimiter; next token will be %p\n",next_context);
- }
-
- pThread->crtInfo.wcstokContext = next_context;
-
-done:
- LOGEXIT("PAL_wcstok() returns %p (%S)\n", retval?retval:W16_NULLSTRING, retval?retval:W16_NULLSTRING);
- PERF_EXIT(wcstok);
- return(retval);
-}
-
diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp
index e5aebdf652c6a5..eca89e0a204c64 100644
--- a/src/coreclr/pal/src/exception/machexception.cpp
+++ b/src/coreclr/pal/src/exception/machexception.cpp
@@ -369,19 +369,13 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE
{
CPalThread *pThread = InternalGetCurrentThread();
- CONTEXT *contextRecord;
- EXCEPTION_RECORD *exceptionRecord;
- AllocateExceptionRecords(&exceptionRecord, &contextRecord);
+ CONTEXT *contextRecord = pContext;
+ g_hardware_exception_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0));
- *contextRecord = *pContext;
- *exceptionRecord = *pExRecord;
-
- contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
+ pContext->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
bool continueExecution;
-
{
- // The exception object takes ownership of the exceptionRecord and contextRecord
- PAL_SEHException exception(exceptionRecord, contextRecord);
+ PAL_SEHException exception(pExRecord, pContext, true);
TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress);
@@ -389,8 +383,8 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE
if (continueExecution)
{
// Make a copy of the exception records so that we can free them before restoring the context
- *pContext = *contextRecord;
- *pExRecord = *exceptionRecord;
+ *pContext = *exception.ExceptionPointers.ContextRecord;
+ *pExRecord = *exception.ExceptionPointers.ExceptionRecord;
}
// The exception records are destroyed by the PAL_SEHException destructor now.
diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp
index 4b149f941b5dc9..3091650ec5faa1 100644
--- a/src/coreclr/pal/src/exception/seh-unwind.cpp
+++ b/src/coreclr/pal/src/exception/seh-unwind.cpp
@@ -496,7 +496,9 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL
#ifndef HOST_WINDOWS
-extern int g_common_signal_handler_context_locvar_offset;
+// Frame pointer relative offset of a local containing a pointer to the windows style context of a location
+// where a hardware exception occured.
+int g_hardware_exception_context_locvar_offset = 0;
BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers)
{
@@ -506,19 +508,17 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
DWORD64 curPc = CONTEXTGetPC(context);
-#ifndef __APPLE__
- // Check if the PC is the return address from the SEHProcessException in the common_signal_handler.
- // If that's the case, extract its local variable containing the windows style context of the hardware
+ // Check if the PC is the return address from the SEHProcessException.
+ // If that's the case, extract its local variable containing a pointer to the windows style context of the hardware
// exception and return that. This skips the hardware signal handler trampoline that the libunwind
- // cannot cross on some systems.
+ // cannot cross on some systems. On macOS, it skips a similar trampoline we create in HijackFaultingThread.
if ((void*)curPc == g_SEHProcessExceptionReturnAddress)
{
- CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset);
- memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT));
+ CONTEXT* exceptionContext = *(CONTEXT**)(CONTEXTGetFP(context) + g_hardware_exception_context_locvar_offset);
+ memcpy_s(context, sizeof(CONTEXT), exceptionContext, sizeof(CONTEXT));
return TRUE;
}
-#endif
if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
{
@@ -699,7 +699,7 @@ PAL_FreeExceptionRecords(IN EXCEPTION_RECORD *exceptionRecord, IN CONTEXT *conte
Note:
The name of this function and the name of the ExceptionRecord
parameter is used in the sos lldb plugin code to read the exception
- record. See coreclr\ToolBox\SOS\lldbplugin\services.cpp.
+ record. See coreclr\tools\SOS\lldbplugin\services.cpp.
This function must not be inlined or optimized so the below PAL_VirtualUnwind
calls end up with RaiseException caller's context and so the above debugger
diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp
index 521150530fa33e..63b7ef115f26d1 100644
--- a/src/coreclr/pal/src/exception/signal.cpp
+++ b/src/coreclr/pal/src/exception/signal.cpp
@@ -116,10 +116,6 @@ struct sigaction g_previous_sigabrt;
#if !HAVE_MACH_EXCEPTIONS
-// Offset of the local variable containing pointer to windows style context in the common_signal_handler function.
-// This offset is relative to the frame pointer.
-int g_common_signal_handler_context_locvar_offset = 0;
-
// TOP of special stack for handling stack overflow
volatile void* g_stackOverflowHandlerStack = NULL;
@@ -240,8 +236,11 @@ BOOL SEHInitializeSignals(CorUnix::CPalThread *pthrCurrent, DWORD flags)
}
#ifdef INJECT_ACTIVATION_SIGNAL
- handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation);
- g_registered_activation_handler = true;
+ if (flags & PAL_INITIALIZE_REGISTER_ACTIVATION_SIGNAL)
+ {
+ handle_signal(INJECT_ACTIVATION_SIGNAL, inject_activation_handler, &g_previous_activation);
+ g_registered_activation_handler = true;
+ }
#endif
return TRUE;
@@ -939,11 +938,12 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext
#if !HAVE_MACH_EXCEPTIONS
sigset_t signal_set;
CONTEXT signalContextRecord;
+ CONTEXT* signalContextRecordPtr = &signalContextRecord;
EXCEPTION_RECORD exceptionRecord;
native_context_t *ucontext;
ucontext = (native_context_t *)sigcontext;
- g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0));
+ g_hardware_exception_context_locvar_offset = (int)((char*)&signalContextRecordPtr - (char*)__builtin_frame_address(0));
if (code == (SIGSEGV | StackOverflowFlag))
{
diff --git a/src/coreclr/pal/src/include/pal/modulename.h b/src/coreclr/pal/src/include/pal/modulename.h
deleted file mode 100644
index 87d54b77a5b95e..00000000000000
--- a/src/coreclr/pal/src/include/pal/modulename.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*++
-
-
-
-Module Name:
-
- include/pal/modulename.h
-
-Abstract:
- Header file for functions to get the name of a module
-
-Revision History:
-
-
-
---*/
-
-#ifndef _PAL_MODULENAME_H_
-#define _PAL_MODULENAME_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif // __cplusplus
-
-const char *PAL_dladdr(LPVOID ProcAddress);
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif /*_PAL_MODULENAME_H_*/
diff --git a/src/coreclr/pal/src/include/pal/palinternal.h b/src/coreclr/pal/src/include/pal/palinternal.h
index 3a12d789103647..ff3703c6ae4f7f 100644
--- a/src/coreclr/pal/src/include/pal/palinternal.h
+++ b/src/coreclr/pal/src/include/pal/palinternal.h
@@ -526,8 +526,6 @@ function_name() to call the system's implementation
#undef wcsstr
#undef wcscmp
#undef wcsncpy
-#undef wcstok
-#undef wcscspn
#undef iswupper
#undef iswspace
#undef towlower
diff --git a/src/coreclr/pal/src/include/pal/seh.hpp b/src/coreclr/pal/src/include/pal/seh.hpp
index 6ad89df0fdd650..327fe0d7fb03e2 100644
--- a/src/coreclr/pal/src/include/pal/seh.hpp
+++ b/src/coreclr/pal/src/include/pal/seh.hpp
@@ -145,5 +145,10 @@ CorUnix::PAL_ERROR SEHDisable(CorUnix::CPalThread *pthrCurrent);
}
+// Offset of the local variable containing pointer to windows style context in the common_signal_handler / PAL_DispatchException function.
+// This offset is relative to the frame pointer.
+extern int g_hardware_exception_context_locvar_offset;
+
+
#endif /* _PAL_SEH_HPP_ */
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/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp
index e792f75a2b22e1..2a559b56e2bef5 100644
--- a/src/coreclr/pal/src/loader/module.cpp
+++ b/src/coreclr/pal/src/loader/module.cpp
@@ -30,7 +30,6 @@ SET_DEFAULT_DEBUG_CHANNEL(LOADER); // some headers have code with asserts, so do
#include "pal/file.h"
#include "pal/utils.h"
#include "pal/init.h"
-#include "pal/modulename.h"
#include "pal/environ.h"
#include "pal/virtual.h"
#include "pal/map.hpp"
@@ -342,9 +341,10 @@ GetProcAddress(
/* if we don't know the module's full name yet, this is our chance to obtain it */
if (!module->lib_name && module->dl_handle)
{
- const char* libName = PAL_dladdr((LPVOID)ProcAddress);
- if (libName)
+ Dl_info dl_info;
+ if (dladdr((LPVOID)ProcAddress, &dl_info) != 0)
{
+ const char* libName = dl_info.dli_fname;
module->lib_name = UTIL_MBToWC_Alloc(libName, -1);
if (nullptr == module->lib_name)
{
@@ -356,6 +356,10 @@ GetProcAddress(
module, libName);
}
}
+ else
+ {
+ TRACE("GetProcAddress: dladdr() call failed!\n");
+ }
}
}
else
@@ -925,7 +929,7 @@ struct CopyModuleDataParam
int result;
};
-void handle_image_range(uint8_t* source_start, size_t size, struct CopyModuleDataParam* param)
+void handle_image_range(uint8_t* source_start, size_t size, struct CopyModuleDataParam* param)
{
uint8_t* source_end = source_start + size;
if (param->destination_buffer_start != NULL)
diff --git a/src/coreclr/pal/src/loader/modulename.cpp b/src/coreclr/pal/src/loader/modulename.cpp
deleted file mode 100644
index 40c1c6de5c3d64..00000000000000
--- a/src/coreclr/pal/src/loader/modulename.cpp
+++ /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.
-
-/*++
-
-
-
-Module Name:
-
- modulename.cpp
-
-Abstract:
-
- Implementation of internal functions to get module names
-
-
-
---*/
-
-#include "pal/thread.hpp"
-#include "pal/malloc.hpp"
-#include "pal/palinternal.h"
-#include "pal/dbgmsg.h"
-#include "pal/modulename.h"
-
-#include
-
-using namespace CorUnix;
-
-SET_DEFAULT_DEBUG_CHANNEL(LOADER);
-
-/*++
- PAL_dladdr
-
- Internal wrapper for dladder used only to get module name
-
-Parameters:
- LPVOID ProcAddress: a pointer to a function in a shared library
-
-Return value:
- Pointer to string with the fullpath to the shared library containing
- ProcAddress.
-
- NULL if error occurred.
-
-Notes:
- The string returned by this function is owned by the OS.
- If you need to keep it, strdup() it, because it is unknown how long
- this ptr will point at the string you want (over the lifetime of
- the system running) It is only safe to use it immediately after calling
- this function.
---*/
-const char *PAL_dladdr(LPVOID ProcAddress)
-{
- Dl_info dl_info;
- if (!dladdr(ProcAddress, &dl_info))
- {
- WARN("dladdr() call failed!\n");
- /* If we get an error, return NULL */
- return (NULL);
- }
- else
- {
- /* Return the module name */
- return dl_info.dli_fname;
- }
-}
-
diff --git a/src/coreclr/pal/src/memory/local.cpp b/src/coreclr/pal/src/memory/local.cpp
deleted file mode 100644
index fc62ef428b1e22..00000000000000
--- a/src/coreclr/pal/src/memory/local.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*++
-
-
-
-Module Name:
-
- local.c
-
-Abstract:
-
- Implementation of local memory management functions.
-
-Revision History:
-
-
-
---*/
-
-#include "pal/palinternal.h"
-#include "pal/dbgmsg.h"
-
-
-SET_DEFAULT_DEBUG_CHANNEL(MEM);
-
-
-/*++
-Function:
- LocalAlloc
-
-See MSDN doc.
---*/
-HLOCAL
-PALAPI
-LocalAlloc(
- IN UINT uFlags,
- IN SIZE_T uBytes)
-{
- LPVOID lpRetVal = NULL;
- PERF_ENTRY(LocalAlloc);
- ENTRY("LocalAlloc (uFlags=%#x, uBytes=%u)\n", uFlags, uBytes);
-
- if ((uFlags & ~LMEM_ZEROINIT) != 0)
- {
- ASSERT("Invalid parameter AllocFlags=0x%x\n", uFlags);
- SetLastError(ERROR_INVALID_PARAMETER);
- goto done;
- }
-
- lpRetVal = PAL_malloc(uBytes);
-
- if (lpRetVal == NULL)
- {
- ERROR("Not enough memory\n");
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto done;
- }
-
- if ((uFlags & LMEM_ZEROINIT) != 0)
- {
- memset(lpRetVal, 0, uBytes);
- }
-
-done:
- LOGEXIT( "LocalAlloc returning %p.\n", lpRetVal );
- PERF_EXIT(LocalAlloc);
- return (HLOCAL) lpRetVal;
-}
-
-/*++
-Function:
- LocalFree
-
-See MSDN doc.
---*/
-HLOCAL
-PALAPI
-LocalFree(
- IN HLOCAL hMem)
-{
- BOOL bRetVal = FALSE;
- PERF_ENTRY(LocalFree);
- ENTRY("LocalFree (hmem=%p)\n", hMem);
-
- free(hMem);
- bRetVal = TRUE;
-
- LOGEXIT( "LocalFree returning %p.\n", bRetVal == TRUE ? (HLOCAL)NULL : hMem );
- PERF_EXIT(LocalFree);
- return bRetVal == TRUE ? (HLOCAL)NULL : hMem;
-}
diff --git a/src/coreclr/pal/src/misc/fmtmessage.cpp b/src/coreclr/pal/src/misc/fmtmessage.cpp
index 81502bfc7722ed..e9d87d19c4a080 100644
--- a/src/coreclr/pal/src/misc/fmtmessage.cpp
+++ b/src/coreclr/pal/src/misc/fmtmessage.cpp
@@ -63,7 +63,7 @@ static LPWSTR FMTMSG_GetMessageString( DWORD dwErrCode )
allocChars = MAX_ERROR_STRING_LENGTH + 1;
}
- LPWSTR lpRetVal = (LPWSTR)LocalAlloc(LMEM_FIXED, allocChars * sizeof(WCHAR));
+ LPWSTR lpRetVal = (LPWSTR)PAL_malloc(allocChars * sizeof(WCHAR));
if (lpRetVal)
{
@@ -135,7 +135,7 @@ static INT FMTMSG__watoi( LPWSTR str )
UINT NumOfBytes = 0; \
nSize *= 2; \
NumOfBytes = nSize * sizeof( WCHAR ); \
- lpTemp = static_cast( LocalAlloc( LMEM_FIXED, NumOfBytes ) ); \
+ lpTemp = static_cast( PAL_malloc( NumOfBytes ) ); \
TRACE( "Growing the buffer.\n" );\
\
if ( !lpTemp ) \
@@ -149,7 +149,7 @@ static INT FMTMSG__watoi( LPWSTR str )
\
*lpWorkingString = '\0';\
PAL_wcscpy( lpTemp, lpReturnString );\
- LocalFree( lpReturnString ); \
+ free( lpReturnString ); \
lpWorkingString = lpReturnString = lpTemp; \
lpWorkingString += nCount; \
} \
@@ -341,7 +341,7 @@ FormatMessageW(
/* Parameter processing. */
if ( dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER )
{
- TRACE( "Allocated %d TCHARs. Don't forget to call LocalFree to "
+ TRACE( "Allocated %d TCHARs. Don't forget to call free to "
"free the memory when done.\n", nSize );
bIsLocalAlloced = TRUE;
}
@@ -418,7 +418,7 @@ FormatMessageW(
}
lpWorkingString = static_cast(
- LocalAlloc( LMEM_FIXED, nSize * sizeof( WCHAR ) ) );
+ PAL_malloc( nSize * sizeof( WCHAR ) ) );
if ( !lpWorkingString )
{
ERROR( "Unable to allocate memory for the working string.\n" );
@@ -675,14 +675,14 @@ FormatMessageW(
{
TRACE( "Copying the string into the buffer.\n" );
PAL_wcsncpy( lpBuffer, lpReturnString, nCount + 1 );
- LocalFree( lpReturnString );
+ free( lpReturnString );
}
}
else /* Error, something occurred. */
{
if ( lpReturnString )
{
- LocalFree( lpReturnString );
+ free( lpReturnString );
}
}
LOGEXIT( "FormatMessageW returns %d.\n", nCount );
diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt
index f58757a1f6d5fc..f14b2442afa78c 100644
--- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt
+++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt
@@ -415,7 +415,6 @@ add_executable_clr(paltests
c_runtime/wcsstr/test1/test1.cpp
c_runtime/wcstod/test1/test1.cpp
c_runtime/wcstod/test2/test2.cpp
- c_runtime/wcstok/test1/test1.cpp
c_runtime/wcstoul/test1/test1.cpp
c_runtime/wcstoul/test2/test2.cpp
c_runtime/wcstoul/test3/test3.cpp
@@ -581,9 +580,6 @@ add_executable_clr(paltests
# filemapping_memmgt/GetProcAddress/test1/testlib.cpp
filemapping_memmgt/GetProcAddress/test2/test2.cpp
# filemapping_memmgt/GetProcAddress/test2/testlib.cpp
- filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp
- filemapping_memmgt/LocalFree/test1/LocalFree.cpp
- filemapping_memmgt/LocalFree/test2/LocalFree.cpp
filemapping_memmgt/MapViewOfFile/test1/MapViewOfFile.cpp
filemapping_memmgt/MapViewOfFile/test2/MapViewOfFile.cpp
filemapping_memmgt/MapViewOfFile/test3/MapViewOfFile.cpp
diff --git a/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp b/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp
deleted file mode 100644
index 564466c2a4e7f3..00000000000000
--- a/src/coreclr/pal/tests/palsuite/c_runtime/wcstok/test1/test1.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*============================================================================
-**
-** Source: test1.c
-**
-** Purpose:
-** Search for a number of tokens within strings. Check that the return values
-** are what is expected, and also that the strings match up with our expected
-** results.
-**
-**
-**==========================================================================*/
-
-#include
-
-PALTEST(c_runtime_wcstok_test1_paltest_wcstok_test1, "c_runtime/wcstok/test1/paltest_wcstok_test1")
-{
- /* foo bar baz */
- WCHAR str[] = {'f','o','o',' ','b','a','r',' ','b','a','z','\0'};
-
- /* foo \0ar baz */
- WCHAR result1[] = {'f','o','o',' ','\0','a','r',' ','b','a','z','\0'};
-
- /* foo \0a\0 baz */
- WCHAR result2[] = {'f','o','o',' ','\0','a','\0',' ','b','a','z','\0'};
-
- WCHAR* tempString;
- int len = 0;
- WCHAR *ptr;
-
- if (PAL_Initialize(argc, argv))
- {
- return FAIL;
- }
-
- len = (wcslen(str)*sizeof(WCHAR)) + 2;
-
- /* Tokenize 'str'. It will hit the 'b' delimiter first. Check to see
- that the ptr is pointing to the start of the string and do a compare
- to ensure the tokenized string is what we expected.
- */
-
- tempString = convert("bz");
- ptr = wcstok(str, tempString);
- free(tempString);
-
- if (ptr != str)
- {
- Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str, ptr);
- }
-
- if (memcmp(str, result1, len) != 0)
- {
- Fail("ERROR: wcstok altered the string in an unexpected fashion.");
- }
-
- /* If NULL is passed as the first parameter, wcstok will continue
- tokenizing the same string. Test that this works properly.
- */
- tempString = convert("r ");
- ptr = wcstok(NULL, tempString);
- free(tempString);
-
- if (ptr != str + 5)
- {
- Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str+5, ptr);
- }
-
- if (memcmp(str, result2, len) != 0)
- {
- Fail("ERROR: wcstok altered the string in an unexpected fashion.");
- }
-
- /* Continue onward, and search for 'X' now, which won't be found. The
- pointer should point just after the last NULL in the string. And
- the string itself shouldn't have changed.
- */
- tempString = convert("X");
- ptr = wcstok(NULL, tempString);
- free(tempString);
-
- if (ptr != str + 7)
- {
- Fail("ERROR: Expected wcstok() to return %p, got %p!\n", str + 7, ptr);
- }
-
- if (memcmp(str, result2, len) != 0)
- {
- Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n");
- }
-
- /* Call wcstok again. Now the ptr should point to the end of the
- string at NULL. And the string itself shouldn't have changed.
- */
- tempString = convert("X");
- ptr = wcstok(NULL, tempString);
- free(tempString);
-
- if (ptr != NULL)
- {
- Fail("ERROR: Expected wcstok() to return %p, got %p!\n", NULL, ptr);
- }
-
- if (memcmp(str, result2, len) != 0)
- {
- Fail("ERROR: wcstok altered the string in an unexpeced fashion.\n");
- }
-
- PAL_Terminate();
- return PASS;
-}
diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt
index c674de294db452..a7e27f9228976c 100644
--- a/src/coreclr/pal/tests/palsuite/compilableTests.txt
+++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt
@@ -348,7 +348,6 @@ c_runtime/wcsrchr/test1/paltest_wcsrchr_test1
c_runtime/wcsstr/test1/paltest_wcsstr_test1
c_runtime/wcstod/test1/paltest_wcstod_test1
c_runtime/wcstod/test2/paltest_wcstod_test2
-c_runtime/wcstok/test1/paltest_wcstok_test1
c_runtime/wcstoul/test1/paltest_wcstoul_test1
c_runtime/wcstoul/test2/paltest_wcstoul_test2
c_runtime/wcstoul/test3/paltest_wcstoul_test3
@@ -487,9 +486,6 @@ filemapping_memmgt/GetModuleFileNameW/test1/paltest_getmodulefilenamew_test1
filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2
filemapping_memmgt/GetProcAddress/test1/paltest_getprocaddress_test1
filemapping_memmgt/GetProcAddress/test2/paltest_getprocaddress_test2
-filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1
-filemapping_memmgt/LocalFree/test1/paltest_localfree_test1
-filemapping_memmgt/LocalFree/test2/paltest_localfree_test2
filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1
filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2
filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3
diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp
deleted file mode 100644
index 5879ed598071a7..00000000000000
--- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalAlloc/test1/LocalAlloc.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*=============================================================
-**
-** Source: LocalAlloc.c
-**
-** Purpose: Positive test the LocalAlloc API.
-** Call LocalAlloc with zero as the allocation attribute
-**
-**
-**============================================================*/
-#include
-
-PALTEST(filemapping_memmgt_LocalAlloc_test1_paltest_localalloc_test1, "filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1")
-{
- HLOCAL LocalHeap;
- HLOCAL FreeHeap;
- int err;
- const SIZE_T heapSize = 64;
-
- /*Initialize the PAL environment*/
- err = PAL_Initialize(argc, argv);
- if(0 != err)
- {
- return FAIL;
- }
-
- /*Allocate the specified number of bytes from the heap*/
- /*with allocation attribute: zero which is required by PAL Doc*/
- LocalHeap = LocalAlloc(0, heapSize);
- if(!LocalHeap)
- {
- Fail("\nFailed to call LocalAlloc API, "
- "error code=%u\n", GetLastError());
- }
-
- /*Free the allocated local heap memory*/
- FreeHeap = LocalFree(LocalHeap);
- if(FreeHeap)
- {
- Fail("Failed to call LocalFree API, "
- "error code=%u\n", GetLastError());
- }
-
- PAL_Terminate();
- return PASS;
-}
diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp
deleted file mode 100644
index 0fcb32d6fc96fb..00000000000000
--- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test1/LocalFree.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*=============================================================
-**
-** Source: LocalFree.c
-**
-** Purpose: Positive test the LocalFree API.
-** Call LocalFree to free a specified local memory object
-**
-**
-**============================================================*/
-#include
-
-PALTEST(filemapping_memmgt_LocalFree_test1_paltest_localfree_test1, "filemapping_memmgt/LocalFree/test1/paltest_localfree_test1")
-{
- HLOCAL LocalHeap;
- HLOCAL FreeHeap;
- int err;
- const SIZE_T heapSize = 64;
-
- /*Initialize the PAL environment*/
- err = PAL_Initialize(argc, argv);
- if(0 != err)
- {
- return FAIL;
- }
-
- /*Allocate the specified number of bytes from the heap*/
- /*with zero ad the allocation attribute*/
- LocalHeap = LocalAlloc(0, heapSize);
- if(!LocalHeap)
- {
- Fail("\nFailed to call LocalAlloc API, "
- "error code=%u\n", GetLastError());
- }
-
- /*Free the allocated local heap memory*/
- FreeHeap = LocalFree(LocalHeap);
- if(FreeHeap)
- {
- Fail("Failed to call LocalFree API, "
- "error code=%u\n", GetLastError());
- }
-
- PAL_Terminate();
- return PASS;
-}
diff --git a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp b/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp
deleted file mode 100644
index 5d66077a2cfd72..00000000000000
--- a/src/coreclr/pal/tests/palsuite/filemapping_memmgt/LocalFree/test2/LocalFree.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-/*=============================================================
-**
-** Source: LocalFree.c
-**
-** Purpose: Positive test the LocalFree API.
-** call LocalFree by passing NULL as local memory
-** object handle
-**
-**
-**============================================================*/
-#include
-
-PALTEST(filemapping_memmgt_LocalFree_test2_paltest_localfree_test2, "filemapping_memmgt/LocalFree/test2/paltest_localfree_test2")
-{
- HLOCAL FreeHeap;
- int err;
-
- /*Initialize the PAL environment*/
- err = PAL_Initialize(argc, argv);
- if(0 != err)
- {
- return FAIL;
- }
-
- /*call LocalFree by passing NULL as local memory object handle*/
- FreeHeap = LocalFree(NULL);
- if(FreeHeap)
- {
- Fail("Failed to call LocalFree API, "
- "error code=%u\n", GetLastError());
- }
-
- PAL_Terminate();
- return PASS;
-}
diff --git a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp
index d71e0ea85c333e..93363488bc61d2 100644
--- a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp
+++ b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test6/loadlibrarya.cpp
@@ -7,9 +7,9 @@
**
** Purpose: Positive test the LoadLibrary API. Test will verify
** that it is unable to load the library twice. Once by
-** using the full path name and secondly by using the
+** using the full path name and secondly by using the
** short name.
-**
+**
**
**============================================================*/
@@ -25,14 +25,13 @@ typedef int (*dllfunct)();
#define GETATTACHCOUNTNAME "_GetAttachCount@0"
#endif
-
/* Helper function to test the loaded library.
*/
BOOL PALAPI TestDll(HMODULE hLib)
{
int RetVal;
char FunctName[] = GETATTACHCOUNTNAME;
- FARPROC DllFunc;
+ FARPROC DllFunc;
/* Access a function from the loaded library.
*/
@@ -45,7 +44,7 @@ BOOL PALAPI TestDll(HMODULE hLib)
return (FALSE);
}
- /* Verify that the DLL_PROCESS_ATTACH is only
+ /* Verify that the DLL_PROCESS_ATTACH is only
* accessed once.*/
RetVal = DllFunc();
if (RetVal != 1)
@@ -70,7 +69,7 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
-
+
/* Initialize the PAL. */
if ((PAL_Initialize(argc, argv)) != 0)
@@ -84,15 +83,15 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
/* Get the full path to the library (DLL).
*/
-
- if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) {
-
+
+ if (NULL != realpath(argv[0],fullpath)) {
+
_splitpath(fullPath,drive,dir,fname,ext);
_makepath(fullPath,drive,dir,LibraryName,"");
-
-
+
+
} else {
- Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. realpath returned NULL\n",argv[0]);
}
/* Call Load library with the short name of
@@ -101,11 +100,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
hShortLib = LoadLibrary(LibraryName);
if(hShortLib == NULL)
{
- Fail("ERROR:%u:Unable to load library %s\n",
- GetLastError(),
+ Fail("ERROR:%u:Unable to load library %s\n",
+ GetLastError(),
LibraryName);
}
-
+
/* Test the loaded library.
*/
if (!TestDll(hShortLib))
@@ -120,8 +119,8 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
hFullLib = LoadLibrary(fullPath);
if(hFullLib == NULL)
{
- Trace("ERROR:%u:Unable to load library %s\n",
- GetLastError(),
+ Trace("ERROR:%u:Unable to load library %s\n",
+ GetLastError(),
fullPath);
iRetVal = FAIL;
goto cleanUpTwo;
@@ -141,11 +140,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
cleanUpTwo:
- /* Call the FreeLibrary API.
- */
+ /* Call the FreeLibrary API.
+ */
if (!FreeLibrary(hFullLib))
{
- Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
GetLastError(),
fullPath);
iRetVal = FAIL;
@@ -153,11 +152,11 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
cleanUpOne:
- /* Call the FreeLibrary API.
- */
+ /* Call the FreeLibrary API.
+ */
if (!FreeLibrary(hShortLib))
{
- Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
GetLastError(),
LibraryName);
iRetVal = FAIL;
@@ -167,5 +166,4 @@ PALTEST(loader_LoadLibraryA_test6_paltest_loadlibrarya_test6, "loader/LoadLibrar
*/
PAL_TerminateEx(iRetVal);
return iRetVal;
-
}
diff --git a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp
index b489ef27f965e7..1bbf9a6d08ad1e 100644
--- a/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp
+++ b/src/coreclr/pal/tests/palsuite/loader/LoadLibraryA/test8/loadlibrarya.cpp
@@ -7,9 +7,9 @@
**
** Purpose: Positive test the LoadLibrary API. Test will verify
** that it is unable to load the library twice. Once by
-** using the full path name and secondly by using the
+** using the full path name and secondly by using the
** short name.
-**
+**
**
**============================================================*/
@@ -25,14 +25,13 @@ typedef int (*dllfunct)();
#define GETATTACHCOUNTNAME "_GetAttachCount@0"
#endif
-
/* Helper function to test the loaded library.
*/
BOOL PALAPI TestDll(HMODULE hLib)
{
int RetVal;
char FunctName[] = GETATTACHCOUNTNAME;
- FARPROC DllFunc;
+ FARPROC DllFunc;
/* Access a function from the loaded library.
*/
@@ -45,7 +44,7 @@ BOOL PALAPI TestDll(HMODULE hLib)
return (FALSE);
}
- /* Verify that the DLL_PROCESS_ATTACH is only
+ /* Verify that the DLL_PROCESS_ATTACH is only
* accessed once.*/
RetVal = DllFunc();
if (RetVal != 1)
@@ -72,7 +71,7 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
char relTestDir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
-
+
BOOL bRc = FALSE;
char relLibPath[_MAX_DIR];
@@ -89,15 +88,15 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
/* Get the full path to the library (DLL).
*/
-
- if (NULL != _fullpath(fullPath,argv[0],_MAX_DIR)) {
-
+
+ if (NULL != realpath(argv[0],fullpath)) {
+
_splitpath(fullPath,drive,dir,fname,ext);
_makepath(fullPath,drive,dir,LibraryName,"");
-
-
+
+
} else {
- Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. _fullpath returned NULL\n",argv[0]);
+ Fail("ERROR: conversion from relative path \" %s \" to absolute path failed. realpath returned NULL\n",argv[0]);
}
/* Get relative path to the library
@@ -112,11 +111,11 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
hShortLib = LoadLibrary(LibraryName);
if(hShortLib == NULL)
{
- Fail("ERROR:%u:Short:Unable to load library %s\n",
- GetLastError(),
+ Fail("ERROR:%u:Short:Unable to load library %s\n",
+ GetLastError(),
LibraryName);
}
-
+
/* Test the loaded library.
*/
if (!TestDll(hShortLib))
@@ -131,8 +130,8 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
hFullLib = LoadLibrary(fullPath);
if(hFullLib == NULL)
{
- Trace("ERROR:%u:Full:Unable to load library %s\n",
- GetLastError(),
+ Trace("ERROR:%u:Full:Unable to load library %s\n",
+ GetLastError(),
fullPath);
iRetVal = FAIL;
goto cleanUpTwo;
@@ -148,14 +147,14 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
/*
** Call the load library with the relative path
- ** wrt to the directory ./testloadlibrary/..
+ ** wrt to the directory ./testloadlibrary/..
** since we don't want to make any assumptions
** regarding the type of build
*/
hRelLib = LoadLibrary(relLibPath);
if(hRelLib == NULL)
{
- Trace("ERROR:%u:Rel:Unable to load library at %s\n",
+ Trace("ERROR:%u:Rel:Unable to load library at %s\n",
GetLastError(), relLibPath);
iRetVal = FAIL;
goto cleanUpTwo;
@@ -190,12 +189,12 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
cleanUpThree:
- /* Call the FreeLibrary API.
- */
+ /* Call the FreeLibrary API.
+ */
if (!FreeLibrary(hRelLib))
{
- Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
GetLastError(),
relLibPath);
iRetVal = FAIL;
@@ -203,11 +202,11 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
cleanUpTwo:
- /* Call the FreeLibrary API.
- */
+ /* Call the FreeLibrary API.
+ */
if (!FreeLibrary(hFullLib))
{
- Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
GetLastError(),
fullPath);
iRetVal = FAIL;
@@ -215,20 +214,18 @@ PALTEST(loader_LoadLibraryA_test8_paltest_loadlibrarya_test8, "loader/LoadLibrar
cleanUpOne:
- /* Call the FreeLibrary API.
- */
+ /* Call the FreeLibrary API.
+ */
if (!FreeLibrary(hShortLib))
{
- Trace("ERROR:%u: Unable to free library \"%s\"\n",
+ Trace("ERROR:%u: Unable to free library \"%s\"\n",
GetLastError(),
LibraryName);
iRetVal = FAIL;
}
-
/* Terminate the PAL.
*/
PAL_TerminateEx(iRetVal);
return iRetVal;
-
}
diff --git a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp
index b16b0ea27754ee..15d94411bb030d 100644
--- a/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp
+++ b/src/coreclr/pal/tests/palsuite/miscellaneous/FormatMessageW/test6/test.cpp
@@ -36,9 +36,9 @@ PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscel
the error message it extracts is correct, only that it does place some
information into the buffer when it is called.
*/
-
+
/*
-
+
ERROR_SUCCESS (0L) is normally returned by GetLastError,
But, the ERROR_SUCCESS is removed from messages for Unix based Systems
To ensure that we have some information into the buffer we are using the message
@@ -54,25 +54,25 @@ PALTEST(miscellaneous_FormatMessageW_test6_paltest_formatmessagew_test6, "miscel
0, /* maximum size of message buffer */
NULL /* array of message inserts */
);
-
- if(ReturnResult == 0)
+
+ if(ReturnResult == 0)
{
Fail("ERROR: The return value was 0, which indicates failure. The "
"function failed when trying to Format a FROM_SYSTEM message.");
}
-
- if(wcslen(OutBuffer) <= 0)
+
+ if(wcslen(OutBuffer) <= 0)
{
Fail("ERROR: There are no characters in the buffer, and when the "
"FORMAT_MESSAGE_FROM_SYSTEM flag is used with ERROR_FILE_NOT_FOUND error, "
"something should be put into the buffer.");
}
-
- LocalFree(OutBuffer);
-
+
+ free(OutBuffer);
+
PAL_Terminate();
return PASS;
-
+
}
diff --git a/src/coreclr/pal/tests/palsuite/paltestlist.txt b/src/coreclr/pal/tests/palsuite/paltestlist.txt
index 2b9ac7ccd4eb1e..2afdf101d5b68b 100644
--- a/src/coreclr/pal/tests/palsuite/paltestlist.txt
+++ b/src/coreclr/pal/tests/palsuite/paltestlist.txt
@@ -333,7 +333,6 @@ c_runtime/wcsrchr/test1/paltest_wcsrchr_test1
c_runtime/wcsstr/test1/paltest_wcsstr_test1
c_runtime/wcstod/test1/paltest_wcstod_test1
c_runtime/wcstod/test2/paltest_wcstod_test2
-c_runtime/wcstok/test1/paltest_wcstok_test1
c_runtime/wcstoul/test1/paltest_wcstoul_test1
c_runtime/wcstoul/test2/paltest_wcstoul_test2
c_runtime/wcstoul/test3/paltest_wcstoul_test3
@@ -449,9 +448,6 @@ filemapping_memmgt/CreateFileMappingW/test9/paltest_createfilemappingw_test9
filemapping_memmgt/FreeLibrary/test2/paltest_freelibrary_test2
filemapping_memmgt/GetModuleFileNameA/test2/paltest_getmodulefilenamea_test2
filemapping_memmgt/GetModuleFileNameW/test2/paltest_getmodulefilenamew_test2
-filemapping_memmgt/LocalAlloc/test1/paltest_localalloc_test1
-filemapping_memmgt/LocalFree/test1/paltest_localfree_test1
-filemapping_memmgt/LocalFree/test2/paltest_localfree_test2
filemapping_memmgt/MapViewOfFile/test1/paltest_mapviewoffile_test1
filemapping_memmgt/MapViewOfFile/test2/paltest_mapviewoffile_test2
filemapping_memmgt/MapViewOfFile/test3/paltest_mapviewoffile_test3
diff --git a/src/coreclr/runtime-prereqs.proj b/src/coreclr/runtime-prereqs.proj
index 1127c3df8bdf3b..36ed2ce497be1e 100644
--- a/src/coreclr/runtime-prereqs.proj
+++ b/src/coreclr/runtime-prereqs.proj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/coreclr/runtime.proj b/src/coreclr/runtime.proj
index 5f062c9af2f403..26801ea8c198cf 100644
--- a/src/coreclr/runtime.proj
+++ b/src/coreclr/runtime.proj
@@ -48,6 +48,7 @@
<_CoreClrBuildArg Condition="'$(ClrAllJitsSubset)' == 'true'" Include="-component alljits" />
<_CoreClrBuildArg Condition="'$(ClrILToolsSubset)' == 'true'" Include="-component iltools" />
<_CoreClrBuildArg Condition="'$(ClrNativeAotSubset)' == 'true'" Include="-component nativeaot" />
+ <_CoreClrBuildArg Condition="'$(ClrSpmiSubset)' == 'true'" Include="-component spmi" />
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 c7906124b45d4b..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")
+ 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"))
+ print(decode_string(command_stdout))
if len(command_stderr) > 0:
- print(command_stderr.decode("utf-8"))
+ 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 963e117688f572..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
+ $(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
+ $(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/scripts/superpmi.md b/src/coreclr/scripts/superpmi.md
index d9404dc32d7406..36e24711637aea 100644
--- a/src/coreclr/scripts/superpmi.md
+++ b/src/coreclr/scripts/superpmi.md
@@ -1,7 +1,7 @@
# Documentation for the superpmi.py tool
SuperPMI is a tool for developing and testing the JIT compiler.
-General information on SuperPMI can be found [here](../ToolBox/superpmi/readme.md).
+General information on SuperPMI can be found [here](../tools/superpmi/readme.md).
## Overview
diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py
index 8433294a146d8a..3c9d417f81cc02 100755
--- a/src/coreclr/scripts/superpmi.py
+++ b/src/coreclr/scripts/superpmi.py
@@ -276,6 +276,7 @@
collect_parser.add_argument("-assemblies", dest="assemblies", nargs="+", default=[], help="A list of managed dlls or directories to recursively use while collecting with PMI or crossgen2. Required if --pmi or --crossgen2 is specified.")
collect_parser.add_argument("-exclude", dest="exclude", nargs="+", default=[], help="A list of files or directories to exclude from the files and directories specified by `-assemblies`.")
collect_parser.add_argument("-pmi_location", help="Path to pmi.dll to use during PMI run. Optional; pmi.dll will be downloaded from Azure Storage if necessary.")
+collect_parser.add_argument("-pmi_path", metavar="PMIPATH_DIR", nargs='*', help="Specify a \"load path\" where assemblies can be found during pmi.dll run. Optional; the argument values are translated to PMIPATH environment variable.")
collect_parser.add_argument("-output_mch_path", help="Location to place the final MCH file.")
collect_parser.add_argument("--merge_mch_files", action="store_true", help="Merge multiple MCH files. Use the -mch_files flag to pass a list of MCH files to merge.")
collect_parser.add_argument("-mch_files", metavar="MCH_FILE", nargs='+', help="Pass a sequence of MCH files which will be merged. Required by --merge_mch_files.")
@@ -831,7 +832,14 @@ async def run_pmi(print_prefix, assembly, self):
pmi_command_env = env_copy.copy()
pmi_complus_env = complus_env.copy()
pmi_complus_env["JitName"] = self.collection_shim_name
- set_and_report_env(pmi_command_env, root_env, pmi_complus_env)
+
+ if self.coreclr_args.pmi_path is not None:
+ pmi_root_env = root_env.copy()
+ pmi_root_env["PMIPATH"] = ";".join(self.coreclr_args.pmi_path)
+ else:
+ pmi_root_env = root_env
+
+ set_and_report_env(pmi_command_env, pmi_root_env, pmi_complus_env)
old_env = os.environ.copy()
os.environ.update(pmi_command_env)
@@ -3105,6 +3113,11 @@ def verify_replay_common_args():
lambda unused: True,
"Unable to set tiered_compilation")
+ coreclr_args.verify(args,
+ "pmi_path",
+ lambda unused: True,
+ "Unable to set pmi_path")
+
if (args.collection_command is None) and (args.pmi is False) and (args.crossgen2 is False):
print("Either a collection command or `--pmi` or `--crossgen2` must be specified")
sys.exit(1)
@@ -3121,6 +3134,12 @@ def verify_replay_common_args():
print("Specify `-assemblies` if `--pmi` or `--crossgen2` is given")
sys.exit(1)
+ if not args.pmi:
+ if args.pmi_path is not None:
+ logging.warning("Warning: -pmi_path is set but --pmi is not.")
+ if args.pmi_location is not None:
+ logging.warning("Warning: -pmi_location is set but --pmi is not.")
+
if args.collection_command is None and args.merge_mch_files is not True:
assert args.collection_args is None
assert (args.pmi is True) or (args.crossgen2 is True)
diff --git a/src/coreclr/tools/CMakeLists.txt b/src/coreclr/tools/CMakeLists.txt
index a50b1e6a1afbd9..db59797e26f789 100644
--- a/src/coreclr/tools/CMakeLists.txt
+++ b/src/coreclr/tools/CMakeLists.txt
@@ -1,3 +1,6 @@
+add_subdirectory(SOS)
+add_subdirectory(superpmi)
+
if (CLR_CMAKE_TARGET_WIN32 AND NOT CLR_CMAKE_CROSS_ARCH)
add_subdirectory(GenClrDebugResource)
add_subdirectory(InjectResource)
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/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index 30189ccc4cb525..cd464db7955341 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -658,7 +658,7 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN
methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_METHODTABLE;
}
methodInfo->regionKind = CorInfoRegionKind.CORINFO_REGION_NONE;
- Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args);
+ Get_CORINFO_SIG_INFO(method, sig: &methodInfo->args, methodIL);
Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals);
return true;
@@ -683,9 +683,9 @@ private bool Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORIN
return (CORINFO_CLASS_STRUCT_**)GetPin(jitVisibleInstantiation);
}
- private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, bool suppressHiddenArgument = false)
+ private void Get_CORINFO_SIG_INFO(MethodDesc method, CORINFO_SIG_INFO* sig, MethodILScope scope, bool suppressHiddenArgument = false)
{
- Get_CORINFO_SIG_INFO(method.Signature, sig);
+ Get_CORINFO_SIG_INFO(method.Signature, sig, scope);
// Does the method have a hidden parameter?
bool hasHiddenParameter = !suppressHiddenArgument && method.RequiresInstArg();
@@ -845,7 +845,7 @@ private static CorInfoCallConvExtension GetMemberFunctionCallingConventionVarian
var c => c
};
- private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig)
+ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* sig, MethodILScope scope)
{
sig->callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask);
@@ -875,7 +875,7 @@ private void Get_CORINFO_SIG_INFO(MethodSignature signature, CORINFO_SIG_INFO* s
sig->pSig = null;
sig->cbSig = 0; // Not used by the JIT
sig->methodSignature = ObjectToHandle(signature);
- sig->scope = null;
+ sig->scope = scope is not null ? ObjectToHandle(scope) : null; // scope can be null for internal calls and COM methods.
sig->token = 0; // Not used by the JIT
}
@@ -1149,7 +1149,7 @@ private void getMethodSig(CORINFO_METHOD_STRUCT_* ftn, CORINFO_SIG_INFO* sig, CO
}
}
- Get_CORINFO_SIG_INFO(method, sig: sig);
+ Get_CORINFO_SIG_INFO(method, sig: sig, scope: null);
}
private bool getMethodInfo(CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_INFO* info)
@@ -1795,7 +1795,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX
var methodIL = HandleToObject(module);
var methodSig = (MethodSignature)methodIL.GetObject((int)sigTOK);
- Get_CORINFO_SIG_INFO(methodSig, sig);
+ Get_CORINFO_SIG_INFO(methodSig, sig, methodIL);
#if !READYTORUN
// Check whether we need to report this as a fat pointer call
@@ -1811,7 +1811,7 @@ private void findSig(CORINFO_MODULE_STRUCT_* module, uint sigTOK, CORINFO_CONTEX
private void findCallSiteSig(CORINFO_MODULE_STRUCT_* module, uint methTOK, CORINFO_CONTEXT_STRUCT* context, CORINFO_SIG_INFO* sig)
{
var methodIL = HandleToObject(module);
- Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig);
+ Get_CORINFO_SIG_INFO(((MethodDesc)methodIL.GetObject((int)methTOK)), sig: sig, methodIL);
}
private CORINFO_CLASS_STRUCT_* getTokenTypeAsHandle(ref CORINFO_RESOLVED_TOKEN pResolvedToken)
@@ -3745,7 +3745,7 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)
#if READYTORUN
// TODO: enable this check in full AOT
- if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty())) // Only blittable arguments
+ if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty(), ((MetadataType)this.MethodBeingCompiled.OwningType).Module)) // Only blittable arguments
{
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramNonBlittableTypes, this.MethodBeingCompiled);
}
diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat
index c775755558de9c..69e3367c4e0942 100644
--- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat
+++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat
@@ -1,4 +1,4 @@
pushd %~dp0
-call ..\..\..\..\..\..\dotnet.cmd run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\aot\jitinterface\jitinterface.h ..\..\..\..\jit\ICorJitInfo_API_names.h ..\..\..\..\jit\ICorJitInfo_API_wrapper.hpp ..\..\..\..\inc\icorjitinfoimpl_generated.h ..\..\..\..\ToolBox\superpmi\superpmi-shim-counter\icorjitinfo.cpp ..\..\..\..\ToolBox\superpmi\superpmi-shim-simple\icorjitinfo.cpp
+call ..\..\..\..\..\..\dotnet.cmd run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\aot\jitinterface\jitinterface.h ..\..\..\..\jit\ICorJitInfo_API_names.h ..\..\..\..\jit\ICorJitInfo_API_wrapper.hpp ..\..\..\..\inc\icorjitinfoimpl_generated.h ..\..\..\..\tools\superpmi\superpmi-shim-counter\icorjitinfo.cpp ..\..\..\..\tools\superpmi\superpmi-shim-simple\icorjitinfo.cpp
call ..\..\..\..\..\..\dotnet.cmd run -- InstructionSetGenerator InstructionSetDesc.txt ..\..\Internal\Runtime\ReadyToRunInstructionSet.cs ..\..\Internal\Runtime\ReadyToRunInstructionSetHelper.cs ..\CorInfoInstructionSet.cs ..\..\..\..\inc\corinfoinstructionset.h ..\..\..\..\inc\readytoruninstructionset.h
popd
diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh
index 7dc71bd378d854..ca9cdcb52ef11f 100755
--- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh
+++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.sh
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
cd "$(dirname ${BASH_SOURCE[0]})"
-../../../../../../dotnet.sh run -- ThunkInput.txt ../CorInfoBase.cs ../../../aot/jitinterface/jitinterface.h ../../../../jit/ICorJitInfo_API_names.h ../../../../jit/ICorJitInfo_API_wrapper.hpp ../../../../inc/icorjitinfoimpl_generated.h ../../../../ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp ../../../../ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
+../../../../../../dotnet.sh run -- ThunkInput.txt ../CorInfoBase.cs ../../../aot/jitinterface/jitinterface.h ../../../../jit/ICorJitInfo_API_names.h ../../../../jit/ICorJitInfo_API_wrapper.hpp ../../../../inc/icorjitinfoimpl_generated.h ../../../../tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp ../../../../tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
../../../../../../dotnet.sh run -- InstructionSetGenerator InstructionSetDesc.txt ../../Internal/Runtime/ReadyToRunInstructionSet.cs ../../Internal/Runtime/ReadyToRunInstructionSetHelper.cs ../CorInfoInstructionSet.cs ../../../../inc/corinfoinstructionset.h ../../../../inc/readytoruninstructionset.h
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/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs
index 71c7423b8fbb04..2190f9ac1a2785 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs
@@ -63,6 +63,11 @@ private static class FieldLayoutFlags
/// True if type transitively has UnsafeValueTypeAttribute
///
public const int IsUnsafeValueType = 0x200;
+
+ ///
+ /// True if the type transitively has any types with LayoutKind.Auto in its layout.
+ ///
+ public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400;
}
private class StaticBlockInfo
@@ -115,6 +120,21 @@ public bool IsUnsafeValueType
}
}
+ ///
+ /// Does a type have auto-layout or transitively have any fields of a type with auto-layout.
+ ///
+ public virtual bool IsAutoLayoutOrHasAutoLayoutFields
+ {
+ get
+ {
+ if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout))
+ {
+ ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields);
+ }
+ return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields);
+ }
+ }
+
///
/// The number of bytes required to hold a field of this type
@@ -406,6 +426,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind)
{
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceLayoutAbiUnstable);
}
+ if (computedLayout.IsAutoLayoutOrHasAutoLayoutFields)
+ {
+ _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields);
+ }
if (computedLayout.Offsets != null)
{
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs
index 863e857a21def8..a19ec4b3603bf4 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs
@@ -82,6 +82,7 @@ public struct ComputedInstanceFieldLayout
public LayoutInt ByteCountUnaligned;
public LayoutInt ByteCountAlignment;
public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions
+ public bool IsAutoLayoutOrHasAutoLayoutFields;
///
/// If Offsets is non-null, then all field based layout is complete.
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 249faef7cd0405..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++;
@@ -112,7 +108,8 @@ out instanceByteSizeAndAlignment
ByteCountAlignment = instanceByteSizeAndAlignment.Alignment,
FieldAlignment = sizeAndAlignment.Alignment,
FieldSize = sizeAndAlignment.Size,
- LayoutAbiStable = true
+ LayoutAbiStable = true,
+ IsAutoLayoutOrHasAutoLayoutFields = false,
};
if (numInstanceFields > 0)
@@ -214,7 +211,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy
}
ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field);
- SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _);
+ SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _);
block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target);
result.Offsets[index] = new FieldAndOffset(field, block.Size);
@@ -305,13 +302,16 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
var offsets = new FieldAndOffset[numInstanceFields];
int fieldOrdinal = 0;
bool layoutAbiStable = true;
+ bool hasAutoLayoutField = false;
foreach (var fieldAndOffset in layoutMetadata.Offsets)
{
TypeDesc fieldType = fieldAndOffset.Field.FieldType;
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
+ if (fieldHasAutoLayout)
+ hasAutoLayoutField = true;
largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired);
@@ -354,7 +354,10 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
layoutMetadata.Size,
out instanceByteSizeAndAlignment);
- ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
+ ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
+ {
+ IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
+ };
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
@@ -388,15 +391,18 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
int fieldOrdinal = 0;
int packingSize = ComputePackingSize(type, layoutMetadata);
bool layoutAbiStable = true;
+ bool hasAutoLayoutField = false;
foreach (var field in type.GetFields())
{
if (field.IsStatic)
continue;
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
+ if (fieldHasAutoLayout)
+ hasAutoLayoutField = true;
largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement);
@@ -415,7 +421,10 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
layoutMetadata.Size,
out instanceByteSizeAndAlignment);
- ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
+ ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
+ {
+ IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
+ };
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
@@ -468,9 +477,9 @@ 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 _);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _);
instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++;
}
}
@@ -507,7 +516,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
TypeDesc fieldType = field.FieldType;
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
@@ -646,7 +655,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
for (int i = 0; i < instanceValueClassFieldsArr.Length; i++)
{
// Align the cumulative field offset to the indeterminate value
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
if (!fieldLayoutAbiStable)
layoutAbiStable = false;
@@ -694,7 +703,10 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
classLayoutSize: 0,
byteCount: out instanceByteSizeAndAlignment);
- ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout();
+ ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
+ {
+ IsAutoLayoutOrHasAutoLayoutFields = true,
+ };
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size;
@@ -707,7 +719,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias)
{
- var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _);
+ var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _);
instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target);
offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias);
@@ -767,10 +779,11 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8
return cumulativeInstanceFieldPos;
}
- private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable)
+ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout)
{
SizeAndAlignment result;
layoutAbiStable = true;
+ fieldTypeHasAutoLayout = true;
if (fieldType.IsDefType)
{
@@ -780,6 +793,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType,
result.Size = defType.InstanceFieldSize;
result.Alignment = defType.InstanceFieldAlignment;
layoutAbiStable = defType.LayoutAbiStable;
+ fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields;
}
else
{
@@ -797,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/EcmaAssembly.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs
index 0e155fda998f34..5a281d21ba11ad 100644
--- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaAssembly.cs
@@ -67,7 +67,7 @@ public override string ToString()
public bool HasAssemblyCustomAttribute(string attributeNamespace, string attributeName)
{
- return _metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(),
+ return !_metadataReader.GetCustomAttributeHandle(_assemblyDefinition.GetCustomAttributes(),
attributeNamespace, attributeName).IsNil;
}
}
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/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs
index c68f9a10fe2fa6..dd91b65fa90798 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs
@@ -20,7 +20,7 @@ string IPrefixMangledSignature.Prefix
{
get
{
- return "Calli";
+ return RuntimeMarshallingEnabled ? "CalliWithRuntimeMarshalling" : "Calli";
}
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs
index 89be9fa3a7d881..cd6e620aa86074 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs
@@ -13,6 +13,11 @@ partial class CalliMarshallingMethodThunk
protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
var otherMethod = (CalliMarshallingMethodThunk)other;
+ int result = RuntimeMarshallingEnabled.CompareTo(otherMethod.RuntimeMarshallingEnabled);
+ if (result != 0)
+ {
+ return result;
+ }
return comparer.Compare(_targetSignature, otherMethod._targetSignature);
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
index bdbd7b67998f48..d0d397bafdf388 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
@@ -21,11 +21,13 @@ public partial class CalliMarshallingMethodThunk : ILStubMethod
private MethodSignature _signature;
public CalliMarshallingMethodThunk(MethodSignature targetSignature, TypeDesc owningType,
- InteropStateManager interopStateManager)
+ InteropStateManager interopStateManager,
+ bool runtimeMarshallingEnabled)
{
_targetSignature = targetSignature;
_owningType = owningType;
_interopStateManager = interopStateManager;
+ RuntimeMarshallingEnabled = runtimeMarshallingEnabled;
}
public MethodSignature TargetSignature
@@ -87,6 +89,8 @@ public override string DiagnosticName
}
}
+ public bool RuntimeMarshallingEnabled { get; }
+
public override PInvokeMetadata GetPInvokeMethodMetadata()
{
// Return PInvokeAttributes.PreserveSig to circumvent marshalling required checks
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
index 276f7dc4a42fcb..5b098630690204 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.cs
@@ -27,6 +27,14 @@ public partial class DelegateMarshallingMethodThunk : ILStubMethod
private readonly MethodDesc _invokeMethod;
private MethodSignature _signature; // signature of the native callable marshalling stub
+ public MethodDesc InvokeMethod
+ {
+ get
+ {
+ return _invokeMethod;
+ }
+ }
+
public DelegateMarshallingMethodThunkKind Kind
{
get;
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
index d77bb5994ec0e5..81245ffe82515a 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
@@ -12,11 +12,6 @@ namespace Internal.IL.Stubs
{
///
/// Provides method bodies for PInvoke methods
- ///
- /// This by no means intends to provide full PInvoke support. The intended use of this is to
- /// a) prevent calls getting generated to targets that require a full marshaller
- /// (this compiler doesn't provide that), and b) offer a hand in some very simple marshalling
- /// situations (but support for this part might go away as the product matures).
///
public struct PInvokeILEmitter
{
@@ -55,23 +50,27 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter
{
MarshalDirection direction = MarshalDirection.Forward;
MethodSignature methodSig;
+ bool runtimeMarshallingEnabled;
switch (targetMethod)
{
case DelegateMarshallingMethodThunk delegateMethod:
methodSig = delegateMethod.DelegateSignature;
direction = delegateMethod.Direction;
+ runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(delegateMethod.DelegateType.Module);
break;
case CalliMarshallingMethodThunk calliMethod:
methodSig = calliMethod.TargetSignature;
+ runtimeMarshallingEnabled = calliMethod.RuntimeMarshallingEnabled;
break;
default:
methodSig = targetMethod.Signature;
+ runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)targetMethod.OwningType).Module);
break;
}
int indexOffset = 0;
if (!methodSig.IsStatic && direction == MarshalDirection.Forward)
{
- // For instance methods(eg. Forward delegate marshalling thunk), first argument is
+ // For instance methods(eg. Forward delegate marshalling thunk), first argument is
// the instance
indexOffset = 1;
}
@@ -88,7 +87,7 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter
// if we don't have metadata for the parameter, create a dummy one
parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null);
}
- else
+ else
{
Debug.Assert(i == parameterMetadataArray[parameterIndex].Index);
parameterMetadata = parameterMetadataArray[parameterIndex++];
@@ -104,7 +103,7 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter
{
// PreserveSig = false can only show up an regular forward PInvokes
Debug.Assert(direction == MarshalDirection.Forward);
-
+
parameterType = methodSig.Context.GetByRefType(parameterType);
isHRSwappedRetVal = true;
}
@@ -114,20 +113,35 @@ private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, Inter
parameterType = methodSig[i - 1];
}
- marshallers[i] = Marshaller.CreateMarshaller(parameterType,
- parameterIndex,
- methodSig.GetEmbeddedSignatureData(),
- MarshallerType.Argument,
- parameterMetadata.MarshalAsDescriptor,
- direction,
- marshallers,
- interopStateManager,
- indexOffset + parameterMetadata.Index,
- flags,
- parameterMetadata.In,
- isHRSwappedRetVal ? true : parameterMetadata.Out,
- isHRSwappedRetVal ? false : parameterMetadata.Return
- );
+ if (runtimeMarshallingEnabled)
+ {
+ marshallers[i] = Marshaller.CreateMarshaller(parameterType,
+ parameterIndex,
+ methodSig.GetEmbeddedSignatureData(),
+ MarshallerType.Argument,
+ parameterMetadata.MarshalAsDescriptor,
+ direction,
+ marshallers,
+ interopStateManager,
+ indexOffset + parameterMetadata.Index,
+ flags,
+ parameterMetadata.In,
+ isHRSwappedRetVal ? true : parameterMetadata.Out,
+ isHRSwappedRetVal ? false : parameterMetadata.Return
+ );
+ }
+ else
+ {
+ marshallers[i] = Marshaller.CreateDisabledMarshaller(
+ parameterType,
+ parameterIndex,
+ MarshallerType.Argument,
+ direction,
+ marshallers,
+ indexOffset + parameterMetadata.Index,
+ flags,
+ parameterMetadata.Return);
+ }
}
return marshallers;
@@ -146,10 +160,10 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn
if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind.ReverseOpenStatic)
{
//
- // For Open static delegates call
+ // For Open static delegates call
// InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer()
// which returns a function pointer. Just call the function pointer and we are done.
- //
+ //
TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1];
for (int i = 1; i < _marshallers.Length; i++)
{
@@ -193,7 +207,7 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn
else if (delegateMethod.Kind == DelegateMarshallingMethodThunkKind
.ForwardNativeFunctionWrapper)
{
- // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, clear the error code before doing P/Invoke
+ // if the SetLastError flag is set in UnmanagedFunctionPointerAttribute, clear the error code before doing P/Invoke
if (_flags.SetLastError)
{
callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
@@ -225,7 +239,7 @@ private void EmitDelegateCall(DelegateMarshallingMethodThunk delegateMethod, PIn
MethodSignatureFlags unmanagedCallingConvention = _flags.UnmanagedCallingConvention;
if (unmanagedCallingConvention == MethodSignatureFlags.None)
unmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConvention;
-
+
MethodSignature nativeSig = new MethodSignature(
MethodSignatureFlags.Static | unmanagedCallingConvention, 0, nativeReturnType, nativeParameterTypes);
@@ -257,9 +271,16 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams)
TypeDesc nativeReturnType = _flags.PreserveSig ? _marshallers[0].NativeParameterType : context.GetWellKnownType(WellKnownType.Int32);
TypeDesc[] nativeParameterTypes = new TypeDesc[isHRSwappedRetVal ? _marshallers.Length : _marshallers.Length - 1];
- // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke
+ bool runtimeMarshallingEnabled = MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module);
+
+ // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke
if (_flags.SetLastError)
{
+ if (!runtimeMarshallingEnabled)
+ {
+ // When runtime marshalling is disabled, we don't support SetLastError
+ throw new NotSupportedException();
+ }
callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastError", null)));
}
@@ -271,6 +292,11 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams)
if (isHRSwappedRetVal)
{
+ if (!runtimeMarshallingEnabled)
+ {
+ // When runtime marshalling is disabled, we don't support HResult-return-swapping
+ throw new NotSupportedException();
+ }
nativeParameterTypes[_marshallers.Length - 1] = _marshallers[0].NativeParameterType;
}
@@ -364,6 +390,9 @@ private void EmitCalli(PInvokeILCodeStreams ilCodeStreams, CalliMarshallingMetho
private MethodIL EmitIL()
{
+ if (_targetMethod.HasCustomAttribute("System.Runtime.InteropServices", "LCIDConversionAttribute"))
+ throw new NotSupportedException();
+
PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams();
ILEmitter emitter = pInvokeILCodeStreams.Emitter;
ILCodeStream marshallingCodestream = pInvokeILCodeStreams.MarshallingCodeStream;
@@ -417,8 +446,8 @@ private MethodIL EmitIL()
return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired());
}
- public static MethodIL EmitIL(MethodDesc method,
- PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration,
+ public static MethodIL EmitIL(MethodDesc method,
+ PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration,
InteropStateManager interopStateManager)
{
try
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs
index 8925f9964b093c..b047f29e9ec64f 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.Aot.cs
@@ -126,7 +126,7 @@ public static MethodIL EmitExceptionBody(string message, MethodDesc method)
TypeSystemContext context = method.Context;
MethodSignature ctorSignature = new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void),
new TypeDesc[] { context.GetWellKnownType(WellKnownType.String) });
- MethodDesc exceptionCtor = method.Context.GetWellKnownType(WellKnownType.Exception).GetKnownMethod(".ctor", ctorSignature);
+ MethodDesc exceptionCtor = InteropTypes.GetMarshalDirectiveException(context).GetKnownMethod(".ctor", ctorSignature);
ILCodeStream codeStream = emitter.NewCodeStream();
codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(message));
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
index f23a4479634a99..d37f44971968b7 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
@@ -5,6 +5,7 @@
using Internal.IL;
using Debug = System.Diagnostics.Debug;
using Internal.IL.Stubs;
+using Internal.TypeSystem.Ecma;
namespace Internal.TypeSystem.Interop
{
@@ -75,6 +76,7 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type,
#if !READYTORUN
case MarshallerKind.Struct:
case MarshallerKind.LayoutClass:
+ Debug.Assert(interopStateManager is not null, "An InteropStateManager is required to look up the native representation of a non-blittable struct or class with layout.");
return interopStateManager.GetStructMarshallingNativeType((MetadataType)type);
#endif
@@ -93,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);
@@ -454,7 +459,7 @@ internal static MarshallerKind GetMarshallerKind(
case NativeTypeKind.Array:
{
if (isField)
- return MarshallerKind.Invalid;
+ return MarshallerKind.FailedTypeLoad;
var arrayType = (ArrayType)type;
@@ -581,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
@@ -844,6 +851,37 @@ private static MarshallerKind GetArrayElementMarshallerKind(
}
}
+ internal static MarshallerKind GetDisabledMarshallerKind(
+ TypeDesc type)
+ {
+ if (type.Category == TypeFlags.Void)
+ {
+ return MarshallerKind.VoidReturn;
+ }
+ else if (type.IsByRef)
+ {
+ // Managed refs are not supported when runtime marshalling is disabled.
+ return MarshallerKind.Invalid;
+ }
+ else if (type.IsPrimitive)
+ {
+ return MarshallerKind.BlittableValue;
+ }
+ else if (type.IsPointer || type.IsFunctionPointer)
+ {
+ return MarshallerKind.BlittableValue;
+ }
+ else if (type.IsValueType)
+ {
+ var defType = (DefType)type;
+ if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields)
+ {
+ return MarshallerKind.BlittableValue;
+ }
+ }
+ return MarshallerKind.Invalid;
+ }
+
internal static bool ShouldCheckForPendingException(TargetDetails target, PInvokeMetadata metadata)
{
if (!target.IsOSX)
@@ -861,5 +899,10 @@ internal static bool ShouldCheckForPendingException(TargetDetails target, PInvok
return metadata.Module.Equals(ObjectiveCLibrary)
&& metadata.Name.StartsWith(ObjectiveCMsgSend);
}
+
+ public static bool IsRuntimeMarshallingEnabled(ModuleDesc module)
+ {
+ return module.Assembly is not EcmaAssembly assembly || !assembly.HasAssemblyCustomAttribute("System.Runtime.CompilerServices", "DisableRuntimeMarshallingAttribute");
+ }
}
}
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/Marshaller.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
index ea0494643a14a5..7b7e3a24d9813a 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
@@ -329,6 +329,44 @@ public static Marshaller CreateMarshaller(TypeDesc parameterType,
return marshaller;
}
+
+ ///
+ /// Create a marshaller
+ ///
+ /// type of the parameter to marshal
+ /// The created Marshaller
+ public static Marshaller CreateDisabledMarshaller(TypeDesc parameterType,
+ int? parameterIndex,
+ MarshallerType marshallerType,
+ MarshalDirection direction,
+ Marshaller[] marshallers,
+ int index,
+ PInvokeFlags flags,
+ bool isReturn)
+ {
+ MarshallerKind marshallerKind = MarshalHelpers.GetDisabledMarshallerKind(parameterType);
+
+ TypeSystemContext context = parameterType.Context;
+ // Create the marshaller based on MarshallerKind
+ Marshaller marshaller = CreateMarshaller(marshallerKind);
+ marshaller.Context = context;
+ marshaller.MarshallerKind = marshallerKind;
+ marshaller.MarshallerType = marshallerType;
+ marshaller.ElementMarshallerKind = MarshallerKind.Unknown;
+ marshaller.ManagedParameterType = parameterType;
+ marshaller.ManagedType = parameterType;
+ marshaller.Return = isReturn;
+ marshaller.IsManagedByRef = false;
+ marshaller.IsNativeByRef = false;
+ marshaller.MarshalDirection = direction;
+ marshaller.MarshalAsDescriptor = null;
+ marshaller.Marshallers = marshallers;
+ marshaller.Index = index;
+ marshaller.PInvokeFlags = flags;
+ marshaller.In = true;
+ marshaller.Out = false;
+ return marshaller;
+ }
#endregion
@@ -1560,7 +1598,7 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)
class AnsiStringMarshaller : Marshaller
{
#if READYTORUN
- const int MAX_LOCAL_BUFFER_LENGTH = 260 + 1; // MAX_PATH + 1
+ const int MAX_LOCAL_BUFFER_LENGTH = 260 + 1; // MAX_PATH + 1
private ILLocalVariable? _localBuffer = null;
#endif
@@ -1597,7 +1635,7 @@ protected override void TransformManagedToNative(ILCodeStream codeStream)
.GetKnownMethod("ConvertToNative", null);
bool bPassByValueInOnly = In && !Out && !IsManagedByRef;
-
+
if (bPassByValueInOnly)
{
var bufSize = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
@@ -1632,7 +1670,7 @@ protected override void TransformManagedToNative(ILCodeStream codeStream)
codeStream.EmitStLoc(bufSize);
// if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
- codeStream.EmitLdc(MAX_LOCAL_BUFFER_LENGTH + 1);
+ codeStream.EmitLdc(MAX_LOCAL_BUFFER_LENGTH + 1);
codeStream.EmitLdLoc(bufSize);
codeStream.Emit(ILOpcode.clt);
codeStream.Emit(ILOpcode.brtrue, noOptimize);
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/Common/TypeSystem/Interop/InteropStateManager.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
index 202fcce90becef..0d594010328e67 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropStateManager.cs
@@ -38,7 +38,7 @@ public InteropStateManager(ModuleDesc generatedAssembly)
//
// Delegate Marshalling Stubs
//
-
+
///
/// Generates marshalling stubs for open static delegates
///
@@ -105,9 +105,9 @@ public PInvokeDelegateWrapper GetPInvokeDelegateWrapper(TypeDesc delegateType)
}
//
- // Struct Marshalling
+ // Struct Marshalling
// To support struct marshalling compiler needs to generate a native type which
- // imitates the original struct being passed to managed side with corresponding
+ // imitates the original struct being passed to managed side with corresponding
// fields of marshalled types. Additionally it needs to generate three thunks
// 1. Managed to Native Thunk: For forward marshalling
// 2. Native to Managed Thunk: For reverse marshalling
@@ -186,9 +186,9 @@ public FieldDesc GetPInvokeLazyFixupField(MethodDesc method)
return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method);
}
- public MethodDesc GetPInvokeCalliStub(MethodSignature signature)
+ public MethodDesc GetPInvokeCalliStub(MethodSignature signature, ModuleDesc moduleContext)
{
- return _pInvokeCalliHashtable.GetOrCreateValue(signature);
+ return _pInvokeCalliHashtable.GetOrCreateValue(new CalliMarshallingMethodThunkKey(signature, MarshalHelpers.IsRuntimeMarshallingEnabled(moduleContext)));
}
private class NativeStructTypeHashtable : LockFreeReaderHashtable
@@ -355,7 +355,7 @@ protected override bool CompareValueToValue(DelegateMarshallingMethodThunk value
protected override DelegateMarshallingMethodThunk CreateValueFromKey(DelegateMarshallingStubHashtableKey key)
{
- return new DelegateMarshallingMethodThunk(key.DelegateType, _owningType,
+ return new DelegateMarshallingMethodThunk(key.DelegateType, _owningType,
_interopStateManager, key.Kind);
}
@@ -478,34 +478,36 @@ public PInvokeLazyFixupFieldHashtable(DefType owningType)
}
}
- private class PInvokeCalliHashtable : LockFreeReaderHashtable
+ private readonly record struct CalliMarshallingMethodThunkKey(MethodSignature Signature, bool RuntimeMarshallingEnabled);
+
+ private class PInvokeCalliHashtable : LockFreeReaderHashtable
{
private readonly InteropStateManager _interopStateManager;
private readonly TypeDesc _owningType;
- protected override int GetKeyHashCode(MethodSignature key)
+ protected override int GetKeyHashCode(CalliMarshallingMethodThunkKey key)
{
return key.GetHashCode();
}
protected override int GetValueHashCode(CalliMarshallingMethodThunk value)
{
- return value.TargetSignature.GetHashCode();
+ return new CalliMarshallingMethodThunkKey(value.TargetSignature, value.RuntimeMarshallingEnabled).GetHashCode();
}
- protected override bool CompareKeyToValue(MethodSignature key, CalliMarshallingMethodThunk value)
+ protected override bool CompareKeyToValue(CalliMarshallingMethodThunkKey key, CalliMarshallingMethodThunk value)
{
- return key.Equals(value.TargetSignature);
+ return key.Signature.Equals(value.TargetSignature) && key.RuntimeMarshallingEnabled == value.RuntimeMarshallingEnabled;
}
protected override bool CompareValueToValue(CalliMarshallingMethodThunk value1, CalliMarshallingMethodThunk value2)
{
- return value1.TargetSignature.Equals(value2.TargetSignature);
+ return value1.TargetSignature.Equals(value2.TargetSignature) && value1.RuntimeMarshallingEnabled == value2.RuntimeMarshallingEnabled;
}
- protected override CalliMarshallingMethodThunk CreateValueFromKey(MethodSignature key)
+ protected override CalliMarshallingMethodThunk CreateValueFromKey(CalliMarshallingMethodThunkKey key)
{
- return new CalliMarshallingMethodThunk(key, _owningType, _interopStateManager);
+ return new CalliMarshallingMethodThunk(key.Signature, _owningType, _interopStateManager, key.RuntimeMarshallingEnabled);
}
public PInvokeCalliHashtable(InteropStateManager interopStateManager, TypeDesc owningType)
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
index 96ffe8868422d1..ac32fbbe54647b 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
@@ -54,6 +54,11 @@ public static MetadataType GetNativeFunctionPointerWrapper(TypeSystemContext con
return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "NativeFunctionPointerWrapper");
}
+ public static MetadataType GetMarshalDirectiveException(TypeSystemContext context)
+ {
+ return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "MarshalDirectiveException");
+ }
+
public static MetadataType GetVariant(TypeSystemContext context)
{
return context.SystemModule.GetKnownType("System.Runtime.InteropServices", "Variant");
diff --git a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
index d1b3d10ed5a3fe..258a005ffdd09f 100644
--- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
+++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs
@@ -2060,7 +2060,7 @@ void ImportLoadField(int token, bool isStatic)
actualThis = StackValue.CreateByRef(actualThis.Type);
var declaredThis = owningType.IsValueType ?
- StackValue.CreateByRef(owningType) : StackValue.CreateObjRef(owningType);
+ StackValue.CreateByRef(owningType, readOnly : true) : StackValue.CreateObjRef(owningType);
CheckIsAssignable(actualThis, declaredThis);
diff --git a/src/coreclr/ToolBox/SOS/CMakeLists.txt b/src/coreclr/tools/SOS/CMakeLists.txt
similarity index 100%
rename from src/coreclr/ToolBox/SOS/CMakeLists.txt
rename to src/coreclr/tools/SOS/CMakeLists.txt
diff --git a/src/coreclr/ToolBox/SOS/DIALib/DIALib.il b/src/coreclr/tools/SOS/DIALib/DIALib.il
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DIALib/DIALib.il
rename to src/coreclr/tools/SOS/DIALib/DIALib.il
diff --git a/src/coreclr/ToolBox/SOS/DIALib/DIALib.ilproj b/src/coreclr/tools/SOS/DIALib/DIALib.ilproj
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DIALib/DIALib.ilproj
rename to src/coreclr/tools/SOS/DIALib/DIALib.ilproj
diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/DacTableGen.csproj b/src/coreclr/tools/SOS/DacTableGen/DacTableGen.csproj
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DacTableGen/DacTableGen.csproj
rename to src/coreclr/tools/SOS/DacTableGen/DacTableGen.csproj
diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/MapSymbolProvider.cs b/src/coreclr/tools/SOS/DacTableGen/MapSymbolProvider.cs
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DacTableGen/MapSymbolProvider.cs
rename to src/coreclr/tools/SOS/DacTableGen/MapSymbolProvider.cs
diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/cvconst.cs b/src/coreclr/tools/SOS/DacTableGen/cvconst.cs
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DacTableGen/cvconst.cs
rename to src/coreclr/tools/SOS/DacTableGen/cvconst.cs
diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/diautil.cs b/src/coreclr/tools/SOS/DacTableGen/diautil.cs
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DacTableGen/diautil.cs
rename to src/coreclr/tools/SOS/DacTableGen/diautil.cs
diff --git a/src/coreclr/ToolBox/SOS/DacTableGen/main.cs b/src/coreclr/tools/SOS/DacTableGen/main.cs
similarity index 100%
rename from src/coreclr/ToolBox/SOS/DacTableGen/main.cs
rename to src/coreclr/tools/SOS/DacTableGen/main.cs
diff --git a/src/coreclr/ToolBox/SOS/Directory.Build.props b/src/coreclr/tools/SOS/Directory.Build.props
similarity index 100%
rename from src/coreclr/ToolBox/SOS/Directory.Build.props
rename to src/coreclr/tools/SOS/Directory.Build.props
diff --git a/src/coreclr/ToolBox/SOS/SOS_README.md b/src/coreclr/tools/SOS/SOS_README.md
similarity index 100%
rename from src/coreclr/ToolBox/SOS/SOS_README.md
rename to src/coreclr/tools/SOS/SOS_README.md
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/GenericCompositionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs
index a4388b4eeb4a96..9857c633784db6 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericCompositionNode.cs
@@ -36,6 +36,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
if (_details.Variance != null)
{
+ sb.Append("__Variance__");
for (int i = 0; i < _details.Variance.Length; i++)
{
sb.Append('_');
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/FeatureSettings.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs
new file mode 100644
index 00000000000000..773c061081e459
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.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.Collections.Generic;
+using System.Xml.XPath;
+using ILLink.Shared;
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ public static class FeatureSettings
+ {
+ public static bool ShouldProcessElement(XPathNavigator nav, IReadOnlyDictionary featureSwitchValues)
+ {
+ var feature = GetAttribute(nav, "feature");
+ if (string.IsNullOrEmpty(feature))
+ return true;
+
+ var value = GetAttribute(nav, "featurevalue");
+ if (string.IsNullOrEmpty(value))
+ {
+ //context.LogError(null, DiagnosticId.XmlFeatureDoesNotSpecifyFeatureValue, documentLocation, feature);
+ return false;
+ }
+
+ if (!bool.TryParse(value, out bool bValue))
+ {
+ //context.LogError(null, DiagnosticId.XmlUnsupportedNonBooleanValueForFeature, documentLocation, feature);
+ return false;
+ }
+
+ var isDefault = GetAttribute(nav, "featuredefault");
+ bool bIsDefault = false;
+ if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault))
+ {
+ //context.LogError(null, DiagnosticId.XmlDocumentLocationHasInvalidFeatureDefault, documentLocation);
+ return false;
+ }
+
+ if (!featureSwitchValues.TryGetValue(feature, out bool featureSetting))
+ return bIsDefault;
+
+ return bValue == featureSetting;
+ }
+
+ public static string GetAttribute(XPathNavigator nav, string attribute)
+ {
+ return nav.GetAttribute(attribute, String.Empty);
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs
index 5f06913b97d37b..20050db2c8cdab 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs
@@ -792,7 +792,7 @@ public MethodIL EmitIL(MethodDesc method)
}
}
- private class SubstitutionsReader : ProcessLinkerXmlBase
+ private class SubstitutionsReader : ProcessXmlBase
{
private readonly Dictionary _methodSubstitutions;
private readonly Dictionary _fieldSubstitutions;
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/ManifestResourceBlockingPolicy.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs
index f9df59bfa816fb..3b2b3a2e25384b 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ManifestResourceBlockingPolicy.cs
@@ -100,7 +100,7 @@ public AssemblyFeatureInfo(EcmaModule module, IReadOnlyDictionary
}
}
- private class SubstitutionsReader : ProcessLinkerXmlBase
+ private class SubstitutionsReader : ProcessXmlBase
{
private readonly HashSet _substitutions = new HashSet();
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs
index c5101bde818fa3..e157381162aa51 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs
@@ -1,316 +1,511 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
using System.Reflection;
+using System.Reflection.Metadata;
using System.Text;
+using System.Text.RegularExpressions;
using System.Xml;
-
+using System.Xml.Linq;
+using System.Xml.XPath;
+using ILLink.Shared;
using Internal.TypeSystem;
+#nullable enable
+
namespace ILCompiler
{
- ///
- /// Base class for readers of IL Linker XML file format.
- ///
- internal abstract class ProcessLinkerXmlBase
+ [Flags]
+ public enum AllowedAssemblies
{
- private readonly XmlReader _reader;
- private readonly ModuleDesc _owningModule;
+ ContainingAssembly = 0x1,
+ AnyAssembly = 0x2 | ContainingAssembly,
+ AllAssemblies = 0x4 | AnyAssembly
+ }
+
+ public abstract class ProcessLinkerXmlBase
+ {
+ const string FullNameAttributeName = "fullname";
+ const string LinkerElementName = "linker";
+ const string TypeElementName = "type";
+ const string SignatureAttributeName = "signature";
+ const string NameAttributeName = "name";
+ const string FieldElementName = "field";
+ const string MethodElementName = "method";
+ const string EventElementName = "event";
+ const string PropertyElementName = "property";
+ const string AllAssembliesFullName = "*";
+ protected const string XmlNamespace = "";
+
+ protected readonly string _xmlDocumentLocation;
+ readonly XPathNavigator _document;
+ protected readonly ModuleDesc? _owningModule;
private readonly IReadOnlyDictionary _featureSwitchValues;
protected readonly TypeSystemContext _context;
- public ProcessLinkerXmlBase(TypeSystemContext context, XmlReader reader, ModuleDesc owningModule, IReadOnlyDictionary featureSwitchValues)
+ protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues)
{
- _reader = reader;
- _owningModule = owningModule;
- _featureSwitchValues = featureSwitchValues;
_context = context;
+ using (documentStream)
+ {
+ _document = XDocument.Load(documentStream, LoadOptions.SetLineInfo).CreateNavigator();
+ }
+ _xmlDocumentLocation = xmlDocumentLocation;
+ _featureSwitchValues = featureSwitchValues;
}
- public void ProcessXml()
+ protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues)
+ : this(context, documentStream, xmlDocumentLocation, featureSwitchValues)
{
- if (_reader.IsStartElement() && _reader.Name == "linker")
+ _owningModule = resourceAssembly ?? throw new ArgumentNullException(nameof(resourceAssembly));
+ }
+
+ protected virtual bool ShouldProcessElement(XPathNavigator nav) => FeatureSettings.ShouldProcessElement(nav, _featureSwitchValues);
+
+ protected virtual void ProcessXml(bool ignoreResource)
+ {
+ if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly) && _owningModule == null)
+ throw new InvalidOperationException("The containing assembly must be specified for XML which is restricted to modifying that assembly only.");
+
+ try
{
- if (!ShouldProcessElement())
+ XPathNavigator nav = _document.CreateNavigator();
+
+ // Initial structure check - ignore XML document which don't look like linker XML format
+ if (!nav.MoveToChild(LinkerElementName, XmlNamespace))
+ return;
+
+ if (_owningModule != null)
+ {
+ if (ignoreResource)
+ return;
+ }
+
+ if (!ShouldProcessElement(nav))
return;
- _reader.Read();
+ ProcessAssemblies(nav);
- ProcessAssemblies();
+ // For embedded XML, allow not specifying the assembly explicitly in XML.
+ if (_owningModule != null)
+ ProcessAssembly(_owningModule, nav, warnOnUnresolvedTypes: true);
+
+ }
+ catch (Exception ex)
+ {
+ // throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.ErrorProcessingXmlLocation, _xmlDocumentLocation), ex);
+ throw ex;
}
}
- protected string GetAttribute(string attribute)
- {
- return _reader.GetAttribute(attribute);
- }
+ protected virtual AllowedAssemblies AllowedAssemblySelector { get => _owningModule != null ? AllowedAssemblies.ContainingAssembly : AllowedAssemblies.AnyAssembly; }
- protected bool IsEmpty()
+ bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyName? assemblyName)
{
- return _reader.IsEmptyElement;
+ assemblyName = null;
+ if (GetFullName(nav) == AllAssembliesFullName)
+ return true;
+
+ assemblyName = GetAssemblyName(nav);
+ return false;
}
- private void ProcessAssemblies()
+ protected virtual void ProcessAssemblies(XPathNavigator nav)
{
- while (_reader.IsStartElement())
+ foreach (XPathNavigator assemblyNav in nav.SelectChildren("assembly", ""))
{
- if (_reader.Name == "assembly")
+ // Errors for invalid assembly names should show up even if this element will be
+ // skipped due to feature conditions.
+ bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyName? name);
+ if (processAllAssemblies && AllowedAssemblySelector != AllowedAssemblies.AllAssemblies)
{
- string assemblyName = _reader.GetAttribute("fullname");
+ //LogWarning(assemblyNav, DiagnosticId.XmlUnsuportedWildcard);
+ continue;
+ }
- if (assemblyName == "*")
+ ModuleDesc? assemblyToProcess = null;
+ if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly))
+ {
+ Debug.Assert(!processAllAssemblies);
+ Debug.Assert(_owningModule != null);
+ if (_owningModule.Assembly.GetName().Name != name!.Name)
{
- // https://github.com/dotnet/runtimelab/issues/1381
- _reader.Skip();
+ //LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _resource.Value.Assembly.Name.Name, name.ToString());
continue;
}
+ assemblyToProcess = _owningModule;
+ }
- // Errors for invalid assembly names should show up even if this element will be
- // skipped due to feature conditions.
- var name = new AssemblyName(assemblyName);
+ if (!ShouldProcessElement(assemblyNav))
+ continue;
- if (!ShouldProcessElement())
- {
- _reader.Skip();
- continue;
- }
-
- ModuleDesc assembly = GetAssembly(name);
+ if (processAllAssemblies)
+ {
+ throw new NotImplementedException();
+ // We could avoid loading all references in this case: https://github.com/dotnet/linker/issues/1708
+ //foreach (ModuleDesc assembly in GetReferencedAssemblies())
+ // ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: false);
+ }
+ else
+ {
+ Debug.Assert(!processAllAssemblies);
+ ModuleDesc? assembly = assemblyToProcess ?? _context.ResolveAssembly(name!);
if (assembly == null)
{
- //Context.LogWarning($"Could not resolve assembly '{name.Name}'", 2007, _xmlDocumentLocation);
- _reader.Skip();
+ //LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name);
continue;
}
- _reader.Read();
-
- ProcessAssembly(assembly);
- }
- else if (_reader.Name == "type")
- {
- ProcessType(_owningModule);
- }
- else if (_reader.Name == "resource")
- {
- ProcessResource(_owningModule);
- }
- else
- {
- _reader.Skip();
+ ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: true);
}
}
}
- protected ModuleDesc GetAssembly(AssemblyName name)
- {
- return _context.ResolveAssembly(name);
- }
- private void ProcessAssembly(ModuleDesc assembly)
+ protected abstract void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes);
+
+ protected virtual void ProcessTypes(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
{
- while (_reader.IsStartElement())
+ foreach (XPathNavigator typeNav in nav.SelectChildren(TypeElementName, XmlNamespace))
{
- if (_reader.Name == "type")
+
+ if (!ShouldProcessElement(typeNav))
+ continue;
+
+ string fullname = GetFullName(typeNav);
+
+ if (fullname.IndexOf("*") != -1)
{
- ProcessType(assembly);
+ if (ProcessTypePattern(fullname, assembly, typeNav))
+ continue;
}
- else if (_reader.Name == "resource")
+
+ // TODO: Process exported types
+
+ // TODO: Semantics differ and xml format is cecil specific, therefore they are discrepancies on things like nested types
+ TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, fullname, throwIfNotFound: false);
+
+ if (type == null)
{
- ProcessResource(assembly);
+ //if (warnOnUnresolvedTypes)
+ // LogWarning(typeNav, DiagnosticId.XmlCouldNotResolveType, fullname);
+ continue;
}
- _reader.Skip();
+ ProcessType(type, typeNav);
}
+ }
+
+ void MatchType(TypeDesc type, Regex regex, XPathNavigator nav)
+ {
+ StringBuilder sb = new StringBuilder();
+ CecilTypeNameFormatter.Instance.AppendName(sb, type);
+ if (regex.Match(sb.ToString()).Success)
+ ProcessType(type, nav);
+ }
- _reader.ReadEndElement();
+ protected virtual bool ProcessTypePattern(string fullname, ModuleDesc assembly, XPathNavigator nav)
+ {
+ Regex regex = new Regex(fullname.Replace(".", @"\.").Replace("*", "(.*)"));
+
+ foreach (TypeDesc type in assembly.GetAllTypes())
+ MatchType(type, regex, nav);
+
+ return true;
}
- private void ProcessType(ModuleDesc assembly)
+ protected abstract void ProcessType(TypeDesc type, XPathNavigator nav);
+
+ protected void ProcessTypeChildren(TypeDesc type, XPathNavigator nav, object? customData = null)
{
- if (ShouldProcessElement())
+ if (nav.HasChildren)
{
- string typeName = _reader.GetAttribute("fullname");
+ ProcessSelectedFields(nav, type);
+ ProcessSelectedMethods(nav, type, customData);
+ // TODO: In order to be compatible with the format we need to be able to recognize properties, events and maybe attributes
+ }
+ }
- if (typeName.Contains('*'))
- throw new NotSupportedException();
+ void ProcessSelectedFields(XPathNavigator nav, TypeDesc type)
+ {
+ foreach (XPathNavigator fieldNav in nav.SelectChildren(FieldElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(fieldNav))
+ continue;
+ ProcessField(type, fieldNav);
+ }
+ }
- TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, typeName, throwIfNotFound: false);
- if (type == null)
+ protected virtual void ProcessField(TypeDesc type, XPathNavigator nav)
+ {
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
+ {
+ FieldDesc? field = GetField(type, signature);
+ if (field == null)
{
- //Context.LogWarning ($"Could not resolve type '{fullname}'", 2008, _xmlDocumentLocation);
- _reader.Skip();
+ //LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, signature, type.GetDisplayName());
return;
}
- _reader.Read();
+ ProcessField(type, field, nav);
+ }
- while (_reader.IsStartElement())
+ string name = GetName(nav);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ foreach (FieldDesc field in type.GetFields())
{
- if (_reader.Name == "method")
- {
- ProcessMethod(type);
- }
- else if (_reader.Name == "field")
+ if (field.Name == name)
{
- ProcessField(type);
- }
- else if (_reader.Name == "attribute")
- {
- ProcessAttribute(type);
+ foundMatch = true;
+ ProcessField(type, field, nav);
}
+ }
+
- _reader.Skip();
+ if (!foundMatch)
+ {
+ // LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName());
}
}
+ }
+
+ protected static FieldDesc? GetField(TypeDesc type, string signature)
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (FieldDesc field in type.GetFields())
+ {
+ sb.Clear();
+ CecilTypeNameFormatter.Instance.AppendName(sb, field.FieldType);
+ if (signature == sb.ToString() + " " + field.Name)
+ return field;
+ }
+
+ return null;
+ }
+
+ protected virtual void ProcessField(TypeDesc type, FieldDesc field, XPathNavigator nav) { }
- _reader.Skip();
+ void ProcessSelectedMethods(XPathNavigator nav, TypeDesc type, object? customData)
+ {
+ foreach (XPathNavigator methodNav in nav.SelectChildren(MethodElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(methodNav))
+ continue;
+ ProcessMethod(type, methodNav, customData);
+ }
}
- private void ProcessMethod(TypeDesc type)
+ protected virtual void ProcessMethod(TypeDesc type, XPathNavigator nav, object? customData)
{
- if (ShouldProcessElement())
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
{
- string signature = _reader.GetAttribute("signature");
- if (!String.IsNullOrEmpty(signature))
+ MethodDesc? method = GetMethod(type, signature);
+ if (method == null)
{
- MethodDesc method = GetMethod(type, signature);
- if (method == null)
- {
- //Context.LogWarning($"Could not find method '{signature}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation);
- return;
- }
-
- ProcessMethod(method);
+ //LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName());
+ return;
}
- string methodName = _reader.GetAttribute("name");
- if (!String.IsNullOrEmpty(methodName))
- {
- bool foundMatch = false;
- foreach (MethodDesc method in type.GetMethods())
- {
- if (method.Name == methodName)
- {
- foundMatch = true;
- ProcessMethod(method);
- }
- }
+ ProcessMethod(type, method, nav, customData);
+ }
- if (!foundMatch)
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ foreach (MethodDesc method in type.GetAllMethods())
+ {
+ if (name == method.Name)
{
- //Context.LogWarning($"Could not find method '{name}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation);
+ foundMatch = true;
+ ProcessMethod(type, method, nav, customData);
}
}
+ if (!foundMatch)
+ {
+ // LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, name, type.GetDisplayName());
+ }
}
}
- protected virtual void ProcessMethod(MethodDesc method)
+ protected virtual MethodDesc? GetMethod(TypeDesc type, string signature) => null;
+
+ protected virtual void ProcessMethod(TypeDesc type, MethodDesc method, XPathNavigator nav, object? customData) { }
+
+#if false
+ void ProcessSelectedEvents(XPathNavigator nav, TypeDefinition type, object? customData)
{
+ foreach (XPathNavigator eventNav in nav.SelectChildren(EventElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(eventNav))
+ continue;
+ ProcessEvent(type, eventNav, customData);
+ }
}
- private void ProcessField(TypeDesc type)
+ protected virtual void ProcessEvent(TypeDefinition type, XPathNavigator nav, object? customData)
{
- if (ShouldProcessElement())
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
{
- string fieldName = _reader.GetAttribute("name");
- if (!String.IsNullOrEmpty(fieldName))
+ EventDefinition? @event = GetEvent(type, signature);
+ if (@event == null)
{
- FieldDesc field = type.GetField(fieldName);
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, signature, type.GetDisplayName());
+ return;
+ }
- if (field == null)
- {
- //Context.LogWarning($"Could not find field '{name}' on type '{type.GetDisplayName()}'", 2012, _xmlDocumentLocation);
- }
- else
+ ProcessEvent(type, @event, nav, customData);
+ }
+
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ foreach (EventDefinition @event in type.Events)
+ {
+ if (@event.Name == name)
{
- ProcessField(field);
+ foundMatch = true;
+ ProcessEvent(type, @event, nav, customData);
}
}
+
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, name, type.GetDisplayName());
+ }
}
}
- protected virtual void ProcessField(FieldDesc field)
+ protected static EventDefinition? GetEvent(TypeDefinition type, string signature)
{
- }
+ if (!type.HasEvents)
+ return null;
- protected virtual void ProcessAttribute(TypeDesc type)
- {
- }
+ foreach (EventDefinition @event in type.Events)
+ if (signature == @event.EventType.FullName + " " + @event.Name)
+ return @event;
- protected virtual void ProcessResource(ModuleDesc module)
- {
+ return null;
}
- protected MethodDesc GetMethod(TypeDesc type, string signature)
- {
- foreach (MethodDesc meth in type.GetMethods())
- if (signature == GetMethodSignature(meth, false))
- return meth;
+ protected virtual void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { }
- return null;
+ void ProcessSelectedProperties(XPathNavigator nav, TypeDefinition type, object? customData)
+ {
+ foreach (XPathNavigator propertyNav in nav.SelectChildren(PropertyElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(propertyNav))
+ continue;
+ ProcessProperty(type, propertyNav, customData);
+ }
}
- public static string GetMethodSignature(MethodDesc meth, bool includeGenericParameters)
+ protected virtual void ProcessProperty(TypeDefinition type, XPathNavigator nav, object? customData)
{
- StringBuilder sb = new StringBuilder();
- CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature.ReturnType);
- sb.Append(' ');
- sb.Append(meth.Name);
- if (includeGenericParameters && meth.HasInstantiation)
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
{
- sb.Append('`');
- sb.Append(meth.Instantiation.Length);
+ PropertyDefinition? property = GetProperty(type, signature);
+ if (property == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ ProcessProperty(type, property, nav, customData, true);
}
- sb.Append('(');
- for (int i = 0; i < meth.Signature.Length; i++)
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
{
- if (i > 0)
- sb.Append(',');
+ bool foundMatch = false;
+ foreach (PropertyDefinition property in type.Properties)
+ {
+ if (property.Name == name)
+ {
+ foundMatch = true;
+ ProcessProperty(type, property, nav, customData, false);
+ }
+ }
- CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature[i]);
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, name, type.GetDisplayName());
+ }
}
+ }
+
+ protected static PropertyDefinition? GetProperty(TypeDefinition type, string signature)
+ {
+ if (!type.HasProperties)
+ return null;
+
+ foreach (PropertyDefinition property in type.Properties)
+ if (signature == property.PropertyType.FullName + " " + property.Name)
+ return property;
- sb.Append(')');
- return sb.ToString();
+ return null;
}
- private bool ShouldProcessElement()
+ protected virtual void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) { }
+#endif
+
+ protected virtual AssemblyName GetAssemblyName(XPathNavigator nav)
{
- string feature = _reader.GetAttribute("feature");
- if (string.IsNullOrEmpty(feature))
- return true;
+ return new AssemblyName(GetFullName(nav));
+ }
- string value = _reader.GetAttribute("featurevalue");
- if (string.IsNullOrEmpty(value))
- {
- //context.LogError($"Failed to process '{documentLocation}'. Feature '{feature}' does not specify a 'featurevalue' attribute", 1001);
- return false;
- }
+ protected static string GetFullName(XPathNavigator nav)
+ {
+ return GetAttribute(nav, FullNameAttributeName);
+ }
- if (!bool.TryParse(value, out bool bValue))
- {
- //context.LogError($"Failed to process '{documentLocation}'. Unsupported non-boolean feature definition '{feature}'", 1002);
- return false;
- }
+ protected static string GetName(XPathNavigator nav)
+ {
+ return GetAttribute(nav, NameAttributeName);
+ }
- var isDefault = _reader.GetAttribute("featuredefault");
- bool bIsDefault = false;
- if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault))
- {
- //context.LogError($"Failed to process '{documentLocation}'. Unsupported value for featuredefault attribute", 1014);
- return false;
- }
+ protected static string GetSignature(XPathNavigator nav)
+ {
+ return GetAttribute(nav, SignatureAttributeName);
+ }
- if (!_featureSwitchValues.TryGetValue(feature, out bool featureSetting))
- return bIsDefault;
+ protected static string GetAttribute(XPathNavigator nav, string attribute)
+ {
+ return nav.GetAttribute(attribute, XmlNamespace);
+ }
- return bValue == featureSetting;
+#if false
+ protected MessageOrigin GetMessageOriginForPosition(XPathNavigator position)
+ {
+ return (position is IXmlLineInfo lineInfo)
+ ? new MessageOrigin(_xmlDocumentLocation, lineInfo.LineNumber, lineInfo.LinePosition, _resource?.Assembly)
+ : new MessageOrigin(_xmlDocumentLocation, 0, 0, _resource?.Assembly);
+ }
+ protected void LogWarning(string message, int warningCode, XPathNavigator position)
+ {
+ _context.LogWarning(message, warningCode, GetMessageOriginForPosition(position));
+ }
+
+ protected void LogWarning(XPathNavigator position, DiagnosticId id, params string[] args)
+ {
+ _context.LogWarning(GetMessageOriginForPosition(position), id, args);
}
+#endif
class CecilTypeNameFormatter : TypeNameFormatter
{
@@ -399,6 +594,106 @@ protected override void AppendNameForNestedType(StringBuilder sb, DefType nested
sb.Append('/');
sb.Append(nestedType.Name);
}
+
+#if false
+ public bool TryConvertValue(string value, TypeDesc type, out object? result)
+ {
+ switch (type.UnderlyingType.Category)
+ {
+ case TypeFlags.Boolean:
+ if ((bool.TryParse(value, out bool bvalue)))
+ {
+ result = bvalue ? 1 : 0;
+ return true;
+ }
+ else
+ goto case TypeFlags.Int32;
+
+ case TypeFlags.Byte:
+ if (!byte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out byte byteresult))
+ break;
+
+ result = (int)byteresult;
+ return true;
+
+ case TypeFlags.SByte:
+ if (!sbyte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out sbyte sbyteresult))
+ break;
+
+ result = (int)sbyteresult;
+ return true;
+
+ case TypeFlags.Int16:
+ if (!short.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out short shortresult))
+ break;
+
+ result = (int)shortresult;
+ return true;
+
+ case TypeFlags.UInt16:
+ if (!ushort.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort ushortresult))
+ break;
+
+ result = (int)ushortresult;
+ return true;
+
+ case TypeFlags.Int32:
+ if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult))
+ break;
+
+ result = iresult;
+ return true;
+
+ case TypeFlags.UInt32:
+ if (!uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint uresult))
+ break;
+
+ result = (int)uresult;
+ return true;
+
+ case TypeFlags.Double:
+ if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out double dresult))
+ break;
+
+ result = dresult;
+ return true;
+
+ case TypeFlags.Single:
+ if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fresult))
+ break;
+
+ result = fresult;
+ return true;
+
+ case TypeFlags.Int64:
+ if (!long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long lresult))
+ break;
+
+ result = lresult;
+ return true;
+
+ case TypeFlags.UInt64:
+ if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong ulresult))
+ break;
+
+ result = (long)ulresult;
+ return true;
+
+ case TypeFlags.Char:
+ if (!char.TryParse(value, out char chresult))
+ break;
+
+ result = (int)chresult;
+ return true;
+
+ default:
+ throw new NotSupportedException(type.ToString());
+ }
+
+ result = null;
+ return false;
+ }
+#endif
}
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs
new file mode 100644
index 00000000000000..b00f56a0c2ce47
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessXmlBase.cs
@@ -0,0 +1,404 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ ///
+ /// Base class for readers of IL Linker XML file format.
+ ///
+ internal abstract class ProcessXmlBase
+ {
+ private readonly XmlReader _reader;
+ private readonly ModuleDesc _owningModule;
+ private readonly IReadOnlyDictionary _featureSwitchValues;
+ protected readonly TypeSystemContext _context;
+
+ public ProcessXmlBase(TypeSystemContext context, XmlReader reader, ModuleDesc owningModule, IReadOnlyDictionary featureSwitchValues)
+ {
+ _reader = reader;
+ _owningModule = owningModule;
+ _featureSwitchValues = featureSwitchValues;
+ _context = context;
+ }
+
+ public void ProcessXml()
+ {
+ if (_reader.IsStartElement() && _reader.Name == "linker")
+ {
+ if (!ShouldProcessElement())
+ return;
+
+ _reader.Read();
+
+ ProcessAssemblies();
+ }
+ }
+
+ protected string GetAttribute(string attribute)
+ {
+ return _reader.GetAttribute(attribute);
+ }
+
+ protected bool IsEmpty()
+ {
+ return _reader.IsEmptyElement;
+ }
+
+ private void ProcessAssemblies()
+ {
+ while (_reader.IsStartElement())
+ {
+ if (_reader.Name == "assembly")
+ {
+ string assemblyName = _reader.GetAttribute("fullname");
+
+ if (assemblyName == "*")
+ {
+ // https://github.com/dotnet/runtimelab/issues/1381
+ _reader.Skip();
+ continue;
+ }
+
+ // Errors for invalid assembly names should show up even if this element will be
+ // skipped due to feature conditions.
+ var name = new AssemblyName(assemblyName);
+
+ if (!ShouldProcessElement())
+ {
+ _reader.Skip();
+ continue;
+ }
+
+ ModuleDesc assembly = GetAssembly(name);
+
+ if (assembly == null)
+ {
+ //Context.LogWarning($"Could not resolve assembly '{name.Name}'", 2007, _xmlDocumentLocation);
+ _reader.Skip();
+ continue;
+ }
+
+ _reader.Read();
+
+ ProcessAssembly(assembly);
+ }
+ else if (_reader.Name == "type")
+ {
+ ProcessType(_owningModule);
+ }
+ else if (_reader.Name == "resource")
+ {
+ ProcessResource(_owningModule);
+ }
+ else
+ {
+ _reader.Skip();
+ }
+ }
+ }
+
+ protected ModuleDesc GetAssembly(AssemblyName name)
+ {
+ return _context.ResolveAssembly(name);
+ }
+
+ private void ProcessAssembly(ModuleDesc assembly)
+ {
+ while (_reader.IsStartElement())
+ {
+ if (_reader.Name == "type")
+ {
+ ProcessType(assembly);
+ }
+ else if (_reader.Name == "resource")
+ {
+ ProcessResource(assembly);
+ }
+
+ _reader.Skip();
+ }
+
+ _reader.ReadEndElement();
+ }
+
+ private void ProcessType(ModuleDesc assembly)
+ {
+ if (ShouldProcessElement())
+ {
+ string typeName = _reader.GetAttribute("fullname");
+
+ if (typeName.Contains('*'))
+ throw new NotSupportedException();
+
+ TypeDesc type = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeName(assembly, typeName, throwIfNotFound: false);
+ if (type == null)
+ {
+ //Context.LogWarning ($"Could not resolve type '{fullname}'", 2008, _xmlDocumentLocation);
+ _reader.Skip();
+ return;
+ }
+
+ _reader.Read();
+
+ while (_reader.IsStartElement())
+ {
+ if (_reader.Name == "method")
+ {
+ ProcessMethod(type);
+ }
+ else if (_reader.Name == "field")
+ {
+ ProcessField(type);
+ }
+ else if (_reader.Name == "attribute")
+ {
+ ProcessAttribute(type);
+ }
+
+ _reader.Skip();
+ }
+ }
+
+ _reader.Skip();
+ }
+
+ private void ProcessMethod(TypeDesc type)
+ {
+ if (ShouldProcessElement())
+ {
+ string signature = _reader.GetAttribute("signature");
+ if (!String.IsNullOrEmpty(signature))
+ {
+ MethodDesc method = GetMethod(type, signature);
+ if (method == null)
+ {
+ //Context.LogWarning($"Could not find method '{signature}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation);
+ return;
+ }
+
+ ProcessMethod(method);
+ }
+
+ string methodName = _reader.GetAttribute("name");
+ if (!String.IsNullOrEmpty(methodName))
+ {
+ bool foundMatch = false;
+ foreach (MethodDesc method in type.GetMethods())
+ {
+ if (method.Name == methodName)
+ {
+ foundMatch = true;
+ ProcessMethod(method);
+ }
+ }
+
+ if (!foundMatch)
+ {
+ //Context.LogWarning($"Could not find method '{name}' on type '{type.GetDisplayName()}'", 2009, _xmlDocumentLocation);
+ }
+ }
+ }
+ }
+
+ protected virtual void ProcessMethod(MethodDesc method)
+ {
+ }
+
+ private void ProcessField(TypeDesc type)
+ {
+ if (ShouldProcessElement())
+ {
+ string fieldName = _reader.GetAttribute("name");
+ if (!String.IsNullOrEmpty(fieldName))
+ {
+ FieldDesc field = type.GetField(fieldName);
+
+ if (field == null)
+ {
+ //Context.LogWarning($"Could not find field '{name}' on type '{type.GetDisplayName()}'", 2012, _xmlDocumentLocation);
+ }
+ else
+ {
+ ProcessField(field);
+ }
+ }
+ }
+ }
+
+ protected virtual void ProcessField(FieldDesc field)
+ {
+ }
+
+ protected virtual void ProcessAttribute(TypeDesc type)
+ {
+ }
+
+ protected virtual void ProcessResource(ModuleDesc module)
+ {
+ }
+
+ protected MethodDesc GetMethod(TypeDesc type, string signature)
+ {
+ foreach (MethodDesc meth in type.GetMethods())
+ if (signature == GetMethodSignature(meth, false))
+ return meth;
+
+ return null;
+ }
+
+ public static string GetMethodSignature(MethodDesc meth, bool includeGenericParameters)
+ {
+ StringBuilder sb = new StringBuilder();
+ CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature.ReturnType);
+ sb.Append(' ');
+ sb.Append(meth.Name);
+ if (includeGenericParameters && meth.HasInstantiation)
+ {
+ sb.Append('`');
+ sb.Append(meth.Instantiation.Length);
+ }
+
+ sb.Append('(');
+ for (int i = 0; i < meth.Signature.Length; i++)
+ {
+ if (i > 0)
+ sb.Append(',');
+
+ CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature[i]);
+ }
+
+ sb.Append(')');
+ return sb.ToString();
+ }
+
+ private bool ShouldProcessElement()
+ {
+ string feature = _reader.GetAttribute("feature");
+ if (string.IsNullOrEmpty(feature))
+ return true;
+
+ string value = _reader.GetAttribute("featurevalue");
+ if (string.IsNullOrEmpty(value))
+ {
+ //context.LogError($"Failed to process '{documentLocation}'. Feature '{feature}' does not specify a 'featurevalue' attribute", 1001);
+ return false;
+ }
+
+ if (!bool.TryParse(value, out bool bValue))
+ {
+ //context.LogError($"Failed to process '{documentLocation}'. Unsupported non-boolean feature definition '{feature}'", 1002);
+ return false;
+ }
+
+ var isDefault = _reader.GetAttribute("featuredefault");
+ bool bIsDefault = false;
+ if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault))
+ {
+ //context.LogError($"Failed to process '{documentLocation}'. Unsupported value for featuredefault attribute", 1014);
+ return false;
+ }
+
+ if (!_featureSwitchValues.TryGetValue(feature, out bool featureSetting))
+ return bIsDefault;
+
+ return bValue == featureSetting;
+ }
+
+ class CecilTypeNameFormatter : TypeNameFormatter
+ {
+ public static readonly CecilTypeNameFormatter Instance = new CecilTypeNameFormatter();
+
+ public override void AppendName(StringBuilder sb, ArrayType type)
+ {
+ AppendName(sb, type.ElementType);
+ sb.Append('[');
+ if (type.Rank > 1)
+ sb.Append(new string(',', type.Rank - 1));
+ sb.Append(']');
+ }
+ public override void AppendName(StringBuilder sb, ByRefType type)
+ {
+ AppendName(sb, type.ParameterType);
+ sb.Append('&');
+ }
+
+ public override void AppendName(StringBuilder sb, PointerType type)
+ {
+ AppendName(sb, type.ParameterType);
+ sb.Append('*');
+ }
+
+ public override void AppendName(StringBuilder sb, FunctionPointerType type)
+ {
+ sb.Append(" ");
+ AppendName(sb, type.Signature.ReturnType);
+ sb.Append(" *");
+
+ sb.Append("(");
+
+ for (int i = 0; i < type.Signature.Length; i++)
+ {
+ var parameter = type.Signature[i];
+ if (i > 0)
+ sb.Append(",");
+
+ AppendName(sb, parameter);
+ }
+
+ sb.Append(")");
+ }
+
+ public override void AppendName(StringBuilder sb, GenericParameterDesc type)
+ {
+ sb.Append(type.Name);
+ }
+ public override void AppendName(StringBuilder sb, SignatureMethodVariable type)
+ {
+ }
+ public override void AppendName(StringBuilder sb, SignatureTypeVariable type)
+ {
+ }
+ protected override void AppendNameForInstantiatedType(StringBuilder sb, DefType type)
+ {
+ AppendName(sb, type.GetTypeDefinition());
+
+ sb.Append('<');
+
+ for (int i = 0; i < type.Instantiation.Length; i++)
+ {
+ if (i != 0)
+ sb.Append(',');
+
+ AppendName(sb, type.Instantiation[i]);
+ }
+
+ sb.Append('>');
+ }
+ protected override void AppendNameForNamespaceType(StringBuilder sb, DefType type)
+ {
+ if (!String.IsNullOrEmpty(type.Namespace))
+ {
+ sb.Append(type.Namespace);
+ sb.Append('.');
+ }
+
+ sb.Append(type.Name);
+ }
+
+ protected override void AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType)
+ {
+ AppendName(sb, containingType);
+ sb.Append('/');
+ sb.Append(nestedType.Name);
+ }
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs
new file mode 100644
index 00000000000000..403eb9207342e5
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Xml.XPath;
+using ILLink.Shared;
+using Mono.Cecil;
+
+namespace Mono.Linker.Steps
+{
+ public class BodySubstitutionParser : ProcessLinkerXmlBase
+ {
+ SubstitutionInfo? _substitutionInfo;
+
+ public BodySubstitutionParser(LinkContext context, Stream documentStream, string xmlDocumentLocation)
+ : base(context, documentStream, xmlDocumentLocation)
+ {
+ }
+
+ public BodySubstitutionParser(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "")
+ : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation)
+ {
+ }
+
+ public void Parse(SubstitutionInfo xmlInfo)
+ {
+ _substitutionInfo = xmlInfo;
+ bool stripSubstitutions = _context.IsOptimizationEnabled(CodeOptimizations.RemoveSubstitutions, _resource?.Assembly);
+ ProcessXml(stripSubstitutions, _context.IgnoreSubstitutions);
+ }
+
+ protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
+ {
+ ProcessTypes(assembly, nav, warnOnUnresolvedTypes);
+ ProcessResources(assembly, nav);
+ }
+
+ protected override TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => null;
+
+ protected override bool ProcessTypePattern(string fullname, AssemblyDefinition assembly, XPathNavigator nav) => false;
+
+ protected override void ProcessType(TypeDefinition type, XPathNavigator nav)
+ {
+ Debug.Assert(ShouldProcessElement(nav));
+ ProcessTypeChildren(type, nav);
+ }
+
+ protected override void ProcessMethod(TypeDefinition type, XPathNavigator methodNav, object? _customData)
+ {
+ Debug.Assert(_substitutionInfo != null);
+ string signature = GetSignature(methodNav);
+ if (string.IsNullOrEmpty(signature))
+ return;
+
+ MethodDefinition? method = FindMethod(type, signature);
+ if (method == null)
+ {
+ LogWarning(methodNav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ string action = GetAttribute(methodNav, "body");
+ switch (action)
+ {
+ case "remove":
+ _substitutionInfo.SetMethodAction(method, MethodAction.ConvertToThrow);
+ return;
+ case "stub":
+ string value = GetAttribute(methodNav, "value");
+ if (!string.IsNullOrEmpty(value))
+ {
+ if (!TryConvertValue(value, method.ReturnType, out object? res))
+ {
+ LogWarning(methodNav, DiagnosticId.XmlInvalidValueForStub, method.GetDisplayName());
+ return;
+ }
+
+ _substitutionInfo.SetMethodStubValue(method, res);
+ }
+
+ _substitutionInfo.SetMethodAction(method, MethodAction.ConvertToStub);
+ return;
+ default:
+ LogWarning(methodNav, DiagnosticId.XmlUnkownBodyModification, action, method.GetDisplayName());
+ return;
+ }
+ }
+
+ protected override void ProcessField(TypeDefinition type, XPathNavigator fieldNav)
+ {
+ Debug.Assert(_substitutionInfo != null);
+ string name = GetAttribute(fieldNav, "name");
+ if (string.IsNullOrEmpty(name))
+ return;
+
+ var field = type.Fields.FirstOrDefault(f => f.Name == name);
+ if (field == null)
+ {
+ LogWarning(fieldNav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName());
+ return;
+ }
+
+ if (!field.IsStatic || field.IsLiteral)
+ {
+ LogWarning(fieldNav, DiagnosticId.XmlSubstitutedFieldNeedsToBeStatic, field.GetDisplayName());
+ return;
+ }
+
+ string value = GetAttribute(fieldNav, "value");
+ if (string.IsNullOrEmpty(value))
+ {
+ LogWarning(fieldNav, DiagnosticId.XmlMissingSubstitutionValueForField, field.GetDisplayName());
+ return;
+ }
+ if (!TryConvertValue(value, field.FieldType, out object? res))
+ {
+ LogWarning(fieldNav, DiagnosticId.XmlInvalidSubstitutionValueForField, value, field.GetDisplayName());
+ return;
+ }
+
+ _substitutionInfo.SetFieldValue(field, res);
+
+ string init = GetAttribute(fieldNav, "initialize");
+ if (init?.ToLowerInvariant() == "true")
+ {
+ _substitutionInfo.SetFieldInit(field);
+ }
+ }
+
+ void ProcessResources(AssemblyDefinition assembly, XPathNavigator nav)
+ {
+ foreach (XPathNavigator resourceNav in nav.SelectChildren("resource", ""))
+ {
+ if (!ShouldProcessElement(resourceNav))
+ continue;
+
+ string name = GetAttribute(resourceNav, "name");
+ if (String.IsNullOrEmpty(name))
+ {
+ LogWarning(resourceNav, DiagnosticId.XmlMissingNameAttributeInResource);
+ continue;
+ }
+
+ string action = GetAttribute(resourceNav, "action");
+ if (action != "remove")
+ {
+ LogWarning(resourceNav, DiagnosticId.XmlInvalidValueForAttributeActionForResource, action, name);
+ continue;
+ }
+
+ EmbeddedResource? resource = assembly.FindEmbeddedResource(name);
+ if (resource == null)
+ {
+ LogWarning(resourceNav, DiagnosticId.XmlCouldNotFindResourceToRemoveInAssembly, name, assembly.Name.Name);
+ continue;
+ }
+
+ _context.Annotations.AddResourceToRemove(assembly, resource);
+ }
+ }
+
+ static MethodDefinition? FindMethod(TypeDefinition type, string signature)
+ {
+ if (!type.HasMethods)
+ return null;
+
+ foreach (MethodDefinition meth in type.Methods)
+ if (signature == DescriptorMarker.GetMethodSignature(meth, includeGenericParameters: true))
+ return meth;
+
+ return null;
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs
new file mode 100644
index 00000000000000..49404575e41f91
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs
@@ -0,0 +1,292 @@
+// 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;
+using System.IO;
+using System.Text;
+using System.Xml.XPath;
+using ILLink.Shared;
+
+using Mono.Cecil;
+
+namespace Mono.Linker.Steps
+{
+ public class DescriptorMarker : ProcessLinkerXmlBase
+ {
+ const string NamespaceElementName = "namespace";
+
+ const string _required = "required";
+ const string _preserve = "preserve";
+ const string _accessors = "accessors";
+
+ static readonly string[] _accessorsAll = new string[] { "all" };
+ static readonly char[] _accessorsSep = new char[] { ';' };
+
+ public DescriptorMarker(LinkContext context, Stream documentStream, string xmlDocumentLocation)
+ : base(context, documentStream, xmlDocumentLocation)
+ {
+ }
+
+ public DescriptorMarker(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "")
+ : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation)
+ {
+ }
+
+ public void Mark()
+ {
+ bool stripDescriptors = _context.IsOptimizationEnabled(CodeOptimizations.RemoveDescriptors, _resource?.Assembly);
+ ProcessXml(stripDescriptors, _context.IgnoreDescriptors);
+ }
+
+ protected override AllowedAssemblies AllowedAssemblySelector { get => AllowedAssemblies.AnyAssembly; }
+
+ protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
+ {
+ if (GetTypePreserve(nav) == TypePreserve.All)
+ {
+ foreach (var type in assembly.MainModule.Types)
+ MarkAndPreserveAll(type, nav);
+
+ foreach (var exportedType in assembly.MainModule.ExportedTypes)
+ _context.MarkingHelpers.MarkExportedType(exportedType, assembly.MainModule, new DependencyInfo(DependencyKind.XmlDescriptor, assembly.MainModule), GetMessageOriginForPosition(nav));
+ }
+ else
+ {
+ ProcessTypes(assembly, nav, warnOnUnresolvedTypes);
+ ProcessNamespaces(assembly, nav);
+ }
+ }
+
+ void ProcessNamespaces(AssemblyDefinition assembly, XPathNavigator nav)
+ {
+ foreach (XPathNavigator namespaceNav in nav.SelectChildren(NamespaceElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(namespaceNav))
+ continue;
+
+ string fullname = GetFullName(namespaceNav);
+ bool foundMatch = false;
+ foreach (TypeDefinition type in assembly.MainModule.Types)
+ {
+ if (type.Namespace != fullname)
+ continue;
+
+ foundMatch = true;
+ MarkAndPreserveAll(type, nav);
+ }
+
+ if (!foundMatch)
+ {
+ LogWarning(namespaceNav, DiagnosticId.XmlCouldNotFindAnyTypeInNamespace, fullname);
+ }
+ }
+ }
+
+ void MarkAndPreserveAll(TypeDefinition type, XPathNavigator nav)
+ {
+ _context.Annotations.Mark(type, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav));
+ _context.Annotations.SetPreserve(type, TypePreserve.All);
+
+ if (!type.HasNestedTypes)
+ return;
+
+ foreach (TypeDefinition nested in type.NestedTypes)
+ MarkAndPreserveAll(nested, nav);
+ }
+
+ protected override TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav)
+ {
+ _context.MarkingHelpers.MarkExportedType(exported, assembly.MainModule, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav));
+ return base.ProcessExportedType(exported, assembly, nav);
+ }
+
+ protected override void ProcessType(TypeDefinition type, XPathNavigator nav)
+ {
+ Debug.Assert(ShouldProcessElement(nav));
+
+ TypePreserve preserve = GetTypePreserve(nav);
+ switch (preserve)
+ {
+ case TypePreserve.Fields when !type.HasFields:
+ LogWarning(nav, DiagnosticId.TypeHasNoFieldsToPreserve, type.GetDisplayName());
+ break;
+
+ case TypePreserve.Methods when !type.HasMethods:
+ LogWarning(nav, DiagnosticId.TypeHasNoMethodsToPreserve, type.GetDisplayName());
+ break;
+
+ case TypePreserve.Fields:
+ case TypePreserve.Methods:
+ case TypePreserve.All:
+ _context.Annotations.SetPreserve(type, preserve);
+ break;
+ }
+
+ bool required = IsRequired(nav);
+ ProcessTypeChildren(type, nav, required);
+
+ if (!required)
+ return;
+
+ _context.Annotations.Mark(type, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav));
+
+ if (type.IsNested)
+ {
+ var currentType = type;
+ while (currentType.IsNested)
+ {
+ var parent = currentType.DeclaringType;
+ _context.Annotations.Mark(parent, new DependencyInfo(DependencyKind.DeclaringType, currentType), GetMessageOriginForPosition(nav));
+ currentType = parent;
+ }
+ }
+ }
+
+ static TypePreserve GetTypePreserve(XPathNavigator nav)
+ {
+ string attribute = GetAttribute(nav, _preserve);
+ if (string.IsNullOrEmpty(attribute))
+ return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All;
+
+ if (Enum.TryParse(attribute, true, out TypePreserve result))
+ return result;
+ return TypePreserve.Nothing;
+ }
+
+ protected override void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav)
+ {
+ if (_context.Annotations.IsMarked(field))
+ LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, field.FullName);
+
+ _context.Annotations.Mark(field, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav));
+ }
+
+ protected override void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData)
+ {
+ if (_context.Annotations.IsMarked(method))
+ LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, method.GetDisplayName());
+
+ _context.Annotations.MarkIndirectlyCalledMethod(method);
+ _context.Annotations.SetAction(method, MethodAction.Parse);
+
+ if (customData is bool required && !required)
+ {
+ _context.Annotations.AddPreservedMethod(type, method);
+ }
+ else
+ {
+ _context.Annotations.Mark(method, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation), GetMessageOriginForPosition(nav));
+ }
+ }
+
+ void ProcessMethodIfNotNull(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData)
+ {
+ if (method == null)
+ return;
+
+ ProcessMethod(type, method, nav, customData);
+ }
+
+ protected override MethodDefinition? GetMethod(TypeDefinition type, string signature)
+ {
+ if (type.HasMethods)
+ foreach (MethodDefinition meth in type.Methods)
+ if (signature == GetMethodSignature(meth, false))
+ return meth;
+
+ return null;
+ }
+
+ public static string GetMethodSignature(MethodDefinition meth, bool includeGenericParameters)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(meth.ReturnType.FullName);
+ sb.Append(" ");
+ sb.Append(meth.Name);
+ if (includeGenericParameters && meth.HasGenericParameters)
+ {
+ sb.Append("`");
+ sb.Append(meth.GenericParameters.Count);
+ }
+
+ sb.Append("(");
+ if (meth.HasParameters)
+ {
+ for (int i = 0; i < meth.Parameters.Count; i++)
+ {
+ if (i > 0)
+ sb.Append(",");
+
+ sb.Append(meth.Parameters[i].ParameterType.FullName);
+ }
+ }
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ protected override void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData)
+ {
+ if (_context.Annotations.IsMarked(@event))
+ LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, @event.FullName);
+
+ ProcessMethod(type, @event.AddMethod, nav, customData);
+ ProcessMethod(type, @event.RemoveMethod, nav, customData);
+ ProcessMethodIfNotNull(type, @event.InvokeMethod, nav, customData);
+ }
+
+ protected override void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature)
+ {
+ string[] accessors = fromSignature ? GetAccessors(nav) : _accessorsAll;
+
+ if (_context.Annotations.IsMarked(property))
+ LogWarning(nav, DiagnosticId.XmlDuplicatePreserveMember, property.FullName);
+
+ if (Array.IndexOf(accessors, "all") >= 0)
+ {
+ ProcessMethodIfNotNull(type, property.GetMethod, nav, customData);
+ ProcessMethodIfNotNull(type, property.SetMethod, nav, customData);
+ return;
+ }
+
+ if (property.GetMethod != null && Array.IndexOf(accessors, "get") >= 0)
+ ProcessMethod(type, property.GetMethod, nav, customData);
+ else if (property.GetMethod == null)
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindGetAccesorOfPropertyOnType, property.Name, type.FullName);
+
+ if (property.SetMethod != null && Array.IndexOf(accessors, "set") >= 0)
+ ProcessMethod(type, property.SetMethod, nav, customData);
+ else if (property.SetMethod == null)
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindSetAccesorOfPropertyOnType, property.Name, type.FullName);
+ }
+
+ static bool IsRequired(XPathNavigator nav)
+ {
+ string attribute = GetAttribute(nav, _required);
+ if (attribute == null || attribute.Length == 0)
+ return true;
+
+ return bool.TryParse(attribute, out bool result) && result;
+ }
+
+ protected static string[] GetAccessors(XPathNavigator nav)
+ {
+ string accessorsValue = GetAttribute(nav, _accessors);
+
+ if (accessorsValue != null)
+ {
+ string[] accessors = accessorsValue.Split(
+ _accessorsSep, StringSplitOptions.RemoveEmptyEntries);
+
+ if (accessors.Length > 0)
+ {
+ for (int i = 0; i < accessors.Length; ++i)
+ accessors[i] = accessors[i].ToLower();
+
+ return accessors;
+ }
+ }
+ return _accessorsAll;
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs
new file mode 100644
index 00000000000000..5e893760226848
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs
@@ -0,0 +1,50 @@
+// 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.Xml.XPath;
+using ILLink.Shared;
+
+namespace Mono.Linker
+{
+ public static class FeatureSettings
+ {
+ public static bool ShouldProcessElement(XPathNavigator nav, LinkContext context, string documentLocation)
+ {
+ var feature = GetAttribute(nav, "feature");
+ if (string.IsNullOrEmpty(feature))
+ return true;
+
+ var value = GetAttribute(nav, "featurevalue");
+ if (string.IsNullOrEmpty(value))
+ {
+ context.LogError(null, DiagnosticId.XmlFeatureDoesNotSpecifyFeatureValue, documentLocation, feature);
+ return false;
+ }
+
+ if (!bool.TryParse(value, out bool bValue))
+ {
+ context.LogError(null, DiagnosticId.XmlUnsupportedNonBooleanValueForFeature, documentLocation, feature);
+ return false;
+ }
+
+ var isDefault = GetAttribute(nav, "featuredefault");
+ bool bIsDefault = false;
+ if (!string.IsNullOrEmpty(isDefault) && (!bool.TryParse(isDefault, out bIsDefault) || !bIsDefault))
+ {
+ context.LogError(null, DiagnosticId.XmlDocumentLocationHasInvalidFeatureDefault, documentLocation);
+ return false;
+ }
+
+ if (!context.FeatureSettings.TryGetValue(feature, out bool featureSetting))
+ return bIsDefault;
+
+ return bValue == featureSetting;
+ }
+
+ public static string GetAttribute(XPathNavigator nav, string attribute)
+ {
+ return nav.GetAttribute(attribute, String.Empty);
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs
new file mode 100644
index 00000000000000..0acfdda2dccbe5
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs
@@ -0,0 +1,578 @@
+// 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;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.XPath;
+using ILLink.Shared;
+using Mono.Cecil;
+
+namespace Mono.Linker.Steps
+{
+ public class LinkAttributesParser : ProcessLinkerXmlBase
+ {
+ AttributeInfo? _attributeInfo;
+
+ public LinkAttributesParser(LinkContext context, Stream documentStream, string xmlDocumentLocation)
+ : base(context, documentStream, xmlDocumentLocation)
+ {
+ }
+
+ public LinkAttributesParser(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation = "")
+ : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation)
+ {
+ }
+
+ public void Parse(AttributeInfo xmlInfo)
+ {
+ _attributeInfo = xmlInfo;
+ bool stripLinkAttributes = _context.IsOptimizationEnabled(CodeOptimizations.RemoveLinkAttributes, _resource?.Assembly);
+ ProcessXml(stripLinkAttributes, _context.IgnoreLinkAttributes);
+ }
+
+ CustomAttribute[]? ProcessAttributes(XPathNavigator nav, ICustomAttributeProvider provider)
+ {
+ var builder = new ArrayBuilder();
+ foreach (XPathNavigator argumentNav in nav.SelectChildren("attribute", string.Empty))
+ {
+ if (!ShouldProcessElement(argumentNav))
+ continue;
+
+ TypeDefinition? attributeType;
+ string internalAttribute = GetAttribute(argumentNav, "internal");
+ if (!string.IsNullOrEmpty(internalAttribute))
+ {
+ attributeType = GenerateRemoveAttributeInstancesAttribute();
+ if (attributeType == null)
+ continue;
+
+ // TODO: Replace with IsAttributeType check once we have it
+ if (provider is not TypeDefinition)
+ {
+ LogWarning(argumentNav, DiagnosticId.XmlRemoveAttributeInstancesCanOnlyBeUsedOnType, attributeType.Name);
+ continue;
+ }
+ }
+ else
+ {
+ string attributeFullName = GetFullName(argumentNav);
+ if (string.IsNullOrEmpty(attributeFullName))
+ {
+ LogWarning(argumentNav, DiagnosticId.XmlElementDoesNotContainRequiredAttributeFullname);
+ continue;
+ }
+
+ if (!GetAttributeType(argumentNav, attributeFullName, out attributeType))
+ continue;
+ }
+
+ CustomAttribute? customAttribute = CreateCustomAttribute(argumentNav, attributeType);
+ if (customAttribute != null)
+ {
+ _context.LogMessage($"Assigning external custom attribute '{FormatCustomAttribute(customAttribute)}' instance to '{provider}'.");
+ builder.Add(customAttribute);
+ }
+ }
+
+ return builder.ToArray();
+
+ static string FormatCustomAttribute(CustomAttribute ca)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append(ca.Constructor.GetDisplayName());
+ sb.Append(" { args: ");
+ for (int i = 0; i < ca.ConstructorArguments.Count; ++i)
+ {
+ if (i > 0)
+ sb.Append(", ");
+
+ var caa = ca.ConstructorArguments[i];
+ sb.Append($"{caa.Type.GetDisplayName()} {caa.Value}");
+ }
+ sb.Append(" }");
+
+ return sb.ToString();
+ }
+ }
+
+ TypeDefinition? GenerateRemoveAttributeInstancesAttribute()
+ {
+ if (_context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition != null)
+ return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition;
+
+ var voidType = BCL.FindPredefinedType("System", "Void", _context);
+ if (voidType == null)
+ return null;
+
+ var attributeType = BCL.FindPredefinedType("System", "Attribute", _context);
+ if (attributeType == null)
+ return null;
+
+ var objectType = BCL.FindPredefinedType("System", "Object", _context);
+ if (objectType == null)
+ return null;
+
+ //
+ // Generates metadata information for internal type
+ //
+ // public sealed class RemoveAttributeInstancesAttribute : Attribute
+ // {
+ // public RemoveAttributeInstancesAttribute () {}
+ // public RemoveAttributeInstancesAttribute (object value1) {}
+ // }
+ //
+ var td = new TypeDefinition("", "RemoveAttributeInstancesAttribute", TypeAttributes.Public);
+ td.BaseType = attributeType;
+
+ const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Final;
+ var ctor = new MethodDefinition(".ctor", ctorAttributes, voidType);
+ td.Methods.Add(ctor);
+
+ ctor = new MethodDefinition(".ctor", ctorAttributes, voidType);
+ ctor.Parameters.Add(new ParameterDefinition(objectType));
+ td.Methods.Add(ctor);
+
+ return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td;
+ }
+
+ CustomAttribute? CreateCustomAttribute(XPathNavigator nav, TypeDefinition attributeType)
+ {
+ CustomAttributeArgument[] arguments = ReadCustomAttributeArguments(nav, attributeType);
+
+ MethodDefinition? constructor = FindBestMatchingConstructor(attributeType, arguments);
+ if (constructor == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindMatchingConstructorForCustomAttribute, attributeType.GetDisplayName());
+ return null;
+ }
+
+ CustomAttribute customAttribute = new CustomAttribute(constructor);
+ foreach (var argument in arguments)
+ customAttribute.ConstructorArguments.Add(argument);
+
+ ReadCustomAttributeProperties(nav, attributeType, customAttribute);
+
+ return customAttribute;
+ }
+
+ MethodDefinition? FindBestMatchingConstructor(TypeDefinition attributeType, CustomAttributeArgument[] args)
+ {
+ var methods = attributeType.Methods;
+ for (int i = 0; i < attributeType.Methods.Count; ++i)
+ {
+ var m = methods[i];
+ if (!m.IsInstanceConstructor())
+ continue;
+
+ var p = m.Parameters;
+ if (args.Length != p.Count)
+ continue;
+
+ bool match = true;
+ for (int ii = 0; match && ii != args.Length; ++ii)
+ {
+ //
+ // No candidates betterness, only exact matches are supported
+ //
+ var parameterType = _context.TryResolve(p[ii].ParameterType);
+ if (parameterType == null || parameterType != _context.TryResolve(args[ii].Type))
+ match = false;
+ }
+
+ if (match)
+ return m;
+ }
+
+ return null;
+ }
+
+ void ReadCustomAttributeProperties(XPathNavigator nav, TypeDefinition attributeType, CustomAttribute customAttribute)
+ {
+ foreach (XPathNavigator propertyNav in nav.SelectChildren("property", string.Empty))
+ {
+ string propertyName = GetName(propertyNav);
+ if (string.IsNullOrEmpty(propertyName))
+ {
+ LogWarning(propertyNav, DiagnosticId.XmlPropertyDoesNotContainAttributeName);
+ continue;
+ }
+
+ PropertyDefinition? property = attributeType.Properties.Where(prop => prop.Name == propertyName).FirstOrDefault();
+ if (property == null)
+ {
+ LogWarning(propertyNav, DiagnosticId.XmlCouldNotFindProperty, propertyName);
+ continue;
+ }
+
+ var caa = ReadCustomAttributeArgument(propertyNav, property);
+ if (caa is null)
+ continue;
+
+ customAttribute.Properties.Add(new CustomAttributeNamedArgument(property.Name, caa.Value));
+ }
+ }
+
+ CustomAttributeArgument[] ReadCustomAttributeArguments(XPathNavigator nav, TypeDefinition attributeType)
+ {
+ var args = new ArrayBuilder();
+
+ foreach (XPathNavigator argumentNav in nav.SelectChildren("argument", string.Empty))
+ {
+ CustomAttributeArgument? caa = ReadCustomAttributeArgument(argumentNav, attributeType);
+ if (caa is not null)
+ args.Add(caa.Value);
+ }
+
+ return args.ToArray() ?? Array.Empty();
+ }
+
+ CustomAttributeArgument? ReadCustomAttributeArgument(XPathNavigator nav, IMemberDefinition memberWithAttribute)
+ {
+ TypeReference? typeref = ResolveArgumentType(nav, memberWithAttribute);
+ if (typeref is null)
+ return null;
+
+ string svalue = nav.Value;
+
+ //
+ // Builds CustomAttributeArgument in the same way as it would be
+ // represented in the metadata if encoded there. This simplifies
+ // any custom attributes handling in linker by using same attributes
+ // value extraction or mathing logic.
+ //
+ switch (typeref.MetadataType)
+ {
+ case MetadataType.Object:
+ var argumentIterator = nav.SelectChildren("argument", string.Empty);
+ if (argumentIterator?.MoveNext() != true)
+ {
+ _context.LogError(null, DiagnosticId.CustomAttributeArgumentForTypeRequiresNestedNode, "System.Object", "argument");
+ return null;
+ }
+
+ var typedef = _context.TryResolve(typeref);
+ if (typedef == null)
+ return null;
+
+ var boxedValue = ReadCustomAttributeArgument(argumentIterator.Current!, typedef);
+ if (boxedValue is null)
+ return null;
+
+ return new CustomAttributeArgument(typeref, boxedValue);
+
+ case MetadataType.Char:
+ case MetadataType.Byte:
+ case MetadataType.SByte:
+ case MetadataType.Int16:
+ case MetadataType.UInt16:
+ case MetadataType.Int32:
+ case MetadataType.UInt32:
+ case MetadataType.UInt64:
+ case MetadataType.Int64:
+ case MetadataType.String:
+ return new CustomAttributeArgument(typeref, ConvertStringValue(svalue, typeref));
+
+ case MetadataType.ValueType:
+ var enumType = _context.Resolve(typeref);
+ if (enumType?.IsEnum != true)
+ goto default;
+
+ var enumField = enumType.Fields.Where(f => f.IsStatic && f.Name == svalue).FirstOrDefault();
+ object evalue = enumField?.Constant ?? svalue;
+
+ typeref = enumType.GetEnumUnderlyingType();
+ return new CustomAttributeArgument(enumType, ConvertStringValue(evalue, typeref));
+
+ case MetadataType.Class:
+ if (!typeref.IsTypeOf("System", "Type"))
+ goto default;
+
+ if (!_context.TypeNameResolver.TryResolveTypeName(svalue, memberWithAttribute, out TypeReference? type, out _))
+ {
+ _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue);
+ return null;
+ }
+
+ return new CustomAttributeArgument(typeref, type);
+ default:
+ // No support for null and arrays, consider adding - dotnet/linker/issues/1957
+ _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.UnexpectedAttributeArgumentType, typeref.GetDisplayName());
+ return null;
+ }
+
+ TypeReference? ResolveArgumentType(XPathNavigator nav, IMemberDefinition memberWithAttribute)
+ {
+ string typeName = GetAttribute(nav, "type");
+ if (string.IsNullOrEmpty(typeName))
+ typeName = "System.String";
+
+ if (!_context.TypeNameResolver.TryResolveTypeName(typeName, memberWithAttribute, out TypeReference? typeref, out _))
+ {
+ _context.LogError(GetMessageOriginForPosition(nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value);
+ return null;
+ }
+
+ return typeref;
+ }
+ }
+
+ object? ConvertStringValue(object value, TypeReference targetType)
+ {
+ TypeCode typeCode;
+ switch (targetType.MetadataType)
+ {
+ case MetadataType.String:
+ typeCode = TypeCode.String;
+ break;
+ case MetadataType.Char:
+ typeCode = TypeCode.Char;
+ break;
+ case MetadataType.Byte:
+ typeCode = TypeCode.Byte;
+ break;
+ case MetadataType.SByte:
+ typeCode = TypeCode.SByte;
+ break;
+ case MetadataType.Int16:
+ typeCode = TypeCode.Int16;
+ break;
+ case MetadataType.UInt16:
+ typeCode = TypeCode.UInt16;
+ break;
+ case MetadataType.Int32:
+ typeCode = TypeCode.Int32;
+ break;
+ case MetadataType.UInt32:
+ typeCode = TypeCode.UInt32;
+ break;
+ case MetadataType.UInt64:
+ typeCode = TypeCode.UInt64;
+ break;
+ case MetadataType.Int64:
+ typeCode = TypeCode.Int64;
+ break;
+ case MetadataType.Boolean:
+ typeCode = TypeCode.Boolean;
+ break;
+ case MetadataType.Single:
+ typeCode = TypeCode.Single;
+ break;
+ case MetadataType.Double:
+ typeCode = TypeCode.Double;
+ break;
+ default:
+ throw new NotSupportedException(targetType.ToString());
+ }
+
+ try
+ {
+ return Convert.ChangeType(value, typeCode);
+ }
+ catch
+ {
+ _context.LogError(null, DiagnosticId.CannotConverValueToType, value.ToString() ?? "", targetType.GetDisplayName());
+ return null;
+ }
+ }
+
+ bool GetAttributeType(XPathNavigator nav, string attributeFullName, [NotNullWhen(true)] out TypeDefinition? attributeType)
+ {
+ string assemblyName = GetAttribute(nav, "assembly");
+ if (string.IsNullOrEmpty(assemblyName))
+ {
+ attributeType = _context.GetType(attributeFullName);
+ }
+ else
+ {
+ AssemblyDefinition? assembly;
+ try
+ {
+ assembly = _context.TryResolve(AssemblyNameReference.Parse(assemblyName));
+ if (assembly == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotResolveAssemblyForAttribute, assemblyName, attributeFullName);
+
+ attributeType = default;
+ return false;
+ }
+ }
+ catch (Exception)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotResolveAssemblyForAttribute, assemblyName, attributeFullName);
+ attributeType = default;
+ return false;
+ }
+
+ attributeType = _context.TryResolve(assembly, attributeFullName);
+ }
+
+ if (attributeType == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlAttributeTypeCouldNotBeFound, attributeFullName);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected override AllowedAssemblies AllowedAssemblySelector
+ {
+ get
+ {
+ if (_resource?.Assembly == null)
+ return AllowedAssemblies.AllAssemblies;
+
+ // Corelib XML may contain assembly wildcard to support compiler-injected attribute types
+ if (_resource?.Assembly.Name.Name == PlatformAssemblies.CoreLib)
+ return AllowedAssemblies.AllAssemblies;
+
+ return AllowedAssemblies.ContainingAssembly;
+ }
+ }
+
+ protected override void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
+ {
+ PopulateAttributeInfo(assembly, nav);
+ ProcessTypes(assembly, nav, warnOnUnresolvedTypes);
+ }
+
+ protected override void ProcessType(TypeDefinition type, XPathNavigator nav)
+ {
+ Debug.Assert(ShouldProcessElement(nav));
+
+ PopulateAttributeInfo(type, nav);
+ ProcessTypeChildren(type, nav);
+
+ if (!type.HasNestedTypes)
+ return;
+
+ foreach (XPathNavigator nestedTypeNav in nav.SelectChildren("type", string.Empty))
+ {
+ foreach (TypeDefinition nested in type.NestedTypes)
+ {
+ if (nested.Name == GetAttribute(nestedTypeNav, "name") && ShouldProcessElement(nestedTypeNav))
+ ProcessType(nested, nestedTypeNav);
+ }
+ }
+ }
+
+ protected override void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav)
+ {
+ PopulateAttributeInfo(field, nav);
+ }
+
+ protected override void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData)
+ {
+ PopulateAttributeInfo(method, nav);
+ ProcessReturnParameters(method, nav);
+ ProcessParameters(method, nav);
+ }
+
+ void ProcessParameters(MethodDefinition method, XPathNavigator nav)
+ {
+ Debug.Assert(_attributeInfo != null);
+ foreach (XPathNavigator parameterNav in nav.SelectChildren("parameter", string.Empty))
+ {
+ var attributes = ProcessAttributes(parameterNav, method);
+ if (attributes != null)
+ {
+ string paramName = GetAttribute(parameterNav, "name");
+ foreach (ParameterDefinition parameter in method.Parameters)
+ {
+ if (paramName == parameter.Name)
+ {
+ if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey(parameter))
+ LogWarning(parameterNav, DiagnosticId.XmlMoreThanOneValyForParameterOfMethod, paramName, method.GetDisplayName());
+ _attributeInfo.AddCustomAttributes(parameter, attributes);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void ProcessReturnParameters(MethodDefinition method, XPathNavigator nav)
+ {
+ bool firstAppearance = true;
+ foreach (XPathNavigator returnNav in nav.SelectChildren("return", string.Empty))
+ {
+ if (firstAppearance)
+ {
+ firstAppearance = false;
+ PopulateAttributeInfo(method.MethodReturnType, returnNav);
+ }
+ else
+ {
+ LogWarning(returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName());
+ }
+ }
+ }
+
+ protected override MethodDefinition? GetMethod(TypeDefinition type, string signature)
+ {
+ if (type.HasMethods)
+ foreach (MethodDefinition method in type.Methods)
+ if (signature.Replace(" ", "") == GetMethodSignature(method) || signature.Replace(" ", "") == GetMethodSignature(method, true))
+ return method;
+
+ return null;
+ }
+
+ static string GetMethodSignature(MethodDefinition method, bool includeReturnType = false)
+ {
+ StringBuilder sb = new StringBuilder();
+ if (includeReturnType)
+ {
+ sb.Append(method.ReturnType.FullName);
+ }
+ sb.Append(method.Name);
+ if (method.HasGenericParameters)
+ {
+ sb.Append("<");
+ for (int i = 0; i < method.GenericParameters.Count; i++)
+ {
+ if (i > 0)
+ sb.Append(",");
+
+ sb.Append(method.GenericParameters[i].Name);
+ }
+ sb.Append(">");
+ }
+ sb.Append("(");
+ if (method.HasParameters)
+ {
+ for (int i = 0; i < method.Parameters.Count; i++)
+ {
+ if (i > 0)
+ sb.Append(",");
+
+ sb.Append(method.Parameters[i].ParameterType.FullName);
+ }
+ }
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ protected override void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature)
+ {
+ PopulateAttributeInfo(property, nav);
+ }
+
+ protected override void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData)
+ {
+ PopulateAttributeInfo(@event, nav);
+ }
+
+ void PopulateAttributeInfo(ICustomAttributeProvider provider, XPathNavigator nav)
+ {
+ Debug.Assert(_attributeInfo != null);
+ var attributes = ProcessAttributes(nav, provider);
+ if (attributes != null)
+ _attributeInfo.AddCustomAttributes(provider, attributes);
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs
new file mode 100644
index 00000000000000..842c56639fdd0e
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs
@@ -0,0 +1,662 @@
+// 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;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Linq;
+using System.Xml.XPath;
+using ILLink.Shared;
+using Mono.Cecil;
+
+namespace Mono.Linker.Steps
+{
+ [Flags]
+ public enum AllowedAssemblies
+ {
+ ContainingAssembly = 0x1,
+ AnyAssembly = 0x2 | ContainingAssembly,
+ AllAssemblies = 0x4 | AnyAssembly
+ }
+
+ public abstract class ProcessLinkerXmlBase
+ {
+ const string FullNameAttributeName = "fullname";
+ const string LinkerElementName = "linker";
+ const string TypeElementName = "type";
+ const string SignatureAttributeName = "signature";
+ const string NameAttributeName = "name";
+ const string FieldElementName = "field";
+ const string MethodElementName = "method";
+ const string EventElementName = "event";
+ const string PropertyElementName = "property";
+ const string AllAssembliesFullName = "*";
+ protected const string XmlNamespace = "";
+
+ protected readonly string _xmlDocumentLocation;
+ readonly XPathNavigator _document;
+ protected readonly (EmbeddedResource Resource, AssemblyDefinition Assembly)? _resource;
+ protected readonly LinkContext _context;
+
+ protected ProcessLinkerXmlBase(LinkContext context, Stream documentStream, string xmlDocumentLocation)
+ {
+ _context = context;
+ using (documentStream)
+ {
+ _document = XDocument.Load(documentStream, LoadOptions.SetLineInfo).CreateNavigator();
+ }
+ _xmlDocumentLocation = xmlDocumentLocation;
+ }
+
+ protected ProcessLinkerXmlBase(LinkContext context, Stream documentStream, EmbeddedResource resource, AssemblyDefinition resourceAssembly, string xmlDocumentLocation)
+ : this(context, documentStream, xmlDocumentLocation)
+ {
+ _resource = (
+ resource ?? throw new ArgumentNullException(nameof(resource)),
+ resourceAssembly ?? throw new ArgumentNullException(nameof(resourceAssembly))
+ );
+ }
+
+ protected virtual bool ShouldProcessElement(XPathNavigator nav) => FeatureSettings.ShouldProcessElement(nav, _context, _xmlDocumentLocation);
+
+ protected virtual void ProcessXml(bool stripResource, bool ignoreResource)
+ {
+ if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly) && _resource == null)
+ throw new InvalidOperationException("The containing assembly must be specified for XML which is restricted to modifying that assembly only.");
+
+ try
+ {
+ XPathNavigator nav = _document.CreateNavigator();
+
+ // Initial structure check - ignore XML document which don't look like linker XML format
+ if (!nav.MoveToChild(LinkerElementName, XmlNamespace))
+ return;
+
+ if (_resource != null)
+ {
+ if (stripResource)
+ _context.Annotations.AddResourceToRemove(_resource.Value.Assembly, _resource.Value.Resource);
+ if (ignoreResource)
+ return;
+ }
+
+ if (!ShouldProcessElement(nav))
+ return;
+
+ ProcessAssemblies(nav);
+
+ // For embedded XML, allow not specifying the assembly explicitly in XML.
+ if (_resource != null)
+ ProcessAssembly(_resource.Value.Assembly, nav, warnOnUnresolvedTypes: true);
+
+ }
+ catch (Exception ex) when (!(ex is LinkerFatalErrorException))
+ {
+ throw new LinkerFatalErrorException(MessageContainer.CreateErrorMessage(null, DiagnosticId.ErrorProcessingXmlLocation, _xmlDocumentLocation), ex);
+ }
+ }
+
+ protected virtual AllowedAssemblies AllowedAssemblySelector { get => _resource != null ? AllowedAssemblies.ContainingAssembly : AllowedAssemblies.AnyAssembly; }
+
+ bool ShouldProcessAllAssemblies(XPathNavigator nav, [NotNullWhen(false)] out AssemblyNameReference? assemblyName)
+ {
+ assemblyName = null;
+ if (GetFullName(nav) == AllAssembliesFullName)
+ return true;
+
+ assemblyName = GetAssemblyName(nav);
+ return false;
+ }
+
+ protected virtual void ProcessAssemblies(XPathNavigator nav)
+ {
+ foreach (XPathNavigator assemblyNav in nav.SelectChildren("assembly", ""))
+ {
+ // Errors for invalid assembly names should show up even if this element will be
+ // skipped due to feature conditions.
+ bool processAllAssemblies = ShouldProcessAllAssemblies(assemblyNav, out AssemblyNameReference? name);
+ if (processAllAssemblies && AllowedAssemblySelector != AllowedAssemblies.AllAssemblies)
+ {
+ LogWarning(assemblyNav, DiagnosticId.XmlUnsuportedWildcard);
+ continue;
+ }
+
+ AssemblyDefinition? assemblyToProcess = null;
+ if (!AllowedAssemblySelector.HasFlag(AllowedAssemblies.AnyAssembly))
+ {
+ Debug.Assert(!processAllAssemblies);
+ Debug.Assert(_resource != null);
+ if (_resource.Value.Assembly.Name.Name != name!.Name)
+ {
+ LogWarning(assemblyNav, DiagnosticId.AssemblyWithEmbeddedXmlApplyToAnotherAssembly, _resource.Value.Assembly.Name.Name, name.ToString());
+ continue;
+ }
+ assemblyToProcess = _resource.Value.Assembly;
+ }
+
+ if (!ShouldProcessElement(assemblyNav))
+ continue;
+
+ if (processAllAssemblies)
+ {
+ // We could avoid loading all references in this case: https://github.com/dotnet/linker/issues/1708
+ foreach (AssemblyDefinition assembly in _context.GetReferencedAssemblies())
+ ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: false);
+ }
+ else
+ {
+ Debug.Assert(!processAllAssemblies);
+ AssemblyDefinition? assembly = assemblyToProcess ?? _context.TryResolve(name!);
+
+ if (assembly == null)
+ {
+ LogWarning(assemblyNav, DiagnosticId.XmlCouldNotResolveAssembly, name!.Name);
+ continue;
+ }
+
+ ProcessAssembly(assembly, assemblyNav, warnOnUnresolvedTypes: true);
+ }
+ }
+ }
+
+ protected abstract void ProcessAssembly(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes);
+
+ protected virtual void ProcessTypes(AssemblyDefinition assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
+ {
+ foreach (XPathNavigator typeNav in nav.SelectChildren(TypeElementName, XmlNamespace))
+ {
+
+ if (!ShouldProcessElement(typeNav))
+ continue;
+
+ string fullname = GetFullName(typeNav);
+
+ if (fullname.IndexOf("*") != -1)
+ {
+ if (ProcessTypePattern(fullname, assembly, typeNav))
+ continue;
+ }
+
+ TypeDefinition type = assembly.MainModule.GetType(fullname);
+
+ if (type == null && assembly.MainModule.HasExportedTypes)
+ {
+ foreach (var exported in assembly.MainModule.ExportedTypes)
+ {
+ if (fullname == exported.FullName)
+ {
+ var resolvedExternal = ProcessExportedType(exported, assembly, typeNav);
+ if (resolvedExternal != null)
+ {
+ type = resolvedExternal;
+ break;
+ }
+ }
+ }
+ }
+
+ if (type == null)
+ {
+ if (warnOnUnresolvedTypes)
+ LogWarning(typeNav, DiagnosticId.XmlCouldNotResolveType, fullname);
+ continue;
+ }
+
+ ProcessType(type, typeNav);
+ }
+ }
+
+ protected virtual TypeDefinition? ProcessExportedType(ExportedType exported, AssemblyDefinition assembly, XPathNavigator nav) => exported.Resolve();
+
+ void MatchType(TypeDefinition type, Regex regex, XPathNavigator nav)
+ {
+ if (regex.Match(type.FullName).Success)
+ ProcessType(type, nav);
+
+ if (!type.HasNestedTypes)
+ return;
+
+ foreach (var nt in type.NestedTypes)
+ MatchType(nt, regex, nav);
+ }
+
+ protected virtual bool ProcessTypePattern(string fullname, AssemblyDefinition assembly, XPathNavigator nav)
+ {
+ Regex regex = new Regex(fullname.Replace(".", @"\.").Replace("*", "(.*)"));
+
+ foreach (TypeDefinition type in assembly.MainModule.Types)
+ {
+ MatchType(type, regex, nav);
+ }
+
+ if (assembly.MainModule.HasExportedTypes)
+ {
+ foreach (var exported in assembly.MainModule.ExportedTypes)
+ {
+ if (regex.Match(exported.FullName).Success)
+ {
+ var type = ProcessExportedType(exported, assembly, nav);
+ if (type != null)
+ {
+ ProcessType(type, nav);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ protected abstract void ProcessType(TypeDefinition type, XPathNavigator nav);
+
+ protected void ProcessTypeChildren(TypeDefinition type, XPathNavigator nav, object? customData = null)
+ {
+ if (nav.HasChildren)
+ {
+ ProcessSelectedFields(nav, type);
+ ProcessSelectedMethods(nav, type, customData);
+ ProcessSelectedEvents(nav, type, customData);
+ ProcessSelectedProperties(nav, type, customData);
+ }
+ }
+
+ void ProcessSelectedFields(XPathNavigator nav, TypeDefinition type)
+ {
+ foreach (XPathNavigator fieldNav in nav.SelectChildren(FieldElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(fieldNav))
+ continue;
+ ProcessField(type, fieldNav);
+ }
+ }
+
+ protected virtual void ProcessField(TypeDefinition type, XPathNavigator nav)
+ {
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
+ {
+ FieldDefinition? field = GetField(type, signature);
+ if (field == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ ProcessField(type, field, nav);
+ }
+
+ string name = GetName(nav);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ if (type.HasFields)
+ {
+ foreach (FieldDefinition field in type.Fields)
+ {
+ if (field.Name == name)
+ {
+ foundMatch = true;
+ ProcessField(type, field, nav);
+ }
+ }
+ }
+
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName());
+ }
+ }
+ }
+
+ protected static FieldDefinition? GetField(TypeDefinition type, string signature)
+ {
+ if (!type.HasFields)
+ return null;
+
+ foreach (FieldDefinition field in type.Fields)
+ if (signature == field.FieldType.FullName + " " + field.Name)
+ return field;
+
+ return null;
+ }
+
+ protected virtual void ProcessField(TypeDefinition type, FieldDefinition field, XPathNavigator nav) { }
+
+ void ProcessSelectedMethods(XPathNavigator nav, TypeDefinition type, object? customData)
+ {
+ foreach (XPathNavigator methodNav in nav.SelectChildren(MethodElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(methodNav))
+ continue;
+ ProcessMethod(type, methodNav, customData);
+ }
+ }
+
+ protected virtual void ProcessMethod(TypeDefinition type, XPathNavigator nav, object? customData)
+ {
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
+ {
+ MethodDefinition? method = GetMethod(type, signature);
+ if (method == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ ProcessMethod(type, method, nav, customData);
+ }
+
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ if (type.HasMethods)
+ {
+ foreach (MethodDefinition method in type.Methods)
+ {
+ if (name == method.Name)
+ {
+ foundMatch = true;
+ ProcessMethod(type, method, nav, customData);
+ }
+ }
+ }
+
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindMethodOnType, name, type.GetDisplayName());
+ }
+ }
+ }
+
+ protected virtual MethodDefinition? GetMethod(TypeDefinition type, string signature) => null;
+
+ protected virtual void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object? customData) { }
+
+ void ProcessSelectedEvents(XPathNavigator nav, TypeDefinition type, object? customData)
+ {
+ foreach (XPathNavigator eventNav in nav.SelectChildren(EventElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(eventNav))
+ continue;
+ ProcessEvent(type, eventNav, customData);
+ }
+ }
+
+ protected virtual void ProcessEvent(TypeDefinition type, XPathNavigator nav, object? customData)
+ {
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
+ {
+ EventDefinition? @event = GetEvent(type, signature);
+ if (@event == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ ProcessEvent(type, @event, nav, customData);
+ }
+
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ foreach (EventDefinition @event in type.Events)
+ {
+ if (@event.Name == name)
+ {
+ foundMatch = true;
+ ProcessEvent(type, @event, nav, customData);
+ }
+ }
+
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindEventOnType, name, type.GetDisplayName());
+ }
+ }
+ }
+
+ protected static EventDefinition? GetEvent(TypeDefinition type, string signature)
+ {
+ if (!type.HasEvents)
+ return null;
+
+ foreach (EventDefinition @event in type.Events)
+ if (signature == @event.EventType.FullName + " " + @event.Name)
+ return @event;
+
+ return null;
+ }
+
+ protected virtual void ProcessEvent(TypeDefinition type, EventDefinition @event, XPathNavigator nav, object? customData) { }
+
+ void ProcessSelectedProperties(XPathNavigator nav, TypeDefinition type, object? customData)
+ {
+ foreach (XPathNavigator propertyNav in nav.SelectChildren(PropertyElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(propertyNav))
+ continue;
+ ProcessProperty(type, propertyNav, customData);
+ }
+ }
+
+ protected virtual void ProcessProperty(TypeDefinition type, XPathNavigator nav, object? customData)
+ {
+ string signature = GetSignature(nav);
+ if (!String.IsNullOrEmpty(signature))
+ {
+ PropertyDefinition? property = GetProperty(type, signature);
+ if (property == null)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, signature, type.GetDisplayName());
+ return;
+ }
+
+ ProcessProperty(type, property, nav, customData, true);
+ }
+
+ string name = GetAttribute(nav, NameAttributeName);
+ if (!String.IsNullOrEmpty(name))
+ {
+ bool foundMatch = false;
+ foreach (PropertyDefinition property in type.Properties)
+ {
+ if (property.Name == name)
+ {
+ foundMatch = true;
+ ProcessProperty(type, property, nav, customData, false);
+ }
+ }
+
+ if (!foundMatch)
+ {
+ LogWarning(nav, DiagnosticId.XmlCouldNotFindPropertyOnType, name, type.GetDisplayName());
+ }
+ }
+ }
+
+ protected static PropertyDefinition? GetProperty(TypeDefinition type, string signature)
+ {
+ if (!type.HasProperties)
+ return null;
+
+ foreach (PropertyDefinition property in type.Properties)
+ if (signature == property.PropertyType.FullName + " " + property.Name)
+ return property;
+
+ return null;
+ }
+
+ protected virtual void ProcessProperty(TypeDefinition type, PropertyDefinition property, XPathNavigator nav, object? customData, bool fromSignature) { }
+
+ protected virtual AssemblyNameReference GetAssemblyName(XPathNavigator nav)
+ {
+ return AssemblyNameReference.Parse(GetFullName(nav));
+ }
+
+ protected static string GetFullName(XPathNavigator nav)
+ {
+ return GetAttribute(nav, FullNameAttributeName);
+ }
+
+ protected static string GetName(XPathNavigator nav)
+ {
+ return GetAttribute(nav, NameAttributeName);
+ }
+
+ protected static string GetSignature(XPathNavigator nav)
+ {
+ return GetAttribute(nav, SignatureAttributeName);
+ }
+
+ protected static string GetAttribute(XPathNavigator nav, string attribute)
+ {
+ return nav.GetAttribute(attribute, XmlNamespace);
+ }
+
+ protected MessageOrigin GetMessageOriginForPosition(XPathNavigator position)
+ {
+ return (position is IXmlLineInfo lineInfo)
+ ? new MessageOrigin(_xmlDocumentLocation, lineInfo.LineNumber, lineInfo.LinePosition, _resource?.Assembly)
+ : new MessageOrigin(_xmlDocumentLocation, 0, 0, _resource?.Assembly);
+ }
+ protected void LogWarning(string message, int warningCode, XPathNavigator position)
+ {
+ _context.LogWarning(message, warningCode, GetMessageOriginForPosition(position));
+ }
+
+ protected void LogWarning(XPathNavigator position, DiagnosticId id, params string[] args)
+ {
+ _context.LogWarning(GetMessageOriginForPosition(position), id, args);
+ }
+
+ public override string ToString() => GetType().Name + ": " + _xmlDocumentLocation;
+
+ public bool TryConvertValue(string value, TypeReference target, out object? result)
+ {
+ switch (target.MetadataType)
+ {
+ case MetadataType.Boolean:
+ if (bool.TryParse(value, out bool bvalue))
+ {
+ result = bvalue ? 1 : 0;
+ return true;
+ }
+
+ goto case MetadataType.Int32;
+
+ case MetadataType.Byte:
+ if (!byte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out byte byteresult))
+ break;
+
+ result = (int)byteresult;
+ return true;
+
+ case MetadataType.SByte:
+ if (!sbyte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out sbyte sbyteresult))
+ break;
+
+ result = (int)sbyteresult;
+ return true;
+
+ case MetadataType.Int16:
+ if (!short.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out short shortresult))
+ break;
+
+ result = (int)shortresult;
+ return true;
+
+ case MetadataType.UInt16:
+ if (!ushort.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ushort ushortresult))
+ break;
+
+ result = (int)ushortresult;
+ return true;
+
+ case MetadataType.Int32:
+ if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult))
+ break;
+
+ result = iresult;
+ return true;
+
+ case MetadataType.UInt32:
+ if (!uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out uint uresult))
+ break;
+
+ result = (int)uresult;
+ return true;
+
+ case MetadataType.Double:
+ if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out double dresult))
+ break;
+
+ result = dresult;
+ return true;
+
+ case MetadataType.Single:
+ if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float fresult))
+ break;
+
+ result = fresult;
+ return true;
+
+ case MetadataType.Int64:
+ if (!long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long lresult))
+ break;
+
+ result = lresult;
+ return true;
+
+ case MetadataType.UInt64:
+ if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong ulresult))
+ break;
+
+ result = (long)ulresult;
+ return true;
+
+ case MetadataType.Char:
+ if (!char.TryParse(value, out char chresult))
+ break;
+
+ result = (int)chresult;
+ return true;
+
+ case MetadataType.String:
+ if (value is string || value == null)
+ {
+ result = value;
+ return true;
+ }
+
+ break;
+
+ case MetadataType.ValueType:
+ if (value is string &&
+ _context.TryResolve(target) is TypeDefinition typeDefinition &&
+ typeDefinition.IsEnum)
+ {
+ var enumField = typeDefinition.Fields.Where(f => f.IsStatic && f.Name == value).FirstOrDefault();
+ if (enumField != null)
+ {
+ result = Convert.ToInt32(enumField.Constant);
+ return true;
+ }
+ }
+
+ break;
+ }
+
+ result = null;
+ return false;
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md
new file mode 100644
index 00000000000000..a75e53a1f949af
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md
@@ -0,0 +1 @@
+Sources taken from https://github.com/dotnet/linker/tree/c4abaf33f967a8fa42eb20fc386b774ad74ef319/src/linker/Linker.Steps.
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs
index a1e931e1725394..430c77f98f9056 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedInteropStubManager.cs
@@ -30,7 +30,7 @@ public UsageBasedInteropStubManager(InteropStateManager interopStateManager, PIn
public override void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
{
- if (method.IsPInvoke)
+ if (method.IsPInvoke && method.OwningType is MetadataType type && MarshalHelpers.IsRuntimeMarshallingEnabled(type.Module))
{
dependencies = dependencies ?? new DependencyList();
@@ -61,12 +61,19 @@ private void AddParameterMarshallingDependencies(ref DependencyList dependencies
if ((type.IsWellKnownType(WellKnownType.MulticastDelegate)
|| type == context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType))
{
- var message = new DiagnosticString(DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed).GetMessage(DiagnosticUtilities.GetMethodSignatureDisplayName(method));
- _logger.LogWarning(
- message,
- (int)DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed,
- method,
- MessageSubCategory.AotAnalysis);
+ // If we hit this p/invoke as part of delegate marshalling (i.e. this is a delegate
+ // that has another delegate in the signature), blame the delegate type, not the marshalling thunk.
+ // This should ideally warn from the use site (e.g. where GetDelegateForFunctionPointer
+ // is called) but it's currently hard to get a warning from those spots and this guarantees
+ // we won't miss a spot (e.g. a p/invoke that has a delegate and that delegate contains
+ // a System.Delegate parameter).
+ MethodDesc reportedMethod = method;
+ if (reportedMethod is Internal.IL.Stubs.DelegateMarshallingMethodThunk delegateThunkMethod)
+ {
+ reportedMethod = delegateThunkMethod.InvokeMethod;
+ }
+
+ _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 bd649904129bf8..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)
@@ -973,7 +970,7 @@ public AssemblyFeatureInfo(EcmaModule module, IReadOnlyDictionary
}
}
- private class LinkAttributesReader : ProcessLinkerXmlBase
+ private class LinkAttributesReader : ProcessXmlBase
{
private readonly HashSet _removedAttributes;
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs
index 830fb11d1ef21a..93fb4cc376c07e 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs
@@ -30,9 +30,9 @@ public override MethodIL GetMethodIL(MethodDesc method)
return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager);
}
- public MethodDesc GetCalliStub(MethodSignature signature)
+ public MethodDesc GetCalliStub(MethodSignature signature, ModuleDesc moduleContext)
{
- return _interopStateManager.GetPInvokeCalliStub(signature);
+ return _interopStateManager.GetPInvokeCalliStub(signature, moduleContext);
}
public string GetDirectCallExternName(MethodDesc method)
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
index 3420564b0715ef..d2df0a825ca402 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
@@ -373,6 +373,7 @@
+
@@ -527,6 +528,7 @@
+
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/Compiler/ReadyToRunHashCode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
index e506bb8b3b6ef8..9380a829b8f3c9 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs
@@ -34,10 +34,10 @@ public static int NameHashCode(string name)
byte[] src = Encoding.UTF8.GetBytes(name);
for (int i = 0; i < src.Length; i += 2)
{
- hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ src[i];
+ hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ (int)unchecked((sbyte)src[i]);
if (i + 1 < src.Length)
{
- hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ src[i + 1];
+ hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ (int)unchecked((sbyte)src[i + 1]);
}
else
{
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs
index a8e42ec37b9bc0..6fc1687d7a7f99 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs
@@ -46,6 +46,13 @@ private void EmitPInvokeCall(PInvokeILCodeStreams ilCodeStreams)
// if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke
if (_importMetadata.Flags.SetLastError)
{
+ if (!MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)_targetMethod.OwningType).Module))
+ {
+ // When runtime marshalling is disabled, we don't support generating the stub IL
+ // in Ready-to-Run so we can correctly throw an exception at runtime when the user tries to
+ // use SetLastError=true when marshalling is disabled.
+ throw new NotSupportedException();
+ }
callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
stubHelpersType.GetKnownMethod("ClearLastError", null)));
}
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.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs
index 927148cf006e26..ddb1d24c1b5357 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs
@@ -43,7 +43,8 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind)
private static Marshaller[] GetMarshallers(
MethodSignature methodSig,
PInvokeFlags flags,
- ParameterMetadata[] parameterMetadataArray)
+ ParameterMetadata[] parameterMetadataArray,
+ bool runtimeMarshallingEnabled)
{
Marshaller[] marshallers = new Marshaller[methodSig.Length + 1];
@@ -64,39 +65,55 @@ private static Marshaller[] GetMarshallers(
}
TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1]; //first item is the return type
- marshallers[i] = CreateMarshaller(parameterType,
- parameterIndex,
- methodSig.GetEmbeddedSignatureData(),
- MarshallerType.Argument,
- parameterMetadata.MarshalAsDescriptor,
- MarshalDirection.Forward,
- marshallers,
- parameterMetadata.Index,
- flags,
- parameterMetadata.In,
- parameterMetadata.Out,
- parameterMetadata.Return);
+ if (runtimeMarshallingEnabled)
+ {
+ marshallers[i] = CreateMarshaller(parameterType,
+ parameterIndex,
+ methodSig.GetEmbeddedSignatureData(),
+ MarshallerType.Argument,
+ parameterMetadata.MarshalAsDescriptor,
+ MarshalDirection.Forward,
+ marshallers,
+ parameterMetadata.Index,
+ flags,
+ parameterMetadata.In,
+ parameterMetadata.Out,
+ parameterMetadata.Return);
+ }
+ else
+ {
+ marshallers[i] = CreateDisabledMarshaller(
+ parameterType,
+ parameterIndex,
+ MarshallerType.Argument,
+ MarshalDirection.Forward,
+ marshallers,
+ parameterMetadata.Index,
+ flags,
+ parameterMetadata.Return);
+ }
}
return marshallers;
}
-
public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod)
{
Debug.Assert(targetMethod.IsPInvoke);
return GetMarshallers(
targetMethod.Signature,
targetMethod.GetPInvokeMethodMetadata().Flags,
- targetMethod.GetParameterMetadata());
+ targetMethod.GetParameterMetadata(),
+ MarshalHelpers.IsRuntimeMarshallingEnabled(((MetadataType)targetMethod.OwningType).Module));
}
- public static Marshaller[] GetMarshallersForSignature(MethodSignature methodSig, ParameterMetadata[] paramMetadata)
+ public static Marshaller[] GetMarshallersForSignature(MethodSignature methodSig, ParameterMetadata[] paramMetadata, ModuleDesc moduleContext)
{
return GetMarshallers(
methodSig,
new PInvokeFlags(PInvokeAttributes.None),
- paramMetadata);
+ paramMetadata,
+ MarshalHelpers.IsRuntimeMarshallingEnabled(moduleContext));
}
public static bool IsMarshallingRequired(MethodDesc targetMethod)
@@ -128,9 +145,9 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod)
return false;
}
- public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata)
+ public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata, ModuleDesc moduleContext)
{
- Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata);
+ Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata, moduleContext);
for (int i = 0; i < marshallers.Length; i++)
{
if (marshallers[i].IsMarshallingRequired())
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index f8282ab82cd27c..c2dcc6b397016c 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -1811,7 +1811,7 @@ private void ceeInfoGetCallInfo(
pResult->wrapperDelegateInvoke = false;
- Get_CORINFO_SIG_INFO(methodToCall, &pResult->sig, useInstantiatingStub);
+ Get_CORINFO_SIG_INFO(methodToCall, &pResult->sig, scope: null, useInstantiatingStub);
}
private uint getMethodAttribs(CORINFO_METHOD_STRUCT_* ftn)
@@ -2579,7 +2579,7 @@ private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_S
else
{
var sig = HandleToObject(callSiteSig->methodSignature);
- return Marshaller.IsMarshallingRequired(sig, Array.Empty());
+ return Marshaller.IsMarshallingRequired(sig, Array.Empty(), ((MetadataType)HandleToObject(callSiteSig->scope).OwningMethod.OwningType).Module);
}
}
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.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
index 5966efead0066f..1b1fbdf550777d 100644
--- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
+++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
@@ -1027,7 +1027,7 @@ private CorInfoHelpFunc getNewHelper(ref CORINFO_RESOLVED_TOKEN pResolvedToken,
TypeDesc type = HandleToObject(pResolvedToken.hClass);
Debug.Assert(!type.IsString && !type.IsArray && !type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
-
+
pHasSideEffects = type.HasFinalizer;
if (type.RequiresAlign8())
@@ -1520,7 +1520,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
targetIsFatFunctionPointer |= (flags & CORINFO_CALLINFO_FLAGS.CORINFO_CALLINFO_CALLVIRT) != 0 && !(pResult->kind == CORINFO_CALL_KIND.CORINFO_CALL);
- Get_CORINFO_SIG_INFO(targetMethod, &pResult->sig, targetIsFatFunctionPointer);
+ Get_CORINFO_SIG_INFO(targetMethod, &pResult->sig, scope: null, targetIsFatFunctionPointer);
if (useFatCallTransform)
{
pResult->sig.flags |= CorInfoSigInfoFlags.CORINFO_SIGFLAG_FAT_CALL;
@@ -1531,7 +1531,7 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
if (pResult->hMethod != pResolvedToken.hMethod)
{
pResult->verMethodFlags = getMethodAttribsInternal(targetMethod);
- Get_CORINFO_SIG_INFO(targetMethod, &pResult->verSig);
+ Get_CORINFO_SIG_INFO(targetMethod, &pResult->verSig, scope: null);
}
else
{
@@ -1791,7 +1791,9 @@ private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_S
#if DEBUG
MethodSignature methodSignature = (MethodSignature)HandleToObject((IntPtr)callSiteSig->pSig);
- MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(methodSignature);
+ MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(
+ methodSignature,
+ ((MetadataType)HandleToObject(callSiteSig->scope).OwningMethod.OwningType).Module);
Debug.Assert(!IsPInvokeStubRequired(stub));
#endif
@@ -1825,7 +1827,9 @@ private bool convertPInvokeCalliToCall(ref CORINFO_RESOLVED_TOKEN pResolvedToken
if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == 0)
return false;
- MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(signature);
+ MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(
+ signature,
+ ((MetadataType)methodIL.OwningMethod.OwningType).Module);
if (!mustConvert && !IsPInvokeStubRequired(stub))
return false;
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/ILCompiler/repro/repro.csproj b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj
index 52b0f44fc48918..c0df3bfd2c6ee3 100644
--- a/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj
+++ b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj
@@ -9,7 +9,7 @@
linux-x64;win-x64;osx-x64
Debug;Release;Checked
true
- 649;169;414
+ false
$"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/ToolBox/superpmi/.clang-format b/src/coreclr/tools/superpmi/.clang-format
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/.clang-format
rename to src/coreclr/tools/superpmi/.clang-format
diff --git a/src/coreclr/ToolBox/superpmi/CMakeLists.txt b/src/coreclr/tools/superpmi/CMakeLists.txt
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/CMakeLists.txt
rename to src/coreclr/tools/superpmi/CMakeLists.txt
diff --git a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt b/src/coreclr/tools/superpmi/mcs/CMakeLists.txt
similarity index 96%
rename from src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt
rename to src/coreclr/tools/superpmi/mcs/CMakeLists.txt
index 56dcaff658cc5a..8ce4c197250822 100644
--- a/src/coreclr/ToolBox/superpmi/mcs/CMakeLists.txt
+++ b/src/coreclr/tools/superpmi/mcs/CMakeLists.txt
@@ -68,4 +68,4 @@ else()
endif(CLR_CMAKE_HOST_UNIX)
-install_clr(TARGETS mcs DESTINATIONS .)
+install_clr(TARGETS mcs DESTINATIONS . COMPONENT spmi)
diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.cpp b/src/coreclr/tools/superpmi/mcs/commandline.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/commandline.cpp
rename to src/coreclr/tools/superpmi/mcs/commandline.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/commandline.h b/src/coreclr/tools/superpmi/mcs/commandline.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/commandline.h
rename to src/coreclr/tools/superpmi/mcs/commandline.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/mcs.cpp b/src/coreclr/tools/superpmi/mcs/mcs.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/mcs.cpp
rename to src/coreclr/tools/superpmi/mcs/mcs.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/mcs.h b/src/coreclr/tools/superpmi/mcs/mcs.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/mcs.h
rename to src/coreclr/tools/superpmi/mcs/mcs.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/removedup.cpp b/src/coreclr/tools/superpmi/mcs/removedup.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/removedup.cpp
rename to src/coreclr/tools/superpmi/mcs/removedup.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/removedup.h b/src/coreclr/tools/superpmi/mcs/removedup.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/removedup.h
rename to src/coreclr/tools/superpmi/mcs/removedup.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbasmdump.cpp b/src/coreclr/tools/superpmi/mcs/verbasmdump.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbasmdump.cpp
rename to src/coreclr/tools/superpmi/mcs/verbasmdump.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbasmdump.h b/src/coreclr/tools/superpmi/mcs/verbasmdump.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbasmdump.h
rename to src/coreclr/tools/superpmi/mcs/verbasmdump.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbconcat.cpp b/src/coreclr/tools/superpmi/mcs/verbconcat.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbconcat.cpp
rename to src/coreclr/tools/superpmi/mcs/verbconcat.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbconcat.h b/src/coreclr/tools/superpmi/mcs/verbconcat.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbconcat.h
rename to src/coreclr/tools/superpmi/mcs/verbconcat.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdump.cpp b/src/coreclr/tools/superpmi/mcs/verbdump.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdump.cpp
rename to src/coreclr/tools/superpmi/mcs/verbdump.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdump.h b/src/coreclr/tools/superpmi/mcs/verbdump.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdump.h
rename to src/coreclr/tools/superpmi/mcs/verbdump.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp b/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp
rename to src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.h b/src/coreclr/tools/superpmi/mcs/verbdumpmap.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.h
rename to src/coreclr/tools/superpmi/mcs/verbdumpmap.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.cpp b/src/coreclr/tools/superpmi/mcs/verbdumptoc.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.cpp
rename to src/coreclr/tools/superpmi/mcs/verbdumptoc.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.h b/src/coreclr/tools/superpmi/mcs/verbdumptoc.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbdumptoc.h
rename to src/coreclr/tools/superpmi/mcs/verbdumptoc.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbfracture.cpp b/src/coreclr/tools/superpmi/mcs/verbfracture.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbfracture.cpp
rename to src/coreclr/tools/superpmi/mcs/verbfracture.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbfracture.h b/src/coreclr/tools/superpmi/mcs/verbfracture.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbfracture.h
rename to src/coreclr/tools/superpmi/mcs/verbfracture.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbildump.cpp b/src/coreclr/tools/superpmi/mcs/verbildump.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbildump.cpp
rename to src/coreclr/tools/superpmi/mcs/verbildump.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbildump.h b/src/coreclr/tools/superpmi/mcs/verbildump.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbildump.h
rename to src/coreclr/tools/superpmi/mcs/verbildump.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbinteg.cpp b/src/coreclr/tools/superpmi/mcs/verbinteg.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbinteg.cpp
rename to src/coreclr/tools/superpmi/mcs/verbinteg.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbinteg.h b/src/coreclr/tools/superpmi/mcs/verbinteg.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbinteg.h
rename to src/coreclr/tools/superpmi/mcs/verbinteg.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp b/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbjitflags.cpp
rename to src/coreclr/tools/superpmi/mcs/verbjitflags.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h b/src/coreclr/tools/superpmi/mcs/verbjitflags.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbjitflags.h
rename to src/coreclr/tools/superpmi/mcs/verbjitflags.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbmerge.cpp b/src/coreclr/tools/superpmi/mcs/verbmerge.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbmerge.cpp
rename to src/coreclr/tools/superpmi/mcs/verbmerge.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbmerge.h b/src/coreclr/tools/superpmi/mcs/verbmerge.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbmerge.h
rename to src/coreclr/tools/superpmi/mcs/verbmerge.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.cpp b/src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.cpp
rename to src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.h b/src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbprintjiteeversion.h
rename to src/coreclr/tools/superpmi/mcs/verbprintjiteeversion.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbremovedup.cpp b/src/coreclr/tools/superpmi/mcs/verbremovedup.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbremovedup.cpp
rename to src/coreclr/tools/superpmi/mcs/verbremovedup.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbremovedup.h b/src/coreclr/tools/superpmi/mcs/verbremovedup.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbremovedup.h
rename to src/coreclr/tools/superpmi/mcs/verbremovedup.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstat.cpp b/src/coreclr/tools/superpmi/mcs/verbstat.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbstat.cpp
rename to src/coreclr/tools/superpmi/mcs/verbstat.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstat.h b/src/coreclr/tools/superpmi/mcs/verbstat.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbstat.h
rename to src/coreclr/tools/superpmi/mcs/verbstat.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstrip.cpp b/src/coreclr/tools/superpmi/mcs/verbstrip.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbstrip.cpp
rename to src/coreclr/tools/superpmi/mcs/verbstrip.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbstrip.h b/src/coreclr/tools/superpmi/mcs/verbstrip.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbstrip.h
rename to src/coreclr/tools/superpmi/mcs/verbstrip.h
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbtoc.cpp b/src/coreclr/tools/superpmi/mcs/verbtoc.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbtoc.cpp
rename to src/coreclr/tools/superpmi/mcs/verbtoc.cpp
diff --git a/src/coreclr/ToolBox/superpmi/mcs/verbtoc.h b/src/coreclr/tools/superpmi/mcs/verbtoc.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/mcs/verbtoc.h
rename to src/coreclr/tools/superpmi/mcs/verbtoc.h
diff --git a/src/coreclr/ToolBox/superpmi/readme.md b/src/coreclr/tools/superpmi/readme.md
similarity index 99%
rename from src/coreclr/ToolBox/superpmi/readme.md
rename to src/coreclr/tools/superpmi/readme.md
index c3de3dfe94288c..b84e8d01697bd3 100644
--- a/src/coreclr/ToolBox/superpmi/readme.md
+++ b/src/coreclr/tools/superpmi/readme.md
@@ -1,6 +1,6 @@
# Overview
-This directory (`src/coreclr/ToolBox/superpmi` in the GitHub
+This directory (`src/coreclr/tools/superpmi` in the GitHub
https://github.com/dotnet/runtime repository) contains the SuperPMI
tool used for testing the .NET just-in-time (JIT) compiler.
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h
rename to src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/asmdumper.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/asmdumper.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.h b/src/coreclr/tools/superpmi/superpmi-shared/asmdumper.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.h
rename to src/coreclr/tools/superpmi/superpmi-shared/asmdumper.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.cpp b/src/coreclr/tools/superpmi/superpmi-shared/callutils.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/callutils.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.h b/src/coreclr/tools/superpmi/superpmi-shared/callutils.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/callutils.h
rename to src/coreclr/tools/superpmi/superpmi-shared/callutils.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.h b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/compileresult.h
rename to src/coreclr/tools/superpmi/superpmi-shared/compileresult.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/crlwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/crlwmlist.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/crlwmlist.h
rename to src/coreclr/tools/superpmi/superpmi-shared/crlwmlist.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.cpp b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/errorhandling.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.h b/src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/errorhandling.h
rename to src/coreclr/tools/superpmi/superpmi-shared/errorhandling.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/hash.cpp b/src/coreclr/tools/superpmi/superpmi-shared/hash.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/hash.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/hash.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/hash.h b/src/coreclr/tools/superpmi/superpmi-shared/hash.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/hash.h
rename to src/coreclr/tools/superpmi/superpmi-shared/hash.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjitcompilerimpl.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitcompilerimpl.h
rename to src/coreclr/tools/superpmi/superpmi-shared/icorjitcompilerimpl.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjithostimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjithostimpl.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjithostimpl.h
rename to src/coreclr/tools/superpmi/superpmi-shared/icorjithostimpl.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/coreclr/tools/superpmi/superpmi-shared/icorjitinfoimpl.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
rename to src/coreclr/tools/superpmi/superpmi-shared/icorjitinfoimpl.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/lightweightmap.h b/src/coreclr/tools/superpmi/superpmi-shared/lightweightmap.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/lightweightmap.h
rename to src/coreclr/tools/superpmi/superpmi-shared/lightweightmap.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/logging.cpp b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/logging.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/logging.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/logging.h b/src/coreclr/tools/superpmi/superpmi-shared/logging.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/logging.h
rename to src/coreclr/tools/superpmi/superpmi-shared/logging.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h
rename to src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.cpp b/src/coreclr/tools/superpmi/superpmi-shared/mclist.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/mclist.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.h b/src/coreclr/tools/superpmi/superpmi-shared/mclist.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/mclist.h
rename to src/coreclr/tools/superpmi/superpmi-shared/mclist.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextiterator.h
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextiterator.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontextreader.h
rename to src/coreclr/tools/superpmi/superpmi-shared/methodcontextreader.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/runtimedetails.h b/src/coreclr/tools/superpmi/superpmi-shared/runtimedetails.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/runtimedetails.h
rename to src/coreclr/tools/superpmi/superpmi-shared/runtimedetails.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.cpp b/src/coreclr/tools/superpmi/superpmi-shared/simpletimer.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/simpletimer.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.h b/src/coreclr/tools/superpmi/superpmi-shared/simpletimer.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/simpletimer.h
rename to src/coreclr/tools/superpmi/superpmi-shared/simpletimer.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmidumphelper.h
rename to src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h b/src/coreclr/tools/superpmi/superpmi-shared/spmirecordhelper.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmirecordhelper.h
rename to src/coreclr/tools/superpmi/superpmi-shared/spmirecordhelper.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/spmiutil.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.h b/src/coreclr/tools/superpmi/superpmi-shared/spmiutil.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/spmiutil.h
rename to src/coreclr/tools/superpmi/superpmi-shared/spmiutil.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h b/src/coreclr/tools/superpmi/superpmi-shared/standardpch.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h
rename to src/coreclr/tools/superpmi/superpmi-shared/standardpch.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.cpp b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/tocfile.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.h b/src/coreclr/tools/superpmi/superpmi-shared/tocfile.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/tocfile.h
rename to src/coreclr/tools/superpmi/superpmi-shared/tocfile.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.cpp b/src/coreclr/tools/superpmi/superpmi-shared/typeutils.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.cpp
rename to src/coreclr/tools/superpmi/superpmi-shared/typeutils.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.h b/src/coreclr/tools/superpmi/superpmi-shared/typeutils.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shared/typeutils.h
rename to src/coreclr/tools/superpmi/superpmi-shared/typeutils.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt
similarity index 95%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt
index 1eb640c4cb9c08..5090fd411dfc99 100644
--- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/CMakeLists.txt
+++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/CMakeLists.txt
@@ -61,4 +61,4 @@ else()
)
endif(CLR_CMAKE_HOST_UNIX)
-install_clr(TARGETS superpmi-shim-collector DESTINATIONS .)
+install_clr(TARGETS superpmi-shim-collector DESTINATIONS . COMPONENT spmi)
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.h
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitcompiler.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.h
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/jithost.h
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/jithost.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.def b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.def
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.def
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.def
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.h b/src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-collector/superpmi-shim-collector.h
rename to src/coreclr/tools/superpmi/superpmi-shim-collector/superpmi-shim-collector.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt
similarity index 96%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt
index 602a6751b02da9..403841d95c8edb 100644
--- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/CMakeLists.txt
+++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/CMakeLists.txt
@@ -63,4 +63,4 @@ else()
)
endif(CLR_CMAKE_HOST_UNIX)
-install_clr(TARGETS superpmi-shim-counter DESTINATIONS .)
+install_clr(TARGETS superpmi-shim-counter DESTINATIONS . COMPONENT spmi)
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitcompiler.h
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitcompiler.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.h
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/jithost.h
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/jithost.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/methodcallsummarizer.h
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/methodcallsummarizer.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.def b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.def
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.def
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.def
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.h b/src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-counter/superpmi-shim-counter.h
rename to src/coreclr/tools/superpmi/superpmi-shim-counter/superpmi-shim-counter.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt
similarity index 96%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt
index b6f4d52ea4cab0..e1c168ef9d9dd9 100644
--- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/CMakeLists.txt
+++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/CMakeLists.txt
@@ -62,4 +62,4 @@ else()
)
endif(CLR_CMAKE_HOST_UNIX)
-install_clr(TARGETS superpmi-shim-simple DESTINATIONS .)
+install_clr(TARGETS superpmi-shim-simple DESTINATIONS . COMPONENT spmi)
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitcompiler.h
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitcompiler.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.h
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/jithost.h
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/jithost.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.def
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.def
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.def
diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h b/src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi-shim-simple/superpmi-shim-simple.h
rename to src/coreclr/tools/superpmi/superpmi-shim-simple/superpmi-shim-simple.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt b/src/coreclr/tools/superpmi/superpmi/CMakeLists.txt
similarity index 96%
rename from src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt
rename to src/coreclr/tools/superpmi/superpmi/CMakeLists.txt
index 4827c195dc2997..63237450898e3b 100644
--- a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt
+++ b/src/coreclr/tools/superpmi/superpmi/CMakeLists.txt
@@ -64,4 +64,4 @@ else()
)
endif(CLR_CMAKE_HOST_UNIX)
-install_clr(TARGETS superpmi DESTINATIONS .)
+install_clr(TARGETS superpmi DESTINATIONS . COMPONENT spmi)
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp b/src/coreclr/tools/superpmi/superpmi/commandline.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp
rename to src/coreclr/tools/superpmi/superpmi/commandline.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.h b/src/coreclr/tools/superpmi/superpmi/commandline.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/commandline.h
rename to src/coreclr/tools/superpmi/superpmi/commandline.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/cycletimer.cpp b/src/coreclr/tools/superpmi/superpmi/cycletimer.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/cycletimer.cpp
rename to src/coreclr/tools/superpmi/superpmi/cycletimer.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/cycletimer.h b/src/coreclr/tools/superpmi/superpmi/cycletimer.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/cycletimer.h
rename to src/coreclr/tools/superpmi/superpmi/cycletimer.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp
rename to src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.h b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.h
rename to src/coreclr/tools/superpmi/superpmi/icorjitinfo.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.cpp b/src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.cpp
rename to src/coreclr/tools/superpmi/superpmi/jitdebugger.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.h b/src/coreclr/tools/superpmi/superpmi/jitdebugger.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jitdebugger.h
rename to src/coreclr/tools/superpmi/superpmi/jitdebugger.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jithost.cpp b/src/coreclr/tools/superpmi/superpmi/jithost.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jithost.cpp
rename to src/coreclr/tools/superpmi/superpmi/jithost.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jithost.h b/src/coreclr/tools/superpmi/superpmi/jithost.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jithost.h
rename to src/coreclr/tools/superpmi/superpmi/jithost.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp b/src/coreclr/tools/superpmi/superpmi/jitinstance.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp
rename to src/coreclr/tools/superpmi/superpmi/jitinstance.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h b/src/coreclr/tools/superpmi/superpmi/jitinstance.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h
rename to src/coreclr/tools/superpmi/superpmi/jitinstance.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.cpp b/src/coreclr/tools/superpmi/superpmi/methodstatsemitter.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.cpp
rename to src/coreclr/tools/superpmi/superpmi/methodstatsemitter.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h b/src/coreclr/tools/superpmi/superpmi/methodstatsemitter.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h
rename to src/coreclr/tools/superpmi/superpmi/methodstatsemitter.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp b/src/coreclr/tools/superpmi/superpmi/metricssummary.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp
rename to src/coreclr/tools/superpmi/superpmi/metricssummary.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h b/src/coreclr/tools/superpmi/superpmi/metricssummary.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h
rename to src/coreclr/tools/superpmi/superpmi/metricssummary.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/neardiffer.cpp b/src/coreclr/tools/superpmi/superpmi/neardiffer.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/neardiffer.cpp
rename to src/coreclr/tools/superpmi/superpmi/neardiffer.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/neardiffer.h b/src/coreclr/tools/superpmi/superpmi/neardiffer.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/neardiffer.h
rename to src/coreclr/tools/superpmi/superpmi/neardiffer.h
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp
rename to src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp
rename to src/coreclr/tools/superpmi/superpmi/superpmi.cpp
diff --git a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.h b/src/coreclr/tools/superpmi/superpmi/superpmi.h
similarity index 100%
rename from src/coreclr/ToolBox/superpmi/superpmi/superpmi.h
rename to src/coreclr/tools/superpmi/superpmi/superpmi.h
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 afc0c057d3ee51..ee90f9db6c538a 100644
--- a/src/coreclr/utilcode/util.cpp
+++ b/src/coreclr/utilcode/util.cpp
@@ -19,66 +19,12 @@
#include "corinfo.h"
#include "volatile.h"
#include "mdfileformat.h"
+#include
#ifndef DACCESS_COMPILE
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.
//*****************************************************************************
@@ -827,7 +773,7 @@ DWORD LCM(DWORD u, DWORD v)
CONTRACTL_END;
#if !defined(FEATURE_REDHAWK) && (defined(TARGET_AMD64) || defined(TARGET_ARM64))
- BOOL enableGCCPUGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCCpuGroup) != 0;
+ BOOL enableGCCPUGroups = Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup);
if (!enableGCCPUGroups)
return;
@@ -1805,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/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h
index 29b9dddfb7de44..33589c27bae392 100644
--- a/src/coreclr/vm/amd64/cgencpu.h
+++ b/src/coreclr/vm/amd64/cgencpu.h
@@ -415,8 +415,6 @@ extern "C" void setFPReturn(int fpSize, INT64 retVal);
extern "C" void getFPReturn(int fpSize, INT64 *retval);
-struct ComToManagedExRecord; // defined in cgencpu.cpp
-
#include
struct DECLSPEC_ALIGN(8) UMEntryThunkCode
{
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/arm64/asmhelpers.S b/src/coreclr/vm/arm64/asmhelpers.S
index 7d8b3c7dd88b23..e7725cd16e63b6 100644
--- a/src/coreclr/vm/arm64/asmhelpers.S
+++ b/src/coreclr/vm/arm64/asmhelpers.S
@@ -551,152 +551,6 @@ LOCAL_LABEL(LNullThis):
LEAF_END SinglecastDelegateInvokeStub, _TEXT
-#ifdef FEATURE_COMINTEROP
-
-#define ComCallPreStub_FrameSize (SIZEOF__GSCookie + SIZEOF__ComMethodFrame)
-#define ComCallPreStub_FirstStackAdjust (8 + SIZEOF__ArgumentRegisters + 2 * 8) // x8, reg args , fp & lr already pushed
-#define ComCallPreStub_StackAlloc0 (ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust)
-#define ComCallPreStub_StackAlloc1 (ComCallPreStub_StackAlloc0 + SIZEOF__FloatArgumentRegisters + 8)// 8 for ErrorReturn
-#define ComCallPreStub_StackAlloc (ComCallPreStub_StackAlloc1 + (ComCallPreStub_StackAlloc1 & 8))
-
-#define ComCallPreStub_FrameOffset (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust))
-#define ComCallPreStub_ErrorReturnOffset0 SIZEOF__FloatArgumentRegisters
-
-#define ComCallPreStub_FirstStackAdjust (ComCallPreStub_ErrorReturnOffset0 + (ComCallPreStub_ErrorReturnOffset0 & 8))
-
-// ------------------------------------------------------------------
-// COM to CLR stub called the first time a particular method is invoked.//
-//
-// On entry:
-// x12 : ComCallMethodDesc* provided by prepad thunk
-// plus user arguments in registers and on the stack
-//
-// On exit:
-// tail calls to real method
-//
-NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler
-
- // Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, -ComCallPreStub_FirstStackAdjust!
- PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc
-
- SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc)
-
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- str x12, [sp, #(ComCallPreStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)]
- add x0, sp, #(ComCallPreStub_FrameOffset)
- add x1, sp, #(ComCallPreStub_ErrorReturnOffset)
- bl C_FUNC(ComPreStubWorker)
-
- cbz x0, LOCAL_LABEL(ComCallPreStub_ErrorExit)
-
- mov x12, x0
-
- // pop the stack and restore original register state
- RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0
- RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc)
-
- EPILOG_STACK_FREE ComCallPreStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust!
-
- // and tailcall to the actual method
- EPILOG_BRANCH_REG x12
-
-ComCallPreStub_ErrorExit
- ldr x0, [sp, #(ComCallPreStub_ErrorReturnOffset)] // ErrorReturn
-
- // pop the stack
- EPILOG_STACK_FREE ComCallPreStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust!
-
- EPILOG_RETURN
-
-NESTED_END ComCallPreStub, _TEXT
-
-// ------------------------------------------------------------------
-// COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker.
-//
-// On entry:
-// x12 : ComCallMethodDesc* provided by prepad thunk
-// plus user arguments in registers and on the stack
-//
-// On exit:
-// Result in x0/d0 as per the real method being called
-//
- NESTED_ENTRY GenericComCallStub, _TEXT, NoHandler
-
- // Save arguments and return address
- PROLOG_SAVE_REG_PAIR fp, lr, -GenericComCallStub_FirstStackAdjust!
- PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc
-
- SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc)
- SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0
-
- str x12, [sp, #(GenericComCallStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)]
- add x1, sp, #GenericComCallStub_FrameOffset
- bl C_FUNC(COMToCLRWorker)
-
- // pop the stack
- EPILOG_STACK_FREE GenericComCallStub_StackAlloc
- EPILOG_RESTORE_REG_PAIR fp, lr, GenericComCallStub_FirstStackAdjust!
-
- EPILOG_RETURN
-
- NESTED_END GenericComCallStub, _TEXT
-
-// ------------------------------------------------------------------
-// COM to CLR stub called from COMToCLRWorker that actually dispatches to the real managed method.
-//
-// On entry:
-// x0 : dwStackSlots, count of argument stack slots to copy
-// x1 : pFrame, ComMethodFrame pushed by GenericComCallStub above
-// x2 : pTarget, address of code to call
-// x3 : pSecretArg, hidden argument passed to target above in x12
-// x4 : pDangerousThis, managed 'this' reference
-//
-// On exit:
-// Result in x0/d0 as per the real method being called
-//
- NESTED_ENTRY COMToCLRDispatchHelper, _TEXT,CallDescrWorkerUnwindFrameChainHandler
-
- PROLOG_SAVE_REG_PAIR fp, lr, -16!
-
- cbz x0, LOCAL_LABEL(COMToCLRDispatchHelper_RegSetup)
-
- add x9, x1, #SIZEOF__ComMethodFrame
- add x9, x9, x0, LSL #3
-COMToCLRDispatchHelper_StackLoop
- ldr x8, [x9, #-8]!
- str x8, [sp, #-8]!
- sub x0, x0, #1
- cbnz x0, LOCAL_LABEL(COMToCLRDispatchHelper_StackLoop)
-
-COMToCLRDispatchHelper_RegSetup
-
- RESTORE_FLOAT_ARGUMENT_REGISTERS x1, -1 * GenericComCallStub_FrameOffset
-
- mov lr, x2
- mov x12, x3
-
- mov x0, x4
-
- ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)]
- ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)]
- ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)]
- ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters - 8)]
-
- ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)]
-
- blr lr
-
- EPILOG_STACK_RESTORE
- EPILOG_RESTORE_REG_PAIR fp, lr, 16!
- EPILOG_RETURN
-
- NESTED_END COMToCLRDispatchHelper, _TEXT
-
-#endif // FEATURE_COMINTEROP
//
// x12 = UMEntryThunk*
//
@@ -1039,39 +893,6 @@ DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj
DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj
#endif
-#ifdef FEATURE_COMINTEROP
-
-// Function used by COM interop to get floating point return value (since it's not in the same
-// register(s) as non-floating point values).
-//
-// On entry//
-// x0 : size of the FP result (4 or 8 bytes)
-// x1 : pointer to 64-bit buffer to receive result
-//
-// On exit:
-// buffer pointed to by x1 on entry contains the float or double argument as appropriate
-//
-LEAF_ENTRY getFPReturn, _TEXT
- str d0, [x1]
-LEAF_END getFPReturn, _TEXT
-
-// ------------------------------------------------------------------
-// Function used by COM interop to set floating point return value (since it's not in the same
-// register(s) as non-floating point values).
-//
-// On entry:
-// x0 : size of the FP result (4 or 8 bytes)
-// x1 : 32-bit or 64-bit FP result
-//
-// On exit:
-// s0 : float result if x0 == 4
-// d0 : double result if x0 == 8
-//
-LEAF_ENTRY setFPReturn, _TEXT
- fmov d0, x1
-LEAF_END setFPReturn, _TEXT
-#endif
-
//
// JIT Static access helpers when coreclr host specifies single appdomain flag
//
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 72a2e1152210b8..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));
@@ -1775,6 +1755,42 @@ BOOL Module::IsRuntimeWrapExceptions()
return !!(m_dwPersistedFlags & WRAP_EXCEPTIONS);
}
+BOOL Module::IsRuntimeMarshallingEnabled()
+{
+ CONTRACTL
+ {
+ THROWS;
+ if (IsRuntimeMarshallingEnabledCached()) GC_NOTRIGGER; else GC_TRIGGERS;
+ MODE_ANY;
+ }
+ CONTRACTL_END
+
+ if (IsRuntimeMarshallingEnabledCached())
+ {
+ return !!(m_dwPersistedFlags & RUNTIME_MARSHALLING_ENABLED);
+ }
+
+ HRESULT hr;
+
+ IMDInternalImport *mdImport = GetAssembly()->GetMDImport();
+
+ mdToken token;
+ if (SUCCEEDED(hr = mdImport->GetAssemblyFromScope(&token)))
+ {
+ const BYTE *pVal;
+ ULONG cbVal;
+
+ hr = mdImport->GetCustomAttributeByName(token,
+ g_DisableRuntimeMarshallingAttribute,
+ (const void**)&pVal, &cbVal);
+ }
+
+ FastInterlockOr(&m_dwPersistedFlags, RUNTIME_MARSHALLING_ENABLED_IS_CACHED |
+ (hr == S_OK ? 0 : RUNTIME_MARSHALLING_ENABLED));
+
+ return hr != S_OK;
+}
+
BOOL Module::IsPreV4Assembly()
{
CONTRACTL
@@ -1786,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;
@@ -1968,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;
@@ -1994,7 +2010,7 @@ void Module::SetDomainFile(DomainFile *pDomainFile)
}
else
{
- pLoaderAllocator = pDomainFile->GetAppDomain()->GetLoaderAllocator();
+ pLoaderAllocator = pDomainAssembly->GetAppDomain()->GetLoaderAllocator();
}
SIZE_T size = GetDomainLocalModuleSize();
@@ -2034,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
@@ -2042,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()
@@ -2057,7 +2073,7 @@ OBJECTREF Module::GetExposedObject()
}
CONTRACT_END;
- RETURN GetDomainFile()->GetExposedModuleObject();
+ RETURN GetDomainAssembly()->GetExposedModuleObject();
}
//
@@ -3284,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)
@@ -3368,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;
}
@@ -3395,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());
}
}
@@ -3438,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);
@@ -3447,7 +3463,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile)
if (IsManifest())
{
if (kFile == mdFileNil)
- pModule = GetAssembly()->GetManifestModule();
+ pModule = GetAssembly()->GetModule();
}
else
{
@@ -3461,7 +3477,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile)
{
if (kMatch == mdFileNil)
{
- pModule = pAssembly->GetManifestModule();
+ pModule = pAssembly->GetModule();
}
else
{
@@ -3469,7 +3485,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile)
}
}
else
- pModule = pAssembly->GetManifestModule()->LookupFile(kMatch);
+ pModule = pAssembly->GetModule()->LookupFile(kMatch);
}
#ifndef DACCESS_COMPILE
@@ -3485,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;
@@ -3507,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,
@@ -3546,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);
@@ -3557,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;
}
@@ -4031,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;
@@ -4042,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();
}
@@ -4063,7 +4079,7 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in
m_pPEAssembly->GetPath().GetCount(),
GetAssembly(),
pDomain,
- pDomainFile,
+ pDomainAssembly,
attaching);
result = TRUE;
@@ -4559,7 +4575,7 @@ Module *Module::GetModuleFromIndex(DWORD ix)
Assembly *pAssembly = this->LookupAssemblyRef(mdAssemblyRefToken);
if (pAssembly)
{
- RETURN pAssembly->GetManifestModule();
+ RETURN pAssembly->GetModule();
}
else
{
@@ -6442,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);
}
}
}
@@ -7437,7 +7449,7 @@ VOID Module::EnsureActive()
MODE_ANY;
}
CONTRACTL_END;
- GetDomainFile()->EnsureActive();
+ GetDomainAssembly()->EnsureActive();
}
#endif // DACCESS_COMPILE
@@ -7456,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
@@ -7477,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 e7dd5629a2c84b..d9cd6742cb6c0e 100644
--- a/src/coreclr/vm/ceeload.h
+++ b/src/coreclr/vm/ceeload.h
@@ -832,8 +832,12 @@ 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,
+ //If runtime marshalling is enabled for this assembly
+ RUNTIME_MARSHALLING_ENABLED = 0x00010000,
};
Volatile m_dwTransientFlags;
@@ -1127,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();
@@ -1190,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
@@ -1218,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();
@@ -1431,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);
@@ -1714,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);
@@ -1985,18 +1970,6 @@ class Module
return dac_cast(m_ModuleID);
}
- SIZE_T * GetAddrModuleID()
- {
- LIMITED_METHOD_CONTRACT;
- return (SIZE_T*) &m_ModuleID;
- }
-
- static SIZE_T GetOffsetOfModuleID()
- {
- LIMITED_METHOD_CONTRACT;
- return offsetof(Module, m_ModuleID);
- }
-
PTR_DomainLocalModule GetDomainLocalModule();
// LoaderHeap for storing IJW thunks
@@ -2071,6 +2044,18 @@ class Module
//-----------------------------------------------------------------------------------------
BOOL IsRuntimeWrapExceptions();
+ //-----------------------------------------------------------------------------------------
+ // If true, the built-in runtime-generated marshalling subsystem will be used for
+ // P/Invokes, function pointer invocations, and delegates defined in this module
+ //-----------------------------------------------------------------------------------------
+ BOOL IsRuntimeMarshallingEnabled();
+
+ BOOL IsRuntimeMarshallingEnabledCached()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (m_dwPersistedFlags & RUNTIME_MARSHALLING_ENABLED_IS_CACHED);
+ }
+
BOOL HasDefaultDllImportSearchPathsAttribute();
BOOL IsDefaultDllImportSearchPathsAttributeCached()
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/class.h b/src/coreclr/vm/class.h
index 0ccacd36a9f914..9aa6c6994e726e 100644
--- a/src/coreclr/vm/class.h
+++ b/src/coreclr/vm/class.h
@@ -363,19 +363,21 @@ class EEClassLayoutInfo
private:
enum {
// TRUE if the GC layout of the class is bit-for-bit identical
- // to its unmanaged counterpart (i.e. no internal reference fields,
- // no ansi-unicode char conversions required, etc.) Used to
- // optimize marshaling.
- e_BLITTABLE = 0x01,
- // Post V1.0 addition: Is this type also sequential in managed memory?
- e_MANAGED_SEQUENTIAL = 0x02,
+ // to its unmanaged counterpart with the runtime marshalling system
+ // (i.e. no internal reference fields, no ansi-unicode char conversions required, etc.)
+ // Used to optimize marshaling.
+ e_BLITTABLE = 0x01,
+ // Is this type also sequential in managed memory?
+ e_MANAGED_SEQUENTIAL = 0x02,
// When a sequential/explicit type has no fields, it is conceptually
// zero-sized, but actually is 1 byte in length. This holds onto this
// fact and allows us to revert the 1 byte of padding when another
// explicit type inherits from this type.
- e_ZERO_SIZED = 0x04,
+ e_ZERO_SIZED = 0x04,
// The size of the struct is explicitly specified in the meta-data.
- e_HAS_EXPLICIT_SIZE = 0x08
+ e_HAS_EXPLICIT_SIZE = 0x08,
+ // The type recursively has a field that is LayoutKind.Auto and not an enum.
+ e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT = 0x10
};
BYTE m_bFlags;
@@ -419,6 +421,12 @@ class EEClassLayoutInfo
return (m_bFlags & e_HAS_EXPLICIT_SIZE) == e_HAS_EXPLICIT_SIZE;
}
+ BOOL HasAutoLayoutField() const
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (m_bFlags & e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT) == e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT;
+ }
+
BYTE GetPackingSize() const
{
LIMITED_METHOD_CONTRACT;
@@ -453,6 +461,13 @@ class EEClassLayoutInfo
m_bFlags = hasExplicitSize ? (m_bFlags | e_HAS_EXPLICIT_SIZE)
: (m_bFlags & ~e_HAS_EXPLICIT_SIZE);
}
+
+ void SetHasAutoLayoutField(BOOL hasAutoLayoutField)
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_bFlags = hasAutoLayoutField ? (m_bFlags | e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT)
+ : (m_bFlags & ~e_HAS_AUTO_LAYOUT_FIELD_IN_LAYOUT);
+ }
};
//
@@ -1395,6 +1410,8 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
BOOL HasExplicitSize();
+ BOOL IsAutoLayoutOrHasAutoLayoutField();
+
static void GetBestFitMapping(MethodTable * pMT, BOOL *pfBestFitMapping, BOOL *pfThrowOnUnmappableChar);
/*
@@ -2082,6 +2099,13 @@ inline BOOL EEClass::HasExplicitSize()
return HasLayout() && GetLayoutInfo()->HasExplicitSize();
}
+inline BOOL EEClass::IsAutoLayoutOrHasAutoLayoutField()
+{
+ LIMITED_METHOD_CONTRACT;
+ // If this type is not auto
+ return !HasLayout() || GetLayoutInfo()->HasAutoLayoutField();
+}
+
//==========================================================================
// These routines manage the prestub (a bootstrapping stub that all
// FunctionDesc's are initialized with.)
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/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp
index 90315764cfbc5d..b95c6d4108ed45 100644
--- a/src/coreclr/vm/classlayoutinfo.cpp
+++ b/src/coreclr/vm/classlayoutinfo.cpp
@@ -226,23 +226,18 @@ namespace
*pLargestAlignmentRequirementOut = LargestAlignmentRequirement;
}
- //=======================================================================
- // This function returns TRUE if the provided corElemType disqualifies
- // the structure from being a managed-sequential structure.
- // The fsig parameter is used when the corElemType doesn't contain enough information
- // to successfully determine if this field disqualifies the type from being
- // managed-sequential.
- // This function also fills in the pManagedPlacementInfo structure for this field.
- //=======================================================================
- BOOL CheckIfDisqualifiedFromManagedSequential(CorElementType corElemType, MetaSig& fsig, RawFieldPlacementInfo* pManagedPlacementInfo)
+ RawFieldPlacementInfo GetFieldPlacementInfo(CorElementType corElemType, TypeHandle pNestedType)
{
- pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE;
- pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE;
+ RawFieldPlacementInfo placementInfo;
+ // Initialize offset to a dummy value as we set it to the correct value later.
+ placementInfo.m_offset = (UINT32)-1;
+ placementInfo.m_size = TARGET_POINTER_SIZE;
+ placementInfo.m_alignment = TARGET_POINTER_SIZE;
// This type may qualify for ManagedSequential. Collect managed size and alignment info.
if (CorTypeInfo::IsPrimitiveType(corElemType))
{
// Safe cast - no primitive type is larger than 4gb!
- pManagedPlacementInfo->m_size = ((UINT32)CorTypeInfo::Size(corElemType));
+ placementInfo.m_size = ((UINT32)CorTypeInfo::Size(corElemType));
#if defined(TARGET_X86) && defined(UNIX_X86_ABI)
switch (corElemType)
{
@@ -251,67 +246,87 @@ namespace
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R8:
{
- pManagedPlacementInfo->m_alignment = 4;
+ placementInfo.m_alignment = 4;
break;
}
default:
{
- pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size;
+ placementInfo.m_alignment = placementInfo.m_size;
break;
}
}
#else // TARGET_X86 && UNIX_X86_ABI
- pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size;
+ placementInfo.m_alignment = placementInfo.m_size;
#endif
- return FALSE;
}
else if (corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR)
{
- pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE;
- pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE;
-
- return FALSE;
+ placementInfo.m_size = TARGET_POINTER_SIZE;
+ placementInfo.m_alignment = TARGET_POINTER_SIZE;
}
else if (corElemType == ELEMENT_TYPE_VALUETYPE)
{
- TypeHandle pNestedType = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
- CLASS_LOAD_APPROXPARENTS,
- TRUE);
+ _ASSERTE(!pNestedType.IsNull());
- pManagedPlacementInfo->m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes());
+ placementInfo.m_size = (pNestedType.GetMethodTable()->GetNumInstanceFieldBytes());
#if !defined(TARGET_64BIT) && (DATA_ALIGNMENT > 4)
- if (pManagedPlacementInfo->m_size >= DATA_ALIGNMENT)
+ if (placementInfo.m_size >= DATA_ALIGNMENT)
{
- pManagedPlacementInfo->m_alignment = DATA_ALIGNMENT;
+ placementInfo.m_alignment = DATA_ALIGNMENT;
}
else
#elif defined(FEATURE_64BIT_ALIGNMENT)
if (pNestedType.RequiresAlign8())
{
- pManagedPlacementInfo->m_alignment = 8;
+ placementInfo.m_alignment = 8;
}
else
#endif // FEATURE_64BIT_ALIGNMENT
if (pNestedType.GetMethodTable()->ContainsPointers())
{
// this field type has GC pointers in it, which need to be pointer-size aligned
- // so do this if it has not been done already
- pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE;
+ placementInfo.m_alignment = TARGET_POINTER_SIZE;
}
else
{
- pManagedPlacementInfo->m_alignment = pNestedType.GetMethodTable()->GetFieldAlignmentRequirement();
+ placementInfo.m_alignment = pNestedType.GetMethodTable()->GetFieldAlignmentRequirement();
}
- // Types that have GC Pointer fields (objects or byrefs) are disqualified from ManagedSequential layout.
- return pNestedType.GetMethodTable()->ContainsPointers() != FALSE;
}
// No other type permitted for ManagedSequential.
+ return placementInfo;
+ }
+
+ BOOL TypeHasGCPointers(CorElementType corElemType, TypeHandle pNestedType)
+ {
+ if (CorTypeInfo::IsPrimitiveType(corElemType) || corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR)
+ {
+ return FALSE;
+ }
+ if (corElemType == ELEMENT_TYPE_VALUETYPE)
+ {
+ _ASSERTE(!pNestedType.IsNull());
+ return pNestedType.GetMethodTable()->ContainsPointers() != FALSE;
+ }
return TRUE;
}
+ BOOL TypeHasAutoLayoutField(CorElementType corElemType, TypeHandle pNestedType)
+ {
+ if (CorTypeInfo::IsPrimitiveType(corElemType) || corElemType == ELEMENT_TYPE_PTR || corElemType == ELEMENT_TYPE_FNPTR)
+ {
+ return FALSE;
+ }
+ if (corElemType == ELEMENT_TYPE_VALUETYPE)
+ {
+ _ASSERTE(!pNestedType.IsNull());
+ return pNestedType.IsEnum() || pNestedType.GetMethodTable()->IsAutoLayoutOrHasAutoLayoutField();
+ }
+ return FALSE;
+ }
+
#ifdef UNIX_AMD64_ABI
void SystemVAmd64CheckForPassNativeStructInRegister(MethodTable* pMT, EEClassNativeLayoutInfo* pNativeLayoutInfo)
{
@@ -437,6 +452,7 @@ namespace
ParseNativeTypeFlags nativeTypeFlags,
const SigTypeContext* pTypeContext,
BOOL* fDisqualifyFromManagedSequential,
+ BOOL* fHasAutoLayoutField,
LayoutRawFieldInfo* pFieldInfoArrayOut,
BOOL* pIsBlittableOut,
ULONG* cInstanceFields
@@ -505,7 +521,16 @@ namespace
#endif
MetaSig fsig(pCOMSignature, cbCOMSignature, pModule, pTypeContext, MetaSig::sigField);
CorElementType corElemType = fsig.NextArgNormalized();
- *fDisqualifyFromManagedSequential |= CheckIfDisqualifiedFromManagedSequential(corElemType, fsig, &pFieldInfoArrayOut->m_placement);
+ TypeHandle typeHandleMaybe;
+ if (corElemType == ELEMENT_TYPE_VALUETYPE) // Only look up the next element in the signature if it is a value type to avoid causing recursive type loads in valid scenarios.
+ {
+ typeHandleMaybe = fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes,
+ CLASS_LOAD_APPROXPARENTS,
+ TRUE);
+ }
+ pFieldInfoArrayOut->m_placement = GetFieldPlacementInfo(corElemType, typeHandleMaybe);
+ *fDisqualifyFromManagedSequential |= TypeHasGCPointers(corElemType, typeHandleMaybe);
+ *fHasAutoLayoutField |= TypeHasAutoLayoutField(corElemType, typeHandleMaybe);
if (!IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags))
*pIsBlittableOut = FALSE;
@@ -598,6 +623,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
// Running tote - if anything in this type disqualifies it from being ManagedSequential, somebody will set this to TRUE by the the time
// function exits.
BOOL fDisqualifyFromManagedSequential;
+ BOOL hasAutoLayoutField = FALSE;
// Check if this type might be ManagedSequential. Only valuetypes marked Sequential can be
// ManagedSequential. Other issues checked below might also disqualify the type.
@@ -612,6 +638,11 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
fDisqualifyFromManagedSequential = TRUE;
}
+ if (pParentMT && !pParentMT->IsValueTypeClass() && pParentMT->IsAutoLayoutOrHasAutoLayoutField())
+ {
+ hasAutoLayoutField = TRUE;
+ }
+
BOOL fHasNonTrivialParent = pParentMT &&
!pParentMT->IsObjectClass() &&
@@ -659,6 +690,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
nativeTypeFlags,
pTypeContext,
&fDisqualifyFromManagedSequential,
+ &hasAutoLayoutField,
pInfoArrayOut,
&isBlittable,
&cInstanceFields
@@ -671,6 +703,8 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
isBlittable = isBlittable && (fHasNonTrivialParent ? pParentMT->IsBlittable() : TRUE);
pEEClassLayoutInfoOut->SetIsBlittable(isBlittable);
+ pEEClassLayoutInfoOut->SetHasAutoLayoutField(hasAutoLayoutField);
+
S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*));
if (cbSortArraySize.IsOverflow())
{
diff --git a/src/coreclr/vm/classnames.h b/src/coreclr/vm/classnames.h
index 94e9b1025c7a4b..7d71ce2c7d891c 100644
--- a/src/coreclr/vm/classnames.h
+++ b/src/coreclr/vm/classnames.h
@@ -113,4 +113,6 @@
#define g_CriticalFinalizerObjectName "CriticalFinalizerObject"
+#define g_DisableRuntimeMarshallingAttribute "System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute"
+
#endif //!__CLASSNAMES_H__
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/dacenumerablehash.inl b/src/coreclr/vm/dacenumerablehash.inl
index e4e5de3b11f3fc..049329bbfbc67d 100644
--- a/src/coreclr/vm/dacenumerablehash.inl
+++ b/src/coreclr/vm/dacenumerablehash.inl
@@ -400,8 +400,8 @@ namespace HashTableDetail
{
// Use the C++ detection idiom (https://isocpp.org/blog/2017/09/detection-idiom-a-stopgap-for-concepts-simon-brand) to call the
// derived table's EnumMemoryRegionsForEntry method if it defines one.
- template
- using void_t = void;
+ template struct make_void { using type = void; };
+ template using void_t = typename make_void::type;
template
struct negation : std::integral_constant { };
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/dllimport.cpp b/src/coreclr/vm/dllimport.cpp
index 6c4ce7608660ee..3a35a8e108fa45 100644
--- a/src/coreclr/vm/dllimport.cpp
+++ b/src/coreclr/vm/dllimport.cpp
@@ -107,6 +107,7 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD)
m_tkMethodDef = pMD->GetMemberDef();
SigTypeContext::InitTypeContext(pMD, &m_typeContext);
+ m_pMetadataModule = pMD->GetModule();
m_pLoaderModule = pMD->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation.
INDEBUG(InitDebugNames());
@@ -133,11 +134,13 @@ StubSigDesc::StubSigDesc(MethodDesc* pMD, const Signature& sig, Module* pModule)
{
m_tkMethodDef = pMD->GetMemberDef();
SigTypeContext::InitTypeContext(pMD, &m_typeContext);
+ m_pMetadataModule = pMD->GetModule();
m_pLoaderModule = pMD->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation.
}
else
{
m_tkMethodDef = mdMethodDefNil;
+ m_pMetadataModule = m_pModule;
m_pLoaderModule = m_pModule;
}
@@ -166,7 +169,8 @@ StubSigDesc::StubSigDesc(MethodTable* pMT, const Signature& sig, Module* pModule
if (pMT != NULL)
{
SigTypeContext::InitTypeContext(pMT, &m_typeContext);
- m_pLoaderModule = pMT->GetLoaderModule(); // Used for ILStubCache selection and MethodTable creation.
+ m_pMetadataModule = pMT->GetModule();
+ m_pLoaderModule = pMT->GetLoaderModule();
}
else
{
@@ -193,6 +197,7 @@ StubSigDesc::StubSigDesc(const Signature& sig, Module* pModule)
m_sig = sig;
m_pModule = pModule;
m_tkMethodDef = mdMethodDefNil;
+ m_pMetadataModule = m_pModule;
m_pLoaderModule = m_pModule;
INDEBUG(InitDebugNames());
@@ -959,7 +964,7 @@ class ILStubState : public StubState
if (pTargetMD)
{
pTargetMD->GetMethodInfoWithNewSig(strNamespaceOrClassName, strMethodName, strMethodSignature);
- uModuleId = (UINT64)pTargetMD->GetModule()->GetAddrModuleID();
+ uModuleId = (UINT64)(TADDR)pTargetMD->GetModule_NoLogging();
}
//
@@ -3287,6 +3292,15 @@ BOOL NDirect::MarshalingRequired(
}
CollateParamTokens(pMDImport, methodToken, numArgs - 1, pParamTokenArray);
+ // We enable the runtime marshalling system whenever it is enabled on the module as a whole
+ // or when the call is a COM interop call. COM interop calls are already using a significant portion of the runtime
+ // marshalling system just to function at all, so we aren't going to disable the parameter marshalling;
+ // we'd rather have developers use the feature flag to diable the whole COM interop subsystem at once.
+ bool runtimeMarshallingEnabled = pModule->IsRuntimeMarshallingEnabled();
+#ifdef FEATURE_COMINTEROP
+ runtimeMarshallingEnabled |= pMD && pMD->IsComPlusCall();
+#endif
+
for (ULONG i = 0; i < numArgs; i++)
{
SigPointer arg = ptr;
@@ -3300,7 +3314,7 @@ BOOL NDirect::MarshalingRequired(
IfFailThrow(arg.GetElemType(NULL)); // skip ELEMENT_TYPE_PTR
IfFailThrow(arg.PeekElemType(&type));
- if (type == ELEMENT_TYPE_VALUETYPE)
+ if (runtimeMarshallingEnabled && type == ELEMENT_TYPE_VALUETYPE)
{
if ((arg.HasCustomModifier(pModule,
"Microsoft.VisualC.NeedsCopyConstructorModifier",
@@ -3331,11 +3345,21 @@ BOOL NDirect::MarshalingRequired(
{
TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext);
- // JIT can handle internal blittable value types
- if (!hndArgType.IsBlittable() && !hndArgType.IsEnum())
+ // When the runtime runtime marshalling system is disabled, we don't support
+ // any types that contain gc pointers, but all "unmanaged" types are treated as blittable
+ // as long as they aren't auto-layout and don't have any auto-layout fields.
+ if (!runtimeMarshallingEnabled &&
+ (hndArgType.GetMethodTable()->ContainsPointers()
+ || hndArgType.GetMethodTable()->IsAutoLayoutOrHasAutoLayoutField()))
{
return TRUE;
}
+ else if (runtimeMarshallingEnabled && !hndArgType.IsBlittable() && !hndArgType.IsEnum())
+ {
+ // When the runtime runtime marshalling system is enabled, we do special handling
+ // for any types that aren't blittable or enums.
+ return TRUE;
+ }
if (i > 0)
{
@@ -3348,10 +3372,15 @@ BOOL NDirect::MarshalingRequired(
case ELEMENT_TYPE_BOOLEAN:
case ELEMENT_TYPE_CHAR:
{
+ // When runtime marshalling is enabled:
// Bool requires marshaling
// Char may require marshaling (MARSHAL_TYPE_ANSICHAR)
- return TRUE;
+ if (runtimeMarshallingEnabled)
+ {
+ return TRUE;
+ }
}
+ FALLTHROUGH;
default:
{
@@ -3376,7 +3405,10 @@ BOOL NDirect::MarshalingRequired(
// check for explicit MarshalAs
NativeTypeParamInfo paramInfo;
- if (pParamTokenArray[i] != mdParamDefNil)
+ // We only check the MarshalAs info when the runtime marshalling system is enabled.
+ // We ignore MarshalAs when the system is disabled, so no reason to disqualify from inlining
+ // when it is present.
+ if (runtimeMarshallingEnabled && pParamTokenArray[i] != mdParamDefNil)
{
if (!ParseNativeTypeInfo(pParamTokenArray[i], pMDImport, ¶mInfo) ||
paramInfo.m_NativeType != NATIVE_TYPE_DEFAULT)
@@ -3594,6 +3626,7 @@ static void CreateNDirectStubWorker(StubState* pss,
CONSISTENCY_CHECK_MSGF(false, ("BreakOnInteropStubSetup: '%s' ", pSigDesc->m_pDebugName));
#endif // _DEBUG
+ bool runtimeMarshallingEnabled = SF_IsCOMStub(dwStubFlags) || pSigDesc->m_pMetadataModule->IsRuntimeMarshallingEnabled();
if (SF_IsCOMStub(dwStubFlags))
{
_ASSERTE(0 == nlType);
@@ -3615,26 +3648,48 @@ static void CreateNDirectStubWorker(StubState* pss,
&pSigDesc->m_typeContext);
if (SF_IsVarArgStub(dwStubFlags))
+ {
+ if (!runtimeMarshallingEnabled)
+ {
+ COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_VARARGS);
+ }
msig.SetTreatAsVarArg();
+ }
bool fThisCall = (unmgdCallConv == CorInfoCallConvExtension::Thiscall);
- pss->SetLastError(nlFlags & nlfLastError);
+ if (nlFlags & nlfLastError)
+ {
+ if (!runtimeMarshallingEnabled)
+ {
+ COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR);
+ }
+ pss->SetLastError(TRUE);
+ }
// This has been in the product since forward P/Invoke via delegates was
// introduced. It's wrong, but please keep it for backward compatibility.
- if (SF_IsDelegateStub(dwStubFlags))
+ if (runtimeMarshallingEnabled && SF_IsDelegateStub(dwStubFlags))
pss->SetLastError(TRUE);
pss->BeginEmit(dwStubFlags);
if (-1 != iLCIDArg)
{
- // The code to handle the LCID will call MarshalLCID before calling MarshalArgument
+ if (!runtimeMarshallingEnabled)
+ {
+ COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID);
+ }
+ // The code to handle the LCID will call MarshalLCID before calling MarshalArgument
// on the argument the LCID should go after. So we just bump up the index here.
iLCIDArg++;
}
+ if (!runtimeMarshallingEnabled && SF_IsHRESULTSwapping(dwStubFlags))
+ {
+ COMPlusThrow(kMarshalDirectiveException, IDS_EE_NDIRECT_DISABLEDMARSHAL_PRESERVESIG);
+ }
+
int numArgs = msig.NumFixedArgs();
// thiscall must have at least one parameter (the "this")
diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h
index f731823ff4a0b0..8b472e3a0aafb6 100644
--- a/src/coreclr/vm/dllimport.h
+++ b/src/coreclr/vm/dllimport.h
@@ -23,7 +23,15 @@ struct StubSigDesc
MethodDesc *m_pMD;
MethodTable *m_pMT;
Signature m_sig;
+ // Module to use for signature reading.
Module *m_pModule;
+ // Module that owns any metadata that influences interop behavior.
+ // This is usually the same as m_pModule, but can differ with vararg
+ // P/Invokes, where the calling assembly's module is assigned to m_pModule
+ // since the specific caller signature is defined in that assembly, not the
+ // assembly that defined the P/Invoke.
+ Module *m_pMetadataModule;
+ // Used for ILStubCache selection and MethodTable creation.
Module *m_pLoaderModule;
mdMethodDef m_tkMethodDef;
SigTypeContext m_typeContext;
diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp
index 455d33813eec03..65d2afd7d05128 100644
--- a/src/coreclr/vm/dllimportcallback.cpp
+++ b/src/coreclr/vm/dllimportcallback.cpp
@@ -195,37 +195,6 @@ extern "C" VOID STDCALL ReversePInvokeBadTransition()
);
}
-// Disable from a place that is calling into managed code via a UMEntryThunk.
-extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThunk *pUMEntryThunk)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_TRIGGERS;
-
- // Do not add a CONTRACT here. We haven't set up SEH.
-
- // WARNING!!!!
- // when we start executing here, we are actually in cooperative mode. But we
- // haven't synchronized with the barrier to reentry yet. So we are in a highly
- // dangerous mode. If we call managed code, we will potentially be active in
- // the GC heap, even as GC's are occuring!
-
- // We must do the following in this order, because otherwise we would be constructing
- // the exception for the abort without synchronizing with the GC. Also, we have no
- // CLR SEH set up, despite the fact that we may throw a ThreadAbortException.
- pThread->RareDisablePreemptiveGC();
- pThread->HandleThreadAbort();
-
-#ifdef DEBUGGING_SUPPORTED
- // If the debugger is attached, we use this opportunity to see if
- // we're disabling preemptive GC on the way into the runtime from
- // unmanaged code. We end up here because
- // Increment/DecrementTraceCallCount() will bump
- // g_TrapReturningThreads for us.
- if (CORDebuggerTraceCall())
- g_pDebugInterface->TraceCall((const BYTE *)pUMEntryThunk->GetManagedTarget());
-#endif // DEBUGGING_SUPPORTED
-}
-
PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk)
{
STATIC_CONTRACT_THROWS;
@@ -234,39 +203,13 @@ PCODE TheUMEntryPrestubWorker(UMEntryThunk * pUMEntryThunk)
Thread * pThread = GetThreadNULLOk();
if (pThread == NULL)
- pThread = CreateThreadBlockThrow();
-
- GCX_COOP_THREAD_EXISTS(pThread);
-
- if (pThread->IsAbortRequested())
- pThread->HandleThreadAbort();
-
- UMEntryThunk::DoRunTimeInit(pUMEntryThunk);
-
- return (PCODE)pUMEntryThunk->GetCode();
-}
-
-void RunTimeInit_Wrapper(LPVOID /* UMThunkMarshInfo * */ ptr)
-{
- WRAPPER_NO_CONTRACT;
-
- UMEntryThunk::DoRunTimeInit((UMEntryThunk*)ptr);
-}
-
-
-// asm entrypoint
-void STDCALL UMEntryThunk::DoRunTimeInit(UMEntryThunk* pUMEntryThunk)
-{
-
- CONTRACTL
{
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- ENTRY_POINT;
- PRECONDITION(CheckPointer(pUMEntryThunk));
+ CREATETHREAD_IF_NULL_FAILFAST(pThread, W("Failed to setup new thread during reverse P/Invoke"));
}
- CONTRACTL_END;
+
+ // Verify the current thread isn't in COOP mode.
+ if (pThread->PreemptiveGCDisabled())
+ ReversePInvokeBadTransition();
INSTALL_MANAGED_EXCEPTION_DISPATCHER;
// this method is called by stubs which are called by managed code,
@@ -274,15 +217,13 @@ void STDCALL UMEntryThunk::DoRunTimeInit(UMEntryThunk* pUMEntryThunk)
// exceptions don't leak out into managed code.
INSTALL_UNWIND_AND_CONTINUE_HANDLER;
- {
- GCX_PREEMP();
-
- ExecutableWriterHolder uMEntryThunkWriterHolder(pUMEntryThunk, sizeof(UMEntryThunk));
- uMEntryThunkWriterHolder.GetRW()->RunTimeInit(pUMEntryThunk);
- }
+ ExecutableWriterHolder uMEntryThunkWriterHolder(pUMEntryThunk, sizeof(UMEntryThunk));
+ uMEntryThunkWriterHolder.GetRW()->RunTimeInit(pUMEntryThunk);
UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;
+
+ return (PCODE)pUMEntryThunk->GetCode();
}
UMEntryThunk* UMEntryThunk::CreateUMEntryThunk()
diff --git a/src/coreclr/vm/dllimportcallback.h b/src/coreclr/vm/dllimportcallback.h
index 14b7db5704824f..fb2214a8c18d5a 100644
--- a/src/coreclr/vm/dllimportcallback.h
+++ b/src/coreclr/vm/dllimportcallback.h
@@ -16,6 +16,12 @@
#include "class.h"
#include "dllimport.h"
+class UMThunkMarshInfo;
+typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo;
+
+class UMEntryThunk;
+typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk;
+
//----------------------------------------------------------------------
// This structure collects all information needed to marshal an
// unmanaged->managed thunk. The only information missing is the
@@ -189,9 +195,6 @@ class UMEntryThunk
#endif // _DEBUG
}
- // asm entrypoint
- static VOID STDCALL DoRunTimeInit(UMEntryThunk* pThis);
-
PCODE GetManagedTarget() const
{
CONTRACT (PCODE)
@@ -396,14 +399,7 @@ class UMEntryThunkCache
};
#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL)
-//-------------------------------------------------------------------------
-// One-time creation of special prestub to initialize UMEntryThunks.
-//-------------------------------------------------------------------------
-Stub *GenerateUMThunkPrestub();
-
EXCEPTION_HANDLER_DECL(FastNExportExceptHandler);
-EXCEPTION_HANDLER_DECL(UMThunkPrestubHandler);
-
#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL
extern "C" void TheUMEntryPrestub(void);
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 be7a6826854f0e..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()
@@ -322,8 +316,6 @@ FCFuncStart(gDelegateFuncs)
FCFuncEnd()
FCFuncStart(gMathFuncs)
- FCFuncElementSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::Abs)
- FCFuncElementSig("Abs", &gsig_SM_Flt_RetFlt, COMSingle::Abs)
FCFuncElement("Acos", COMDouble::Acos)
FCFuncElement("Acosh", COMDouble::Acosh)
FCFuncElement("Asin", COMDouble::Asin)
@@ -772,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..31d858814d020c 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));
}
@@ -94,6 +97,14 @@ BOOL FieldDesc::IsObjRef()
return CorTypeInfo::IsObjRef_NoThrow(GetFieldType());
}
+// Return whether the field is a GC ref type
+BOOL FieldDesc::IsByRef()
+{
+ WRAPPER_NO_CONTRACT;
+ SUPPORTS_DAC;
+ return CorTypeInfo::IsByRef_NoThrow(GetFieldType());
+}
+
BOOL FieldDesc::MightHaveName(ULONG nameHashValue)
{
LIMITED_METHOD_CONTRACT;
@@ -152,6 +163,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/field.h b/src/coreclr/vm/field.h
index 25e9e19fb7306a..72378df259060a 100644
--- a/src/coreclr/vm/field.h
+++ b/src/coreclr/vm/field.h
@@ -353,6 +353,8 @@ class FieldDesc
BOOL IsObjRef();
+ BOOL IsByRef();
+
UINT LoadSize();
// Return -1 if the type isn't loaded yet (i.e. if LookupFieldTypeHandle() would return null)
diff --git a/src/coreclr/vm/frames.cpp b/src/coreclr/vm/frames.cpp
index 2f7a4d91c9ec4b..9377b4ec028b72 100644
--- a/src/coreclr/vm/frames.cpp
+++ b/src/coreclr/vm/frames.cpp
@@ -63,21 +63,12 @@ void Frame::Log() {
MethodDesc* method = GetFunction();
-#ifdef TARGET_X86
- if (GetVTablePtr() == UMThkCallFrame::GetMethodFrameVPtr())
- method = ((UMThkCallFrame*) this)->GetUMEntryThunk()->GetMethod();
-#endif
-
STRESS_LOG3(LF_STUBS, LL_INFO1000000, "STUBS: In Stub with Frame %p assoc Method %pM FrameType = %pV\n", this, method, *((void**) this));
char buff[64];
const char* frameType;
if (GetVTablePtr() == PrestubMethodFrame::GetMethodFrameVPtr())
frameType = "PreStub";
-#ifdef TARGET_X86
- else if (GetVTablePtr() == UMThkCallFrame::GetMethodFrameVPtr())
- frameType = "UMThkCallFrame";
-#endif
else if (GetVTablePtr() == PInvokeCalliFrame::GetMethodFrameVPtr())
{
sprintf_s(buff, ARRAY_SIZE(buff), "PInvoke CALLI target" FMT_ADDR,
@@ -1603,32 +1594,6 @@ void ComMethodFrame::DoSecondPassHandlerCleanup(Frame * pCurFrame)
#endif // FEATURE_COMINTEROP
-
-#ifdef TARGET_X86
-
-PTR_UMEntryThunk UMThkCallFrame::GetUMEntryThunk()
-{
- LIMITED_METHOD_DAC_CONTRACT;
- return dac_cast(GetDatum());
-}
-
-#ifdef DACCESS_COMPILE
-void UMThkCallFrame::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
-{
- WRAPPER_NO_CONTRACT;
- UnmanagedToManagedFrame::EnumMemoryRegions(flags);
-
- // Pieces of the UMEntryThunk need to be saved.
- UMEntryThunk *pThunk = GetUMEntryThunk();
- DacEnumMemoryRegion(dac_cast(pThunk), sizeof(UMEntryThunk));
-
- UMThunkMarshInfo *pMarshInfo = pThunk->GetUMThunkMarshInfo();
- DacEnumMemoryRegion(dac_cast(pMarshInfo), sizeof(UMThunkMarshInfo));
-}
-#endif
-
-#endif // TARGET_X86
-
#ifndef DACCESS_COMPILE
#if defined(_MSC_VER) && defined(TARGET_X86)
@@ -1952,16 +1917,18 @@ VOID InlinedCallFrame::Init()
}
-
+#ifdef FEATURE_COMINTEROP
void UnmanagedToManagedFrame::ExceptionUnwind()
{
WRAPPER_NO_CONTRACT;
AppDomain::ExceptionUnwind(this);
}
+#endif // FEATURE_COMINTEROP
#endif // !DACCESS_COMPILE
+#ifdef FEATURE_COMINTEROP
PCODE UnmanagedToManagedFrame::GetReturnAddress()
{
WRAPPER_NO_CONTRACT;
@@ -1980,6 +1947,7 @@ PCODE UnmanagedToManagedFrame::GetReturnAddress()
return pRetAddr;
}
}
+#endif // FEATURE_COMINTEROP
#ifndef DACCESS_COMPILE
//=================================================================================
diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h
index c2946ced0b2f66..82e57cbbb04017 100644
--- a/src/coreclr/vm/frames.h
+++ b/src/coreclr/vm/frames.h
@@ -90,23 +90,18 @@
// | |
// | +-TPMethodFrame - for calls on transparent proxy
// |
+#ifdef FEATURE_COMINTEROP
// +-UnmanagedToManagedFrame - this frame represents a transition from
// | | unmanaged code back to managed code. It's
// | | main functions are to stop COM+ exception
// | | propagation and to expose unmanaged parameters.
// | |
-#ifdef FEATURE_COMINTEROP
-// | |
// | +-ComMethodFrame - this frame represents a transition from
// | | com to com+
// | |
// | +-ComPrestubMethodFrame - prestub frame for calls from COM to CLR
// |
#endif //FEATURE_COMINTEROP
-#ifdef TARGET_X86
-// | +-UMThkCallFrame - this frame represents an unmanaged->managed
-// | transition through N/Direct
-#endif
#if defined(TARGET_X86) && !defined(UNIX_X86_ABI)
// +-TailCallFrame - padding for tailcalls
// |
@@ -172,16 +167,9 @@ Delegate over a native function pointer:
Reverse P/Invoke (used for C++ exports & fixups as well as delegates
obtained from function pointers):
Normal stub:
- x86: The stub is generated by UMEntryThunk::CompileUMThunkWorker
- (in DllImportCallback.cpp) and it is frameless. It calls directly
- the managed target or to IL stub if marshaling is required.
- non-x86: The stub exists statically as UMThunkStub and calls to IL stub.
+ The stub exists statically as UMThunkStub and calls to IL stub.
Prestub:
- The prestub is generated by GenerateUMThunkPrestub (x86) or exists statically
- as TheUMEntryPrestub (64-bit), and it erects an UMThkCallFrame frame.
-
-Reverse P/Invoke AppDomain selector stub:
- The asm helper is IJWNOADThunkJumpTarget (in asmhelpers.asm) and it is frameless.
+ The prestub exists statically as TheUMEntryPrestub.
//------------------------------------------------------------------------
#endif // 0
@@ -212,8 +200,8 @@ FRAME_TYPE_NAME(HelperMethodFrame_3OBJ)
FRAME_TYPE_NAME(HelperMethodFrame_PROTECTOBJ)
FRAME_ABSTRACT_TYPE_NAME(FramedMethodFrame)
FRAME_TYPE_NAME(MulticastFrame)
-FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame)
#ifdef FEATURE_COMINTEROP
+FRAME_ABSTRACT_TYPE_NAME(UnmanagedToManagedFrame)
FRAME_TYPE_NAME(ComMethodFrame)
FRAME_TYPE_NAME(ComPlusMethodFrame)
FRAME_TYPE_NAME(ComPrestubMethodFrame)
@@ -238,9 +226,6 @@ FRAME_TYPE_NAME(DebuggerClassInitMarkFrame)
FRAME_TYPE_NAME(DebuggerSecurityCodeMarkFrame)
FRAME_TYPE_NAME(DebuggerExitFrame)
FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame)
-#ifdef TARGET_X86
-FRAME_TYPE_NAME(UMThkCallFrame)
-#endif
FRAME_TYPE_NAME(InlinedCallFrame)
#if defined(TARGET_X86) && !defined(UNIX_X86_ABI)
FRAME_TYPE_NAME(TailCallFrame)
@@ -281,9 +266,6 @@ class Frame;
class FramedMethodFrame;
typedef VPTR(class FramedMethodFrame) PTR_FramedMethodFrame;
struct HijackArgs;
-class UMEntryThunk;
-class UMThunkMarshInfo;
-class Marshaler;
struct ResolveCacheElem;
#if defined(DACCESS_COMPILE)
class DacDbiInterfaceImpl;
@@ -1814,6 +1796,8 @@ class MulticastFrame : public TransitionFrame
};
+#ifdef FEATURE_COMINTEROP
+
//-----------------------------------------------------------------------
// Transition frame from unmanaged to managed
//-----------------------------------------------------------------------
@@ -1922,8 +1906,6 @@ class UnmanagedToManagedFrame : public Frame
#endif
};
-#ifdef FEATURE_COMINTEROP
-
//------------------------------------------------------------------------
// This frame represents a transition from COM to COM+
//------------------------------------------------------------------------
@@ -2774,43 +2756,6 @@ class DebuggerU2MCatchHandlerFrame : public Frame
DEFINE_VTABLE_GETTER_AND_DTOR(DebuggerU2MCatchHandlerFrame)
};
-
-class UMThunkMarshInfo;
-typedef DPTR(class UMThunkMarshInfo) PTR_UMThunkMarshInfo;
-
-class UMEntryThunk;
-typedef DPTR(class UMEntryThunk) PTR_UMEntryThunk;
-
-#if defined(TARGET_X86)
-//------------------------------------------------------------------------
-// This frame guards an unmanaged->managed transition thru a UMThk
-//------------------------------------------------------------------------
-
-class UMThkCallFrame : public UnmanagedToManagedFrame
-{
- VPTR_VTABLE_CLASS(UMThkCallFrame, UnmanagedToManagedFrame)
-
-public:
-
-#ifdef DACCESS_COMPILE
- virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
-#endif
-
- PTR_UMEntryThunk GetUMEntryThunk();
-
- static int GetOffsetOfUMEntryThunk()
- {
- WRAPPER_NO_CONTRACT;
- return GetOffsetOfDatum();
- }
-
-protected:
-
- // Keep as last entry in class
- DEFINE_VTABLE_GETTER_AND_CTOR_AND_DTOR(UMThkCallFrame)
-};
-#endif // TARGET_X86 && !TARGET_UNIX
-
// Frame for the Reverse PInvoke (i.e. UnmanagedCallersOnlyAttribute).
struct ReversePInvokeFrame
{
@@ -2821,29 +2766,6 @@ struct ReversePInvokeFrame
#endif
};
-#if defined(TARGET_X86) && defined(FEATURE_COMINTEROP)
-//-------------------------------------------------------------------------
-// Exception handler for COM to managed frame
-// and the layout of the exception registration record structure in the stack
-// the layout is similar to the NT's EXCEPTIONREGISTRATION record
-// followed by the UnmanagedToManagedFrame specific info
-
-struct ComToManagedExRecord
-{
- EXCEPTION_REGISTRATION_RECORD m_ExReg;
- ArgumentRegisters m_argRegs;
- GSCookie m_gsCookie;
- UMThkCallFrame m_frame;
-
- UnmanagedToManagedFrame * GetCurrFrame()
- {
- LIMITED_METHOD_CONTRACT;
- return &m_frame;
- }
-};
-#endif // TARGET_X86 && FEATURE_COMINTEROP
-
-
//------------------------------------------------------------------------
// This frame is pushed by any JIT'ted method that contains one or more
// inlined N/Direct calls. Note that the JIT'ted method keeps it pushed
diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm
index d3eb78da472562..896c249822c552 100644
--- a/src/coreclr/vm/i386/asmhelpers.asm
+++ b/src/coreclr/vm/i386/asmhelpers.asm
@@ -43,7 +43,6 @@ EXTERN _COMPlusFrameHandlerRevCom:PROC
endif ; FEATURE_COMINTEROP
EXTERN __alloca_probe:PROC
EXTERN _NDirectImportWorker@4:PROC
-EXTERN _UMThunkStubRareDisableWorker@8:PROC
EXTERN _VarargPInvokeStubWorker@12:PROC
EXTERN _GenericPInvokeCalliStubWorker@12:PROC
@@ -53,6 +52,7 @@ EXTERN _CopyCtorCallStubWorker@4:PROC
endif
EXTERN _PreStubWorker@8:PROC
+EXTERN _TheUMEntryPrestubWorker@4:PROC
ifdef FEATURE_COMINTEROP
EXTERN _CLRToCOMWorker@8:PROC
@@ -255,9 +255,6 @@ COMPlusNestedExceptionHandler proto c
FastNExportExceptHandler proto c
.safeseh FastNExportExceptHandler
-UMThunkPrestubHandler proto c
-.safeseh UMThunkPrestubHandler
-
ifdef FEATURE_COMINTEROP
COMPlusFrameHandlerRevCom proto c
.safeseh COMPlusFrameHandlerRevCom
@@ -872,23 +869,6 @@ getFPReturn4:
retn 8
_getFPReturn@8 endp
-; VOID __cdecl UMThunkStubRareDisable()
-;
-; @todo: this is very similar to StubRareDisable
-;
-_UMThunkStubRareDisable proc public
- push eax
- push ecx
-
- push eax ; Push the UMEntryThunk
- push ecx ; Push thread
- call _UMThunkStubRareDisableWorker@8
-
- pop ecx
- pop eax
- retn
-_UMThunkStubRareDisable endp
-
; void __stdcall JIT_ProfilerEnterLeaveTailcallStub(UINT_PTR ProfilerHandle)
_JIT_ProfilerEnterLeaveTailcallStub@4 proc public
@@ -1432,6 +1412,22 @@ public _ThePreStubPatchLabel@0
ret
_ThePreStubPatch@0 endp
+_TheUMEntryPrestub@0 proc public
+ ; push argument registers
+ push ecx
+ push edx
+
+ push eax ; UMEntryThunk*
+ call _TheUMEntryPrestubWorker@4
+
+ ; pop argument registers
+ pop edx
+ pop ecx
+
+ ; eax = PCODE
+ jmp eax ; Tail Jmp
+_TheUMEntryPrestub@0 endp
+
ifdef FEATURE_COMINTEROP
;==========================================================================
; CLR -> COM generic or late-bound call
diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp
index f0a81d6daeea16..d2d5d1676e95c8 100644
--- a/src/coreclr/vm/i386/cgenx86.cpp
+++ b/src/coreclr/vm/i386/cgenx86.cpp
@@ -931,58 +931,6 @@ WORD GetUnpatchedCodeData(LPCBYTE pAddr)
#ifndef DACCESS_COMPILE
-#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL)
-//-------------------------------------------------------------------------
-// One-time creation of special prestub to initialize UMEntryThunks.
-//-------------------------------------------------------------------------
-Stub *GenerateUMThunkPrestub()
-{
- CONTRACT(Stub*)
- {
- STANDARD_VM_CHECK;
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- CPUSTUBLINKER sl;
- CPUSTUBLINKER *psl = &sl;
-
- CodeLabel* rgRareLabels[] = { psl->NewCodeLabel(),
- psl->NewCodeLabel(),
- psl->NewCodeLabel()
- };
-
-
- CodeLabel* rgRejoinLabels[] = { psl->NewCodeLabel(),
- psl->NewCodeLabel(),
- psl->NewCodeLabel()
- };
-
- // emit the initial prolog
- psl->EmitComMethodStubProlog(UMThkCallFrame::GetMethodFrameVPtr(), rgRareLabels, rgRejoinLabels, FALSE /*Don't profile*/);
-
- // mov ecx, [esi+UMThkCallFrame.pUMEntryThunk]
- psl->X86EmitIndexRegLoad(kECX, kESI, UMThkCallFrame::GetOffsetOfUMEntryThunk());
-
- // The call conv is a __stdcall
- psl->X86EmitPushReg(kECX);
-
- // call UMEntryThunk::DoRunTimeInit
- psl->X86EmitCall(psl->NewExternalCodeLabel((LPVOID)UMEntryThunk::DoRunTimeInit), 4);
-
- // mov ecx, [esi+UMThkCallFrame.pUMEntryThunk]
- psl->X86EmitIndexRegLoad(kEAX, kESI, UMThkCallFrame::GetOffsetOfUMEntryThunk());
-
- // lea eax, [eax + UMEntryThunk.m_code] // point to fixedup UMEntryThunk
- psl->X86EmitOp(0x8d, kEAX, kEAX,
- UMEntryThunk::GetCodeOffset() + UMEntryThunkCode::GetEntryPointOffset());
-
- psl->EmitComMethodStubEpilog(UMThkCallFrame::GetMethodFrameVPtr(), rgRareLabels, rgRejoinLabels, FALSE /*Don't profile*/);
-
- RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap());
-}
-#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL
-
Stub *GenerateInitPInvokeFrameHelper()
{
CONTRACT(Stub*)
diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp
index 3d2e0e4dddeca0..15dd0667dd6c4f 100644
--- a/src/coreclr/vm/i386/excepx86.cpp
+++ b/src/coreclr/vm/i386/excepx86.cpp
@@ -113,17 +113,6 @@ static void RtlUnwindCallback()
_ASSERTE(!"Should never get here");
}
-BOOL NExportSEH(EXCEPTION_REGISTRATION_RECORD* pEHR)
-{
- LIMITED_METHOD_CONTRACT;
-
- if ((LPVOID)pEHR->Handler == (LPVOID)UMThunkPrestubHandler)
- {
- return TRUE;
- }
- return FALSE;
-}
-
BOOL FastNExportSEH(EXCEPTION_REGISTRATION_RECORD* pEHR)
{
LIMITED_METHOD_CONTRACT;
@@ -156,9 +145,8 @@ BOOL IsUnmanagedToManagedSEHHandler(EXCEPTION_REGISTRATION_RECORD *pEstablisherF
//
// ComPlusFrameSEH() is for COMPlusFrameHandler & COMPlusNestedExceptionHandler.
// FastNExportSEH() is for FastNExportExceptHandler.
- // NExportSEH() is for UMThunkPrestubHandler.
//
- return (ComPlusFrameSEH(pEstablisherFrame) || FastNExportSEH(pEstablisherFrame) || NExportSEH(pEstablisherFrame) || ReverseCOMSEH(pEstablisherFrame));
+ return (ComPlusFrameSEH(pEstablisherFrame) || FastNExportSEH(pEstablisherFrame) || ReverseCOMSEH(pEstablisherFrame));
}
Frame *GetCurrFrame(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame)
@@ -166,10 +154,7 @@ Frame *GetCurrFrame(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame)
Frame *pFrame;
WRAPPER_NO_CONTRACT;
_ASSERTE(IsUnmanagedToManagedSEHHandler(pEstablisherFrame));
- if (NExportSEH(pEstablisherFrame))
- pFrame = ((ComToManagedExRecord *)pEstablisherFrame)->GetCurrFrame();
- else
- pFrame = ((FrameHandlerExRecord *)pEstablisherFrame)->GetCurrFrame();
+ pFrame = ((FrameHandlerExRecord *)pEstablisherFrame)->GetCurrFrame();
// Assert that the exception frame is on the thread or that the exception frame is the top frame.
_ASSERTE(GetThreadNULLOk() == NULL || GetThread()->GetFrame() == (Frame*)-1 || GetThread()->GetFrame() <= pFrame);
@@ -3384,52 +3369,6 @@ EXCEPTION_HANDLER_IMPL(FastNExportExceptHandler)
return retval;
}
-
-// Just like a regular NExport handler -- except it pops an extra frame on unwind. A handler
-// like this is needed by the COMMethodStubProlog code. It first pushes a frame -- and then
-// pushes a handler. When we unwind, we need to pop the extra frame to avoid corrupting the
-// frame chain in the event of an unmanaged catcher.
-//
-EXCEPTION_HANDLER_IMPL(UMThunkPrestubHandler)
-{
- // @todo: we'd like to have a dynamic contract here, but there's a problem. (Bug 129180) Enter on the CRST used
- // in HandleManagedFault leaves the no-trigger count incremented. The destructor of this contract will restore
- // it to zero, then when we leave the CRST in LinkFrameAndThrow, we assert because we're trying to decrement the
- // gc-trigger count down past zero. The solution is to fix what we're doing with this CRST.
- STATIC_CONTRACT_THROWS; // COMPlusFrameHandler throws
- STATIC_CONTRACT_GC_TRIGGERS;
- STATIC_CONTRACT_MODE_ANY;
-
- EXCEPTION_DISPOSITION retval = ExceptionContinueSearch;
-
- // We must forward to the COMPlusFrameHandler. This will unwind the Frame Chain up to here, and also leave the
- // preemptive GC mode set correctly.
- retval = EXCEPTION_HANDLER_FWD(COMPlusFrameHandler);
-
-#ifdef _DEBUG
- // If the exception is escaping the last CLR personality routine on the stack,
- // then state a flag on the thread to indicate so.
- if (retval == ExceptionContinueSearch)
- {
- SetReversePInvokeEscapingUnhandledExceptionStatus(IS_UNWINDING(pExceptionRecord->ExceptionFlags), pEstablisherFrame);
- }
-#endif // _DEBUG
-
- if (IS_UNWINDING(pExceptionRecord->ExceptionFlags))
- {
- // Pops an extra frame on unwind.
-
- GCX_COOP(); // Must be cooperative to modify frame chain.
-
- Thread *pThread = GetThread();
- Frame *pFrame = pThread->GetFrame();
- pFrame->ExceptionUnwind();
- pFrame->Pop(pThread);
- }
-
- return retval;
-}
-
#ifdef FEATURE_COMINTEROP
// The reverse COM interop path needs to be sure to pop the ComMethodFrame that is pushed, but we do not want
// to have an additional FS:0 handler between the COM callsite and the call into managed. So we push this
diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp
index 3f4a7ed5312738..74d55fd4544db3 100644
--- a/src/coreclr/vm/i386/stublinkerx86.cpp
+++ b/src/coreclr/vm/i386/stublinkerx86.cpp
@@ -2445,44 +2445,21 @@ VOID StubLinkerCPU::X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedR
#endif // TARGET_UNIX
}
-#if defined(TARGET_X86)
+#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
-#if defined(PROFILING_SUPPORTED) && !defined(FEATURE_STUBS_AS_IL)
+#if defined(PROFILING_SUPPORTED)
VOID StubLinkerCPU::EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame)
{
STANDARD_VM_CONTRACT;
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // Load the methoddesc into ECX (UMThkCallFrame->m_pvDatum->m_pMD)
- X86EmitIndexRegLoad(kECX, regFrame, UMThkCallFrame::GetOffsetOfDatum());
- X86EmitIndexRegLoad(kECX, kECX, UMEntryThunk::GetOffsetOfMethodDesc());
-
- // Push arguments and notify profiler
- X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason
- X86EmitPushReg(kECX); // MethodDesc*
- X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*));
- }
-
-#ifdef FEATURE_COMINTEROP
- else if (pFrameVptr == ComMethodFrame::GetMethodFrameVPtr())
- {
- // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD)
- X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum());
- X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc());
-
- // Push arguments and notify profiler
- X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason
- X86EmitPushReg(kECX); // MethodDesc*
- X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*));
- }
-#endif // FEATURE_COMINTEROP
+ // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD)
+ X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum());
+ X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc());
- // Unrecognized frame vtbl
- else
- {
- _ASSERTE(!"Unrecognized vtble passed to EmitComMethodStubProlog with profiling turned on.");
- }
+ // Push arguments and notify profiler
+ X86EmitPushImm32(COR_PRF_TRANSITION_CALL); // Reason
+ X86EmitPushReg(kECX); // MethodDesc*
+ X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerUnmanagedToManagedTransitionMD), 2*sizeof(void*));
}
@@ -2491,50 +2468,21 @@ VOID StubLinkerCPU::EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame)
CONTRACTL
{
STANDARD_VM_CHECK;
-#ifdef FEATURE_COMINTEROP
- PRECONDITION(pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr() || pFrameVptr == ComMethodFrame::GetMethodFrameVPtr());
-#else
- PRECONDITION(pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr());
-#endif // FEATURE_COMINTEROP
+ PRECONDITION(pFrameVptr == ComMethodFrame::GetMethodFrameVPtr());
}
CONTRACTL_END;
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // Load the methoddesc into ECX (UMThkCallFrame->m_pvDatum->m_pMD)
- X86EmitIndexRegLoad(kECX, regFrame, UMThkCallFrame::GetOffsetOfDatum());
- X86EmitIndexRegLoad(kECX, kECX, UMEntryThunk::GetOffsetOfMethodDesc());
-
- // Push arguments and notify profiler
- X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason
- X86EmitPushReg(kECX); // MethodDesc*
- X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*));
- }
-
-#ifdef FEATURE_COMINTEROP
- else if (pFrameVptr == ComMethodFrame::GetMethodFrameVPtr())
- {
- // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD)
- X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum());
- X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc());
-
- // Push arguments and notify profiler
- X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason
- X86EmitPushReg(kECX); // MethodDesc*
- X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*));
- }
-#endif // FEATURE_COMINTEROP
+ // Load the methoddesc into ECX (Frame->m_pvDatum->m_pMD)
+ X86EmitIndexRegLoad(kECX, regFrame, ComMethodFrame::GetOffsetOfDatum());
+ X86EmitIndexRegLoad(kECX, kECX, ComCallMethodDesc::GetOffsetOfMethodDesc());
- // Unrecognized frame vtbl
- else
- {
- _ASSERTE(!"Unrecognized vtble passed to EmitComMethodStubEpilog with profiling turned on.");
- }
+ // Push arguments and notify profiler
+ X86EmitPushImm32(COR_PRF_TRANSITION_RETURN); // Reason
+ X86EmitPushReg(kECX); // MethodDesc*
+ X86EmitCall(NewExternalCodeLabel((LPVOID) ProfilerManagedToUnmanagedTransitionMD), 2*sizeof(void*));
}
-#endif // PROFILING_SUPPORTED && !FEATURE_STUBS_AS_IL
-
+#endif // PROFILING_SUPPORTED
-#ifndef FEATURE_STUBS_AS_IL
//========================================================================
// Prolog for entering managed code from COM
// pushes the appropriate frame ptr
@@ -2584,13 +2532,6 @@ void StubLinkerCPU::EmitComMethodStubProlog(TADDR pFrameVptr,
// lea esi, [esp+4] ;; set ESI -> new frame
X86EmitEspOffset(0x8d, kESI, 4); // lea ESI, [ESP+4]
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // Preserve argument registers for thiscall/fastcall
- X86EmitPushReg(kECX);
- X86EmitPushReg(kEDX);
- }
-
// Emit Setup thread
EmitSetup(rgRareLabels[0]); // rareLabel for rare setup
EmitLabel(rgRejoinLabels[0]); // rejoin label for rare setup
@@ -2639,23 +2580,6 @@ void StubLinkerCPU::EmitComMethodStubProlog(TADDR pFrameVptr,
// mov [ebx + Thread.GetFrame()], esi
X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kESI);
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // push UnmanagedToManagedExceptHandler
- X86EmitPushImmPtr((LPVOID)UMThunkPrestubHandler);
-
- // mov eax, fs:[0]
- static const BYTE codeSEH1[] = { 0x64, 0xA1, 0x0, 0x0, 0x0, 0x0};
- EmitBytes(codeSEH1, sizeof(codeSEH1));
-
- // push eax
- X86EmitPushReg(kEAX);
-
- // mov dword ptr fs:[0], esp
- static const BYTE codeSEH2[] = { 0x64, 0x89, 0x25, 0x0, 0x0, 0x0, 0x0};
- EmitBytes(codeSEH2, sizeof(codeSEH2));
- }
-
#if _DEBUG
if (Frame::ShouldLogTransitions())
{
@@ -2692,19 +2616,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr,
EmitCheckGSCookie(kESI, UnmanagedToManagedFrame::GetOffsetOfGSCookie());
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // if we are using exceptions, unlink the SEH
- // mov ecx,[esp] ;;pointer to the next exception record
- X86EmitEspOffset(0x8b, kECX, 0);
-
- // mov dword ptr fs:[0], ecx
- static const BYTE codeSEH[] = { 0x64, 0x89, 0x0D, 0x0, 0x0, 0x0, 0x0 };
- EmitBytes(codeSEH, sizeof(codeSEH));
-
- X86EmitAddEsp(sizeof(EXCEPTION_REGISTRATION_RECORD));
- }
-
// mov [ebx + Thread.GetFrame()], edi ;; restore previous frame
X86EmitIndexRegStore(kEBX, Thread::GetOffsetOfCurrentFrame(), kEDI);
@@ -2714,13 +2625,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr,
EmitEnable(rgRareLabels[2]); // rare gc
EmitLabel(rgRejoinLabels[2]); // rejoin for rare gc
- if (pFrameVptr == UMThkCallFrame::GetMethodFrameVPtr())
- {
- // Restore argument registers for thiscall/fastcall
- X86EmitPopReg(kEDX);
- X86EmitPopReg(kECX);
- }
-
// add esp, popstack
X86EmitAddEsp(sizeof(GSCookie) + UnmanagedToManagedFrame::GetOffsetOfCalleeSavedRegisters());
@@ -2761,7 +2665,6 @@ void StubLinkerCPU::EmitComMethodStubEpilog(TADDR pFrameVptr,
EmitLabel(rgRareLabels[0]); // label for rare setup thread
EmitRareSetup(rgRejoinLabels[0], /*fThrow*/ TRUE); // emit rare setup thread
}
-#endif // !FEATURE_STUBS_AS_IL
//---------------------------------------------------------------
// Emit code to store the setup current Thread structure in eax.
@@ -2792,16 +2695,12 @@ VOID StubLinkerCPU::EmitRareSetup(CodeLabel *pRejoinPoint, BOOL fThrow)
{
STANDARD_VM_CONTRACT;
-#ifndef FEATURE_COMINTEROP
- _ASSERTE(fThrow);
-#else // !FEATURE_COMINTEROP
if (!fThrow)
{
X86EmitPushReg(kESI);
X86EmitCall(NewExternalCodeLabel((LPVOID) CreateThreadBlockReturnHr), sizeof(void*));
}
else
-#endif // !FEATURE_COMINTEROP
{
X86EmitCall(NewExternalCodeLabel((LPVOID) CreateThreadBlockThrow), 0);
}
@@ -2811,10 +2710,6 @@ VOID StubLinkerCPU::EmitRareSetup(CodeLabel *pRejoinPoint, BOOL fThrow)
X86EmitNearJump(pRejoinPoint);
}
-//========================================================================
-#endif // TARGET_X86
-//========================================================================
-#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
//========================================================================
// Epilog for stubs that enter managed code from COM
//
@@ -2920,9 +2815,9 @@ void StubLinkerCPU::EmitSharedComMethodStubEpilog(TADDR pFrameVptr,
EmitRareSetup(rgRejoinLabels[0],/*fThrow*/ FALSE); // emit rare setup thread
}
-//========================================================================
#endif // defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
+
#if !defined(FEATURE_STUBS_AS_IL) && defined(TARGET_X86)
/*==============================================================================
Pushes a TransitionFrame on the stack
@@ -3437,7 +3332,7 @@ VOID StubLinkerCPU::EmitUnwindInfoCheckSubfunction()
#endif // defined(_DEBUG) && defined(STUBLINKER_GENERATES_UNWIND_INFO)
-#ifdef TARGET_X86
+#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
//-----------------------------------------------------------------------
// Generates the inline portion of the code to enable preemptive GC. Hopefully,
@@ -3579,7 +3474,6 @@ VOID StubLinkerCPU::EmitRareDisable(CodeLabel *pRejoinPoint)
X86EmitNearJump(pRejoinPoint);
}
-#ifdef FEATURE_COMINTEROP
//-----------------------------------------------------------------------
// Generates the out-of-line portion of the code to disable preemptive GC.
// After the work is done, the code normally jumps back to the "pRejoinPoint"
@@ -3611,10 +3505,8 @@ VOID StubLinkerCPU::EmitRareDisableHRESULT(CodeLabel *pRejoinPoint, CodeLabel *p
X86EmitNearJump(pExitPoint);
}
-#endif // FEATURE_COMINTEROP
-
-#endif // TARGET_X86
+#endif // defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray)
diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h
index 02ab6e9d253ea7..c719057e97ea39 100644
--- a/src/coreclr/vm/i386/stublinkerx86.h
+++ b/src/coreclr/vm/i386/stublinkerx86.h
@@ -250,17 +250,6 @@ class StubLinkerCPU : public StubLinker
);
VOID X86EmitPushEBPframe();
-#if defined(TARGET_X86)
-#if defined(PROFILING_SUPPORTED) && !defined(FEATURE_STUBS_AS_IL)
- // These are used to emit calls to notify the profiler of transitions in and out of
- // managed code through COM->COM+ interop or N/Direct
- VOID EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame);
- VOID EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame);
-#endif // PROFILING_SUPPORTED && !FEATURE_STUBS_AS_IL
-#endif // TARGET_X86
-
-
-
// Emits the most efficient form of the operation:
//
// opcode altreg, [basereg + scaledreg*scale + ofs]
@@ -340,6 +329,7 @@ class StubLinkerCPU : public StubLinker
#endif
}
+#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
VOID EmitEnable(CodeLabel *pForwardRef);
VOID EmitRareEnable(CodeLabel *pRejoinPoint);
@@ -349,20 +339,13 @@ class StubLinkerCPU : public StubLinker
VOID EmitSetup(CodeLabel *pForwardRef);
VOID EmitRareSetup(CodeLabel* pRejoinPoint, BOOL fThrow);
+#endif // FEATURE_COMINTEROP && TARGET_X86
#ifndef FEATURE_STUBS_AS_IL
VOID EmitMethodStubProlog(TADDR pFrameVptr, int transitionBlockOffset);
VOID EmitMethodStubEpilog(WORD numArgBytes, int transitionBlockOffset);
VOID EmitCheckGSCookie(X86Reg frameReg, int gsCookieOffset);
-
-#ifdef TARGET_X86
- void EmitComMethodStubProlog(TADDR pFrameVptr, CodeLabel** rgRareLabels,
- CodeLabel** rgRejoinLabels, BOOL bShouldProfile);
-
- void EmitComMethodStubEpilog(TADDR pFrameVptr, CodeLabel** rgRareLabels,
- CodeLabel** rgRejoinLabels, BOOL bShouldProfile);
-#endif // TARGET_X86
#endif // !FEATURE_STUBS_AS_IL
#ifdef TARGET_X86
@@ -379,6 +362,20 @@ class StubLinkerCPU : public StubLinker
VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg);
#if defined(FEATURE_COMINTEROP) && defined(TARGET_X86)
+
+#if defined(PROFILING_SUPPORTED)
+ // These are used to emit calls to notify the profiler of transitions in and out of
+ // managed code through COM->COM+ interop or N/Direct
+ VOID EmitProfilerComCallProlog(TADDR pFrameVptr, X86Reg regFrame);
+ VOID EmitProfilerComCallEpilog(TADDR pFrameVptr, X86Reg regFrame);
+#endif // PROFILING_SUPPORTED
+
+ void EmitComMethodStubProlog(TADDR pFrameVptr, CodeLabel** rgRareLabels,
+ CodeLabel** rgRejoinLabels, BOOL bShouldProfile);
+
+ void EmitComMethodStubEpilog(TADDR pFrameVptr, CodeLabel** rgRareLabels,
+ CodeLabel** rgRejoinLabels, BOOL bShouldProfile);
+
//========================================================================
// shared Epilog for stubs that enter managed code from COM
// uses a return thunk within the method desc
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..7c298b847400e4 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());
@@ -2029,54 +2029,54 @@ bool CEEInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod,
return result;
}
+static unsigned MarkGCField(BYTE* gcPtrs, CorInfoGCType type)
+{
+ STANDARD_VM_CONTRACT;
+
+ // Ensure that if we have multiple fields with the same offset,
+ // that we don't double count the data in the gc layout.
+ if (*gcPtrs == TYPE_GC_NONE)
+ {
+ *gcPtrs = type;
+ return 1;
+ }
+ else if (*gcPtrs != type)
+ {
+ COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
+ }
+
+ return 0;
+}
+
/*********************************************************************/
static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs)
{
STANDARD_VM_CONTRACT;
- unsigned result = 0;
-
_ASSERTE(pMT->IsValueType());
if (pMT->HasSameTypeDefAs(g_pByReferenceClass))
- {
- if (gcPtrs[0] == TYPE_GC_NONE)
- {
- gcPtrs[0] = TYPE_GC_BYREF;
- result++;
- }
- else if (gcPtrs[0] != TYPE_GC_BYREF)
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- }
- return result;
- }
+ return MarkGCField(gcPtrs, TYPE_GC_BYREF);
+ unsigned result = 0;
ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
{
int fieldStartIndex = pFD->GetOffset() / TARGET_POINTER_SIZE;
- if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE)
- {
- if (pFD->IsObjRef())
- {
- if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE)
- {
- gcPtrs[fieldStartIndex] = TYPE_GC_REF;
- result++;
- }
- else if (gcPtrs[fieldStartIndex] != TYPE_GC_REF)
- {
- COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
- }
- }
- }
- else
+ if (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
{
MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
result += ComputeGCLayout(pFieldMT, gcPtrs + fieldStartIndex);
}
+ else if (pFD->IsObjRef())
+ {
+ result += MarkGCField(gcPtrs + fieldStartIndex, TYPE_GC_REF);
+ }
+ else if (pFD->IsByRef())
+ {
+ result += MarkGCField(gcPtrs + fieldStartIndex, TYPE_GC_BYREF);
+ }
}
return result;
}
@@ -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/methodtable.h b/src/coreclr/vm/methodtable.h
index 86a033a0593a29..76c552a3042849 100644
--- a/src/coreclr/vm/methodtable.h
+++ b/src/coreclr/vm/methodtable.h
@@ -1517,6 +1517,8 @@ class MethodTable
inline BOOL HasExplicitSize();
+ inline BOOL IsAutoLayoutOrHasAutoLayoutField();
+
UINT32 GetNativeSize();
DWORD GetBaseSize()
diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl
index d14a73532b6e12..72b628dae9545a 100644
--- a/src/coreclr/vm/methodtable.inl
+++ b/src/coreclr/vm/methodtable.inl
@@ -947,6 +947,13 @@ inline BOOL MethodTable::HasExplicitSize()
return GetClass()->HasExplicitSize();
}
+//==========================================================================================
+inline BOOL MethodTable::IsAutoLayoutOrHasAutoLayoutField()
+{
+ LIMITED_METHOD_CONTRACT;
+ return GetClass()->IsAutoLayoutOrHasAutoLayoutField();
+}
+
//==========================================================================================
inline DWORD MethodTable::GetPerInstInfoSize()
{
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index 694e03cca35f2a..82499f314e4f3d 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:
@@ -3970,7 +3991,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
{
Module * pTokenModule;
dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule);
- fIsByValue = TRUE;
// By-value class
BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0);
@@ -4042,6 +4062,11 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
pByValueClass = (MethodTable *)-1;
}
} // If 'this' is a value class
+ }
+ // TypedReference shares the rest of the code here
+IS_VALUETYPE:
+ {
+ fIsByValue = TRUE;
// It's not self-referential so try to load it
if (pByValueClass == NULL)
@@ -8648,6 +8673,14 @@ MethodTableBuilder::HandleExplicitLayout(
BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
}
}
+
+ if (!numInstanceFieldBytes.IsOverflow() && numInstanceFieldBytes.Value() == 0)
+ {
+ // If we calculate a 0-byte size here, we should have also calculated a 0-byte size
+ // in the initial layout algorithm.
+ _ASSERTE(GetLayoutInfo()->IsZeroSized());
+ numInstanceFieldBytes = S_UINT32(1);
+ }
}
// The GC requires that all valuetypes containing orefs be sized to a multiple of TARGET_POINTER_SIZE.
diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp
index c5731840122845..5a071c2b9f8f99 100644
--- a/src/coreclr/vm/mlinfo.cpp
+++ b/src/coreclr/vm/mlinfo.cpp
@@ -1056,6 +1056,78 @@ OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo()
}
#endif // FEATURE_COMINTEROP
+namespace
+{
+ MarshalInfo::MarshalType GetDisabledMarshallerType(
+ Module* pModule,
+ SigPointer sig,
+ const SigTypeContext * pTypeContext,
+ MethodTable** pMTOut,
+ UINT* errorResIDOut)
+ {
+ switch (sig.PeekElemTypeNormalized(pModule, pTypeContext))
+ {
+ case ELEMENT_TYPE_BOOLEAN:
+ case ELEMENT_TYPE_U1:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_U1;
+ case ELEMENT_TYPE_I1:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_1;
+ case ELEMENT_TYPE_CHAR:
+ case ELEMENT_TYPE_U2:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_U2;
+ case ELEMENT_TYPE_I2:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_2;
+ case ELEMENT_TYPE_U4:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_U4;
+ case ELEMENT_TYPE_I4:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_4;
+ case ELEMENT_TYPE_U8:
+ case ELEMENT_TYPE_I8:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_8;
+#ifdef TARGET_64BIT
+ case ELEMENT_TYPE_U:
+ case ELEMENT_TYPE_PTR:
+ case ELEMENT_TYPE_FNPTR:
+ case ELEMENT_TYPE_I:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_8;
+#else
+ case ELEMENT_TYPE_U:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_U4;
+ case ELEMENT_TYPE_PTR:
+ case ELEMENT_TYPE_FNPTR:
+ case ELEMENT_TYPE_I:
+ return MarshalInfo::MARSHAL_TYPE_GENERIC_4;
+#endif
+ case ELEMENT_TYPE_R4:
+ return MarshalInfo::MARSHAL_TYPE_FLOAT;
+ case ELEMENT_TYPE_R8:
+ return MarshalInfo::MARSHAL_TYPE_DOUBLE;
+ case ELEMENT_TYPE_VAR:
+ case ELEMENT_TYPE_VALUETYPE:
+ {
+ TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
+ MethodTable* pMT = sigTH.GetMethodTable();
+
+ if (!pMT->IsValueType() || pMT->ContainsPointers())
+ {
+ *errorResIDOut = IDS_EE_BADMARSHAL_MARSHAL_DISABLED;
+ return MarshalInfo::MARSHAL_TYPE_UNKNOWN;
+ }
+ if (pMT->IsAutoLayoutOrHasAutoLayoutField())
+ {
+ *errorResIDOut = IDS_EE_BADMARSHAL_AUTOLAYOUT;
+ return MarshalInfo::MARSHAL_TYPE_UNKNOWN;
+ }
+ *pMTOut = pMT;
+ return MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS;
+ }
+ default:
+ *errorResIDOut = IDS_EE_BADMARSHAL_MARSHAL_DISABLED;
+ return MarshalInfo::MARSHAL_TYPE_UNKNOWN;
+ }
+ }
+}
+
//==========================================================================
// Constructs MarshalInfo.
//==========================================================================
@@ -1163,7 +1235,30 @@ MarshalInfo::MarshalInfo(Module* pModule,
m_byref = TRUE;
#endif
+ // For COM IL-stub scenarios, we do not support disabling the runtime marshalling support.
+ // The runtime-integrated COM support uses a significant portion of the marshalling infrastructure as well as
+ // quite a bit of its own custom marshalling infrastructure to function in basically any aspect.
+ // As a result, disabling marshalling in COM scenarios isn't useful. Instead, we recommend that people set the
+ // feature switch to false to disable the runtime COM support if they want it disabled.
+ // For field marshalling scenarios, we also don't disable runtime marshalling. If we're already in a field
+ // marshalling scenario, we've already decided that the context for the owning type is using runtime marshalling,
+ // so the fields of the struct should also use runtime marshalling.
+ const bool useRuntimeMarshalling = ms != MARSHAL_SCENARIO_NDIRECT || pModule->IsRuntimeMarshallingEnabled();
+ if (!useRuntimeMarshalling)
+ {
+ m_in = TRUE;
+ m_out = FALSE;
+ m_byref = FALSE;
+ m_type = GetDisabledMarshallerType(
+ pModule,
+ sig,
+ pTypeContext,
+ &m_pMT,
+ &m_resID);
+ m_args.m_pMT = m_pMT;
+ return;
+ }
// Retrieve the native type for the current parameter.
if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo))
@@ -1322,6 +1417,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
switch (mtype)
{
case ELEMENT_TYPE_BOOLEAN:
+
switch (nativeType)
{
case NATIVE_TYPE_BOOLEAN:
@@ -1482,10 +1578,6 @@ MarshalInfo::MarshalInfo(Module* pModule,
break;
case ELEMENT_TYPE_I:
- // Technically the "native int" and "native uint" types aren't supported in the WinRT scenario,
- // but we need to not block ourselves from using them to enable accurate managed->native marshalling of
- // projected types such as NotifyCollectionChangedEventArgs and NotifyPropertyChangedEventArgs.
-
if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
{
m_resID = IDS_EE_BADMARSHAL_I;
@@ -1499,7 +1591,6 @@ MarshalInfo::MarshalInfo(Module* pModule,
break;
case ELEMENT_TYPE_U:
-
if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
{
m_resID = IDS_EE_BADMARSHAL_I;
@@ -1564,6 +1655,21 @@ MarshalInfo::MarshalInfo(Module* pModule,
{
TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
+ if (sigTH.GetMethodTable()->IsValueType())
+ {
+ // For value types, we need to handle the "value type marshalled as a COM interface"
+ // case here for back-compat.
+ // Otherwise, we can go to the value-type case.
+#ifdef FEATURE_COMINTEROP
+ if (nativeType != NATIVE_TYPE_INTF)
+ {
+ goto lValueClass;
+ }
+#else
+ goto lValueClass;
+#endif
+ }
+
// Disallow marshaling generic types.
if (sigTH.HasInstantiation())
{
@@ -1968,14 +2074,13 @@ MarshalInfo::MarshalInfo(Module* pModule,
}
}
-
else if (m_pMT->IsArray())
{
_ASSERTE(!"This invalid signature should never be hit!");
IfFailGoto(E_FAIL, lFail);
}
#endif // FEATURE_COMINTEROP
- else if (!m_pMT->IsValueType())
+ else
{
if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT))
{
@@ -1990,12 +2095,6 @@ MarshalInfo::MarshalInfo(Module* pModule,
IfFailGoto(E_FAIL, lFail);
#endif // FEATURE_COMINTEROP
}
-
- else
- {
- _ASSERTE(m_pMT->IsValueType());
- goto lValueClass;
- }
}
break;
}
@@ -2166,8 +2265,7 @@ MarshalInfo::MarshalInfo(Module* pModule,
|| m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR64T))
|| m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR128T))
|| m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR256T))
- // Crossgen scenarios block Vector from even being loaded
- || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTORT))
+ || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTORT))
)))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
@@ -2902,6 +3000,15 @@ UINT16 MarshalInfo::GetNativeSize(MarshalType mtype)
if (nativeSize == VARIABLESIZE)
{
_ASSERTE(IsValueClass(mtype));
+ // For blittable types, use the GetNumInstanceFieldBytes method.
+ // When we generate IL stubs when marshalling is disabled,
+ // we reuse the blittable value class marshalling mechanism.
+ // In that scenario, only GetNumInstanceFieldBytes will return the correct value.
+ // GetNativeSize will return the size for when runtime marshalling is enabled.
+ if (mtype == MARSHAL_TYPE_BLITTABLEVALUECLASS)
+ {
+ return (UINT16) m_pMT->GetNumInstanceFieldBytes();
+ }
return (UINT16) m_pMT->GetNativeSize();
}
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/object.inl b/src/coreclr/vm/object.inl
index e61f2eb443babf..46b8db4d0d841f 100644
--- a/src/coreclr/vm/object.inl
+++ b/src/coreclr/vm/object.inl
@@ -272,38 +272,4 @@ inline TypeHandle Object::GetGCSafeTypeHandle() const
return TypeHandle(pMT);
}
-template
-inline void FindByRefPointerOffsetsInByRefLikeObject(PTR_MethodTable pMT, SIZE_T baseOffset, const F processPointerOffset)
-{
- WRAPPER_NO_CONTRACT;
- _ASSERTE(pMT != nullptr);
- _ASSERTE(pMT->IsByRefLike());
-
- if (pMT->HasSameTypeDefAs(g_pByReferenceClass))
- {
- processPointerOffset(baseOffset);
- return;
- }
-
- ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
- for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
- {
- if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE)
- {
- continue;
- }
-
- // TODO: GetApproxFieldTypeHandleThrowing may throw. This is a potential stress problem for fragile NGen of non-CoreLib
- // assemblies. It won't ever throw for CoreCLR with R2R. Figure out if anything needs to be done to deal with the
- // exception.
- PTR_MethodTable pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
- if (!pFieldMT->IsByRefLike())
- {
- continue;
- }
-
- FindByRefPointerOffsetsInByRefLikeObject(pFieldMT, baseOffset + pFD->GetOffset(), processPointerOffset);
- }
-}
-
#endif // _OBJECT_INL_
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 d8488e7e583b8a..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()))
@@ -2262,10 +2262,6 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo
// use the prestub.
//==========================================================================
-#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL)
-static PCODE g_UMThunkPreStub;
-#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL
-
#ifndef DACCESS_COMPILE
void ThePreStubManager::Init(void)
@@ -2286,10 +2282,6 @@ void InitPreStubManager(void)
{
STANDARD_VM_CONTRACT;
-#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL)
- g_UMThunkPreStub = GenerateUMThunkPrestub()->GetEntryPoint();
-#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL
-
ThePreStubManager::Init();
}
@@ -2297,11 +2289,7 @@ PCODE TheUMThunkPreStub()
{
LIMITED_METHOD_CONTRACT;
-#if defined(TARGET_X86) && !defined(FEATURE_STUBS_AS_IL)
- return g_UMThunkPreStub;
-#else // TARGET_X86 && !FEATURE_STUBS_AS_IL
return GetEEFuncEntryPoint(TheUMEntryPrestub);
-#endif // TARGET_X86 && !FEATURE_STUBS_AS_IL
}
PCODE TheVarargNDirectStub(BOOL hasRetBuffArg)
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 749fa73126b084..5162ac38a3bb4c 100644
--- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp
+++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp
@@ -1274,7 +1274,7 @@ bool AllocByClassHelper(Object * pBO, void * pv)
_ASSERTE(pv != NULL);
{
- BEGIN_PROFILER_CALLBACK(CORProfilerTrackAllocations());
+ BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC());
// Pass along the call
g_profControlBlock.AllocByClass(
(ObjectID) pBO,
@@ -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/siginfo.cpp b/src/coreclr/vm/siginfo.cpp
index a197fbc87cabd9..5a277914d8cee5 100644
--- a/src/coreclr/vm/siginfo.cpp
+++ b/src/coreclr/vm/siginfo.cpp
@@ -4903,20 +4903,67 @@ void PromoteCarefully(promote_func fn,
(*fn) (ppObj, sc, flags);
}
+class ByRefPointerOffsetsReporter
+{
+ promote_func* _fn;
+ ScanContext* _sc;
+ PTR_VOID _src;
+
+ void Report(SIZE_T pointerOffset)
+ {
+ WRAPPER_NO_CONTRACT;
+ PTR_PTR_Object fieldRef = dac_cast(PTR_BYTE(_src) + pointerOffset);
+ (*_fn)(fieldRef, _sc, GC_CALL_INTERIOR);
+ }
+
+public:
+ ByRefPointerOffsetsReporter(promote_func* fn, ScanContext* sc, PTR_VOID pSrc)
+ : _fn{fn}
+ , _sc{sc}
+ , _src{pSrc}
+ {
+ WRAPPER_NO_CONTRACT;
+ }
+
+ void Find(PTR_MethodTable pMT, SIZE_T baseOffset)
+ {
+ WRAPPER_NO_CONTRACT;
+ _ASSERTE(pMT != nullptr);
+ _ASSERTE(pMT->IsByRefLike());
+
+ if (pMT->HasSameTypeDefAs(g_pByReferenceClass))
+ {
+ Report(baseOffset);
+ return;
+ }
+
+ ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
+ for (FieldDesc* pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
+ {
+ if (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
+ {
+ PTR_MethodTable pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
+ if (pFieldMT->IsByRefLike())
+ {
+ Find(pFieldMT, baseOffset + pFD->GetOffset());
+ }
+ }
+ else if (pFD->IsByRef())
+ {
+ Report(baseOffset + pFD->GetOffset());
+ }
+ }
+ }
+};
+
void ReportPointersFromValueType(promote_func *fn, ScanContext *sc, PTR_MethodTable pMT, PTR_VOID pSrc)
{
WRAPPER_NO_CONTRACT;
if (pMT->IsByRefLike())
{
- FindByRefPointerOffsetsInByRefLikeObject(
- pMT,
- 0 /* baseOffset */,
- [&](SIZE_T pointerOffset)
- {
- PTR_PTR_Object fieldRef = dac_cast(PTR_BYTE(pSrc) + pointerOffset);
- (*fn)(fieldRef, sc, GC_CALL_INTERIOR);
- });
+ ByRefPointerOffsetsReporter reporter{fn, sc, pSrc};
+ reporter.Find(pMT, 0 /* baseOffset */);
}
if (!pMT->ContainsPointers())
diff --git a/src/coreclr/vm/stubgen.cpp b/src/coreclr/vm/stubgen.cpp
index f829212a8ef6ed..2249756c3358aa 100644
--- a/src/coreclr/vm/stubgen.cpp
+++ b/src/coreclr/vm/stubgen.cpp
@@ -2669,7 +2669,7 @@ void ILStubLinker::TransformArgForJIT(LocalDesc *pLoc)
// JIT will handle structures
if (pLoc->InternalToken.IsValueType())
{
- _ASSERTE(pLoc->InternalToken.IsBlittable());
+ _ASSERTE(pLoc->InternalToken.IsNativeValueType() || !pLoc->InternalToken.GetMethodTable()->ContainsPointers());
break;
}
FALLTHROUGH;
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.Der.cs b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs
index b750a2de5e9d8f..d3c442760423c4 100644
--- a/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs
+++ b/src/libraries/Common/src/Internal/Cryptography/AsymmetricAlgorithmHelpers.Der.cs
@@ -143,7 +143,6 @@ static int GetDerLengthLength(int payloadLength)
}
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
///
/// Converts IeeeP1363 format to the specified signature format
///
@@ -182,7 +181,6 @@ internal static byte[] ConvertSignatureToIeeeP1363(
currentFormat.ToString());
}
}
-#endif
public static int BitsToBytes(int bitLength)
{
@@ -214,7 +212,6 @@ private static void CopySignatureField(ReadOnlySpan signatureField, Span signatureField, Span 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.Native/Interop.LChflags.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs
index 2b1b67784e87d8..cbc05ad5a85b69 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs
@@ -25,5 +25,11 @@ internal enum UserFlags : uint
[GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflagsCanSetHiddenFlag")]
[SuppressGCTransition]
private static partial int LChflagsCanSetHiddenFlag();
+
+ internal static readonly bool SupportsHiddenFlag = (CanGetHiddenFlag() != 0);
+
+ [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CanGetHiddenFlag")]
+ [SuppressGCTransition]
+ private static partial int CanGetHiddenFlag();
}
}
diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
index 593c6f4e593f6d..95e9ab89fc5054 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs
@@ -105,18 +105,28 @@ internal static unsafe SafeEvpPKeyHandle DecodePkcs8PrivateKey(
}
[GeneratedDllImport(Libraries.CryptoNative)]
- private static partial int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey);
+ private static partial int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey, out int p8size);
private static int GetPkcs8PrivateKeySize(IntPtr pkey)
{
- int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey);
+ const int Success = 1;
+ const int Error = -1;
+ const int MissingPrivateKey = -2;
- if (ret < 0)
+ int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey, out int p8size);
+
+ switch (ret)
{
- throw CreateOpenSslCryptographicException();
+ case Success:
+ return p8size;
+ case Error:
+ throw CreateOpenSslCryptographicException();
+ case MissingPrivateKey:
+ throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
+ default:
+ Debug.Fail($"Unexpected return '{ret}' value from {nameof(CryptoNative_GetPkcs8PrivateKeySize)}.");
+ throw new CryptographicException();
}
-
- return ret;
}
[GeneratedDllImport(Libraries.CryptoNative)]
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/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
index c01b829cd189d2..379ab7586ed38c 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs
@@ -6,6 +6,7 @@
using System.Diagnostics;
using System.Net.Security;
using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;
@@ -47,7 +48,7 @@ internal static partial class Ssl
internal static partial void SslSetAcceptState(SafeSslHandle ssl);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAlpnProtos")]
- internal static partial int SslSetAlpnProtos(SafeSslHandle ssl, IntPtr protos, int len);
+ internal static unsafe partial int SslSetAlpnProtos(SafeSslHandle ssl, byte* protos, int len);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetVersion")]
internal static partial IntPtr SslGetVersion(SafeSslHandle ssl);
@@ -168,16 +169,7 @@ internal static class Capabilities
internal static readonly bool Tls13Supported = Tls13SupportedImpl() != 0;
}
- internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, List protocols)
- {
- byte[] buffer = ConvertAlpnProtocolListToByteArray(protocols);
- fixed (byte* b = buffer)
- {
- return SslSetAlpnProtos(ssl, (IntPtr)b, buffer.Length);
- }
- }
-
- internal static byte[] ConvertAlpnProtocolListToByteArray(List applicationProtocols)
+ internal static int GetAlpnProtocolListSerializedLength(List applicationProtocols)
{
int protocolSize = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
@@ -190,16 +182,37 @@ internal static byte[] ConvertAlpnProtocolListToByteArray(List applicationProtocols, Span buffer)
+ {
+ Debug.Assert(GetAlpnProtocolListSerializedLength(applicationProtocols) == buffer.Length,
+ "GetAlpnProtocolListSerializedSize(applicationProtocols) == buffer.Length");
+
+ int offset = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
- buffer[offset++] = (byte)(protocol.Protocol.Length);
- protocol.Protocol.Span.CopyTo(buffer.AsSpan(offset));
+ buffer[offset++] = (byte)protocol.Protocol.Length;
+ protocol.Protocol.Span.CopyTo(buffer.Slice(offset));
offset += protocol.Protocol.Length;
}
+ }
+
+ internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, List applicationProtocols)
+ {
+ int length = GetAlpnProtocolListSerializedLength(applicationProtocols);
+ Span buffer = length <= 256 ? stackalloc byte[256].Slice(0, length) : new byte[length];
+ SerializeAlpnProtocolList(applicationProtocols, buffer);
+ return SslSetAlpnProtos(ssl, buffer);
+ }
- return buffer;
+ internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, Span serializedProtocols)
+ {
+ fixed (byte* pBuffer = &MemoryMarshal.GetReference(serializedProtocols))
+ {
+ return SslSetAlpnProtos(ssl, pBuffer, serializedProtocols.Length);
+ }
}
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslAddExtraChainCert")]
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs
index 0a60ee7918ac3c..b57a4b0f619273 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs
@@ -19,7 +19,7 @@ internal enum CryptCreateHashFlags : int
internal static partial bool CryptCreateHash(
SafeProvHandle hProv,
int Algid,
- SafeKeyHandle hKey,
+ SafeCapiKeyHandle hKey,
CryptCreateHashFlags dwFlags,
out SafeHashHandle phHash);
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs
index 7865c1180ff8ff..3f05d5c223e7c6 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs
@@ -16,7 +16,7 @@ internal enum CryptDecryptFlags : int
[GeneratedDllImport(Libraries.Advapi32, SetLastError = true)]
public static partial bool CryptDecrypt(
- SafeKeyHandle hKey,
+ SafeCapiKeyHandle hKey,
SafeHashHandle hHash,
bool Final,
int dwFlags,
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs
index 2bc7d4ed8d8ba7..51b77aef3d0ac5 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs
@@ -14,6 +14,6 @@ internal static partial bool CryptDeriveKey(
int Algid,
SafeHashHandle hBaseData,
int dwFlags,
- out SafeKeyHandle phKey);
+ out SafeCapiKeyHandle phKey);
}
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs
index fa883e5eef421d..17e50c1e59d0fd 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs
@@ -10,7 +10,7 @@ internal static partial class Advapi32
{
[GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
public static partial bool CryptEncrypt(
- SafeKeyHandle hKey,
+ SafeCapiKeyHandle hKey,
SafeHashHandle hHash,
bool Final,
int dwFlags,
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs
index 9eb16f40190356..633997f99880ee 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs
@@ -10,8 +10,8 @@ internal static partial class Advapi32
{
[GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
public static partial bool CryptExportKey(
- SafeKeyHandle hKey,
- SafeKeyHandle hExpKey,
+ SafeCapiKeyHandle hKey,
+ SafeCapiKeyHandle hExpKey,
int dwBlobType,
int dwFlags,
byte[]? pbData,
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs
index d19c090d84d604..cf6aaf36b1c151 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs
@@ -9,6 +9,6 @@ internal static partial class Interop
internal static partial class Advapi32
{
[GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static partial bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeKeyHandle phKey);
+ internal static partial bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeCapiKeyHandle phKey);
}
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs
index 9737c2b0663886..63f33ffa392275 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs
@@ -19,7 +19,7 @@ internal enum CryptGetKeyParamFlags : int
[GeneratedDllImport(Libraries.Advapi32, SetLastError = true)]
public static partial bool CryptGetKeyParam(
- SafeKeyHandle hKey,
+ SafeCapiKeyHandle hKey,
CryptGetKeyParamFlags dwParam,
byte[]? pbData,
ref int pdwDataLen,
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs
index c5080a00784701..88b5d00e563892 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs
@@ -9,6 +9,6 @@ internal static partial class Interop
internal static partial class Advapi32
{
[GeneratedDllImport(Libraries.Advapi32, SetLastError = true)]
- internal static partial bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeKeyHandle phUserKey);
+ internal static partial bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeCapiKeyHandle phUserKey);
}
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs
index f5e73879d99ca3..3c8cb90d99f5c8 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs
@@ -13,8 +13,8 @@ internal static unsafe partial bool CryptImportKey(
SafeProvHandle hProv,
byte* pbData,
int dwDataLen,
- SafeKeyHandle hPubKey,
+ SafeCapiKeyHandle hPubKey,
int dwFlags,
- out SafeKeyHandle phKey);
+ out SafeCapiKeyHandle phKey);
}
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs
index 5fb1c83ff37e51..07d510705e2f73 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs
@@ -9,9 +9,9 @@ internal static partial class Interop
internal static partial class Advapi32
{
[GeneratedDllImport(Libraries.Advapi32, SetLastError = true)]
- public static partial bool CryptSetKeyParam(SafeKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags);
+ public static partial bool CryptSetKeyParam(SafeCapiKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags);
[GeneratedDllImport(Libraries.Advapi32, SetLastError = true)]
- public static partial bool CryptSetKeyParam(SafeKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags);
+ public static partial bool CryptSetKeyParam(SafeCapiKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags);
}
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs
index 0d9f3a17031410..dd7a12c30b397e 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs
@@ -38,7 +38,7 @@ public static partial bool CryptVerifySignature(
SafeHashHandle hHash,
byte[] pbSignature,
int dwSigLen,
- SafeKeyHandle hPubKey,
+ SafeCapiKeyHandle hPubKey,
string? szDescription,
CryptSignAndVerifyHashFlags dwFlags);
}
diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs
index 5f12dd16db064a..b8a0e5c944b20f 100644
--- a/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs
+++ b/src/libraries/Common/src/Interop/Windows/Advapi32/SafeKeyHandle.cs
@@ -16,13 +16,13 @@ namespace System.Security.Cryptography
/// of the key handle and provider handle. This also applies to hash handles, which point to a
/// CRYPT_HASH_CTX. Those structures are defined in COMCryptography.h
///
- internal sealed class SafeKeyHandle : SafeHandleZeroOrMinusOneIsInvalid
+ internal sealed class SafeCapiKeyHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private int _keySpec;
private bool _fPublicOnly;
private SafeProvHandle? _parent;
- public SafeKeyHandle() : base(true)
+ public SafeCapiKeyHandle() : base(true)
{
SetHandle(IntPtr.Zero);
_keySpec = 0;
@@ -70,14 +70,14 @@ internal void SetParent(SafeProvHandle parent)
_parent.DangerousAddRef(ref ignored);
}
- internal static SafeKeyHandle InvalidHandle
+ internal static SafeCapiKeyHandle InvalidHandle
{
- get { return SafeHandleCache.GetInvalidHandle(() => new SafeKeyHandle()); }
+ get { return SafeHandleCache.GetInvalidHandle(() => new SafeCapiKeyHandle()); }
}
protected override void Dispose(bool disposing)
{
- if (!SafeHandleCache.IsCachedInvalidHandle(this))
+ if (!SafeHandleCache.IsCachedInvalidHandle(this))
{
base.Dispose(disposing);
}
diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs
index 13d709643a1846..913261e58915cb 100644
--- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs
@@ -37,7 +37,7 @@ internal static unsafe SafeKeyHandle BCryptImportKey(SafeAlgorithmHandle hAlg, R
}
[StructLayout(LayoutKind.Sequential)]
- private struct BCRYPT_KEY_DATA_BLOB_HEADER
+ internal struct BCRYPT_KEY_DATA_BLOB_HEADER
{
public uint dwMagic;
public uint dwVersion;
diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs
index 406e0177f8ecfb..5d9fbe7595ed0a 100644
--- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs
+++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs
@@ -11,8 +11,11 @@ internal static partial class Interop
{
internal static partial class NCrypt
{
+ internal const string NCRYPT_CIPHER_KEY_BLOB = "CipherKeyBlob";
internal const string NCRYPT_PKCS8_PRIVATE_KEY_BLOB = "PKCS8_PRIVATEKEY";
+ internal const int NCRYPT_CIPHER_KEY_BLOB_MAGIC = 0x52485043; //'CPHR'
+
[GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)]
internal static partial ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags);
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/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs
index 20f987f6cc0530..54d6284d601c93 100644
--- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.cs
+++ b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeX509ChainHandle.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.
-using Internal.Cryptography.Pal;
+using System.Security.Cryptography.X509Certificates;
namespace Microsoft.Win32.SafeHandles
{
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/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs
index 6e109d6f8c5471..e254c3a1ef0bc1 100644
--- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs
+++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http3/QPack/H3StaticTable.Http3.cs
@@ -48,7 +48,7 @@ public static bool TryGetStatusIndex(int status, out int index)
// TODO: just use Dictionary directly to avoid interface dispatch.
public static IReadOnlyDictionary MethodIndex => s_methodIndex;
- public static ref HeaderField Get(int index) => ref s_staticTable[index];
+ public static ref readonly HeaderField Get(int index) => ref s_staticTable[index];
private static readonly HeaderField[] s_staticTable = new HeaderField[]
{
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/Net/SocketProtocolSupportPal.Unix.cs b/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs
index 8de1e2a0f4ce31..c755c16517c77a 100644
--- a/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs
+++ b/src/libraries/Common/src/System/Net/SocketProtocolSupportPal.Unix.cs
@@ -15,7 +15,9 @@ private static unsafe bool IsSupported(AddressFamily af)
IntPtr socket = invalid;
try
{
- return Interop.Sys.Socket(af, SocketType.Dgram, 0, &socket) != Interop.Error.EAFNOSUPPORT;
+ Interop.Error result = Interop.Sys.Socket(af, SocketType.Dgram, 0, &socket);
+ // we get EAFNOSUPPORT when family is not supported by Kernel, EPROTONOSUPPORT may come from policy enforcement like FreeBSD jail()
+ return result != Interop.Error.EAFNOSUPPORT && result != Interop.Error.EPROTONOSUPPORT;
}
finally
{
diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs
index a16f66c40c89eb..67e9d869a68dbd 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1Reader/AsnValueReader.cs
@@ -34,6 +34,18 @@ internal Asn1Tag PeekTag()
return Asn1Tag.Decode(_span, out _);
}
+ internal ReadOnlySpan PeekContentBytes()
+ {
+ AsnDecoder.ReadEncodedValue(
+ _span,
+ _ruleSet,
+ out int contentOffset,
+ out int contentLength,
+ out _);
+
+ return _span.Slice(contentOffset, contentLength);
+ }
+
internal ReadOnlySpan PeekEncodedValue()
{
AsnDecoder.ReadEncodedValue(_span, _ruleSet, out _, out _, out int consumed);
diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs
index b5e8c50c42b51e..f9ec1cb44be8eb 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.ImportExport.cs
@@ -11,432 +11,425 @@
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class DSAImplementation
+ public sealed partial class DSACng : DSA
{
-#endif
- public sealed partial class DSACng : DSA
- {
- // For keysizes up to and including 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB.
- // For keysizes exceeding 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB_V2.
- private const int MaxV1KeySize = 1024;
-
- private const int Sha1HashOutputSize = 20;
- private const int Sha256HashOutputSize = 32;
- private const int Sha512HashOutputSize = 64;
+ // For keysizes up to and including 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB.
+ // For keysizes exceeding 1024 bits, CNG's blob format is BCRYPT_DSA_KEY_BLOB_V2.
+ private const int MaxV1KeySize = 1024;
- public override void ImportParameters(DSAParameters parameters)
- {
- if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields);
+ private const int Sha1HashOutputSize = 20;
+ private const int Sha256HashOutputSize = 32;
+ private const int Sha512HashOutputSize = 64;
- // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check
- // is just to maintain parity with DSACryptoServiceProvider, which also performs this check.
- if (parameters.J != null && parameters.J.Length >= parameters.P.Length)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ);
+ public override void ImportParameters(DSAParameters parameters)
+ {
+ if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields);
- bool hasPrivateKey = parameters.X != null;
+ // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check
+ // is just to maintain parity with DSACryptoServiceProvider, which also performs this check.
+ if (parameters.J != null && parameters.J.Length >= parameters.P.Length)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ);
- int keySizeInBytes = parameters.P.Length;
- int keySizeInBits = keySizeInBytes * 8;
+ bool hasPrivateKey = parameters.X != null;
- if (parameters.G.Length != keySizeInBytes || parameters.Y.Length != keySizeInBytes)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY);
+ int keySizeInBytes = parameters.P.Length;
+ int keySizeInBits = keySizeInBytes * 8;
- if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX);
+ if (parameters.G.Length != keySizeInBytes || parameters.Y.Length != keySizeInBytes)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY);
- byte[] blob;
- if (keySizeInBits <= MaxV1KeySize)
- {
- GenerateV1DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey);
- }
- else
- {
- GenerateV2DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey);
- }
+ if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX);
- ImportKeyBlob(blob, hasPrivateKey);
+ byte[] blob;
+ if (keySizeInBits <= MaxV1KeySize)
+ {
+ GenerateV1DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey);
}
-
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- ReadOnlySpan source,
- out int bytesRead)
+ else
{
- ThrowIfDisposed();
- base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead);
+ GenerateV2DsaBlob(out blob, parameters, keySizeInBytes, hasPrivateKey);
}
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- ReadOnlySpan source,
- out int bytesRead)
+ ImportKeyBlob(blob, hasPrivateKey);
+ }
+
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead);
+ }
+
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead);
+ }
+
+ public override byte[] ExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ PbeParameters pbeParameters)
+ {
+ if (pbeParameters == null)
+ throw new ArgumentNullException(nameof(pbeParameters));
+
+ return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
+ this,
+ passwordBytes,
+ pbeParameters);
+ }
+
+ public override byte[] ExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ PbeParameters pbeParameters)
+ {
+ if (pbeParameters == null)
{
- ThrowIfDisposed();
- base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead);
+ throw new ArgumentNullException(nameof(pbeParameters));
}
- public override byte[] ExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- PbeParameters pbeParameters)
- {
- if (pbeParameters == null)
- throw new ArgumentNullException(nameof(pbeParameters));
+ PasswordBasedEncryption.ValidatePbeParameters(
+ pbeParameters,
+ password,
+ ReadOnlySpan.Empty);
- return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
- this,
- passwordBytes,
- pbeParameters);
+ if (CngPkcs8.IsPlatformScheme(pbeParameters))
+ {
+ return ExportEncryptedPkcs8(password, pbeParameters.IterationCount);
}
- public override byte[] ExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- PbeParameters pbeParameters)
- {
- if (pbeParameters == null)
- {
- throw new ArgumentNullException(nameof(pbeParameters));
- }
+ return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
+ this,
+ password,
+ pbeParameters);
+ }
- PasswordBasedEncryption.ValidatePbeParameters(
- pbeParameters,
- password,
- ReadOnlySpan.Empty);
+ public override bool TryExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ PbeParameters pbeParameters,
+ Span destination,
+ out int bytesWritten)
+ {
+ if (pbeParameters == null)
+ throw new ArgumentNullException(nameof(pbeParameters));
+
+ PasswordBasedEncryption.ValidatePbeParameters(
+ pbeParameters,
+ ReadOnlySpan.Empty,
+ passwordBytes);
+
+ return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
+ this,
+ passwordBytes,
+ pbeParameters,
+ destination,
+ out bytesWritten);
+ }
- if (CngPkcs8.IsPlatformScheme(pbeParameters))
- {
- return ExportEncryptedPkcs8(password, pbeParameters.IterationCount);
- }
+ public override bool TryExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ PbeParameters pbeParameters,
+ Span destination,
+ out int bytesWritten)
+ {
+ if (pbeParameters == null)
+ throw new ArgumentNullException(nameof(pbeParameters));
- return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
- this,
- password,
- pbeParameters);
- }
+ PasswordBasedEncryption.ValidatePbeParameters(
+ pbeParameters,
+ password,
+ ReadOnlySpan.Empty);
- public override bool TryExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- PbeParameters pbeParameters,
- Span destination,
- out int bytesWritten)
+ if (CngPkcs8.IsPlatformScheme(pbeParameters))
{
- if (pbeParameters == null)
- throw new ArgumentNullException(nameof(pbeParameters));
-
- PasswordBasedEncryption.ValidatePbeParameters(
- pbeParameters,
- ReadOnlySpan.Empty,
- passwordBytes);
-
- return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
- this,
- passwordBytes,
- pbeParameters,
+ return TryExportEncryptedPkcs8(
+ password,
+ pbeParameters.IterationCount,
destination,
out bytesWritten);
}
- public override bool TryExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- PbeParameters pbeParameters,
- Span destination,
- out int bytesWritten)
+ return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
+ this,
+ password,
+ pbeParameters,
+ destination,
+ out bytesWritten);
+ }
+
+ private static unsafe void GenerateV1DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivate)
+ {
+ // We need to build a key blob structured as follows:
+ //
+ // BCRYPT_DSA_KEY_BLOB header
+ // byte[cbKey] P
+ // byte[cbKey] G
+ // byte[cbKey] Y
+ // -- Private only --
+ // byte[Sha1HashOutputSize] X
+
+ int blobSize =
+ sizeof(BCRYPT_DSA_KEY_BLOB) +
+ cbKey +
+ cbKey +
+ cbKey;
+
+ if (includePrivate)
+ {
+ blobSize += Sha1HashOutputSize;
+ }
+
+ blob = new byte[blobSize];
+ fixed (byte* pDsaBlob = &blob[0])
{
- if (pbeParameters == null)
- throw new ArgumentNullException(nameof(pbeParameters));
+ // Build the header
+ BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob;
- PasswordBasedEncryption.ValidatePbeParameters(
- pbeParameters,
- password,
- ReadOnlySpan.Empty);
+ pBcryptBlob->Magic = includePrivate ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC;
+ pBcryptBlob->cbKey = cbKey;
- if (CngPkcs8.IsPlatformScheme(pbeParameters))
+ int offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey
+
+ if (parameters.Seed != null)
{
- return TryExportEncryptedPkcs8(
- password,
- pbeParameters.IterationCount,
- destination,
- out bytesWritten);
+ // The Seed length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message.
+ if (parameters.Seed.Length != Sha1HashOutputSize)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_SeedRestriction_ShortKey);
+
+ Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Seed);
+ }
+ else
+ {
+ // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject
+ // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng.
+ Interop.BCrypt.EmitByte(blob, ref offset, 0xff, Sha1HashOutputSize + sizeof(int));
}
- return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
- this,
- password,
- pbeParameters,
- destination,
- out bytesWritten);
- }
+ // The Q length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message.
+ if (parameters.Q!.Length != Sha1HashOutputSize)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_QRestriction_ShortKey);
- private static unsafe void GenerateV1DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivate)
- {
- // We need to build a key blob structured as follows:
- //
- // BCRYPT_DSA_KEY_BLOB header
- // byte[cbKey] P
- // byte[cbKey] G
- // byte[cbKey] Y
- // -- Private only --
- // byte[Sha1HashOutputSize] X
-
- int blobSize =
- sizeof(BCRYPT_DSA_KEY_BLOB) +
- cbKey +
- cbKey +
- cbKey;
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Q);
+
+ Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}");
+ Interop.BCrypt.Emit(blob, ref offset, parameters.P!);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.G!);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Y!);
if (includePrivate)
{
- blobSize += Sha1HashOutputSize;
+ Interop.BCrypt.Emit(blob, ref offset, parameters.X!);
}
- blob = new byte[blobSize];
- fixed (byte* pDsaBlob = &blob[0])
- {
- // Build the header
- BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob;
-
- pBcryptBlob->Magic = includePrivate ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC;
- pBcryptBlob->cbKey = cbKey;
-
- int offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey
+ Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}");
+ }
+ }
- if (parameters.Seed != null)
- {
- // The Seed length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message.
- if (parameters.Seed.Length != Sha1HashOutputSize)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_SeedRestriction_ShortKey);
+ private static unsafe void GenerateV2DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivateParameters)
+ {
+ // We need to build a key blob structured as follows:
+ // BCRYPT_DSA_KEY_BLOB_V2 header
+ // byte[cbSeedLength] Seed
+ // byte[cbGroupSize] Q
+ // byte[cbKey] P
+ // byte[cbKey] G
+ // byte[cbKey] Y
+ // -- Private only --
+ // byte[cbGroupSize] X
+
+ int blobSize =
+ sizeof(BCRYPT_DSA_KEY_BLOB_V2) +
+ (parameters.Seed == null ? parameters.Q!.Length : parameters.Seed.Length) + // Use Q size if Seed is not present
+ parameters.Q!.Length +
+ parameters.P!.Length +
+ parameters.G!.Length +
+ parameters.Y!.Length +
+ (includePrivateParameters ? parameters.X!.Length : 0);
+
+ blob = new byte[blobSize];
+ fixed (byte* pDsaBlob = &blob[0])
+ {
+ // Build the header
+ BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob;
- Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter);
- Interop.BCrypt.Emit(blob, ref offset, parameters.Seed);
- }
- else
- {
- // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject
- // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng.
- Interop.BCrypt.EmitByte(blob, ref offset, 0xff, Sha1HashOutputSize + sizeof(int));
- }
+ pBcryptBlob->Magic = includePrivateParameters ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2 : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2;
+ pBcryptBlob->cbKey = cbKey;
- // The Q length is hardcoded into BCRYPT_DSA_KEY_BLOB, so check it now we can give a nicer error message.
- if (parameters.Q!.Length != Sha1HashOutputSize)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_QRestriction_ShortKey);
+ // For some reason, Windows bakes the hash algorithm into the key itself. Furthermore, it demands that the Q length match the
+ // length of the named hash algorithm's output - otherwise, the Import fails. So we have to give it the hash algorithm that matches
+ // the Q length - and if there is no matching hash algorithm, we throw up our hands and throw a PlatformNotSupported.
+ //
+ // Note that this has no bearing on the hash algorithm you pass to SignData(). The class library (not Windows) hashes that according
+ // to the hash algorithm passed to SignData() and presents the hash result to NCryptSignHash(), truncating the hash to the Q length
+ // if necessary (and as demanded by the NIST spec.) Windows will be no wiser and we'll get the result we want.
+ pBcryptBlob->hashAlgorithm = parameters.Q.Length switch
+ {
+ Sha1HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA1,
+ Sha256HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA256,
+ Sha512HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA512,
+ _ => throw new PlatformNotSupportedException(SR.Cryptography_InvalidDsaParameters_QRestriction_LargeKey),
+ };
+ pBcryptBlob->standardVersion = DSAFIPSVERSION_ENUM.DSA_FIPS186_3;
- Interop.BCrypt.Emit(blob, ref offset, parameters.Q);
+ int offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4]
- Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}");
+ if (parameters.Seed != null)
+ {
+ Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter);
+ Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
+ pBcryptBlob->cbSeedLength = parameters.Seed.Length;
+ pBcryptBlob->cbGroupSize = parameters.Q.Length;
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Seed);
+ }
+ else
+ {
+ // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject
+ // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng.
+ Interop.BCrypt.EmitByte(blob, ref offset, 0xff, sizeof(int));
+ Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
+ int defaultSeedLength = parameters.Q.Length;
+ pBcryptBlob->cbSeedLength = defaultSeedLength;
+ pBcryptBlob->cbGroupSize = parameters.Q.Length;
+ Interop.BCrypt.EmitByte(blob, ref offset, 0xff, defaultSeedLength);
+ }
- Interop.BCrypt.Emit(blob, ref offset, parameters.P!);
- Interop.BCrypt.Emit(blob, ref offset, parameters.G!);
- Interop.BCrypt.Emit(blob, ref offset, parameters.Y!);
- if (includePrivate)
- {
- Interop.BCrypt.Emit(blob, ref offset, parameters.X!);
- }
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Q);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.P);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.G);
+ Interop.BCrypt.Emit(blob, ref offset, parameters.Y);
- Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}");
+ if (includePrivateParameters)
+ {
+ Interop.BCrypt.Emit(blob, ref offset, parameters.X!);
}
+
+ Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}");
}
+ }
- private static unsafe void GenerateV2DsaBlob(out byte[] blob, DSAParameters parameters, int cbKey, bool includePrivateParameters)
- {
- // We need to build a key blob structured as follows:
- // BCRYPT_DSA_KEY_BLOB_V2 header
- // byte[cbSeedLength] Seed
- // byte[cbGroupSize] Q
- // byte[cbKey] P
- // byte[cbKey] G
- // byte[cbKey] Y
- // -- Private only --
- // byte[cbGroupSize] X
-
- int blobSize =
- sizeof(BCRYPT_DSA_KEY_BLOB_V2) +
- (parameters.Seed == null ? parameters.Q!.Length : parameters.Seed.Length) + // Use Q size if Seed is not present
- parameters.Q!.Length +
- parameters.P!.Length +
- parameters.G!.Length +
- parameters.Y!.Length +
- (includePrivateParameters ? parameters.X!.Length : 0);
-
- blob = new byte[blobSize];
- fixed (byte* pDsaBlob = &blob[0])
- {
- // Build the header
- BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob;
-
- pBcryptBlob->Magic = includePrivateParameters ? KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2 : KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2;
- pBcryptBlob->cbKey = cbKey;
-
- // For some reason, Windows bakes the hash algorithm into the key itself. Furthermore, it demands that the Q length match the
- // length of the named hash algorithm's output - otherwise, the Import fails. So we have to give it the hash algorithm that matches
- // the Q length - and if there is no matching hash algorithm, we throw up our hands and throw a PlatformNotSupported.
- //
- // Note that this has no bearing on the hash algorithm you pass to SignData(). The class library (not Windows) hashes that according
- // to the hash algorithm passed to SignData() and presents the hash result to NCryptSignHash(), truncating the hash to the Q length
- // if necessary (and as demanded by the NIST spec.) Windows will be no wiser and we'll get the result we want.
- pBcryptBlob->hashAlgorithm = parameters.Q.Length switch
- {
- Sha1HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA1,
- Sha256HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA256,
- Sha512HashOutputSize => HASHALGORITHM_ENUM.DSA_HASH_ALGORITHM_SHA512,
- _ => throw new PlatformNotSupportedException(SR.Cryptography_InvalidDsaParameters_QRestriction_LargeKey),
- };
- pBcryptBlob->standardVersion = DSAFIPSVERSION_ENUM.DSA_FIPS186_3;
+ public override DSAParameters ExportParameters(bool includePrivateParameters)
+ {
+ byte[] dsaBlob = ExportKeyBlob(includePrivateParameters);
- int offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4]
+ KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(dsaBlob, 0);
- if (parameters.Seed != null)
- {
- Interop.BCrypt.EmitBigEndian(blob, ref offset, parameters.Counter);
- Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
- pBcryptBlob->cbSeedLength = parameters.Seed.Length;
- pBcryptBlob->cbGroupSize = parameters.Q.Length;
- Interop.BCrypt.Emit(blob, ref offset, parameters.Seed);
- }
- else
- {
- // If Seed is not present, back fill both counter and seed with 0xff. Do not use parameters.Counter as CNG is more strict than CAPI and will reject
- // anything other than 0xffffffff. That could complicate efforts to switch usage of DSACryptoServiceProvider to DSACng.
- Interop.BCrypt.EmitByte(blob, ref offset, 0xff, sizeof(int));
- Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
- int defaultSeedLength = parameters.Q.Length;
- pBcryptBlob->cbSeedLength = defaultSeedLength;
- pBcryptBlob->cbGroupSize = parameters.Q.Length;
- Interop.BCrypt.EmitByte(blob, ref offset, 0xff, defaultSeedLength);
- }
+ // Check the magic value in the key blob header. If the blob does not have the required magic,
+ // then throw a CryptographicException.
+ CheckMagicValueOfKey(magic, includePrivateParameters);
- Interop.BCrypt.Emit(blob, ref offset, parameters.Q);
- Interop.BCrypt.Emit(blob, ref offset, parameters.P);
- Interop.BCrypt.Emit(blob, ref offset, parameters.G);
- Interop.BCrypt.Emit(blob, ref offset, parameters.Y);
+ unsafe
+ {
+ DSAParameters dsaParams = default;
- if (includePrivateParameters)
+ fixed (byte* pDsaBlob = dsaBlob)
+ {
+ int offset;
+ if (magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC)
{
- Interop.BCrypt.Emit(blob, ref offset, parameters.X!);
+ if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB))
+ throw ErrorCode.E_FAIL.ToCryptographicException();
+
+ BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob;
+ // We now have a buffer laid out as follows:
+ // BCRYPT_DSA_KEY_BLOB header
+ // byte[cbKey] P
+ // byte[cbKey] G
+ // byte[cbKey] Y
+ // -- Private only --
+ // byte[Sha1HashOutputSize] X
+
+ offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey
+
+ // Read out a (V1) BCRYPT_DSA_KEY_BLOB structure.
+ dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4));
+ dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
+ dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
+
+ Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}");
+ dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ if (includePrivateParameters)
+ {
+ dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
+ }
}
+ else
+ {
+ Debug.Assert(magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2);
- Debug.Assert(offset == blobSize, $"Expected offset = blobSize, got {offset} != {blobSize}");
- }
- }
+ if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2))
+ throw ErrorCode.E_FAIL.ToCryptographicException();
- public override DSAParameters ExportParameters(bool includePrivateParameters)
- {
- byte[] dsaBlob = ExportKeyBlob(includePrivateParameters);
+ BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob;
+ // We now have a buffer laid out as follows:
+ // BCRYPT_DSA_KEY_BLOB_V2 header
+ // byte[cbSeedLength] Seed
+ // byte[cbGroupSize] Q
+ // byte[cbKey] P
+ // byte[cbKey] G
+ // byte[cbKey] Y
+ // -- Private only --
+ // byte[cbGroupSize] X
- KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(dsaBlob, 0);
+ offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4]
- // Check the magic value in the key blob header. If the blob does not have the required magic,
- // then throw a CryptographicException.
- CheckMagicValueOfKey(magic, includePrivateParameters);
+ // Read out a BCRYPT_DSA_KEY_BLOB_V2 structure.
+ dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4));
- unsafe
- {
- DSAParameters dsaParams = default;
+ Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
- fixed (byte* pDsaBlob = dsaBlob)
- {
- int offset;
- if (magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC)
- {
- if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB))
- throw ErrorCode.E_FAIL.ToCryptographicException();
-
- BCRYPT_DSA_KEY_BLOB* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB*)pDsaBlob;
- // We now have a buffer laid out as follows:
- // BCRYPT_DSA_KEY_BLOB header
- // byte[cbKey] P
- // byte[cbKey] G
- // byte[cbKey] Y
- // -- Private only --
- // byte[Sha1HashOutputSize] X
-
- offset = sizeof(KeyBlobMagicNumber) + sizeof(int); // skip Magic and cbKey
-
- // Read out a (V1) BCRYPT_DSA_KEY_BLOB structure.
- dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4));
- dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
- dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
-
- Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB)}");
- dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- if (includePrivateParameters)
- {
- dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, Sha1HashOutputSize);
- }
- }
- else
+ dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbSeedLength);
+ dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize);
+ dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
+ if (includePrivateParameters)
{
- Debug.Assert(magic == KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 || magic == KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2);
-
- if (dsaBlob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2))
- throw ErrorCode.E_FAIL.ToCryptographicException();
-
- BCRYPT_DSA_KEY_BLOB_V2* pBcryptBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pDsaBlob;
- // We now have a buffer laid out as follows:
- // BCRYPT_DSA_KEY_BLOB_V2 header
- // byte[cbSeedLength] Seed
- // byte[cbGroupSize] Q
- // byte[cbKey] P
- // byte[cbKey] G
- // byte[cbKey] Y
- // -- Private only --
- // byte[cbGroupSize] X
-
- offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2) - 4; //skip to Count[4]
-
- // Read out a BCRYPT_DSA_KEY_BLOB_V2 structure.
- dsaParams.Counter = BinaryPrimitives.ReadInt32BigEndian(Interop.BCrypt.Consume(dsaBlob, ref offset, 4));
-
- Debug.Assert(offset == sizeof(BCRYPT_DSA_KEY_BLOB_V2), $"Expected offset = sizeof(BCRYPT_DSA_KEY_BLOB_V2), got {offset} != {sizeof(BCRYPT_DSA_KEY_BLOB_V2)}");
-
- dsaParams.Seed = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbSeedLength);
- dsaParams.Q = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize);
- dsaParams.P = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- dsaParams.G = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- dsaParams.Y = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbKey);
- if (includePrivateParameters)
- {
- dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize);
- }
+ dsaParams.X = Interop.BCrypt.Consume(dsaBlob, ref offset, pBcryptBlob->cbGroupSize);
}
+ }
- // If no counter/seed information is present, normalize Counter and Seed to 0/null to maintain parity with the CAPI version of DSA.
- if (dsaParams.Counter == -1)
- {
- dsaParams.Counter = 0;
- dsaParams.Seed = null;
- }
+ // If no counter/seed information is present, normalize Counter and Seed to 0/null to maintain parity with the CAPI version of DSA.
+ if (dsaParams.Counter == -1)
+ {
+ dsaParams.Counter = 0;
+ dsaParams.Seed = null;
+ }
- Debug.Assert(offset == dsaBlob.Length, $"Expected offset = dsaBlob.Length, got {offset} != {dsaBlob.Length}");
+ Debug.Assert(offset == dsaBlob.Length, $"Expected offset = dsaBlob.Length, got {offset} != {dsaBlob.Length}");
- return dsaParams;
- }
+ return dsaParams;
}
}
+ }
- ///
- /// This function checks the magic value in the key blob header
- ///
- /// The expected magic number.
- /// Private blob if true else public key blob
- private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters)
+ ///
+ /// This function checks the magic value in the key blob header
+ ///
+ /// The expected magic number.
+ /// Private blob if true else public key blob
+ private static void CheckMagicValueOfKey(KeyBlobMagicNumber magic, bool includePrivateParameters)
+ {
+ if (includePrivateParameters)
{
- if (includePrivateParameters)
- {
- if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2)
- throw new CryptographicException(SR.Cryptography_NotValidPrivateKey);
- }
- else
- {
- if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2)
- throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey);
- }
+ if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2)
+ throw new CryptographicException(SR.Cryptography_NotValidPrivateKey);
+ }
+ else
+ {
+ if (magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC && magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2)
+ throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey);
}
-
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
+
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs
index 7971a35a2adf9d..9393dc735880f4 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.SignVerify.cs
@@ -9,199 +9,174 @@
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class DSAImplementation
+ public sealed partial class DSACng : DSA
{
-#endif
- public sealed partial class DSACng : DSA
- {
- // As of FIPS 186-4 the maximum Q size is 32 bytes.
- //
- // See also: cbGroupSize at
- // https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_dsa_key_blob_v2
- private const int WindowsMaxQSize = 32;
+ // As of FIPS 186-4 the maximum Q size is 32 bytes.
+ //
+ // See also: cbGroupSize at
+ // https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/ns-bcrypt-_bcrypt_dsa_key_blob_v2
+ private const int WindowsMaxQSize = 32;
- public override byte[] CreateSignature(byte[] rgbHash)
+ public override byte[] CreateSignature(byte[] rgbHash)
+ {
+ if (rgbHash == null)
{
- if (rgbHash == null)
- {
- throw new ArgumentNullException(nameof(rgbHash));
- }
-
- Span stackBuf = stackalloc byte[WindowsMaxQSize];
- ReadOnlySpan source = AdjustHashSizeIfNecessary(rgbHash, stackBuf);
-
- using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
- {
- unsafe
- {
- return CngCommon.SignHash(keyHandle, source, AsymmetricPaddingMode.None, null, source.Length * 2);
- }
- }
+ throw new ArgumentNullException(nameof(rgbHash));
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- protected override unsafe bool TryCreateSignatureCore(
- ReadOnlySpan hash,
- Span destination,
- DSASignatureFormat signatureFormat,
- out int bytesWritten)
-#else
- public override unsafe bool TryCreateSignature(ReadOnlySpan hash, Span destination, out int bytesWritten)
-#endif
- {
- Span stackBuf = stackalloc byte[WindowsMaxQSize];
- ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf);
+ Span stackBuf = stackalloc byte[WindowsMaxQSize];
+ ReadOnlySpan source = AdjustHashSizeIfNecessary(rgbHash, stackBuf);
- using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ {
+ unsafe
{
- if (!CngCommon.TrySignHash(keyHandle, source, destination, AsymmetricPaddingMode.None, null, out bytesWritten))
- {
- bytesWritten = 0;
- return false;
- }
+ return CngCommon.SignHash(keyHandle, source, AsymmetricPaddingMode.None, null, source.Length * 2);
}
+ }
+ }
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
- {
- return true;
- }
+ protected override unsafe bool TryCreateSignatureCore(
+ ReadOnlySpan hash,
+ Span destination,
+ DSASignatureFormat signatureFormat,
+ out int bytesWritten)
+ {
+ Span stackBuf = stackalloc byte[WindowsMaxQSize];
+ ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf);
- if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence)
+ using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ {
+ if (!CngCommon.TrySignHash(keyHandle, source, destination, AsymmetricPaddingMode.None, null, out bytesWritten))
{
- Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
- throw new CryptographicException(
- SR.Cryptography_UnknownSignatureFormat,
- signatureFormat.ToString());
+ bytesWritten = 0;
+ return false;
}
+ }
- return AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer(
- destination.Slice(0, bytesWritten),
- destination,
- out bytesWritten);
-#else
+ if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
+ {
return true;
-#endif
}
- public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature)
+ if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence)
{
- if (rgbHash == null)
- {
- throw new ArgumentNullException(nameof(rgbHash));
- }
- if (rgbSignature == null)
- {
- throw new ArgumentNullException(nameof(rgbSignature));
- }
+ Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
+ throw new CryptographicException(
+ SR.Cryptography_UnknownSignatureFormat,
+ signatureFormat.ToString());
+ }
+
+ return AsymmetricAlgorithmHelpers.TryConvertIeee1363ToDer(
+ destination.Slice(0, bytesWritten),
+ destination,
+ out bytesWritten);
+ }
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- return VerifySignatureCore(rgbHash, rgbSignature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
-#else
- return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature);
-#endif
+ public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature)
+ {
+ if (rgbHash == null)
+ {
+ throw new ArgumentNullException(nameof(rgbHash));
+ }
+ if (rgbSignature == null)
+ {
+ throw new ArgumentNullException(nameof(rgbSignature));
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- protected override bool VerifySignatureCore(
- ReadOnlySpan hash,
- ReadOnlySpan signature,
- DSASignatureFormat signatureFormat)
+ return VerifySignatureCore(rgbHash, rgbSignature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
+ }
+
+ protected override bool VerifySignatureCore(
+ ReadOnlySpan hash,
+ ReadOnlySpan signature,
+ DSASignatureFormat signatureFormat)
+ {
+ Span stackBuf = stackalloc byte[WindowsMaxQSize];
+ ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf);
+
+ if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
{
- Span stackBuf = stackalloc byte[WindowsMaxQSize];
- ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf);
+ // source.Length is the field size, in bytes, so just convert to bits.
+ int fieldSizeBits = source.Length * 8;
+ signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature, fieldSizeBits);
+ }
+ else if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
+ {
+ Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
+ throw new CryptographicException(
+ SR.Cryptography_UnknownSignatureFormat,
+ signatureFormat.ToString());
+ }
- if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
- {
- // source.Length is the field size, in bytes, so just convert to bits.
- int fieldSizeBits = source.Length * 8;
- signature = this.ConvertSignatureToIeeeP1363(signatureFormat, signature, fieldSizeBits);
- }
- else if (signatureFormat != DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
- {
- Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
- throw new CryptographicException(
- SR.Cryptography_UnknownSignatureFormat,
- signatureFormat.ToString());
- }
-#else
- public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature)
+ using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
{
- Span stackBuf = stackalloc byte[WindowsMaxQSize];
- ReadOnlySpan source = AdjustHashSizeIfNecessary(hash, stackBuf);
-#endif
- using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ unsafe
{
- unsafe
- {
- return CngCommon.VerifyHash(keyHandle, source, signature, AsymmetricPaddingMode.None, null);
- }
+ return CngCommon.VerifyHash(keyHandle, source, signature, AsymmetricPaddingMode.None, null);
}
}
+ }
- private ReadOnlySpan AdjustHashSizeIfNecessary(ReadOnlySpan hash, Span stackBuf)
- {
- Debug.Assert(stackBuf.Length == WindowsMaxQSize);
+ private ReadOnlySpan AdjustHashSizeIfNecessary(ReadOnlySpan hash, Span stackBuf)
+ {
+ Debug.Assert(stackBuf.Length == WindowsMaxQSize);
- // Windows CNG requires that the hash output and q match sizes, but we can better
- // interoperate with other FIPS 186-3 implementations if we perform truncation
- // here, before sending it to CNG. Since this is a scenario presented in the
- // CAVP reference test suite, we can confirm our implementation.
- //
- // If, on the other hand, Q is too big, we need to left-pad the hash with zeroes
- // (since it gets treated as a big-endian number). Since this is also a scenario
- // presented in the CAVP reference test suite, we can confirm our implementation.
+ // Windows CNG requires that the hash output and q match sizes, but we can better
+ // interoperate with other FIPS 186-3 implementations if we perform truncation
+ // here, before sending it to CNG. Since this is a scenario presented in the
+ // CAVP reference test suite, we can confirm our implementation.
+ //
+ // If, on the other hand, Q is too big, we need to left-pad the hash with zeroes
+ // (since it gets treated as a big-endian number). Since this is also a scenario
+ // presented in the CAVP reference test suite, we can confirm our implementation.
- int qLength = ComputeQLength();
- Debug.Assert(qLength <= WindowsMaxQSize);
+ int qLength = ComputeQLength();
+ Debug.Assert(qLength <= WindowsMaxQSize);
- if (qLength == hash.Length)
- {
- return hash;
- }
+ if (qLength == hash.Length)
+ {
+ return hash;
+ }
- if (qLength < hash.Length)
- {
- return hash.Slice(0, qLength);
- }
+ if (qLength < hash.Length)
+ {
+ return hash.Slice(0, qLength);
+ }
+
+ int zeroByteCount = qLength - hash.Length;
+ stackBuf.Slice(0, zeroByteCount).Clear();
+ hash.CopyTo(stackBuf.Slice(zeroByteCount));
+ return stackBuf.Slice(0, qLength);
+ }
- int zeroByteCount = qLength - hash.Length;
- stackBuf.Slice(0, zeroByteCount).Clear();
- hash.CopyTo(stackBuf.Slice(zeroByteCount));
- return stackBuf.Slice(0, qLength);
+ private int ComputeQLength()
+ {
+ byte[] blob;
+ using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ {
+ blob = this.ExportKeyBlob(false);
}
- private int ComputeQLength()
+ unsafe
{
- byte[] blob;
- using (SafeNCryptKeyHandle keyHandle = GetDuplicatedKeyHandle())
+ if (blob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2))
{
- blob = this.ExportKeyBlob(false);
+ return Sha1HashOutputSize;
}
- unsafe
+ fixed (byte* pBlobBytes = blob)
{
- if (blob.Length < sizeof(BCRYPT_DSA_KEY_BLOB_V2))
+ BCRYPT_DSA_KEY_BLOB_V2* pBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pBlobBytes;
+ if (pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 && pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2)
{
+ // This is a V1 BCRYPT_DSA_KEY_BLOB, which hardcodes the Q length to 20 bytes.
return Sha1HashOutputSize;
}
- fixed (byte* pBlobBytes = blob)
- {
- BCRYPT_DSA_KEY_BLOB_V2* pBlob = (BCRYPT_DSA_KEY_BLOB_V2*)pBlobBytes;
- if (pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PUBLIC_MAGIC_V2 && pBlob->Magic != KeyBlobMagicNumber.BCRYPT_DSA_PRIVATE_MAGIC_V2)
- {
- // This is a V1 BCRYPT_DSA_KEY_BLOB, which hardcodes the Q length to 20 bytes.
- return Sha1HashOutputSize;
- }
-
- return pBlob->cbGroupSize;
- }
+ return pBlob->cbGroupSize;
}
}
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs b/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs
index a89f2706a23d43..d9f8ed5cafa680 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/DSACng.cs
@@ -5,84 +5,80 @@
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class DSAImplementation
+ public sealed partial class DSACng : DSA
{
-#endif
- public sealed partial class DSACng : DSA
+ ///
+ /// Create a DSACng algorithm with a random 2048 bit key pair.
+ ///
+ [SupportedOSPlatform("windows")]
+ public DSACng()
+ : this(keySize: s_defaultKeySize)
{
- ///
- /// Create a DSACng algorithm with a random 2048 bit key pair.
- ///
- public DSACng()
- : this(keySize: s_defaultKeySize)
- {
- }
+ }
- ///
- /// Creates a new DSACng object that will use a randomly generated key of the specified size.
- /// Valid key sizes range from 512 to 3072 bits, in increments of 64. It's suggested that a
- /// minimum size of 2048 bits be used for all keys.
- ///
- /// Size of the key to generate, in bits.
- /// if is not valid
- public DSACng(int keySize)
- {
- LegalKeySizesValue = s_legalKeySizes;
- KeySize = keySize;
- }
+ ///
+ /// Creates a new DSACng object that will use a randomly generated key of the specified size.
+ /// Valid key sizes range from 512 to 3072 bits, in increments of 64. It's suggested that a
+ /// minimum size of 2048 bits be used for all keys.
+ ///
+ /// Size of the key to generate, in bits.
+ /// if is not valid
+ [SupportedOSPlatform("windows")]
+ public DSACng(int keySize)
+ {
+ LegalKeySizesValue = s_legalKeySizes;
+ KeySize = keySize;
+ }
- public override KeySizes[] LegalKeySizes
+ public override KeySizes[] LegalKeySizes
+ {
+ get
{
- get
- {
- return base.LegalKeySizes;
- }
+ return base.LegalKeySizes;
}
+ }
- public override string SignatureAlgorithm => "DSA";
- public override string? KeyExchangeAlgorithm => null;
-
- // Need to override since base methods throw a "override me" exception: makes SignData/VerifyData function.
- protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
- CngCommon.HashData(data, offset, count, hashAlgorithm);
+ public override string SignatureAlgorithm => "DSA";
+ public override string? KeyExchangeAlgorithm => null;
- protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
- CngCommon.HashData(data, hashAlgorithm);
+ // Need to override since base methods throw a "override me" exception: makes SignData/VerifyData function.
+ protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>
+ CngCommon.HashData(data, offset, count, hashAlgorithm);
- protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
- CngCommon.TryHashData(source, destination, hashAlgorithm, out bytesWritten);
+ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
+ CngCommon.HashData(data, hashAlgorithm);
- private void ForceSetKeySize(int newKeySize)
- {
- // Our LegalKeySizes value stores the values that we encoded as being the correct
- // legal key size limitations for this algorithm, as documented on MSDN.
- //
- // But on a new OS version we might not question if our limit is accurate, or MSDN
- // could have been inaccurate to start with.
- //
- // Since the key is already loaded, we know that Windows thought it to be valid;
- // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
- // check.
- //
- KeySizeValue = newKeySize;
- }
+ protected override bool TryHashData(ReadOnlySpan source, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
+ CngCommon.TryHashData(source, destination, hashAlgorithm, out bytesWritten);
- private static bool Supports2048KeySize()
- {
- Debug.Assert(OperatingSystem.IsWindows());
- Version version = Environment.OSVersion.Version;
- bool isAtLeastWindows8 = version.Major > 6 || (version.Major == 6 && version.Minor >= 2);
- return isAtLeastWindows8;
- }
+ private void ForceSetKeySize(int newKeySize)
+ {
+ // Our LegalKeySizes value stores the values that we encoded as being the correct
+ // legal key size limitations for this algorithm, as documented on MSDN.
+ //
+ // But on a new OS version we might not question if our limit is accurate, or MSDN
+ // could have been inaccurate to start with.
+ //
+ // Since the key is already loaded, we know that Windows thought it to be valid;
+ // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
+ // check.
+ //
+ KeySizeValue = newKeySize;
+ }
- private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) };
- private static readonly int s_defaultKeySize = Supports2048KeySize() ? 2048 : 1024;
+ private static bool Supports2048KeySize()
+ {
+ Debug.Assert(OperatingSystem.IsWindows());
+ Version version = Environment.OSVersion.Version;
+ bool isAtLeastWindows8 = version.Major > 6 || (version.Major == 6 && version.Minor >= 2);
+ return isAtLeastWindows8;
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
+
+ private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) };
+ private static readonly int s_defaultKeySize = Supports2048KeySize() ? 2048 : 1024;
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs
index d51e1a3a8e5d3e..8a8445fe17f5b3 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/DSAOpenSsl.cs
@@ -3,425 +3,400 @@
using System.Diagnostics;
using System.IO;
+using System.Runtime.Versioning;
using Internal.Cryptography;
using Microsoft.Win32.SafeHandles;
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- public partial class DSA : AsymmetricAlgorithm
+ public sealed partial class DSAOpenSsl : DSA
{
- private static DSA CreateCore()
+ // The biggest key allowed by FIPS 186-4 has N=256 (bit), which
+ // maximally produces a 72-byte DER signature.
+ // If a future version of the standard continues to enhance DSA,
+ // we may want to bump this limit to allow the max-1 (expected size)
+ // TryCreateSignature to pass.
+ // Future updates seem unlikely, though, as FIPS 186-5 October 2019 draft has
+ // DSA as a no longer supported/updated algorithm.
+ private const int SignatureStackBufSize = 72;
+ private const int BitsPerByte = 8;
+
+ private Lazy _key = null!;
+
+ [UnsupportedOSPlatform("android")]
+ [UnsupportedOSPlatform("browser")]
+ [UnsupportedOSPlatform("ios")]
+ [UnsupportedOSPlatform("tvos")]
+ [UnsupportedOSPlatform("windows")]
+ public DSAOpenSsl()
+ : this(2048)
{
- return new DSAImplementation.DSAOpenSsl();
}
- }
- internal static partial class DSAImplementation
- {
-#endif
- public sealed partial class DSAOpenSsl : DSA
+ [UnsupportedOSPlatform("android")]
+ [UnsupportedOSPlatform("browser")]
+ [UnsupportedOSPlatform("ios")]
+ [UnsupportedOSPlatform("tvos")]
+ [UnsupportedOSPlatform("windows")]
+ public DSAOpenSsl(int keySize)
{
- // The biggest key allowed by FIPS 186-4 has N=256 (bit), which
- // maximally produces a 72-byte DER signature.
- // If a future version of the standard continues to enhance DSA,
- // we may want to bump this limit to allow the max-1 (expected size)
- // TryCreateSignature to pass.
- // Future updates seem unlikely, though, as FIPS 186-5 October 2019 draft has
- // DSA as a no longer supported/updated algorithm.
- private const int SignatureStackBufSize = 72;
- private const int BitsPerByte = 8;
-
- private Lazy _key = null!;
-
- public DSAOpenSsl()
- : this(2048)
- {
- }
-
- public DSAOpenSsl(int keySize)
- {
- ThrowIfNotSupported();
- LegalKeySizesValue = s_legalKeySizes;
- base.KeySize = keySize;
- _key = new Lazy(GenerateKey);
- }
+ ThrowIfNotSupported();
+ LegalKeySizesValue = s_legalKeySizes;
+ base.KeySize = keySize;
+ _key = new Lazy(GenerateKey);
+ }
- public override int KeySize
+ public override int KeySize
+ {
+ set
{
- set
+ if (KeySize == value)
{
- if (KeySize == value)
- {
- return;
- }
+ return;
+ }
- // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key
- base.KeySize = value;
+ // Set the KeySize before FreeKey so that an invalid value doesn't throw away the key
+ base.KeySize = value;
- ThrowIfDisposed();
- FreeKey();
- _key = new Lazy(GenerateKey);
- }
+ ThrowIfDisposed();
+ FreeKey();
+ _key = new Lazy(GenerateKey);
}
+ }
- private void ForceSetKeySize(int newKeySize)
- {
- // In the event that a key was loaded via ImportParameters or an IntPtr/SafeHandle
- // it could be outside of the bounds that we currently represent as "legal key sizes".
- // Since that is our view into the underlying component it can be detached from the
- // component's understanding. If it said it has opened a key, and this is the size, trust it.
- KeySizeValue = newKeySize;
- }
+ private void ForceSetKeySize(int newKeySize)
+ {
+ // In the event that a key was loaded via ImportParameters or an IntPtr/SafeHandle
+ // it could be outside of the bounds that we currently represent as "legal key sizes".
+ // Since that is our view into the underlying component it can be detached from the
+ // component's understanding. If it said it has opened a key, and this is the size, trust it.
+ KeySizeValue = newKeySize;
+ }
- public override KeySizes[] LegalKeySizes
+ public override KeySizes[] LegalKeySizes
+ {
+ get
{
- get
- {
- return base.LegalKeySizes;
- }
+ return base.LegalKeySizes;
}
+ }
- public override DSAParameters ExportParameters(bool includePrivateParameters)
- {
- // It's entirely possible that this line will cause the key to be generated in the first place.
- SafeDsaHandle key = GetKey();
-
- DSAParameters dsaParameters = Interop.Crypto.ExportDsaParameters(key, includePrivateParameters);
- bool hasPrivateKey = dsaParameters.X != null;
-
- if (hasPrivateKey != includePrivateParameters)
- throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
+ public override DSAParameters ExportParameters(bool includePrivateParameters)
+ {
+ // It's entirely possible that this line will cause the key to be generated in the first place.
+ SafeDsaHandle key = GetKey();
- return dsaParameters;
- }
+ DSAParameters dsaParameters = Interop.Crypto.ExportDsaParameters(key, includePrivateParameters);
+ bool hasPrivateKey = dsaParameters.X != null;
- public override void ImportParameters(DSAParameters parameters)
- {
- if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields);
+ if (hasPrivateKey != includePrivateParameters)
+ throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
- // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check
- // is just to maintain parity with DSACNG and DSACryptoServiceProvider, which also perform this check.
- if (parameters.J != null && parameters.J.Length >= parameters.P.Length)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ);
+ return dsaParameters;
+ }
- bool hasPrivateKey = parameters.X != null;
+ public override void ImportParameters(DSAParameters parameters)
+ {
+ if (parameters.P == null || parameters.Q == null || parameters.G == null || parameters.Y == null)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MissingFields);
- int keySize = parameters.P.Length;
- if (parameters.G.Length != keySize || parameters.Y.Length != keySize)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY);
+ // J is not required and is not even used on CNG blobs. It should however be less than P (J == (P-1) / Q). This validation check
+ // is just to maintain parity with DSACNG and DSACryptoServiceProvider, which also perform this check.
+ if (parameters.J != null && parameters.J.Length >= parameters.P.Length)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPJ);
- if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length)
- throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX);
+ bool hasPrivateKey = parameters.X != null;
- ThrowIfDisposed();
+ int keySize = parameters.P.Length;
+ if (parameters.G.Length != keySize || parameters.Y.Length != keySize)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedPGY);
- SafeDsaHandle key;
- if (!Interop.Crypto.DsaKeyCreateByExplicitParameters(
- out key,
- parameters.P, parameters.P.Length,
- parameters.Q, parameters.Q.Length,
- parameters.G, parameters.G.Length,
- parameters.Y, parameters.Y.Length,
- parameters.X, parameters.X != null ? parameters.X.Length : 0))
- {
- throw Interop.Crypto.CreateOpenSslCryptographicException();
- }
+ if (hasPrivateKey && parameters.X!.Length != parameters.Q.Length)
+ throw new ArgumentException(SR.Cryptography_InvalidDsaParameters_MismatchedQX);
- SetKey(key);
- }
+ ThrowIfDisposed();
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- ReadOnlySpan source,
- out int bytesRead)
+ SafeDsaHandle key;
+ if (!Interop.Crypto.DsaKeyCreateByExplicitParameters(
+ out key,
+ parameters.P, parameters.P.Length,
+ parameters.Q, parameters.Q.Length,
+ parameters.G, parameters.G.Length,
+ parameters.Y, parameters.Y.Length,
+ parameters.X, parameters.X != null ? parameters.X.Length : 0))
{
- ThrowIfDisposed();
- base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead);
+ throw Interop.Crypto.CreateOpenSslCryptographicException();
}
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- ReadOnlySpan source,
- out int bytesRead)
- {
- ThrowIfDisposed();
- base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead);
- }
+ SetKey(key);
+ }
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- FreeKey();
- _key = null!;
- }
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ base.ImportEncryptedPkcs8PrivateKey(passwordBytes, source, out bytesRead);
+ }
- base.Dispose(disposing);
- }
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ base.ImportEncryptedPkcs8PrivateKey(password, source, out bytesRead);
+ }
- private void FreeKey()
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
{
- if (_key != null && _key.IsValueCreated)
- {
- SafeDsaHandle handle = _key.Value;
-
- if (handle != null)
- {
- handle.Dispose();
- }
- }
+ FreeKey();
+ _key = null!;
}
- private static void CheckInvalidKey(SafeDsaHandle key)
+ base.Dispose(disposing);
+ }
+
+ private void FreeKey()
+ {
+ if (_key != null && _key.IsValueCreated)
{
- if (key == null || key.IsInvalid)
+ SafeDsaHandle handle = _key.Value;
+
+ if (handle != null)
{
- throw new CryptographicException(SR.Cryptography_OpenInvalidHandle);
+ handle.Dispose();
}
}
+ }
- private SafeDsaHandle GenerateKey()
+ private static void CheckInvalidKey(SafeDsaHandle key)
+ {
+ if (key == null || key.IsInvalid)
{
- SafeDsaHandle key;
+ throw new CryptographicException(SR.Cryptography_OpenInvalidHandle);
+ }
+ }
- if (!Interop.Crypto.DsaGenerateKey(out key, KeySize))
- {
- throw Interop.Crypto.CreateOpenSslCryptographicException();
- }
+ private SafeDsaHandle GenerateKey()
+ {
+ SafeDsaHandle key;
- return key;
+ if (!Interop.Crypto.DsaGenerateKey(out key, KeySize))
+ {
+ throw Interop.Crypto.CreateOpenSslCryptographicException();
}
- protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
- {
- // we're sealed and the base should have checked this already
- Debug.Assert(data != null);
- Debug.Assert(offset >= 0 && offset <= data.Length);
- Debug.Assert(count >= 0 && count <= data.Length);
- Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
+ return key;
+ }
- return AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm);
- }
+ protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
+ {
+ // we're sealed and the base should have checked this already
+ Debug.Assert(data != null);
+ Debug.Assert(offset >= 0 && offset <= data.Length);
+ Debug.Assert(count >= 0 && count <= data.Length);
+ Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
- protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
- AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm);
+ return AsymmetricAlgorithmHelpers.HashData(data, offset, count, hashAlgorithm);
+ }
- protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
- AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten);
+ protected override byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm) =>
+ AsymmetricAlgorithmHelpers.HashData(data, hashAlgorithm);
- public override byte[] CreateSignature(byte[] rgbHash)
- {
- if (rgbHash == null)
- throw new ArgumentNullException(nameof(rgbHash));
+ protected override bool TryHashData(ReadOnlySpan data, Span destination, HashAlgorithmName hashAlgorithm, out int bytesWritten) =>
+ AsymmetricAlgorithmHelpers.TryHashData(data, destination, hashAlgorithm, out bytesWritten);
- SafeDsaHandle key = GetKey();
- int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key);
- int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte;
- Span signDestination = stackalloc byte[SignatureStackBufSize];
+ public override byte[] CreateSignature(byte[] rgbHash)
+ {
+ if (rgbHash == null)
+ throw new ArgumentNullException(nameof(rgbHash));
- ReadOnlySpan derSignature = SignHash(rgbHash, signDestination, signatureSize, key);
- return AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize);
- }
+ SafeDsaHandle key = GetKey();
+ int signatureSize = Interop.Crypto.DsaEncodedSignatureSize(key);
+ int signatureFieldSize = Interop.Crypto.DsaSignatureFieldSize(key) * BitsPerByte;
+ Span signDestination = stackalloc byte[SignatureStackBufSize];
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- public override bool TryCreateSignature(
- ReadOnlySpan hash,
- Span destination,
- out int bytesWritten)
- {
- return TryCreateSignatureCore(
- hash,
- destination,
- DSASignatureFormat.IeeeP1363FixedFieldConcatenation,
- out bytesWritten);
- }
+ ReadOnlySpan derSignature = SignHash(rgbHash, signDestination, signatureSize, key);
+ return AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, signatureFieldSize);
+ }
+
+ public override bool TryCreateSignature(
+ ReadOnlySpan hash,
+ Span destination,
+ out int bytesWritten)
+ {
+ return TryCreateSignatureCore(
+ hash,
+ destination,
+ DSASignatureFormat.IeeeP1363FixedFieldConcatenation,
+ out bytesWritten);
+ }
+
+ protected override bool TryCreateSignatureCore(
+ ReadOnlySpan hash,
+ Span destination,
+ DSASignatureFormat signatureFormat,
+ out int bytesWritten)
+ {
+ SafeDsaHandle key = GetKey();
+ int maxSignatureSize = Interop.Crypto.DsaEncodedSignatureSize(key);
+ Span signDestination = stackalloc byte[SignatureStackBufSize];
- protected override bool TryCreateSignatureCore(
- ReadOnlySpan hash,
- Span destination,
- DSASignatureFormat signatureFormat,
- out int bytesWritten)
-#else
- public override bool TryCreateSignature(ReadOnlySpan hash, Span destination, out int bytesWritten)
-#endif
+ if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
{
- SafeDsaHandle key = GetKey();
- int maxSignatureSize = Interop.Crypto.DsaEncodedSignatureSize(key);
- Span signDestination = stackalloc byte[SignatureStackBufSize];
+ int fieldSizeBytes = Interop.Crypto.DsaSignatureFieldSize(key);
+ int p1363SignatureSize = 2 * fieldSizeBytes;
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
-#endif
+ if (destination.Length < p1363SignatureSize)
{
- int fieldSizeBytes = Interop.Crypto.DsaSignatureFieldSize(key);
- int p1363SignatureSize = 2 * fieldSizeBytes;
-
- if (destination.Length < p1363SignatureSize)
- {
- bytesWritten = 0;
- return false;
- }
+ bytesWritten = 0;
+ return false;
+ }
- int fieldSizeBits = fieldSizeBytes * 8;
+ int fieldSizeBits = fieldSizeBytes * 8;
- ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key);
- bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination);
- Debug.Assert(bytesWritten == p1363SignatureSize);
- return true;
- }
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
+ ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key);
+ bytesWritten = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(derSignature, fieldSizeBits, destination);
+ Debug.Assert(bytesWritten == p1363SignatureSize);
+ return true;
+ }
+ else if (signatureFormat == DSASignatureFormat.Rfc3279DerSequence)
+ {
+ if (destination.Length >= maxSignatureSize)
{
- if (destination.Length >= maxSignatureSize)
- {
- signDestination = destination;
- }
- else if (maxSignatureSize > signDestination.Length)
- {
- Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)");
- bytesWritten = 0;
- return false;
- }
-
- ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key);
-
- if (destination == signDestination)
- {
- bytesWritten = derSignature.Length;
- return true;
- }
-
- return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten);
+ signDestination = destination;
}
- else
+ else if (maxSignatureSize > signDestination.Length)
{
- Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
- throw new CryptographicException(
- SR.Cryptography_UnknownSignatureFormat,
- signatureFormat.ToString());
+ Debug.Fail($"Stack-based signDestination is insufficient ({maxSignatureSize} needed)");
+ bytesWritten = 0;
+ return false;
}
-#endif
- }
- private static ReadOnlySpan SignHash(
- ReadOnlySpan hash,
- Span destination,
- int signatureLength,
- SafeDsaHandle key)
- {
- if (signatureLength > destination.Length)
- {
- Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)");
- destination = new byte[signatureLength];
- }
+ ReadOnlySpan derSignature = SignHash(hash, signDestination, maxSignatureSize, key);
- if (!Interop.Crypto.DsaSign(key, hash, destination, out int actualLength))
+ if (destination == signDestination)
{
- throw Interop.Crypto.CreateOpenSslCryptographicException();
+ bytesWritten = derSignature.Length;
+ return true;
}
- Debug.Assert(
- actualLength <= signatureLength,
- "DSA_sign reported an unexpected signature size",
- "DSA_sign reported signatureSize was {0}, when <= {1} was expected",
- actualLength,
- signatureLength);
-
- return destination.Slice(0, actualLength);
+ return Helpers.TryCopyToDestination(derSignature, destination, out bytesWritten);
}
+ else
+ {
+ Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
+ throw new CryptographicException(
+ SR.Cryptography_UnknownSignatureFormat,
+ signatureFormat.ToString());
+ }
+ }
- public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature)
+ private static ReadOnlySpan SignHash(
+ ReadOnlySpan hash,
+ Span destination,
+ int signatureLength,
+ SafeDsaHandle key)
+ {
+ if (signatureLength > destination.Length)
{
- if (rgbHash == null)
- throw new ArgumentNullException(nameof(rgbHash));
- if (rgbSignature == null)
- throw new ArgumentNullException(nameof(rgbSignature));
+ Debug.Fail($"Stack-based signDestination is insufficient ({signatureLength} needed)");
+ destination = new byte[signatureLength];
+ }
- return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature);
+ if (!Interop.Crypto.DsaSign(key, hash, destination, out int actualLength))
+ {
+ throw Interop.Crypto.CreateOpenSslCryptographicException();
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
+ Debug.Assert(
+ actualLength <= signatureLength,
+ "DSA_sign reported an unexpected signature size",
+ "DSA_sign reported signatureSize was {0}, when <= {1} was expected",
+ actualLength,
+ signatureLength);
- public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) =>
- VerifySignatureCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
+ return destination.Slice(0, actualLength);
+ }
- protected override bool VerifySignatureCore(
- ReadOnlySpan hash,
- ReadOnlySpan signature,
- DSASignatureFormat signatureFormat)
-#else
- public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature)
-#endif
- {
- SafeDsaHandle key = GetKey();
+ public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature)
+ {
+ if (rgbHash == null)
+ throw new ArgumentNullException(nameof(rgbHash));
+ if (rgbSignature == null)
+ throw new ArgumentNullException(nameof(rgbSignature));
+
+ return VerifySignature((ReadOnlySpan)rgbHash, (ReadOnlySpan)rgbSignature);
+ }
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
- {
-#endif
- int expectedSignatureBytes = Interop.Crypto.DsaSignatureFieldSize(key) * 2;
- if (signature.Length != expectedSignatureBytes)
- {
- // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER.
- return false;
- }
-
- signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature);
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- }
- else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence)
- {
- Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
- throw new CryptographicException(
- SR.Cryptography_UnknownSignatureFormat,
- signatureFormat.ToString());
- }
-#endif
- return Interop.Crypto.DsaVerify(key, hash, signature);
- }
- private void ThrowIfDisposed()
+ public override bool VerifySignature(ReadOnlySpan hash, ReadOnlySpan signature) =>
+ VerifySignatureCore(hash, signature, DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
+
+ protected override bool VerifySignatureCore(
+ ReadOnlySpan