diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index f6ec0a4e1da7e2..447d17d5160111 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,7 +15,7 @@
]
},
"microsoft.dotnet.xharness.cli": {
- "version": "1.0.0-prerelease.22074.1",
+ "version": "1.0.0-prerelease.22101.2",
"commands": [
"xharness"
]
diff --git a/.github/fabricbot.json b/.github/fabricbot.json
index accae195f26ee0..bb429f3f8d9354 100644
--- a/.github/fabricbot.json
+++ b/.github/fabricbot.json
@@ -190,6 +190,14 @@
"dotnet/area-system-runtime-intrinsics"
]
},
+ {
+ "labels": [
+ "area-System.Runtime.InteropServices"
+ ],
+ "mentionees": [
+ "dotnet/interop-contrib"
+ ]
+ },
{
"labels": [
"area-System.CodeDom"
@@ -9969,5 +9977,1227 @@
}
]
}
+ },
+ {
+ "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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "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: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "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: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
}
-]
\ No newline at end of file
+]
diff --git a/docs/area-owners.md b/docs/area-owners.md
index 70cc2e4e82fdd9..b310d60381e72a 100644
--- a/docs/area-owners.md
+++ b/docs/area-owners.md
@@ -4,7 +4,7 @@ If you need to tag folks on an issue or PR, you will generally want to tag the o
## Areas
-Note: Editing this file doesn't update the mapping used by the `@msftbot` issue notification bot to tag owners. Some area owners prefer not to get those notifications. To update those notifications, contact any one of `@danmoseley`, `@jeffschw`, `@marek-safar`, `@ericstj`, `@karelz`, or `@jeffhandley`; they have permissions to update [`msftbot` configuration](https://portal.fabricbot.ms/bot/?repo=dotnet/runtime). If you're a community member interested in these notifications, you won't appear in this table but we can add you to notifications - just let us know.
+Note: Editing this file doesn't update the mapping used by `@msftbot` for area-specific issue/PR notifications. That configuration is part of the [`fabricbot.json`](../.github/fabricbot.json) file, and many areas use GitHub teams for those notifications. If you're a community member interested in receiving area-specific issue/PR notifications, you won't appear in this table or be added to those GitHub teams, but you can create a PR that updates `fabricbot.json` to add yourself to those notifications. See [automation.md](infra/automation.md) for more information on the schema and tools used by FabricBot.
| Area | Lead | Owners (area experts to tag in PR's and issues) | Notes |
|------------------------------------------------|---------------|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
diff --git a/docs/coding-guidelines/libraries-packaging.md b/docs/coding-guidelines/libraries-packaging.md
index 66909e4df855cf..be1a1c8ae8fda8 100644
--- a/docs/coding-guidelines/libraries-packaging.md
+++ b/docs/coding-guidelines/libraries-packaging.md
@@ -92,6 +92,3 @@ In order to mitigate design-time/build-time performance issues with source gener
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/OsrDetailsAndDebugging.md b/docs/design/features/OsrDetailsAndDebugging.md
new file mode 100644
index 00000000000000..9f479f689a5abd
--- /dev/null
+++ b/docs/design/features/OsrDetailsAndDebugging.md
@@ -0,0 +1,493 @@
+# OSR Details and Debugging
+
+This document describes some of the rationale behind OSR, things you
+may need to think about when OSR is enabled, and some debugging
+techniques that you can use when things go wrong.
+
+It is primarily aimed at JIT developers but may prove useful to a
+broader audience.
+
+## Background
+
+OSR (On Stack Replacement) describes the ability of the runtime to
+transfer control from one native code version to another while there
+are active stack frames for the method.
+
+The primary goal of OSR is to allow the runtime to initially jit most
+methods without optimization, and then transition control (via OSR) if
+and when the invocations of those methods become compute
+intensive. During a transition the active invocations are rewritten
+"on stack" to have the proper frame shape and code references.
+
+In this way OSR is similar to tiering, but tiering can only change
+between native code versions when a method is called. So, for
+instance, if a user puts all their code inside loops in `Main` then
+tiering will never have an opportunity to update the code being run,
+as `Main` is only ever called once.
+
+OSR is also in many ways similar to EnC (Edit and Continue), though
+there are key differences. EnC transitions are initiated by user
+edits via the debugger, and typically this means the IL version of the
+method has changed. OSR transitions are mediated by the runtime, and
+the transitioned-to methods represent different native code
+compilation of the same IL code version.
+
+In our particular implementation OSR is used to transition from a
+Tier0 (or "quick") jitted (and hence unoptimized) native code
+version to an OSR version that is optimized. OSR versions of the
+native code for a method are unusual in many ways; we discuss this
+further below.
+
+For more detail on the OSR design, see the References section.
+
+### Tiered Compilation
+
+OSR is built on top of Tiered Compilation, which we briefly recap.
+
+Tiered Compilation is a runtime and jit feature that allows methods to
+be initially jitted quickly, without optimization, and then be
+rejitted later on with optimization, if the methods are frequently
+called. This allows applications to start up quickly as less time
+is spent jitting up front, but still obtain full steady-state
+performance over time.
+
+There are different polices that apply to determine which methods
+are handled via tiered compilation, and how they are optimized.
+* The normal case is that a method is first quickly jitted (at Tier0)
+and then rejitted (at Tier1) (on a background thread) once the
+method has been called frequently.
+* If a method has been prejitted then the prejitted code serves
+the place of the Tier0 code.
+* Some methods bypass tiering and are immediately optimized
+the first time they are jitted:
+ * Methods marked with the `AggressiveOptimization` attribute
+ * Dynamic methods and methods from collectible assemblies
+ * By default in .NET 3.0, 5.0, 6.0: methods with loops.
+This policy is controlled by `DOTNET_COMPlus_TC_QuickJitForLoops`;
+ see next section.
+
+### Dynamic and Full PGO
+
+Dynamic PGO was introduced in the .NET 6.0 release. It also relies
+on tiered compilation.
+
+In Dynamic PGO, any method jitted at Tier0 has additional
+instrumentation code added to the Tier0 version to collect profile
+data. This data is made available to JIT when the method is
+recompiled at Tier1.
+
+Full PGO is an offshoot of Dynamic PGO where we force all methods
+to pass through Tier0.
+
+### Quick Jit For Loops (aka `QJFL`)
+
+Tiered compilation was introduced in the .NET Core 3.0 release.
+
+Initially, all methods that got jitted went through Tier0. But
+during the development cycle we got a fair amount of feedback that
+this had adverse performance impacts as performance-sensitive user
+code could be trapped in the Tier0 version.
+
+In response to this we changed the default behavior: methods with
+loops would be initially optimized and not participate in tiered jitting.
+We often use the shorthand `QJFL=0` to describe this behavior.
+
+While `QJFL=0` addressed the immediate problems users had with tiered
+compilation, it had some downsides:
+
+* Not all methods with loops are performance sensitive, so in many
+cases we saw increased startup JIT time without any steady state
+benefit. In some applications where startup JIT time is significant
+the impact was on the order of 20%.
+
+* In fact, early optimization of methods may lead to lower
+steady-state performance, because (a) class initializers may not yet
+have run, so early optimized methods must run class initializer checks
+and also cannot examine readonly static fields; (b) Dynamic PGO can
+only operate on methods that pass through Tier0.
+
+One can change the default behavior by setting QJFL to 1; some
+startup-sensitive applications (eg `Powershell`) do this.
+
+### Rationale for Enabling OSR
+
+OSR allows the runtime to jit most methods at Tier0, and to transition
+from Tier0 code when and if needed, and so allows us to change the
+default to `QJFL=1`.
+
+Enabling OSR will lead to:
+* better startup perf in general (upwards of 20% in some cases)
+* improved steady state perf
+* improved perf from Dynamic PGO (closing the gap between Dynamic
+ PGO and Full PGO)
+
+## How OSR Works
+
+### Enabling OSR
+
+OSR is enabled by setting
+`DOTNET_TC_QuickJitForLoops=1` (aka `QJFL=1`)
+`DOTNET_TC_OnStackReplacement=1` (aka `OSR=1`)
+
+and is influenced by
+`DOTNET_TieredPGO=1` (`BBINSTR=1` at TIER0)
+
+### Choosing which methods are "OSR Eligible"
+
+The runtime makes a JIT request at TIER0, and passes the current
+values of QJFL, OSR, and BBINSTR.
+
+The JIT does an initial IL scan for the method; during this scan it
+checks for several things:
+* if there is any lexically backwards IL branch (`compHasBackwardsBranch`)
+* if there is any lexically backwards branch in catch, filter, finally,
+or fault region (aka "loop in handler").
+* if there is any `localloc`
+* if the method is a reverse PInvoke
+* if there is any `tail.` prefixed call.
+
+If `QJFL=0 && compHasBackwardsBranch`, the JIT changes the
+optimization level to full opt and notifies the runtime that the
+method is no longer going to participate in tiered compilation.
+This is the default behavior in older releases.
+
+If `QJFL=1 && OSR==0 && !compHasBackwardsBranch`, the JIT compiles the
+method at Tier0.
+
+If `QJFL=1 && OSR==1 && compHasBackwardsBranch`, the JIT checks to see
+if the method has a loop in a handler, localloc, or is a reverse
+PInvoke. If not, the method is "OSR Eligible". If so, the JIT will
+switch the method to optimized.
+
+If there is a `tail.` prefixed call and BBINSTR=0, the JIT will
+override all the above and switch the method to optimized.
+
+### Jitting of OSR Eligible Methods at Tier0
+
+During importation, the jit looks for blocks that are the targets of
+the lexical back edges. It marks these as needing patchpoints. Note these
+points are required to be stack empty points in valid IL.
+
+During the patchpoint phase, if any block was marked, the jit adds a
+new integer local to the method (the patchpoint counter) and adds IR
+to initialize the counter on method entry to the value of
+`DOTNET_TC_OnStackReplacement_InitialCounter` (by default this is
+0x1000).
+
+At each marked block the JIT adds code to decrement the counter and
+conditionally invoke `CORINFO_HELP_PATCHPOINT` if the counter value is zero
+or negative. The helper arguments are the IL offset of the block and
+the address of the counter.
+
+The remainder of compilation proceeds normally, but when the method is
+finished, the JIT creates a patchpoint descriptor to note the method's
+frame size, virtual offset of all IL locals, and the offset of some
+other key frame information (generics context, etc). This descriptor
+is passed back to the runtime, where it is stored alongside the
+method's debug info.
+
+We rely on the fact that Tier0 methods are not optimized and do not
+keep any IL state in registers at stack empty points, and there is a
+one to one mapping between IL state and stack slots. Thus a single
+patchpoint descriptor suffices for all the patchpoints in the method
+and no liveness analysis is required to determine what it should
+contain.
+
+A Tier0 method may contain many patchpoints. In our current
+implementation the runtime may create one OSR method per patchpoint.
+Each OSR method may comprise most or all of the original method. So in the worst case we can have a lot of OSR codegen, but it is currently thought such cases
+will be rare. We may need to implement some policy to avoid this.
+
+### Execution of Tier0 Code with Patchpoints
+
+When a Tier0 method with Patchpoints is called, it counts down the
+per-call patchpoint counter each time a patchpoint is reached.
+
+If the counter reaches zero the code invokes the
+`CORINFO_HELP_PATCHPOINT` runtime helper. The helper then uses the
+return address of the helper call as a key into a patchpoint info
+table.
+
+The first time the patchpoint is seen by the runtime it adds an entry
+to the table. The local counter in the method is reloaded with a value
+determined by `DOTNET_OSR_CounterBump` (currently 0x1000). If a
+patchpoint at a given offset is hit more than `DOTNET_OSR_HitLimit` times
+(currently 0x10) then the runtime will create an OSR method for that
+offset.
+
+Note this means that a single call can trigger OSR creation after
+(0x1000 x 0x11) ~ 69,000 executions at that offset. This number was
+chosen to try and balance the perf loss from continued execution of
+the Tier0 code versus the one time cost to create the optimized OSR
+version and the expected perf win from subsequent execution in the OSR
+code. It may need some adjusting.
+
+The OSR method is created synchronously on the thread that hits the
+hit limit threshold. If a second thread arrives while the OSR method
+is being created it will simply have its counter reloaded and continue
+executing Tier0 code for the time being. Eventually it may come back.
+
+Once the method is ready the initiating thread is transitioned to the
+OSR method; any subsequently arriving executions from other active
+frames will likewise transition as they hit the patchpoint.
+
+The OSR method does not return control to the Tier0 method (it is a
+"full continuation" of the Tier0 method at the patchpoint).
+
+### Creation of the OSR Method
+
+The OSR method is specific to a Tier0 method at a specific IL
+offset. When the runtime decides to create an OSR method it invokes
+the jit and passes a special OSR flag and the IL offset.
+
+This compilation is similar to a normal optimized compilation, with
+a few twists:
+* Importation starts at the specified IL offset and pulls in all the
+code reachable from that point. Typically (but not always) the method entry (IL offset 0) is unreachable
+and so the OSR method only imports a subset of the full method.
+* Control normally branches from the first block (`fgFirstBB`) to the block at the OSR IL offset (the "osr entry").
+Special care is needed when the osr entry is in the middle of a try or in a nested try.
+* If dynamic PGO is enabled the OSR method will read the PGO data captured by the Tier0
+method, but we also instrument the OSR method to ensure any Tier1 version we produce
+later on sees all the PGO data it would have seen if we'd forcibly kept the method at Tier0.
+
+The JIT may need to import the entry block if it can be reached by tail
+recursion to loop optimizations, even if there no explicit IL branch
+to offset 0 in the IL reachable from the OSR IL offset. This was the
+source of a number of subtle bugs -- the call site that eventually may
+loop back to the method entry could come from an inlinee, or via
+devirtualization, etc.
+
+For the most part the jit treats an OSR method just like any other
+optimized jitted method. But aside from importation, frame layout,
+PGO, and prolog/epilog codegen details bleed through in only a handful
+of places.
+
+One of these is that an OSR method will never need to zero init any locals or see undefined values for locals; all this is dealt with by the Tier0 frame. (The OSR method may still need to zero temps it has allocated).
+
+#### Frame Layout
+
+For and OSR method, the OSR frame logically "incorporates" the Tier0 method frame. Because the OSR method has different register saves and different temporaries, there is an OSR specific portion of the frame that extends beyond the Tier0 frame.
+
+On x64, Tier0 frames are always RBP frames. On Arm64, Tier0 frames can be any of the 5 frame types the jit can create.
+
+On x64 we currently have the frame pointer (if needed) refer to the base of the OSR extension. On arm64 the frame pointer refers to the base of the Tier0 frame. This divergence is historical and we should likely fix x64 to follow the same plan as arm64.
+
+Locals corresponding to Tier0 args or locals (aka `lvaIsOSRLocal`) that have stack homes in OSR methods will use the Tier0 slot for that home in the OSR method. So it is not uncommon for the OSR method to be accessing parts of the Tier0 frame throughout its execution. Those slots are reported to GC as necessary.
+
+But often much of the Tier0 frame is effectively dead after the transition and execution of the OSR method's prolog, as the Tier0 live state is enregistered by the OSR method.
+
+#### OSR Prolog
+
+The OSR prolog is conceptually similar to a normal method prolog, with a few key difference.
+
+When an OSR method is entered, all callee-save registers have the values they had when the Tier0 method was called, but the values in argument registers are unknown (and almost certainly not the args passed to the Tier0 method). The OSR method must initialize any live-in enregistered args or locals from the corresponding slots on the Tier0 frame. This happens in `genEnregisterOSRArgsAndLocals`.
+
+If the OSR method needs to report a generics context it uses the Tier0 frame slot; we ensure this is possible by forcing a Tier0 method with patchpoints to always report its generics context.
+
+An OSR method does not need to register function entry callbacks as it is never called; similarly it does not need to acquire the synchronous method monitor, as the Tier0 frame will have already done that.
+
+#### OSR Epilog
+
+The OSR epilog does the following:
+* undoes the OSR contribution to the frame (SP add)
+* restores the callee-saved registers saved by the OSR prolog
+* undoes the Tier0 frame (SP add)
+* restores any Tier0 callees saves needed (x64 only, restores RPB)
+* returns to the Tier0/OSR method's caller
+
+This epilog has a non-standard format because of the two SP adjustments.
+This is currently breaking x64 epilog unwind.
+
+On Arm64 we have epilog unwind codes and the second SP adjust does not appear to cause problems.
+
+#### Funclets in OSR Methods
+
+OSR funclets are more or less normal funclets.
+
+On Arm64, to satisfy PSPSYm reporting constraints, the funclet frame must be padded to include the Tier0 frame size. This is conceptually similar to the way the funclet frames also pad for homed varargs arguments -- in both cases the padded space is never used, it is just there to ensure the PSPSym ends up at the same caller-SP relative offset for the main function and any funclet.
+
+#### OSR Unwind Info
+
+On x64 the prolog unwind includes a phantom SP adjustment at offset 0 for the Tier0 frame.
+
+As noted above the two SP adjusts in the x64 epilog are currently causing problems if we try and unwind in the epilog. Unwinding in the prolog and method body seems to work correctly; the unwind codes properly describe what needs to be done.
+
+On arm64 there are unwind codes for epilogs and this problem does not seem to arise.
+
+When an OSR method is active, stack frames will show just that method and not the Tier0 method.
+
+#### OSR GC Info
+
+OSR GC info is standard. The only unusual aspect is that some special offsets (generics context, etc) may refer to slots in the Tier0 frame.
+
+### Execution of an OSR Method
+
+OSR methods are never called directly; they can only be invoked by `CORINFO_HELP_PATCHPOINT` when called from a Tier0 method with patchpoints.
+
+On x64, to preserve proper stack alignment, the runtime helper will "push" a phantom return address on the stack (x64 methods assume SP is aligned 8 mod 16 on entry). This is not necessary on arm64 as calls do not push to the stack.
+
+When the OSR method returns, it cleans up both its own stack and the
+Tier0 method stack.
+
+Note if a Tier0 method is recursive and has loops there can be some interesting dynamics. After a sufficient amount of looping an OSR method will be created, and the currently active Tier0 instance will transition to the OSR method. When the OSR method makes a recursive call, it will invoke the Tier0 method, which will then fairly quickly transition to the OSR version just created.
+
+## Debugging OSR
+
+### Seeing which OSR methods are created
+
+* `DOTNET_DumpJittedMethods=1` will specially mark OSR methods with the inspiring IL offsets.
+
+For example, running a libraries test with some stressful OSR settings, there ended up being 699 OSR methods jitted out of 160675 total methods. Grepping for OSR in the dump output, the last few lines were:
+
+```
+Compiling 32408 System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[WrapperForPoint_3D][System.Text.Json.Serialization.Tests.WrapperForPoint_3D]::OnTryRead, IL size = 850, hash=0x5a693818 Tier1-OSR @0x5f
+Compiling 32411 System.Text.Json.Serialization.Tests.ConverterForPoint3D::Read, IL size = 40, hash=0x294c33b5 Tier1-OSR @0xf
+Compiling 32412 System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1[WrapperForPoint_3D][System.Text.Json.Serialization.Tests.WrapperForPoint_3D]::OnTryWrite, IL size = 757, hash=0x1ed8b727 Tier1-OSR @0x60
+Compiling 32629 System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1[KeyValuePair`2][System.Collections.Generic.KeyValuePair`2[System.__Canon,System.__Canon]]::ReadConstructorArgumentsWithContinuation, IL size = 192, hash=0x7ab2e686 Tier1-OSR @0x0
+Compiling 32655 System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1[Point_3D_Struct][System.Text.Json.Serialization.Tests.Point_3D_Struct]::ReadConstructorArgumentsWithContinuation, IL size = 192, hash=0xb37dcd36 Tier1-OSR @0x0
+```
+Here the annotations like `@0x5f` tell you the IL offset for the particular OSR method.
+
+As an aside, seeing patchpoints at offset `@0x0` is a pretty clear indication that the example was run with random patchpoints enabled, as IL offset 0 is rarely the start of a loop.
+
+Also note that an OSR method will always be invoked immediately after it is jitted. So each of the OSR methods above was executed at least once.
+
+### Controlling which methods are OSR Eligible
+
+* `DOTNET_TC_QuickJitForLoops=0` -- no methods are OSR eligible, all get switched to optimized
+* `DOTNET_TC_OnStackReplacement=0` -- no methods are OSR eligible, all get jitted at Tier0
+* `DOTNET_JitEnableOsrRange=...` -- use method hash to refine which methods are OSR eligible
+* `DOTNET_JitEnablePatchpointRange=...` -- use method hash to refine which Tier0 methods get patchpoints
+
+Binary searching using the `Enable` controls has proven to be a reliable
+way to track down issues in OSR codegen.
+
+On the same example as above, now run with `COMPlus_JitEnableOsrRange=00000000-7FFFFFFF` there were 249 OSR methods created. Methods with hashes outside this range that would have been handled by OSR were instead immediately optimized and bypassed tiering. So you can systematically reduce the set of OSR methods created to try and find the method or methods that are causing a test failure.
+
+If you are not familiar with range syntax, ranges values are in hex, and entries can be intervals (as above), singletons, or unions of intervals and singletons, eg
+```
+COMPlus_JitEnableOsrRange=00000000-3FFFFFFF,067a3f68,F0000000-FFFFFFFF
+```
+I find I rarely need to use anything other than a single range.
+
+### Changing rate at which OSR methods get created
+
+These config values can alter the runtime policy and cause OSR methods to be created more eagerly or less eagerly:
+
+* `DOTNET_OSR_HitCount=N` -- alter the number of times the runtime sees helper call at a given offset until
+it creates an OSR method. A value of 0 or 1 eagerly creates OSR methods.
+* `DOTNET_OSR_CounterBump=N` -- alter the local counter reload value done by the runtime. A low value means
+Tier0 methods with patchpoints will call back into the runtime more often.
+* `DOTNET_TC_OnStackReplacement_InitialCounter=N` -- alter the initial counter value the jit bakes into the Tier0 method.
+A low value means the initial call into the runtime will happen more quickly.
+
+Note setting all 3 of these to 0 or 1 will cause OSR methods to be
+created the first time a patchpoint is hit.
+
+If a method has multiple (say two) patchpoints, it may require some
+fiddling with these settings to ensure that both OSR versions get
+created in a given run.
+
+### Tracing Runtime Policy
+
+Setting
+
+* `DOTNET_LogEnable=1`
+* `DOTNET_LogFacility=0x00400000`
+* `DOTNET_LogLevel=5`
+* and say `DOTNET_LogToConsole=1`
+
+will log runtime behavior from calls to `CORINFO_HELP_PATCHPOINT` from Tier0 methods.
+
+For example:
+```
+TID 4bdc2: Jit_Patchpoint: patchpoint [17] (0x0000FFFF1E5F3BB8) hit 1 in Method=0x0000FFFF1EAD9130M (Xunit.JsonDeserializer::DeserializeInternal) [il offset 45] (limit 2)
+TID 4bdc2: Jit_Patchpoint: patchpoint [17] (0x0000FFFF1E5F3BB8) TRIGGER at count 2
+TID 4bdc2: JitPatchpointWorker: creating OSR version of Method=0x0000FFFF1EAD9130M (Xunit.JsonDeserializer::DeserializeInternal) at offset 45
+TID 4bdc2: Jit_Patchpoint: patchpoint [17] (0x0000FFFF1E5F3BB8) TRANSITION to ip 0x0000FFFF1E5F6820
+TID 4bdc2: Jit_Patchpoint: patchpoint [18] (0x0000FFFF1E5F6BE0) hit 1 in Method=0x0000FFFF1EB03B58M (Xunit.JsonBoolean::.ctor) [il offset 0] (limit 2)
+TID 4bdc2: Jit_Patchpoint: patchpoint [18] (0x0000FFFF1E5F6BE0) TRIGGER at count 2
+TID 4bdc2: JitPatchpointWorker: creating OSR version of Method=0x0000FFFF1EB03B58M (Xunit.JsonBoolean::.ctor) at offset 0
+TID 4bdc2: Jit_Patchpoint: patchpoint [18] (0x0000FFFF1E5F6BE0) TRANSITION to ip 0x0000FFFF1E5F6D00
+```
+Here the number in brackets `[17]` is the number of distinct patchpoints that have called the runtime helper; from the runtime side this serve as a sort of patchpoint ID.
+
+A `hit` is just a call from an Tier0 method to the helper. A `TRIGGER` is a hit that now has reached the `DOTNET_OSR_HitCount` limit, and at this point an OSR method is created. A `TRANSITION` is the transition of control from the Tier0 method to the OSR method.
+
+You can use the following config settings to further alter runtime policy:
+* `DOTNET_OSR_LowId`
+* `DOTNET_OSR_HighId`
+These collectively form an inclusive range describing which patchpoint IDs will
+be allowed to `TRIGGER` (and therefore `TRANSITION`).
+
+So you can also use this to control which OSR methods are created by the runtime, without altering JIT behavior.
+
+### Changing where patchpoints are placed in Tier0 code
+
+* `DOTNET_JitOffsetOnStackReplacement=offset` -- only place patchpoints at given IL offset (and if stack empty)
+* `DOTNET_JitRandomOnStackReplacement=val` -- in addition to normal OSR patchpoints, place patchpoints randomly
+ at stack empty points at the starts of non-handler blocks (value is likelihood, in hex, so 0 will not add any extra, 0x64 will
+add as many extra as possible)
+
+The latter is used by OSR stress (in conjunction with low values for
+the policy config) to create large numbers of OSR methods.
+
+### Controlling what gets dumped
+
+Enabling jit dumps via name or hash can lead to multiple jit
+compilations being dumped: one for Tier0, one for each OSR method, and
+one for Tier1). You can control this via:
+
+* `DOTNET_JitDumpTier0=0` -- suppress dumping all Tier0 jit requests
+* `DOTNET_JitDumpAtOSROffset=N` -- only dump OSR jit requests at indicated IL offset
+
+### Observing OSR from ETW
+
+OSR methods are marked specially in the ETW MethodJitting events. This
+value is not yet parsed in tracevent/perfview/SOS.
+
+In SOS, OSR version of methods are currently marked as "unknown tier".
+
+### OSR when Debugging
+
+When single-stepping at source level through Tier0 code with
+patchpoints, the transition to OSR will happen behind the scenes.
+
+Because OSR code is optimized and Tier0 code is not, you may see a
+sudden degradation in what the debugger displays if you step at the
+exact point the OSR transition happens. Breakpoints applied at Tier0
+will be reapplied to the OSR method, though they may not "take" if the
+source to IL to native mapping information is missing.
+
+If you step at assembly level you can see the invocation of the
+patchpoint helper, etc.
+
+OSR methods show up normally in the stack, unless execution is paused
+in the OSR epilog (working on this). You will only see one entry for
+a Tier0 method that's transitioned to an OSR method.
+
+## OSR and Performance
+
+As noted above, the combination of `QJFL=1` and `OSR=1` will typically provide better startup and comparable of better steady-state. But it's also possible
+to spend considerable time in OSR methods (eg the all-in-`Main` benchmark).
+
+Generally speaking the performance of an OSR method should be comparable to the equivalent Tier1 method. In practice we see variations of +/- 20% or so. There are a number or reasons for this:
+* OSR methods are often a subset of the full Tier1 method, and in many cases just comprise one loop. The JIT can often generate much better code for a single loop in isolation than a single loop in a more complex method.
+* A few optimizations are disabled in OSR methods, notably struct promotion.
+* OSR methods may only see fractional PGO data (as parts of the Tier0 method may not have executed yet). The JIT doesn't cope very well yet with this sort of partial PGO coverage.
+
+### Impact on BenchmarkDotNet Results
+
+BenchmarkDotNet (BDN) typically does a pretty good job of ensuring that measurements are made on the most optimized version of a method. Usually this is the Tier1 version. As such, we don't expect to see OSR have much impact on BDN derived results.
+
+However, one can configure BenchmarkDotNet in ways that make it more likely that it will measure OSR methods, or some combination of OSR and Tier1 -- in particular reducing the number of warmup iterations. By default a method must be called 30 times to be rejitted at Tier1. So if BDN benchmark is run with less than 30 iterations, there's a chance it may not be measuring Tier1 code for all methods. And when OSR is enabled, this will often mean measuring OSR method perf.
+
+This happens more often with benchmarks that either (a) do a lot of internal looping to boost the elapsed time of a measurement interval, rather than relying on BDN to determine the appropriate iteration strategy, or (b) are very long running, so that BDN determines that it does not need to run many iterations to obtain measurements of "significant" duration (250 ms or so).
+
+In the performance repo configurations we reduce the number of warmup iterations and have some benchmarks that fall into both categories above. We'll likely need to make some adjustment to these benchmarks to ensure that we're measuring Tier1 code performance.
+
+## References
+
+* [OSR Design Document](https://github.com/dotnet/runtime/blob/main/docs/design/features/OnStackReplacement.md). May be a bit dated in places.
+* [OSR Next Steps Issue](https://github.com/dotnet/runtime/issues/33658). Has a lot of information on issues encountered during bring-up, current limitations, and ideas for things we might revisit.
\ No newline at end of file
diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md
index 3206fc7349c200..155ed05186e7b0 100644
--- a/docs/workflow/building/coreclr/nativeaot.md
+++ b/docs/workflow/building/coreclr/nativeaot.md
@@ -59,7 +59,7 @@ The workflow looks like this:
## Running tests
-If you haven't built the tests yet, run `src\tests\build[.cmd|.sh] nativeaot [Debug|Release] tree nativeaot`. This will build the smoke tests only - they usually suffice to ensure the runtime and compiler is in a workable shape. To build all Pri-0 tests, drop the `tree nativeaot` parameter. The `Debug`/`Release` parameter should match the build configuration you used to build the runtime.
+If you haven't built the tests yet, run `src\tests\build.cmd nativeaot [Debug|Release] tree nativeaot` on Windows, or `src/tests/build.sh -nativeaot [Debug|Release] -tree:nativeaot` on Linux. This will build the smoke tests only - they usually suffice to ensure the runtime and compiler is in a workable shape. To build all Pri-0 tests, drop the `tree nativeaot` parameter. The `Debug`/`Release` parameter should match the build configuration you used to build the runtime.
To run all the tests that got built, run `src\tests\run.cmd runnativeaottests [Debug|Release]` on Windows, or `src/tests/run.sh --runnativeaottests [Debug|Release]` on Linux. The `Debug`/`Release` flag should match the flag that was passed to `build.cmd` in the previous step.
diff --git a/docs/workflow/building/mono/README.md b/docs/workflow/building/mono/README.md
index 56c95551f5eba8..602e65d1c90112 100644
--- a/docs/workflow/building/mono/README.md
+++ b/docs/workflow/building/mono/README.md
@@ -33,6 +33,16 @@ build.cmd mono
```
When the build completes, product binaries will be dropped in the `artifacts\bin\mono\..` folder.
+If you need to run library tests or run HelloWorld sample with your change to mono, you want to build mono with this command instead:
+
+```bash
+./build.sh mono+libs.pretest
+```
+or on Windows,
+```cmd
+build.cmd mono+libs.pretest
+```
+
If you want to skip restoring nuget packages, when only making change to mono, you want to use this command:
```bash
./build.sh mono --build
diff --git a/eng/BeforeTargetFrameworkInference.targets b/eng/BeforeTargetFrameworkInference.targets
index b82462e1acc1da..60b412845483fe 100644
--- a/eng/BeforeTargetFrameworkInference.targets
+++ b/eng/BeforeTargetFrameworkInference.targets
@@ -1,20 +1,5 @@
-
- <_OriginalTargetFramework>$(TargetFramework)
- $(TargetFramework.SubString($([MSBuild]::Add($(TargetFramework.IndexOf('-')), 1))))
-
- $([System.Text.RegularExpressions.Regex]::Replace('$(TargetFramework)', '$(TargetFrameworkPattern)', '${1}'))
-
-
-
- $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)', '$(TargetFramework)-$(Configuration)'))
- $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)', '$(TargetFramework)-$(TargetFrameworkSuffix)-$(Configuration)'))
-
- $([MSBuild]::NormalizeDirectory('$(BaseOutputPath)', '$(TargetFramework)-$(Configuration)'))
- $([MSBuild]::NormalizeDirectory('$(BaseOutputPath)', '$(TargetFramework)-$(TargetFrameworkSuffix)-$(Configuration)'))
-
-
diff --git a/eng/Subsets.props b/eng/Subsets.props
index 5ea1ff48e23f4a..de8a2710eb6862 100644
--- a/eng/Subsets.props
+++ b/eng/Subsets.props
@@ -37,7 +37,7 @@
clr+libs+host+packs
-
+
<_subset Condition="'$(Subset)' != ''">+$(Subset.ToLowerInvariant())+
<_subset Condition="'$(Subset)' == ''">+$(DefaultSubsets)+
@@ -58,7 +58,7 @@
- clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs+clr.spmi
+ clr.native+linuxdac+clr.corelib+clr.tools+clr.nativecorelib+clr.packages+clr.nativeaotlibs
clr.iltools+clr.packages
@@ -101,11 +101,11 @@
-
+
-
-
-
+
+
+
@@ -117,6 +117,7 @@
+
@@ -124,7 +125,7 @@
Description="Packaging of cross OS DAC. Requires all assets needed to be present at a folder specified by $(CrossDacArtifactsDir). See 'Microsoft.CrossOsDiag.Private.CoreCLR.proj' for details." />
-
+
@@ -134,14 +135,14 @@
-
+
-
+
@@ -150,7 +151,7 @@
-
+
@@ -249,6 +250,9 @@
+
+
+
-
+
https://github.com/dotnet/icu
- 80a658fa6aa6601d67bfe5a294e0d1b7e1184a5c
+ cd095b0fb4c6f8adca9e44ef17346b3e13a73a7c
https://github.com/dotnet/msquic
a7213b4676c1803bb251771291a525482d42e511
-
+
https://github.com/dotnet/emsdk
- aaa56a6622c4991cf65d553250af3c0ade1320bc
+ 8f6606fae08ffa42b025dc42ebe2eea91db3a242
https://github.com/dotnet/wcf
@@ -50,77 +50,77 @@
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
https://github.com/microsoft/vstest
@@ -170,117 +170,117 @@
https://github.com/dotnet/runtime-assets
8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/llvm-project
- 44adf6c047663fe20c388bfb769e18dd3c91f7e0
+ 20080e62c2ea6ed059be57b88268dd8cd28604e6
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/runtime
- 09ff1acdad2e7789908b5db9bb89896144c13042
+ bc6d349ecd72eec162f0532e6b6218fdbaa07ddb
-
+
https://github.com/dotnet/linker
- e485816b48273d03bd6266a64dad9bea97f861d5
+ 3f704bb49eb2fb2847ceaecfbabe8d5f3e0c86c9
-
+
https://github.com/dotnet/xharness
- 0137095821e2e5a9e030d97248503387b8d72a18
+ 4d24e26939bf0770047cd59299235cf6caa86cdb
-
+
https://github.com/dotnet/xharness
- 0137095821e2e5a9e030d97248503387b8d72a18
+ 4d24e26939bf0770047cd59299235cf6caa86cdb
-
+
https://github.com/dotnet/xharness
- 0137095821e2e5a9e030d97248503387b8d72a18
+ 4d24e26939bf0770047cd59299235cf6caa86cdb
-
+
https://github.com/dotnet/arcade
- 86a931a4ebfa4d65630f0ff6cedf787d2e48a3b9
+ 4d6406fa2e84c8516a338694be3a4097e6e1f104
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 91d6b3c1f51888d166701510189505f35714665c
+ 47c55c3cf08885d691aa9d581d40310fe448c1ea
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 91d6b3c1f51888d166701510189505f35714665c
+ 47c55c3cf08885d691aa9d581d40310fe448c1ea
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 91d6b3c1f51888d166701510189505f35714665c
+ 47c55c3cf08885d691aa9d581d40310fe448c1ea
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 91d6b3c1f51888d166701510189505f35714665c
+ 47c55c3cf08885d691aa9d581d40310fe448c1ea
-
+
https://github.com/dotnet/hotreload-utils
- d3e96c2e8ed4d58de217c44423c9ba3b90333724
+ 3d4988f053ae6b9803e76687b02fee3f8a83156c
https://github.com/dotnet/runtime-assets
8813c6d9e73b5cb0b4ccf4c0b8c609ad344636a7
-
+
https://github.com/dotnet/roslyn-analyzers
- f471d3381584f10f9908432e0b2b2b8ef07a0aa6
+ 60eb13c44c366205e5a4dec195404477009c41de
https://github.com/dotnet/sdk
diff --git a/eng/Versions.props b/eng/Versions.props
index aae2d08e090181..aef6a22a358d5b 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -50,34 +50,35 @@
3.3.2
4.0.1
4.0.1
- 7.0.0-preview1.22068.2
+ 7.0.0-preview1.22102.1
2.0.0-alpha.1.21525.11
- 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
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 2.5.1-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22102.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
+ 7.0.0-beta.22080.1
6.0.0-preview.1.102
- 7.0.0-alpha.1.22073.5
- 7.0.0-alpha.1.22073.5
- 7.0.0-alpha.1.22073.5
+ 7.0.0-preview.2.22080.2
+ 7.0.0-preview.2.22080.2
+ 7.0.0-preview.2.22080.2
3.1.0
- 7.0.0-alpha.1.22073.5
+ 7.0.0-preview.2.22080.2
1.0.0-alpha.1.22073.1
1.0.0-alpha.1.22073.1
1.0.0-alpha.1.22073.1
@@ -120,11 +121,11 @@
5.0.0
5.0.0
4.9.0-rc2.21473.1
- 7.0.0-alpha.1.22073.5
- 7.0.0-alpha.1.22073.5
+ 7.0.0-preview.2.22080.2
+ 7.0.0-preview.2.22080.2
4.5.4
4.5.0
- 7.0.0-alpha.1.22073.5
+ 7.0.0-preview.2.22080.2
7.0.0-beta.22075.1
7.0.0-beta.22075.1
@@ -139,10 +140,10 @@
7.0.0-beta.22075.1
7.0.0-beta.22075.1
- 1.0.0-prerelease.21577.2
- 1.0.0-prerelease.21577.2
- 1.0.0-prerelease.21577.2
- 1.0.0-prerelease.21577.2
+ 1.0.0-prerelease.22078.3
+ 1.0.0-prerelease.22078.3
+ 1.0.0-prerelease.22078.3
+ 1.0.0-prerelease.22078.3
16.9.0-beta1.21055.5
2.0.0-beta1.20253.1
@@ -160,10 +161,10 @@
1.0.1-prerelease-00006
16.9.0-preview-20201201-01
- 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
+ 1.0.0-prerelease.22101.2
+ 1.0.0-prerelease.22101.2
+ 1.0.0-prerelease.22101.2
+ 1.0.2-alpha.0.22081.2
2.4.2-pre.22
0.12.0-pre.20
2.4.2
@@ -177,23 +178,23 @@
6.0.0-preview-20220104.1
- 7.0.100-1.22063.2
+ 7.0.100-1.22081.3
$(MicrosoftNETILLinkTasksVersion)
- 7.0.0-preview.2.22074.5
+ 7.0.0-preview.2.22101.1
7.0.0-alpha.1.21529.3
- 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
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
+ 11.1.0-alpha.1.22081.2
- 7.0.0-alpha.2.22071.3
+ 7.0.0-alpha.2.22102.3
$(MicrosoftNETWorkloadEmscriptenManifest70100Version)
1.1.87-gba258badda
diff --git a/eng/build.ps1 b/eng/build.ps1
index 83b9e5104d9000..b424add6fdd97e 100644
--- a/eng/build.ps1
+++ b/eng/build.ps1
@@ -216,10 +216,7 @@ if ($vs) {
# Respect the RuntimeConfiguration variable for building inside VS with different runtime configurations
$env:RUNTIMECONFIGURATION=$runtimeConfiguration
}
-
- # Restore the solution to workaround https://github.com/dotnet/runtime/issues/32205
- Invoke-Expression "& dotnet restore $vs"
-
+
# Launch Visual Studio with the locally defined environment variables
."$vs"
diff --git a/eng/common/internal/NuGet.config b/eng/common/internal/NuGet.config
index 769650362f4aa4..19d3d311b166f5 100644
--- a/eng/common/internal/NuGet.config
+++ b/eng/common/internal/NuGet.config
@@ -2,6 +2,6 @@
-
+
diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml
index 7678b94ce740c0..c5c2a9915121b3 100644
--- a/eng/common/templates/job/job.yml
+++ b/eng/common/templates/job/job.yml
@@ -24,6 +24,7 @@ parameters:
enablePublishBuildAssets: false
enablePublishTestResults: false
enablePublishUsingPipelines: false
+ disableComponentGovernance: false
mergeTestResults: false
testRunTitle: ''
testResultsFormat: ''
@@ -137,6 +138,9 @@ jobs:
richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin
continueOnError: true
+ - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.disableComponentGovernance, 'true')) }}:
+ - task: ComponentGovernanceComponentDetection@0
+
- ${{ if eq(parameters.enableMicrobuild, 'true') }}:
- ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- task: MicroBuildCleanup@1
diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml
index fe9dfdf720cf8a..d91bf9147116f0 100644
--- a/eng/common/templates/job/publish-build-assets.yml
+++ b/eng/common/templates/job/publish-build-assets.yml
@@ -38,10 +38,6 @@ jobs:
value: ${{ parameters.configuration }}
- group: Publish-Build-Assets
- group: AzureDevOps-Artifact-Feeds-Pats
- # Skip component governance and codesign validation for SDL. These jobs
- # create no content.
- - name: skipComponentGovernanceDetection
- value: true
- name: runCodesignValidationInjection
value: false
diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml
index 554e71cfc436dd..70d44735ace4a9 100644
--- a/eng/common/templates/jobs/jobs.yml
+++ b/eng/common/templates/jobs/jobs.yml
@@ -8,6 +8,10 @@ parameters:
# Optional: Enable publishing using release pipelines
enablePublishUsingPipelines: false
+ # Optional: Disable component governance detection. In general, component governance
+ # should be on for all jobs. Use only in the event of issues.
+ disableComponentGovernance: false
+
# Optional: Enable running the source-build jobs to build repo from source
enableSourceBuild: false
diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml
index c830e6f277606e..1ac7f49a43ca87 100644
--- a/eng/common/templates/post-build/common-variables.yml
+++ b/eng/common/templates/post-build/common-variables.yml
@@ -22,9 +22,5 @@ variables:
- name: SymbolToolVersion
value: 1.0.1
- # Skip component governance and codesign validation for SDL. These jobs
- # create no content.
- - name: skipComponentGovernanceDetection
- value: true
- name: runCodesignValidationInjection
value: false
diff --git a/eng/fabricbot/Makefile b/eng/fabricbot/Makefile
new file mode 100644
index 00000000000000..86b05f747200a6
--- /dev/null
+++ b/eng/fabricbot/Makefile
@@ -0,0 +1,4 @@
+generate:
+ node scripts/updateAreaPodConfigs.js
+
+.DEFAULT_GOAL := generate
\ No newline at end of file
diff --git a/eng/fabricbot/README.md b/eng/fabricbot/README.md
new file mode 100644
index 00000000000000..90f33835768c7f
--- /dev/null
+++ b/eng/fabricbot/README.md
@@ -0,0 +1,17 @@
+# FabricBot scripts
+
+Contains scripts used for generating FabricBot automation across all our triage boards. Scripts require nodejs to run:
+
+```bash
+$ node scripts/updateAreaPodConfigs.js
+```
+
+or if your system has `make`
+
+```bash
+$ make
+```
+
+Running the script will generate JSON configuration files under the `generated/` subfolder. The generated files are being tracked by git to simplify auditing changes of the generator script. When making changes to the generator script, please ensure that you have run the script and have committed the new generated files.
+
+Please note that the generated files themselves have no impact on live FabricBot configuration. The changes need to be copied manually under the `.github/fabricbot.json` folder at the root of the `runtime` and `dotnet-api-docs` repos.
diff --git a/eng/fabricbot/generated/areapods-dotnet-api-docs.json b/eng/fabricbot/generated/areapods-dotnet-api-docs.json
new file mode 100644
index 00000000000000..620f3ff8dd8f91
--- /dev/null
+++ b/eng/fabricbot/generated/areapods-dotnet-api-docs.json
@@ -0,0 +1,4934 @@
+[
+ {
+ "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-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "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 / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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 / Jeff - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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 / Jeff - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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-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": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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-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": "isCloseAndComment",
+ "parameters": {}
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "activitySenderHasPermissions",
+ "parameters": {
+ "permissions": "write"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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: Buyaa / Jose / Steve - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "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",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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-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": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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-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": "isCloseAndComment",
+ "parameters": {}
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "activitySenderHasPermissions",
+ "parameters": {
+ "permissions": "write"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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: Eirik / Krzysztof / Layomi - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "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",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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-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": "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": "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": "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
+ }
+ }
+ ]
+ }
+ },
+ {
+ "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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "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: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "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: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }
+]
\ No newline at end of file
diff --git a/eng/fabricbot/generated/areapods-runtime.json b/eng/fabricbot/generated/areapods-runtime.json
new file mode 100644
index 00000000000000..ee2a44f79cf3bf
--- /dev/null
+++ b/eng/fabricbot/generated/areapods-runtime.json
@@ -0,0 +1,5534 @@
+[
+ {
+ "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-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "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 / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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 / Jeff - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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 / Jeff - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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: Eric / Jeff - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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-Meta"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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 / Jeff - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-Meta"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eric / Jeff - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eric / Jeff - 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-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": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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-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": "isCloseAndComment",
+ "parameters": {}
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "activitySenderHasPermissions",
+ "parameters": {
+ "permissions": "write"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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: Buyaa / Jose / Steve - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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: Buyaa / Jose / Steve - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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-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",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.CodeDom"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Configuration"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Emit"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Reflection.Metadata"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Resources"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.CompilerServices"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.RegularExpressions"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Channels"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Threading.Tasks"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.DirectoryServices"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Buyaa / Jose / Steve - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Buyaa / Jose / Steve - 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-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": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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-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": "isCloseAndComment",
+ "parameters": {}
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "activitySenderHasPermissions",
+ "parameters": {
+ "permissions": "write"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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: Eirik / Krzysztof / Layomi - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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: Eirik / Krzysztof / Layomi - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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-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",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Collections"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Linq"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Json"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Xml"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Eirik / Krzysztof / Layomi - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Eirik / Krzysztof / Layomi - 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-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-author-action"
+ }
+ },
+ {
+ "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
+ }
+ }
+ ]
+ }
+ },
+ {
+ "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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "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: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Buffers"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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: Michael / Tanner - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Buffers"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Numerics.Tensors"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Runtime.Intrinsics"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Michael / Tanner - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Michael / Tanner - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "isAction",
+ "parameters": {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters": {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "labelAdded",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters": {}
+ },
+ {
+ "operator": "or",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Add new issue to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "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: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issue_comment"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Needs Further Triage",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - Issue Triage",
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - Issue Triage] Remove relabeled issues",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ },
+ {
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - Issue Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - Issue Triage] Move to Triaged Column",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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-System.Formats.Asn1"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ },
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Add new PR to Board",
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - 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: Jeremy / Levi - PRs",
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Asn1"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Formats.Cbor"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Security"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encoding"
+ }
+ }
+ ]
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": {
+ "label": "area-System.Text.Encodings.Web"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": "[Area Pod: Jeremy / Levi - PRs] Remove relabeled PRs",
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": "Area Pod: Jeremy / Levi - PRs",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }
+]
\ No newline at end of file
diff --git a/eng/fabricbot/scripts/updateAreaPodConfigs.js b/eng/fabricbot/scripts/updateAreaPodConfigs.js
new file mode 100644
index 00000000000000..682fee443930ab
--- /dev/null
+++ b/eng/fabricbot/scripts/updateAreaPodConfigs.js
@@ -0,0 +1,598 @@
+// Generates FabricBot config for all area pod triage/PR boards
+//
+// Running the script using node will update the `../generated*Configs.json` files with the new configuration.
+// The generated JSON can then be pasted in the `.github/fabricbot.json` file in dotnet/runtime,
+// see https://github.com/dotnet/runtime/blob/main/docs/infra/automation.md for more details.
+
+const path = require('path');
+const fs = require('fs');
+
+let generatedRuntimeConfigsFile = path.join(__dirname, '..', 'generated', 'areapods-runtime.json');
+let generatedApiDocsConfigsFile = path.join(__dirname, '..', 'generated', 'areapods-dotnet-api-docs.json');
+
+let areaPods = [
+ {
+ "pod": "Eric / Jeff",
+ "enabled": true,
+ "areas": [
+ "area-Meta"
+ ]
+ },
+ {
+ "pod": "Buyaa / Jose / Steve",
+ "enabled": true,
+ "areas": [
+ "area-System.CodeDom",
+ "area-System.Configuration",
+ "area-System.Reflection",
+ "area-System.Reflection.Emit",
+ "area-System.Reflection.Metadata",
+ "area-System.Resources",
+ "area-System.Runtime.CompilerServices",
+ "area-System.Text.RegularExpressions",
+ "area-System.Threading.Channels",
+ "area-System.Threading.Tasks",
+ "area-System.DirectoryServices"
+ ]
+ },
+ {
+ "pod": "Eirik / Krzysztof / Layomi",
+ "enabled": true,
+ "areas": [
+ "area-System.Collections",
+ "area-System.Linq",
+ "area-System.Text.Json",
+ "area-System.Xml"
+ ]
+ },
+ {
+ "pod": "Eric / Maryam / Tarek",
+ "enabled": true,
+ "areas": [
+ "area-DependencyModel",
+ "area-Extensions-Caching",
+ "area-Extensions-Configuration",
+ "area-Extensions-DependencyInjection",
+ "area-Extensions-Hosting",
+ "area-Extensions-Logging",
+ "area-Extensions-Options",
+ "area-Extensions-Primitives",
+ "area-System.ComponentModel",
+ "area-System.ComponentModel.Composition",
+ "area-System.Composition",
+ "area-System.Diagnostics.Activity",
+ "area-System.Globalization"
+ ]
+ },
+ {
+ "pod": "Carlos / Santi",
+ "enabled": true,
+ "areas": [
+ "area-Infrastructure-libraries",
+ "area-Microsoft.Win32",
+ "area-System.Diagnostics.EventLog",
+ "area-System.Diagnostics.PerformanceCounter",
+ "area-System.Diagnostics.TraceSource",
+ "area-System.Drawing",
+ "area-System.Management",
+ "area-System.ServiceProcess"
+ ]
+ },
+ {
+ "pod": "Adam / David",
+ "enabled": true,
+ "areas": [
+ "area-Extensions-FileSystem",
+ "area-System.Console",
+ "area-System.Diagnostics.Process",
+ "area-System.IO",
+ "area-System.IO.Compression",
+ "area-System.Linq.Parallel",
+ "area-System.Memory"
+ ]
+ },
+ {
+ "pod": "Michael / Tanner",
+ "enabled": true,
+ "areas": [
+ "area-System.Buffers",
+ "area-System.Numerics",
+ "area-System.Numerics.Tensors",
+ "area-System.Runtime",
+ "area-System.Runtime.Intrinsics"
+ ]
+ },
+ {
+ "pod": "Jeremy / Levi",
+ "enabled": true,
+ "areas": [
+ "area-System.Formats.Asn1",
+ "area-System.Formats.Cbor",
+ "area-System.Security",
+ "area-System.Text.Encoding",
+ "area-System.Text.Encodings.Web"
+ ]
+ }
+];
+
+let areaPodConfig = {
+ issueTriageRemove: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": areas.map(area => ({
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": { "label": area }
+ }
+ ]
+ }))
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames": [
+ "issues",
+ "project_card"
+ ],
+ "taskName": `[Area Pod: ${pod} - Issue Triage] Remove relabeled issues`,
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }),
+ issueTriageNeedsTriage: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config":
+ {
+ "conditions":
+ {
+ "operator": "and",
+ "operands":
+ [
+ {
+ "operator": "or",
+ "operands":
+ [
+ {
+ "operator": "and",
+ "operands":
+ [
+ {
+ "operator": "or",
+ "operands": areas.map(area => ({
+ "name": "hasLabel",
+ "parameters": { "label": area }
+ }))
+ },
+ {
+ "operator": "or",
+ "operands":
+ [
+ {
+ "name": "isAction",
+ "parameters":
+ {
+ "action": "reopened"
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInMilestone",
+ "parameters":
+ {}
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "operator": "or",
+ "operands": areas.map(area => ({
+ "name": "labelAdded",
+ "parameters": { "label": area }
+ }))
+ }
+ ]
+ },
+ {
+ "name": "isOpen",
+ "parameters":
+ {}
+ },
+ {
+ "operator": "or",
+ "operands":
+ [
+ {
+ "operator": "not",
+ "operands":
+ [
+ {
+ "name": "isInProject",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "isOrgProject": true,
+ "columnName": "Triaged"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames":
+ [
+ "issues",
+ "project_card"
+ ],
+ "taskName": `[Area Pod: ${pod} - Issue Triage] Add new issue to Board`,
+ "actions":
+ [
+ {
+ "name": "addToProject",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }),
+ issueTriageNeedsFurtherTriage: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssueCommentResponder",
+ "version": "1.0",
+ "config":
+ {
+ "conditions":
+ {
+ "operator": "and",
+ "operands":
+ [
+ {
+ "operator": "or",
+ "operands": areas.map(area => ({
+ "name": "hasLabel",
+ "parameters": { "label": area }
+ }))
+ },
+ {
+ "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: ${pod} - Issue Triage`,
+ "isOrgProject": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "isInProjectColumn",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "issue",
+ "eventNames":
+ [
+ "issue_comment"
+ ],
+ "taskName": `[Area Pod: ${pod} - Issue Triage] Needs Further Triage`,
+ "actions":
+ [
+ {
+ "name": "addToProject",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "columnName": "Needs Triage",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }),
+ issueTriageTriaged: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "IssuesOnlyResponder",
+ "version": "1.0",
+ "config":
+ {
+ "conditions":
+ {
+ "operator": "and",
+ "operands":
+ [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - 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: ${pod} - Issue Triage] Move to Triaged Column`,
+ "actions":
+ [
+ {
+ "name": "addToProject",
+ "parameters":
+ {
+ "projectName": `Area Pod: ${pod} - Issue Triage`,
+ "columnName": "Triaged",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }),
+
+ /* Pull Requests */
+
+ pullRequestAdd: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "operator": "or",
+ "operands": areas.map(area => ({
+ "name": "hasLabel",
+ "parameters": { "label": area }
+ }))
+ },
+ {
+ "operator": "not",
+ "operands": [
+ {
+ "name": "isInProject",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - PRs`,
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": `[Area Pod: ${pod} - PRs] Add new PR to Board`,
+ "actions": [
+ {
+ "name": "addToProject",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - PRs`,
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ }),
+ prRemove: ({pod, areas}) => ({
+ "taskType": "trigger",
+ "capabilityId": "IssueResponder",
+ "subCapability": "PullRequestResponder",
+ "version": "1.0",
+ "config": {
+ "conditions": {
+ "operator": "and",
+ "operands": [
+ {
+ "name": "isInProjectColumn",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - PRs`,
+ "columnName": "Needs Champion",
+ "isOrgProject": true
+ }
+ },
+ {
+ "operator": "and",
+ "operands": areas.map(area => ({
+ "operator": "not",
+ "operands": [
+ {
+ "name": "hasLabel",
+ "parameters": { "label": area }
+ }
+ ]
+ }))
+ }
+ ]
+ },
+ "eventType": "pull_request",
+ "eventNames": [
+ "pull_request",
+ "issues",
+ "project_card"
+ ],
+ "taskName": `[Area Pod: ${pod} - PRs] Remove relabeled PRs`,
+ "actions": [
+ {
+ "name": "removeFromProject",
+ "parameters": {
+ "projectName": `Area Pod: ${pod} - PRs`,
+ "isOrgProject": true
+ }
+ }
+ ]
+ }
+ })
+};
+
+// Generate runtime automation
+let generatedRuntimeTasks = areaPods
+ .filter(areaPod => areaPod.enabled)
+ .flatMap(areaPod =>
+ [
+ areaPodConfig.issueTriageNeedsTriage(areaPod),
+ areaPodConfig.issueTriageNeedsFurtherTriage(areaPod),
+ areaPodConfig.issueTriageRemove(areaPod),
+ areaPodConfig.issueTriageTriaged(areaPod),
+ areaPodConfig.pullRequestAdd(areaPod),
+ areaPodConfig.prRemove(areaPod),
+ ]);
+
+let generatedRuntimeJson = JSON.stringify(generatedRuntimeTasks, null, 2);
+fs.writeFileSync(generatedRuntimeConfigsFile, generatedRuntimeJson);
+console.log(`Written generated tasks to ${generatedRuntimeConfigsFile}`);
+
+// Generate dotnet-api-docs automation
+let generatedApiDocsTasks = areaPods
+ .filter(areaPod => areaPod.enabled)
+ .flatMap(areaPod =>
+ [
+ areaPodConfig.issueTriageNeedsTriage(areaPod),
+ areaPodConfig.issueTriageNeedsFurtherTriage(areaPod),
+ areaPodConfig.issueTriageRemove(areaPod),
+ // areaPodConfig.issueTriageTriaged(areaPod),
+ areaPodConfig.pullRequestAdd(areaPod),
+ areaPodConfig.prRemove(areaPod),
+ ]);
+
+let generatedApiDocsJson = JSON.stringify(generatedApiDocsTasks, null, 2);
+fs.writeFileSync(generatedApiDocsConfigsFile, generatedApiDocsJson);
+console.log(`Written generated tasks to ${generatedApiDocsConfigsFile}`);
diff --git a/eng/illink.targets b/eng/illink.targets
index 018075d8b660b5..d88f0862621419 100644
--- a/eng/illink.targets
+++ b/eng/illink.targets
@@ -200,8 +200,7 @@
+ Condition="'$(ILLinkTrimAssembly)' == ''">
false
diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets
index aab934c42ae6b6..c2f64bf1abf8a5 100644
--- a/eng/liveBuilds.targets
+++ b/eng/liveBuilds.targets
@@ -190,6 +190,7 @@
$(LibrariesNativeArtifactsPath)src\*.c;
$(LibrariesNativeArtifactsPath)src\*.js;
$(LibrariesNativeArtifactsPath)src\emcc-default.rsp;
+ $(LibrariesNativeArtifactsPath)src\emcc-link.rsp;
$(LibrariesNativeArtifactsPath)src\emcc-props.json;"
NativeSubDirectory="src"
IsNative="true" />
diff --git a/eng/packaging.targets b/eng/packaging.targets
index c305c64dd94090..7a29b7d99273d1 100644
--- a/eng/packaging.targets
+++ b/eng/packaging.targets
@@ -10,7 +10,7 @@
AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(PackDependsOn)
AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(BeforePack)
$(TargetsForTfmSpecificContentInPackage);AddRuntimeSpecificFilesToPackage;IncludePrivateProjectReferencesWithPackAttributeInPackage
- false
+ false
true
$(MSBuildThisFileDirectory)useSharedDesignerContext.txt
@@ -73,7 +73,6 @@
-
@@ -96,19 +95,18 @@
-
+
+ Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(TargetPlatformIdentifier)' != ''">
$(TargetDir)$(TargetName).pdb
- <_packageTargetRuntime Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">$(PackageTargetRuntime)
- <_packageTargetRuntime Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">win
+ <_packageTargetRuntime>$(TargetPlatformIdentifier.ToLowerInvariant().Replace('windows', 'win'))
+ <_targetFrameworkWithoutSuffix>$(TargetFramework)
+ <_targetFrameworkWithoutSuffix Condition="$(TargetFramework.Contains('-'))">$(TargetFramework.SubString(0, $(TargetFramework.IndexOf('-'))))
@@ -116,10 +114,10 @@
@(BuiltProjectOutputGroupOutput);
@(DocumentationProjectOutputGroupOutput)" />
+ PackagePath="runtimes/$(_packageTargetRuntime)/$(BuildOutputTargetFolder)/$(_targetFrameworkWithoutSuffix)" />
diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml
index 7b404e2c37b745..bf6fdc7c4d1732 100644
--- a/eng/pipelines/common/evaluate-default-paths.yml
+++ b/eng/pipelines/common/evaluate-default-paths.yml
@@ -116,6 +116,9 @@ jobs:
- src/mono/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/*
- src/mono/nuget/Microsoft.NET.Runtime.MonoTargets.Sdk/*
- src/mono/mono/*
+ - eng/testing/scenarios/BuildWasmAppsJobsList.txt
+ - eng/Version.Details.xml
+ - src/mono/wasm/emscripten-version.txt
- subset: wasmdebuggertests
include:
- src/mono/wasm/debugger/*
diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml
index 4f0200380bc9f7..d815a72e3511b7 100644
--- a/eng/pipelines/common/platform-matrix.yml
+++ b/eng/pipelines/common/platform-matrix.yml
@@ -53,7 +53,7 @@ jobs:
${{ 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')))) }}:
+- ${{ if containsValue(parameters.platforms, 'Linux_armv6') }}:
- template: xplat-setup.yml
parameters:
jobTemplate: ${{ parameters.jobTemplate }}
@@ -303,7 +303,7 @@ jobs:
targetRid: browser-wasm
platform: Browser_wasm
container:
- image: ubuntu-18.04-webassembly-20210707133424-12f133e
+ image: ubuntu-18.04-webassembly-20211208134944-544b18c
registry: mcr
jobParameters:
hostedOs: Linux
diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml
index ec233f348b0ecb..278648bc277afb 100644
--- a/eng/pipelines/coreclr/perf.yml
+++ b/eng/pipelines/coreclr/perf.yml
@@ -484,7 +484,7 @@ jobs:
additionalSetupParameters: '--latestdotnet'
logicalmachine: 'perftiger'
- # build maui workload packs
+ # build maui runtime packs
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
@@ -497,6 +497,8 @@ jobs:
- Android_arm64
- MacCatalyst_x64
- iOSSimulator_x64
+ - iOS_arm64
+ - iOS_arm
jobParameters:
buildArgs: -s mono+libs+host+packs -c $(_BuildConfig)
nameSuffix: Maui_Packs_Mono
@@ -521,6 +523,8 @@ jobs:
- Build_Android_x64_release_Maui_Packs_Mono
- Build_MacCatalyst_x64_release_Maui_Packs_Mono
- Build_iOSSimulator_x64_release_Maui_Packs_Mono
+ - Build_iOS_arm_release_Maui_Packs_Mono
+ - Build_iOS_arm64_release_Maui_Packs_Mono
buildArgs: -s mono -c $(_BuildConfig)
nameSuffix: MACiOSAndroidMaui
isOfficialBuild: false
diff --git a/eng/pipelines/coreclr/superpmi-asmdiffs.yml b/eng/pipelines/coreclr/superpmi-asmdiffs.yml
index d8835b40b8133d..e30209172c42bf 100644
--- a/eng/pipelines/coreclr/superpmi-asmdiffs.yml
+++ b/eng/pipelines/coreclr/superpmi-asmdiffs.yml
@@ -9,6 +9,8 @@ pr:
include:
- main
paths:
+ # If you are changing these and start including eng/common, adjust the Maestro subscriptions
+ # so that this build can block dependency auto-updates (this build is currently ignored)
include:
- src/coreclr/jit/*
exclude:
diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml
index 9048e8ed4fe8a2..7ef9a25a2474ca 100644
--- a/eng/pipelines/coreclr/templates/build-job.yml
+++ b/eng/pipelines/coreclr/templates/build-job.yml
@@ -220,7 +220,7 @@ jobs:
# Run CoreCLR Tools unit tests
- ${{ if eq(parameters.testGroup, 'clrTools') }}:
- - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.tools $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) -ci -test
+ - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.toolstests $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) -ci -test
displayName: Run CoreCLR Tools unit tests
# Build native test components
diff --git a/eng/pipelines/coreclr/templates/build-perf-maui-apps.yml b/eng/pipelines/coreclr/templates/build-perf-maui-apps.yml
index 3940fb596a7368..5ca99a4e844114 100644
--- a/eng/pipelines/coreclr/templates/build-perf-maui-apps.yml
+++ b/eng/pipelines/coreclr/templates/build-perf-maui-apps.yml
@@ -31,7 +31,7 @@ steps:
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-!(*.symbols).nupkg
# Other artifacts to include once they are being built
- # IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg
+ # EX. IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NETCore.App.Runtime.Mono.maccatalyst-*.nupkg
- task: CopyFiles@2
displayName: Flatten packages
@@ -80,6 +80,20 @@ steps:
destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.android-x64
overwriteExistingFiles: true
cleanDestinationFolder: false
+ - task: ExtractFiles@1
+ displayName: Extract ios-arm runtime
+ inputs:
+ archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm.*.zip
+ destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm
+ overwriteExistingFiles: true
+ cleanDestinationFolder: false
+ - task: ExtractFiles@1
+ displayName: Extract ios-arm64 runtime
+ inputs:
+ archiveFilePatterns: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm64.*.zip
+ destinationFolder: $(Build.SourcesDirectory)/MauiTesting/ArtifactPacks/Microsoft.NETCore.App.Runtime.Mono.ios-arm64
+ overwriteExistingFiles: true
+ cleanDestinationFolder: false
- task: ExtractFiles@1
displayName: Extract maccatalyst-x64 runtime
inputs:
@@ -96,14 +110,16 @@ steps:
cleanDestinationFolder: false
- script: |
- curl -o ./rollback.json 'maui.blob.core.windows.net/metadata/rollbacks/main.json'
- ./dotnet.sh workload update --from-rollback-file ./rollback.json
- ./dotnet.sh workload install maui --skip-manifest-update
+ curl -o dotnet-install.sh 'https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh'
+ chmod -R a+rx .
+ ./dotnet-install.sh --channel 6.0.2xx --quality signed --install-dir .
+ ./dotnet --info
+ ./dotnet workload install maui --from-rollback-file https://aka.ms/dotnet/maui/main.json --source https://aka.ms/dotnet6/nuget/index.json --source https://api.nuget.org/v3/index.json
displayName: Install MAUI workload
workingDirectory: $(Build.SourcesDirectory)
- script: |
- ./dotnet.sh new maui -n MauiTesting
+ ./dotnet new maui -n MauiTesting
cd MauiTesting
cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.props ./Directory.Build.props
cp $(Build.SourcesDirectory)/src/tests/Common/maui/MauiScenario.targets ./Directory.Build.targets
@@ -112,21 +128,21 @@ steps:
- script: |
chmod -R a+r .
- ../dotnet.sh publish -bl:MauiAndroid.binlog -f net6.0-android -c Release
+ ../dotnet publish -bl:MauiAndroid.binlog -f net6.0-android -c Release
mv ./bin/Release/net6.0-android/com.companyname.MauiTesting-Signed.apk ./MauiAndroidDefault.apk
displayName: Build MAUI Android
workingDirectory: $(Build.SourcesDirectory)/MauiTesting
- script: |
chmod -R a+r .
- ../dotnet.sh publish -bl:MauiiOS.binlog -f net6.0-ios -c Release
+ ../dotnet build -bl:MauiiOS.binlog -f net6.0-ios -c Release
mv ./bin/Release/net6.0-ios/iossimulator-x64/MauiTesting.app ./MauiiOSDefault.app
displayName: Build MAUI iOS
workingDirectory: $(Build.SourcesDirectory)/MauiTesting
- script: |
chmod -R a+r .
- ../dotnet.sh publish -bl:MauiMacCatalyst.binlog -f net6.0-maccatalyst -c Release
+ ../dotnet publish -bl:MauiMacCatalyst.binlog -f net6.0-maccatalyst -c Release
mv ./bin/Release/net6.0-maccatalyst/maccatalyst-x64/MauiTesting.app ./MauiMacCatalystDefault.app
displayName: Build MAUI MacCatalyst
workingDirectory: $(Build.SourcesDirectory)/MauiTesting
diff --git a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
index 6e8ace4e7935c2..57d99f231c5f82 100644
--- a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
+++ b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
@@ -35,19 +35,6 @@ steps:
- script: rm -r -f $(Build.SourcesDirectory)/artifacts/bin/AndroidSampleApp
workingDirectory: $(Build.SourcesDirectory)/artifacts/bin
displayName: clean bindir
- - script: make run MONO_ARCH=arm64 DEPLOY_AND_RUN=false RUNTIME_COMPONENTS=diagnostics_tracing
- workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/Android
- displayName: Build HelloAndroid sample app
- - script: mv $(Build.SourcesDirectory)/artifacts/bin/AndroidSampleApp/arm64/Release/android-arm64/publish/apk/bin/HelloAndroid.apk $(Build.SourcesDirectory)/artifacts/bin/AndroidSampleApp/arm64/Release/android-arm64/publish/apk/bin/HelloAndroidWithDiag.apk
- - template: /eng/pipelines/common/upload-artifact-step.yml
- parameters:
- rootFolder: $(Build.SourcesDirectory)/artifacts/bin/AndroidSampleApp/arm64/Release/android-arm64/publish/apk/bin/HelloAndroidWithDiag.apk
- includeRootFolder: true
- displayName: Android Mono Artifacts With Diag
- artifactName: AndroidMonoWithDiagarm64
- archiveExtension: '.tar.gz'
- archiveType: tar
- tarCompression: gz
- ${{ if eq(parameters.osGroup, 'iOS') }}:
- script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false
diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index 0b2e6f7f80ed2a..0c3151159daecd 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -29,7 +29,7 @@ jobs:
# iOS/tvOS simulator x64/x86
- ${{ if in(parameters.platform, 'iOSSimulator_x64', 'tvOSSimulator_x64') }}:
- - OSX.1015.Amd64.Open
+ - OSX.1200.Amd64.Open
# Android arm64
- ${{ if in(parameters.platform, 'Android_arm64') }}:
@@ -106,17 +106,16 @@ jobs:
# OSX arm64
- ${{ if eq(parameters.platform, 'OSX_arm64') }}:
- ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}:
- - OSX.1100.ARM64.Open
+ - OSX.1200.ARM64.Open
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- - OSX.1100.ARM64
+ - OSX.1200.ARM64
# OSX x64
- ${{ if eq(parameters.platform, 'OSX_x64') }}:
- ${{ if eq(variables['System.TeamProject'], 'public') }}:
- - OSX.1014.Amd64.Open
+ - OSX.1200.Amd64.Open
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- - OSX.1014.Amd64
- - OSX.1015.Amd64
+ - OSX.1200.Amd64
# windows x64
- ${{ if eq(parameters.platform, 'windows_x64') }}:
diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml
index 627d42fd7add18..18912fe315115f 100644
--- a/eng/pipelines/coreclr/templates/perf-job.yml
+++ b/eng/pipelines/coreclr/templates/perf-job.yml
@@ -166,13 +166,6 @@ jobs:
artifactFileName: 'MauiAndroidApp.tar.gz'
artifactName: 'MauiAndroidApp'
displayName: 'Maui Android App'
- - template: /eng/pipelines/common/download-artifact-step.yml
- parameters:
- unpackFolder: $(Build.SourcesDirectory)/androidHelloWorldWithDiag
- cleanUnpackFolder: false
- artifactFileName: 'AndroidMonoWithDiagarm64.tar.gz'
- artifactName: 'AndroidMonoWithDiagarm64'
- displayName: 'Mono Android Diagnostic Helloworld'
# Download iOSMono tests and MauiiOS/MacCatalyst
- ${{ if eq(parameters.runtimeType, 'iOSMono') }}:
diff --git a/eng/pipelines/libraries/enterprise/linux.yml b/eng/pipelines/libraries/enterprise/linux.yml
index aa2ccee679549e..fdf003536a6116 100644
--- a/eng/pipelines/libraries/enterprise/linux.yml
+++ b/eng/pipelines/libraries/enterprise/linux.yml
@@ -10,6 +10,8 @@ pr:
- release/*.*
paths:
+ # If you are changing these and start including eng/common, adjust the Maestro subscriptions
+ # so that this build can block dependency auto-updates (this build is currently ignored)
include:
- eng/pipelines/libraries/enterprise/*
- src/libraries/Common/src/System/Net/*
diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index f82e09c9e0a124..b76b762ebc3bb0 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -91,14 +91,11 @@ jobs:
# OSX arm64
- ${{ if eq(parameters.platform, 'OSX_arm64') }}:
- - OSX.1100.ARM64.Open
+ - OSX.1200.ARM64.Open
# OSX x64
- ${{ if eq(parameters.platform, 'OSX_x64') }}:
- - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- - OSX.1014.Amd64.Open
- - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- - OSX.1015.Amd64.Open
+ - OSX.1200.Amd64.Open
# Android
- ${{ if in(parameters.platform, 'Android_x86', 'Android_x64') }}:
@@ -108,11 +105,11 @@ jobs:
# iOS Simulator/Mac Catalyst arm64
- ${{ if in(parameters.platform, 'MacCatalyst_arm64', 'iOSSimulator_arm64') }}:
- - OSX.1100.ARM64.Open
+ - OSX.1200.ARM64.Open
# iOS/tvOS simulator x64/x86 & MacCatalyst x64
- ${{ if in(parameters.platform, 'iOSSimulator_x64', 'iOSSimulator_x86', 'tvOSSimulator_x64', 'MacCatalyst_x64') }}:
- - OSX.1015.Amd64.Open
+ - OSX.1200.Amd64.Open
# iOS devices
- ${{ if in(parameters.platform, 'iOS_arm64') }}:
@@ -129,26 +126,26 @@ jobs:
# 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
+ - Windows.Amd64.Server2022.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 or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- Windows.10.Amd64.ServerRS5.Open
- ${{ 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
+ - Windows.Amd64.Server2022.Open
+ - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c
- ${{ 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
- ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}:
- - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c
+ - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c
- ${{ 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
# .NETFramework
- ${{ if eq(parameters.jobParameters.framework, 'net48') }}:
- - Windows.10.Amd64.Client19H1.Open
+ - Windows.10.Amd64.Client21H1.Open
# windows x86
- ${{ if eq(parameters.platform, 'windows_x86') }}:
@@ -162,14 +159,14 @@ jobs:
- ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}:
- ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}:
- Windows.10.Amd64.ServerRS5.Open
- - Windows.10.Amd64.Server19H1.Open
+ - Windows.10.Amd64.Server20H2.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') }}:
- - Windows.10.Amd64.Client19H1.Open
+ - Windows.10.Amd64.Client21H1.Open
# windows arm
- ${{ if eq(parameters.platform, 'windows_arm') }}:
@@ -185,6 +182,6 @@ jobs:
# WebAssembly windows
- ${{ if eq(parameters.platform, 'Browser_wasm_win') }}:
- - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-webassembly-amd64-20210702131541-6837048
+ - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-webassembly-amd64-20211208140215-544b18c
${{ insert }}: ${{ parameters.jobParameters }}
diff --git a/eng/pipelines/mono/templates/workloads-build.yml b/eng/pipelines/mono/templates/workloads-build.yml
index a6b6e759306880..0b6e057e8222d9 100644
--- a/eng/pipelines/mono/templates/workloads-build.yml
+++ b/eng/pipelines/mono/templates/workloads-build.yml
@@ -65,6 +65,7 @@ jobs:
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoTargets.Sdk*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.MonoAOTCompiler.Task*.nupkg
IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Sdk*.nupkg
+ IntermediateArtifacts/MonoRuntimePacks/Shipping/Microsoft.NET.Runtime.WebAssembly.Templates*.nupkg
- task: CopyFiles@2
displayName: Flatten packages
diff --git a/eng/pipelines/runtime-extra-platforms.yml b/eng/pipelines/runtime-extra-platforms.yml
index a0642f4ab521c7..729a0187ba562b 100644
--- a/eng/pipelines/runtime-extra-platforms.yml
+++ b/eng/pipelines/runtime-extra-platforms.yml
@@ -118,89 +118,6 @@ jobs:
#### MONO LEGS
-#
-# Build the whole product using Mono and run libraries tests, for Wasm.Build.Tests
-#
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: Release
- runtimeFlavor: mono
- platforms:
- # 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:
- # map dependencies variables to local variables
- - name: wasmbuildtestsContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'] ]
- jobParameters:
- isExtraPlatforms: ${{ variables.isExtraPlatformsBuild }}
- testGroup: innerloop
- nameSuffix: WasmBuildTests
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmBuildTests=true /p:TestAssemblies=false /p:BrowserHost=$(_hostedOs)
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmbuildtests.containsChange'], true),
- eq(variables['isRollingBuild'], 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: >-
- or(
- eq(variables['wasmbuildtestsContainsChange'], true),
- eq(variables['isRollingBuild'], true))
-
-#
-# Build Browser_wasm, on windows, run console and browser tests
-#
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: release
- runtimeFlavor: mono
- platforms:
- - Browser_wasm_win
- variables:
- # map dependencies variables to local variables
- - name: librariesContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
- - name: monoContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
- jobParameters:
- testGroup: innerloop
- nameSuffix: LibraryTests
- buildArgs: -subset mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:BrowserHost=windows
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true),
- eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
- eq(variables['isRollingBuild'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Windows_wasm_$(_BuildConfig)
- extraHelixArguments: /p:BrowserHost=windows
- scenarios:
- - normal
- - wasmtestonbrowser
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isRollingBuild'], true))
-
#
# Build for Browser/wasm, with EnableAggressiveTrimming=true
#
@@ -238,11 +155,6 @@ jobs:
extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg)
scenarios:
- normal
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isRollingBuild'], true))
#
# Build for Browser/wasm with RunAOTCompilation=true
@@ -282,11 +194,6 @@ jobs:
extraHelixArguments: /p:NeedsToBuildWasmAppsOnHelix=true $(_runSmokeTestsOnlyArg) /p:BrowserHost=$(_hostedOs)
scenarios:
- normal
- condition: >-
- or(
- eq(variables['librariesContainsChange'], true),
- eq(variables['monoContainsChange'], true),
- eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run libraries tests
@@ -415,32 +322,34 @@ jobs:
runtimeFlavor: mono
platforms:
- Browser_wasm
+ - Browser_wasm_win
variables:
# map dependencies variables to local variables
+ - name: librariesContainsChange
+ value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
- name: monoContainsChange
value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ]
jobParameters:
testGroup: innerloop
- nameSuffix: AllSubsets_Mono
- buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true
+ nameSuffix: LibraryTests
+ buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=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['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
creator: dotnet-bot
testRunNamePrefixSuffix: Mono_$(_BuildConfig)
+ extraHelixArguments: /p:BrowserHost=$(_hostedOs)
scenarios:
- normal
- WasmTestOnBrowser
- WasmTestOnNodeJs
- condition: >-
- or(
- eq(variables['monoContainsChange'], true),
- eq(variables['isRollingBuild'], true))
#
# Build the whole product using Mono and run runtime tests
@@ -480,67 +389,6 @@ jobs:
eq(dependencies.evaluate_paths.outputs['SetPathVars_runtimetests.containsChange'], true),
eq(variables['isRollingBuild'], true))
-# Wasm debugger tests
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: Release
- runtimeFlavor: mono
- platforms:
- - Browser_wasm
- variables:
- # map dependencies variables to local variables
- - name: wasmdebuggertestsContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ]
- jobParameters:
- testGroup: innerloop
- nameSuffix: Mono_DebuggerTests
- buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
- eq(variables['isRollingBuild'], true))
- # extra steps, run tests
- extraStepsTemplate: /eng/pipelines/libraries/helix.yml
- extraStepsParameters:
- creator: dotnet-bot
- testRunNamePrefixSuffix: Mono_$(_BuildConfig)
- scenarios:
- - wasmdebuggertests
-
-# Wasm debugger tests - windows
-- template: /eng/pipelines/common/platform-matrix.yml
- parameters:
- jobTemplate: /eng/pipelines/common/global-build-job.yml
- helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
- buildConfig: Release
- runtimeFlavor: mono
- platforms:
- - Browser_wasm_win
- variables:
- # map dependencies variables to local variables
- - name: wasmdebuggertestsContainsChange
- value: $[ dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'] ]
- jobParameters:
- testGroup: innerloop
- nameSuffix: Mono_DebuggerTests
- buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows
- timeoutInMinutes: 180
- condition: >-
- or(
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.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
- scenarios:
- - wasmdebuggertests
-
#
# Build the whole product using Mono for Android and run runtime tests with Android emulator
#
diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml
index c51d639d29f0f2..e8f707ff5e6d58 100644
--- a/eng/pipelines/runtime-staging.yml
+++ b/eng/pipelines/runtime-staging.yml
@@ -444,7 +444,9 @@ jobs:
buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false /p:BrowserHost=windows
timeoutInMinutes: 180
condition: >-
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true)
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
@@ -454,7 +456,7 @@ jobs:
scenarios:
- wasmdebuggertests
-# Wasm debugger tests
+# Wasm debugger tests - linux
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/common/global-build-job.yml
@@ -473,7 +475,9 @@ jobs:
buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:TestWasmDebuggerTests=true /p:TestAssemblies=false
timeoutInMinutes: 180
condition: >-
- eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true)
+ or(
+ eq(dependencies.evaluate_paths.outputs['SetPathVars_wasmdebuggertests.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
# extra steps, run tests
extraStepsTemplate: /eng/pipelines/libraries/helix.yml
extraStepsParameters:
diff --git a/eng/slngen.nuget.config b/eng/slngen.nuget.config
deleted file mode 100644
index a66b7f9b013241..00000000000000
--- a/eng/slngen.nuget.config
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/eng/targetframeworksuffix.props b/eng/targetframeworksuffix.props
index ccbf1aa2883664..f7074fe3e199f4 100644
--- a/eng/targetframeworksuffix.props
+++ b/eng/targetframeworksuffix.props
@@ -8,105 +8,91 @@
This is required for platforms not expected to have a version,
and we currently omit the version for all platforms. -->
0.0
+ $(TargetFramework.SubString($([MSBuild]::Add($(TargetFramework.IndexOf('-')), 1))))
-
- $(TargetFrameworkSuffix)
+
1.0
- $(TargetFrameworkSuffix),Version=$(TargetPlatformVersion)
-
+
true
- win
-
+
true
- unix
-
+
true
true
- linux
-
+
true
true
true
- android
-
+
true
true
- osx
-
+
true
true
- maccatalyst
-
+
true
true
- tvos
-
+
true
true
- ios
-
+
true
true
- freebsd
-
+
true
true
- netbsd
-
+
true
true
- illumos
-
+
true
true
- solaris
-
+
true
- browser
-
+
true
diff --git a/eng/testing/performance/android_scenarios.proj b/eng/testing/performance/android_scenarios.proj
index 52af8fa1678dc8..fefff6deeefe08 100644
--- a/eng/testing/performance/android_scenarios.proj
+++ b/eng/testing/performance/android_scenarios.proj
@@ -49,8 +49,14 @@
$(WorkItemDirectory)
- echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)helloandroid;copy %HELIX_CORRELATION_PAYLOAD%\HelloAndroidWithDiag.apk .;$(Python) pre.py
- $(Python) test.py devicestartup --device-type android --package-path pub\HelloAndroidWithDiag.apk --package-name net.dot.HelloAndroid --exit-code 42 --scenario-name "%(Identity)"
+ echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)helloandroid;copy %HELIX_CORRELATION_PAYLOAD%\HelloAndroid.apk .;$(Python) pre.py
+ $(Python) test.py devicestartup --device-type android --package-path pub\HelloAndroid.apk --package-name net.dot.HelloAndroid --scenario-name "%(Identity)"
+ $(Python) post.py
+
+
+ $(WorkItemDirectory)
+ echo on;set XHARNESSPATH=$(XharnessPath);cd $(ScenarioDirectory)mauiandroid;copy %HELIX_CORRELATION_PAYLOAD%\MauiAndroidDefault.apk .;$(Python) pre.py
+ $(Python) test.py devicestartup --device-type android --package-path pub\MauiAndroidDefault.apk --package-name com.companyname.mauitesting --scenario-name "%(Identity)"
$(Python) post.py
diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1
index d85325ee1349d5..7f1be6761b5049 100644
--- a/eng/testing/performance/performance-setup.ps1
+++ b/eng/testing/performance/performance-setup.ps1
@@ -148,14 +148,9 @@ if ($AndroidMono) {
{
mkdir $WorkItemDirectory
}
- if(Test-Path "$SourceDirectory\androidHelloWorld\HelloAndroid.apk") {
- Copy-Item -path "$SourceDirectory\androidHelloWorld\HelloAndroid.apk" $PayloadDirectory -Verbose
- }
-
- if(Test-Path "$SourceDirectory\androidHelloWorldWithDiag\HelloAndroidWithDiag.apk") {
- Copy-Item -path "$SourceDirectory\androidHelloWorldWithDiag\HelloAndroidWithDiag.apk" $PayloadDirectory -Verbose
- }
- Copy-Item -path "$SourceDirectory\MauiAndroidDefault.apk" $PayloadDirectory
+
+ Copy-Item -path "$SourceDirectory\androidHelloWorld\HelloAndroid.apk" $PayloadDirectory -Verbose
+ Copy-Item -path "$SourceDirectory\MauiAndroidDefault.apk" $PayloadDirectory -Verbose
$SetupArguments = $SetupArguments -replace $Architecture, 'arm64'
}
diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
index 8afeea6cdeeb13..c44096b4b7b476 100644
--- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt
+++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt
@@ -17,3 +17,4 @@ Wasm.Build.Tests.SatelliteAssembliesTests
Wasm.Build.Tests.WasmBuildAppTest
Wasm.Build.Tests.WasmNativeDefaultsTests
Wasm.Build.Tests.WorkloadTests
+Wasm.Build.Tests.WasmTemplateTests
diff --git a/eng/testing/scenarios/WasmDebuggerTestsJobsList.txt b/eng/testing/scenarios/WasmDebuggerTestsJobsList.txt
index d4ef9dcbfc399b..93917d7b22907d 100644
--- a/eng/testing/scenarios/WasmDebuggerTestsJobsList.txt
+++ b/eng/testing/scenarios/WasmDebuggerTestsJobsList.txt
@@ -16,3 +16,4 @@ DebuggerTests.PointerTests
DebuggerTests.SetVariableValueTests
DebuggerTests.MiscTests
DebuggerTests.SteppingTests
+DebuggerTests.SetNextIpTests
diff --git a/eng/testing/tests.props b/eng/testing/tests.props
index 3025ab62335049..f23f4cc62e9560 100644
--- a/eng/testing/tests.props
+++ b/eng/testing/tests.props
@@ -24,10 +24,9 @@
- $(NetCoreAppCurrent)-$(Configuration)
- $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleTestRunner', '$(MobileRunnersDirSuffix)'))
- $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidTestRunner', '$(MobileRunnersDirSuffix)'))
- $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmTestRunner', '$(MobileRunnersDirSuffix)'))
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleTestRunner', '$(Configuration)', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidTestRunner', '$(Configuration)', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmTestRunner', '$(Configuration)', '$(NetCoreAppCurrent)'))
$(PackageRID)
true
diff --git a/global.json b/global.json
index 43ff763c74d864..cdc6966b29227b 100644
--- a/global.json
+++ b/global.json
@@ -12,12 +12,11 @@
"python3": "3.7.1"
},
"msbuild-sdks": {
- "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.DotNet.Arcade.Sdk": "7.0.0-beta.22080.1",
+ "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.22080.1",
+ "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.22080.1",
"Microsoft.Build.NoTargets": "3.1.0",
"Microsoft.Build.Traversal": "3.0.23",
- "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.22073.5"
+ "Microsoft.NET.Sdk.IL": "7.0.0-preview.2.22080.2"
}
}
diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index 3d21bffd3d24f8..9cbfee4fb88b0b 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -309,7 +309,7 @@
causing impactful slowdowns while typing in the Corelib project.
-->
-
+
diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.sln b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.sln
index 4629497f45f7cc..66c65e680d4693 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.sln
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.sln
@@ -6,7 +6,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "S
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "System.Private.CoreLib.Shared", "..\..\libraries\System.Private.CoreLib\src\System.Private.CoreLib.Shared.shproj", "{845C8B26-350B-4E63-BD11-2C8150444E28}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib.Generators", "..\..\libraries\System.Private.CoreLib\generators\System.Private.CoreLib.Generators.csproj", "{7196828B-5E00-4BC6-9A1E-492C948E41A3}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib.Generators", "..\..\libraries\System.Private.CoreLib\gen\System.Private.CoreLib.Generators.csproj", "{7196828B-5E00-4BC6-9A1E-492C948E41A3}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
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 9def7541aa4c6a..3e8bd014fb0aa3 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
@@ -32,94 +32,6 @@
namespace System.Reflection.Emit
{
- // When the user calls AppDomain.DefineDynamicAssembly the loader creates a new InternalAssemblyBuilder.
- // This InternalAssemblyBuilder can be retrieved via a call to Assembly.GetAssemblies() by untrusted code.
- // In the past, when InternalAssemblyBuilder was AssemblyBuilder, the untrusted user could down cast the
- // Assembly to an AssemblyBuilder and emit code with the elevated permissions of the trusted code which
- // originally created the AssemblyBuilder via DefineDynamicAssembly. Today, this can no longer happen
- // because the Assembly returned via AssemblyGetAssemblies() will be an InternalAssemblyBuilder.
-
- // Only the caller of DefineDynamicAssembly will get an AssemblyBuilder.
- // There is a 1-1 relationship between InternalAssemblyBuilder and AssemblyBuilder.
- // AssemblyBuilder is composed of its InternalAssemblyBuilder.
- // The AssemblyBuilder data members (e.g. m_foo) were changed to properties which then delegate
- // the access to the composed InternalAssemblyBuilder. This way, AssemblyBuilder simply wraps
- // InternalAssemblyBuilder and still operates on InternalAssemblyBuilder members.
- // This also makes the change transparent to the loader. This is good because most of the complexity
- // of Assembly building is in the loader code so not touching that code reduces the chance of
- // introducing new bugs.
- internal sealed class InternalAssemblyBuilder : RuntimeAssembly
- {
- private InternalAssemblyBuilder() { }
-
- public override bool Equals(object? obj)
- {
- if (obj == null)
- {
- return false;
- }
-
- if (obj is InternalAssemblyBuilder)
- {
- return (object)this == obj;
- }
-
- return obj.Equals(this);
- }
-
- public override int GetHashCode() => base.GetHashCode();
-
- // Assembly methods that are overridden by AssemblyBuilder should be overridden by InternalAssemblyBuilder too
- #region Methods inherited from Assembly
-
- public override string[] GetManifestResourceNames()
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- [RequiresAssemblyFiles(ThrowingMessageInRAF)]
- public override FileStream GetFile(string name)
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- [RequiresAssemblyFiles(ThrowingMessageInRAF)]
- public override FileStream[] GetFiles(bool getResourceModules)
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- public override Stream? GetManifestResourceStream(Type type, string name)
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- public override Stream? GetManifestResourceStream(string name)
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- public override ManifestResourceInfo? GetManifestResourceInfo(string resourceName)
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- public override string Location => string.Empty;
-
- [RequiresAssemblyFiles(ThrowingMessageInRAF)]
- public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
-
- [RequiresUnreferencedCode("Types might be removed")]
- public override Type[] GetExportedTypes()
- {
- throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
- }
-
- public override string ImageRuntimeVersion => Assembly.GetExecutingAssembly().ImageRuntimeVersion;
-
- #endregion
- }
-
public sealed partial class AssemblyBuilder : Assembly
{
[MethodImpl(MethodImplOptions.InternalCall)]
@@ -129,14 +41,14 @@ public sealed partial class AssemblyBuilder : Assembly
// This is only valid in the "external" AssemblyBuilder
internal AssemblyBuilderData _assemblyData;
- private readonly InternalAssemblyBuilder _internalAssemblyBuilder;
+ private readonly RuntimeAssembly _internalAssembly;
private ModuleBuilder _manifestModuleBuilder;
// Set to true if the manifest module was returned by code:DefineDynamicModule to the user
private bool _isManifestModuleUsedAsDefinedModule;
private const string ManifestModuleName = "RefEmit_InMemoryManifestModule";
- internal ModuleBuilder GetModuleBuilder(InternalModuleBuilder module)
+ internal ModuleBuilder GetModuleBuilder(RuntimeModule module)
{
Debug.Assert(module != null);
Debug.Assert(InternalAssembly == module.Assembly);
@@ -155,7 +67,7 @@ internal ModuleBuilder GetModuleBuilder(InternalModuleBuilder module)
internal object SyncRoot => InternalAssembly.SyncRoot;
- internal InternalAssemblyBuilder InternalAssembly => _internalAssemblyBuilder;
+ internal RuntimeAssembly InternalAssembly => _internalAssembly;
#endregion
@@ -190,13 +102,13 @@ internal AssemblyBuilder(AssemblyName name,
assemblyAttributes = new List(unsafeAssemblyAttributes);
}
- Assembly? retAssembly = null;
+ RuntimeAssembly? retAssembly = null;
CreateDynamicAssembly(ObjectHandleOnStack.Create(ref name),
new StackCrawlMarkHandle(ref stackMark),
(int)access,
ObjectHandleOnStack.Create(ref assemblyLoadContext),
ObjectHandleOnStack.Create(ref retAssembly));
- _internalAssemblyBuilder = (InternalAssemblyBuilder)retAssembly!;
+ _internalAssembly = retAssembly!;
_assemblyData = new AssemblyBuilderData(access);
@@ -216,7 +128,7 @@ internal AssemblyBuilder(AssemblyName name,
[MemberNotNull(nameof(_manifestModuleBuilder))]
private void InitManifestModule()
{
- InternalModuleBuilder modBuilder = (InternalModuleBuilder)GetInMemoryAssemblyModule(InternalAssembly);
+ RuntimeModule modBuilder = (RuntimeModule)GetInMemoryAssemblyModule(InternalAssembly);
// Note that this ModuleBuilder cannot be used for RefEmit yet
// because it hasn't been initialized.
@@ -386,10 +298,9 @@ internal static void CheckContext(params Type?[]? types)
}
}
- public override bool Equals(object? obj) => InternalAssembly.Equals(obj);
+ public override bool Equals(object? obj) => base.Equals(obj);
- // Need a dummy GetHashCode to pair with Equals
- public override int GetHashCode() => InternalAssembly.GetHashCode();
+ public override int GetHashCode() => base.GetHashCode();
#region ICustomAttributeProvider Members
public override object[] GetCustomAttributes(bool inherit) =>
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
index 0e4741ea643d03..c98d78da4c84bf 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
@@ -41,7 +41,7 @@ public sealed class DynamicMethod : MethodInfo
// We capture the creation context so that we can do the checks against the same context,
// irrespective of when the method gets compiled. Note that the DynamicMethod does not know when
// it is ready for use since there is not API which indictates that IL generation has completed.
- private static volatile InternalModuleBuilder? s_anonymouslyHostedDynamicMethodsModule;
+ private static volatile RuntimeModule? s_anonymouslyHostedDynamicMethodsModule;
private static readonly object s_anonymouslyHostedDynamicMethodsModuleLock = new object();
//
@@ -244,7 +244,7 @@ private static RuntimeModule GetDynamicMethodsModule()
null);
// this always gets the internal module.
- s_anonymouslyHostedDynamicMethodsModule = (InternalModuleBuilder)assembly.ManifestModule!;
+ s_anonymouslyHostedDynamicMethodsModule = (RuntimeModule)assembly.ManifestModule!;
}
return s_anonymouslyHostedDynamicMethodsModule;
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 cbe0a7b39dde5b..f1ffa97874925f 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
@@ -10,31 +10,6 @@
namespace System.Reflection.Emit
{
- internal sealed partial class InternalModuleBuilder : RuntimeModule
- {
- // InternalModuleBuilder should not contain any data members as its reflectbase is the same as Module.
-
- private InternalModuleBuilder() { }
-
- public override bool Equals(object? obj)
- {
- if (obj == null)
- {
- return false;
- }
-
- if (obj is InternalModuleBuilder)
- {
- return (object)this == obj;
- }
-
- return obj.Equals(this);
- }
-
- // Need a dummy GetHashCode to pair with Equals
- public override int GetHashCode() => base.GetHashCode();
- }
-
// deliberately not [serializable]
public partial class ModuleBuilder : Module
{
@@ -75,7 +50,7 @@ internal static string UnmangleTypeName(string typeName)
// _TypeBuilder contains both TypeBuilder and EnumBuilder objects
private Dictionary _typeBuilderDict = null!;
internal ModuleBuilderData _moduleData = null!;
- internal InternalModuleBuilder _internalModuleBuilder;
+ internal RuntimeModule _internalModule;
// This is the "external" AssemblyBuilder
// only the "external" ModuleBuilder has this set
private readonly AssemblyBuilder _assemblyBuilder;
@@ -85,9 +60,9 @@ internal static string UnmangleTypeName(string typeName)
#region Constructor
- internal ModuleBuilder(AssemblyBuilder assemblyBuilder, InternalModuleBuilder internalModuleBuilder)
+ internal ModuleBuilder(AssemblyBuilder assemblyBuilder, RuntimeModule internalModule)
{
- _internalModuleBuilder = internalModuleBuilder;
+ _internalModule = internalModule;
_assemblyBuilder = assemblyBuilder;
}
@@ -323,8 +298,7 @@ internal void Init(string strModuleName)
#region Module Overrides
- // _internalModuleBuilder is null iff this is a "internal" ModuleBuilder
- internal InternalModuleBuilder InternalModule => _internalModuleBuilder;
+ internal RuntimeModule InternalModule => _internalModule;
protected override ModuleHandle GetModuleHandleImpl() => new ModuleHandle(InternalModule);
@@ -513,10 +487,9 @@ internal SignatureHelper GetMemberRefSignature(MethodBase? method, int cGenericP
#endregion
- public override bool Equals(object? obj) => InternalModule.Equals(obj);
+ public override bool Equals(object? obj) => base.Equals(obj);
- // Need a dummy GetHashCode to pair with Equals
- public override int GetHashCode() => InternalModule.GetHashCode();
+ public override int GetHashCode() => base.GetHashCode();
#region ICustomAttributeProvider Members
@@ -1127,7 +1100,7 @@ private int GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition)
// the file name of the referenced module.
if (refedModuleBuilder == null)
{
- refedModuleBuilder = ContainingAssemblyBuilder.GetModuleBuilder((InternalModuleBuilder)refedModule);
+ refedModuleBuilder = ContainingAssemblyBuilder.GetModuleBuilder((RuntimeModule)refedModule);
}
referencedModuleFileName = refedModuleBuilder._moduleData._moduleName;
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
index 877c449ad45808..7eed453959c668 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
@@ -16,7 +16,7 @@
namespace System.Reflection
{
- internal partial class RuntimeAssembly : Assembly
+ internal sealed partial class RuntimeAssembly : Assembly
{
internal RuntimeAssembly() { throw new NotSupportedException(); }
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
index cba7d80fa15b09..e8b52d01d5e0da 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs
@@ -9,7 +9,7 @@
namespace System.Reflection
{
- internal partial class RuntimeModule : Module
+ internal sealed partial class RuntimeModule : Module
{
internal RuntimeModule() { throw new NotSupportedException(); }
diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp
index 2d979c395610e9..ceadbf1af995b4 100644
--- a/src/coreclr/gc/unix/gcenv.unix.cpp
+++ b/src/coreclr/gc/unix/gcenv.unix.cpp
@@ -946,7 +946,12 @@ static size_t GetLogicalProcessorCacheSizeFromOS()
{
int64_t cacheSizeFromSysctl = 0;
size_t sz = sizeof(cacheSizeFromSysctl);
- const bool success = sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
+ const bool success = false
+ // macOS-arm64: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency
+ // and performance cores separetely. "perflevel0" stands for "performance"
+ || sysctlbyname("hw.perflevel0.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
+ // macOS-arm64: these report cache sizes for efficiency cores only:
+ || sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
|| sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
|| sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0;
if (success)
diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h
index e544430fa587ba..93459c739f78e8 100644
--- a/src/coreclr/inc/clrconfigvalues.h
+++ b/src/coreclr/inc/clrconfigvalues.h
@@ -804,7 +804,6 @@ CONFIG_DWORD_INFO(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "")
#define INTERNAL_NoGuiOnAssert_Default 1
RETAIL_CONFIG_DWORD_INFO(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "")
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "")
-CONFIG_DWORD_INFO(INTERNAL_NoStringInterning, W("NoStringInterning"), 1, "Disallows string interning. I see no value in it anymore.")
CONFIG_DWORD_INFO(INTERNAL_PauseOnLoad, W("PauseOnLoad"), 0, "Stops in SystemDomain::init. I think it can be removed.")
CONFIG_DWORD_INFO(INTERNAL_PerfAllocsSizeThreshold, W("PerfAllocsSizeThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.")
CONFIG_DWORD_INFO(INTERNAL_PerfNumAllocsThreshold, W("PerfNumAllocsThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.")
diff --git a/src/coreclr/inc/corhdr.h b/src/coreclr/inc/corhdr.h
index 11dd7029884539..b4ea57f811ce14 100644
--- a/src/coreclr/inc/corhdr.h
+++ b/src/coreclr/inc/corhdr.h
@@ -1683,17 +1683,6 @@ typedef enum CorAttributeTargets
#define DEBUGGABLE_ATTRIBUTE_TYPE_NAME "DebuggableAttribute"
-// Keep in sync with CompilationRelaxations.cs
-typedef enum CompilationRelaxationsEnum
-{
- CompilationRelaxations_NoStringInterning = 0x0008,
-
-} CompilationRelaxationEnum;
-
-#define COMPILATIONRELAXATIONS_TYPE_W W("System.Runtime.CompilerServices.CompilationRelaxationsAttribute")
-#define COMPILATIONRELAXATIONS_TYPE "System.Runtime.CompilerServices.CompilationRelaxationsAttribute"
-
-
// Keep in sync with RuntimeCompatibilityAttribute.cs
#define RUNTIMECOMPATIBILITY_TYPE_W W("System.Runtime.CompilerServices.RuntimeCompatibilityAttribute")
#define RUNTIMECOMPATIBILITY_TYPE "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute"
diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h
index 3bad0df909e9a6..46099e21382b54 100644
--- a/src/coreclr/inc/corinfo.h
+++ b/src/coreclr/inc/corinfo.h
@@ -928,16 +928,6 @@ enum CorInfoInline
INLINE_NEVER = -2, // This method should never be inlined, regardless of context
};
-enum CorInfoInlineRestrictions
-{
- INLINE_RESPECT_BOUNDARY = 0x00000001, // You can inline if there are no calls from the method being inlined
- INLINE_NO_CALLEE_LDSTR = 0x00000002, // You can inline only if you guarantee that if inlinee does an ldstr
- // inlinee's module will never see that string (by any means).
- // This is due to how we implement the NoStringInterningAttribute
- // (by reusing the fixup table).
- INLINE_SAME_THIS = 0x00000004, // You can inline only if the callee is on the same this reference as caller
-};
-
enum CorInfoInlineTypeCheck
{
CORINFO_INLINE_TYPECHECK_NONE = 0x00000000, // It's not okay to compare type's vtable with a native type handle
@@ -1997,9 +1987,7 @@ class ICorStaticInfo
) = 0;
// Decides if you have any limitations for inlining. If everything's OK, it will return
- // INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
- // function must respect. If caller passes pRestrictions = NULL, if there are any restrictions
- // INLINE_FAIL will be returned
+ // INLINE_PASS.
//
// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
//
@@ -2007,8 +1995,7 @@ class ICorStaticInfo
virtual CorInfoInline canInline (
CORINFO_METHOD_HANDLE callerHnd, /* IN */
- CORINFO_METHOD_HANDLE calleeHnd, /* IN */
- uint32_t* pRestrictions /* OUT */
+ CORINFO_METHOD_HANDLE calleeHnd /* IN */
) = 0;
// Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all
diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h
index 21236cc92cb17d..132707a4ef485d 100644
--- a/src/coreclr/inc/icorjitinfoimpl_generated.h
+++ b/src/coreclr/inc/icorjitinfoimpl_generated.h
@@ -42,8 +42,7 @@ bool getMethodInfo(
CorInfoInline canInline(
CORINFO_METHOD_HANDLE callerHnd,
- CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions) override;
+ CORINFO_METHOD_HANDLE calleeHnd) override;
void reportInliningDecision(
CORINFO_METHOD_HANDLE inlinerHnd,
diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h
index e7b8884419e5a6..66de16f77a0ca5 100644
--- a/src/coreclr/inc/jiteeversionguid.h
+++ b/src/coreclr/inc/jiteeversionguid.h
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED
-constexpr GUID JITEEVersionIdentifier = { /* 323185e9-208a-4b35-a413-23f9aac2d5f7 */
- 0x323185e9,
- 0x208a,
- 0x4b35,
- {0xa4, 0x13, 0x23, 0xf9, 0xaa, 0xc2, 0xd5, 0xf7}
+constexpr GUID JITEEVersionIdentifier = { /* ccb0c159-04b3-47f6-993e-79114c9cbef8 */
+ 0xccb0c159,
+ 0x04b3,
+ 0x47f6,
+ {0x99, 0x3e, 0x79, 0x11, 0x4c, 0x9c, 0xbe, 0xf8}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
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/stresslog.h b/src/coreclr/inc/stresslog.h
index 4ee3acaeb8bb6c..35381a17cbb310 100644
--- a/src/coreclr/inc/stresslog.h
+++ b/src/coreclr/inc/stresslog.h
@@ -740,6 +740,7 @@ class ThreadStressLog {
#if defined(MEMORY_MAPPED_STRESSLOG) && !defined(STRESS_LOG_ANALYZER)
void* __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT;
+ void __cdecl operator delete (void * chunk);
#endif
~ThreadStressLog ()
diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt
index ebca7e65daaac7..0534375b821af1 100644
--- a/src/coreclr/jit/CMakeLists.txt
+++ b/src/coreclr/jit/CMakeLists.txt
@@ -104,6 +104,7 @@ set( JIT_SOURCES
fgprofile.cpp
fgstmt.cpp
flowgraph.cpp
+ forwardsub.cpp
gcdecode.cpp
gcencode.cpp
gcinfo.cpp
diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
index 6de2cf03a26b1b..2cd1c0d4235d9a 100644
--- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
+++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
@@ -61,11 +61,10 @@ bool WrapICorJitInfo::getMethodInfo(
CorInfoInline WrapICorJitInfo::canInline(
CORINFO_METHOD_HANDLE callerHnd,
- CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions)
+ CORINFO_METHOD_HANDLE calleeHnd)
{
API_ENTER(canInline);
- CorInfoInline temp = wrapHnd->canInline(callerHnd, calleeHnd, pRestrictions);
+ CorInfoInline temp = wrapHnd->canInline(callerHnd, calleeHnd);
API_LEAVE(canInline);
return temp;
}
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp
index cf87223f71760b..c19a7d2e50a716 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -4657,6 +4657,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Figure out what locals are address-taken.
//
DoPhase(this, PHASE_STR_ADRLCL, &Compiler::fgMarkAddressExposedLocals);
+ // Run a simple forward substitution pass.
+ //
+ DoPhase(this, PHASE_FWD_SUB, &Compiler::fgForwardSub);
// Apply the type update to implicit byref parameters; also choose (based on address-exposed
// analysis) which implicit byref promotions to keep (requires copy to initialize) or discard.
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 967d27eac4703b..69d88c4a57e280 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -5506,7 +5506,7 @@ class Compiler
// Does value-numbering for a block assignment.
void fgValueNumberBlockAssignment(GenTree* tree);
- bool fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree, GenTreeLclVarCommon* rhsLclVarTree);
+ bool fgValueNumberBlockAssignmentTypeCheck(LclVarDsc* dstVarDsc, FieldSeqNode* dstFldSeq, GenTree* src);
// Does value-numbering for a cast tree.
void fgValueNumberCastTree(GenTree* tree);
@@ -6423,7 +6423,7 @@ class Compiler
bool fgMorphCanUseLclFldForCopy(unsigned lclNum1, unsigned lclNum2);
- GenTreeLclVar* fgMorphTryFoldObjAsLclVar(GenTreeObj* obj);
+ GenTreeLclVar* fgMorphTryFoldObjAsLclVar(GenTreeObj* obj, bool destroyNodes = true);
GenTreeOp* fgMorphCommutative(GenTreeOp* tree);
GenTree* fgMorphCastedBitwiseOp(GenTreeOp* tree);
@@ -6562,6 +6562,10 @@ class Compiler
void fgMarkAddressExposedLocals();
void fgMarkAddressExposedLocals(Statement* stmt);
+ PhaseStatus fgForwardSub();
+ bool fgForwardSubBlock(BasicBlock* block);
+ bool fgForwardSubStatement(Statement* statement);
+
static fgWalkPreFn fgUpdateSideEffectsPre;
static fgWalkPostFn fgUpdateSideEffectsPost;
diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h
index 8f72dcce2360cd..3b1907e86fde0b 100644
--- a/src/coreclr/jit/compphases.h
+++ b/src/coreclr/jit/compphases.h
@@ -43,6 +43,7 @@ CompPhaseNameMacro(PHASE_UPDATE_FINALLY_FLAGS, "Update finally target flags",
CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1, false)
CompPhaseNameMacro(PHASE_EARLY_UPDATE_FLOW_GRAPH,"Update flow graph early pass", "UPD-FG-E", false, -1, false)
CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1, false)
+CompPhaseNameMacro(PHASE_FWD_SUB, "Forward Substitution", "FWD-SUB", false, -1, false)
CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1, false)
CompPhaseNameMacro(PHASE_PROMOTE_STRUCTS, "Morph - Promote Structs", "PROMOTER" ,false, -1, false)
CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1, false)
diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp
index d90c5771ce1a96..c203a1729dd401 100644
--- a/src/coreclr/jit/emitxarch.cpp
+++ b/src/coreclr/jit/emitxarch.cpp
@@ -423,6 +423,10 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr
case IF_RWR:
case IF_RRD:
case IF_RRW:
+ case IF_RWR_RRD_RRD:
+ case IF_RWR_RRD_MRD:
+ case IF_RWR_RRD_ARD:
+ case IF_RWR_RRD_SRD:
break;
default:
return false;
diff --git a/src/coreclr/jit/forwardsub.cpp b/src/coreclr/jit/forwardsub.cpp
new file mode 100644
index 00000000000000..77f0c6d99f4363
--- /dev/null
+++ b/src/coreclr/jit/forwardsub.cpp
@@ -0,0 +1,790 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "jitpch.h"
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+
+//------------------------------------------------------------------------
+// Simple Forward Substitution
+//
+// This phase tries to reconnect trees that were split early on by
+// phases like the importer and inlining. We run it before morph
+// to provide more context for morph's tree based optimizations, and
+// we run it after the local address visitor because that phase sets
+// address exposure for locals and computes (early) ref counts.
+//
+// The general pattern we look for is
+//
+// Statement(n):
+// GT_ASG(lcl, tree)
+// Statement(n+1):
+// ... use of lcl ...
+//
+// where those are the only appearances of lcl and lcl is not address
+// exposed.
+//
+// The "optimization" here transforms this to
+//
+// ~~Statement(n)~~ (removed)
+// Statement(n+1):
+// ... use of tree ...
+//
+// As always our main concerns are throughput, legality, profitability,
+// and ensuring downstream phases do not get confused.
+//
+// For throughput, we try and early out on illegal or unprofitable cases
+// before doing the more costly bits of analysis. We only scan a limited
+// amount of IR and just give up if we can't find what we are looking for.
+//
+// If we're successful we will backtrack a bit, to try and catch cases like
+//
+// Statement(n):
+// lcl1 = tree1
+// Statement(n+1):
+// lcl2 = tree2
+// Statement(n+2):
+// use ... lcl1 ... use ... lcl2 ...
+//
+// If we can forward sub tree2, then the def and use of lcl1 become
+// adjacent.
+//
+// For legality we must show that evaluating "tree" at its new position
+// can't change any observable behavior. This largely means running an
+// interference analysis between tree and the portion of Statement(n+1)
+// that will evaluate before "tree". This analysis is complicated by some
+// missing flags on trees, in particular modelling the potential uses
+// of exposed locals. We run supplementary scans looking for those.
+//
+// Ideally we'd update the tree with our findings, or better yet ensure
+// that upstream phases didn't leave the wrong flags.
+//
+// For profitability we first try and avoid code growth. We do this
+// by only substituting in cases where lcl has exactly one def and one use.
+// This info is computed for us but the RCS_Early ref counting done during
+// the immediately preceeding fgMarkAddressExposedLocals phase.
+//
+// Because of this, once we've substituted "tree" we know that lcl is dead
+// and we can remove the assignment statement.
+//
+// Even with ref count screening, we don't know for sure where the
+// single use of local might be, so we have to seach for it.
+//
+// We also take pains not to create overly large trees as the recursion
+// done by morph incorporates a lot of state; deep trees may lead to
+// stack overflows.
+//
+// There are a fair number of ad-hoc restrictions on what can be
+// substituted where; these reflect various blemishes or implicit
+// contracts in our IR shapes that we should either remove or mandate.
+//
+// Possible enhancements:
+// * Allow fwd sub of "simple, cheap" trees when there's more than one use.
+// * Search more widely for the use.
+// * Use height/depth to avoid blowing morph's recursion, rather than tree size.
+// * Sub across a block boundary if successor block is unique, join-free,
+// and in the same EH region.
+// * Rerun this later, after we have built SSA, and handle single-def single-use
+// from SSA perspective.
+// * Fix issue in morph that can unsoundly reorder call args, and remove
+// extra effects computation from ForwardSubVisitor.
+// * We can be more aggressive with GTF_IND_INVARIANT / GTF_IND_NONFAULTING
+// nodes--even though they may be marked GTF_GLOB_REF, they can be freely
+// reordered. See if this offers any benefit.
+//
+//------------------------------------------------------------------------
+
+//------------------------------------------------------------------------
+// fgForwardSub: run forward substitution in this method
+//
+// Returns:
+// suitable phase status
+//
+PhaseStatus Compiler::fgForwardSub()
+{
+ if (!opts.OptimizationEnabled())
+ {
+ return PhaseStatus::MODIFIED_NOTHING;
+ }
+
+#if defined(DEBUG)
+ if (JitConfig.JitNoForwardSub() > 0)
+ {
+ return PhaseStatus::MODIFIED_NOTHING;
+ }
+#endif
+
+ bool changed = false;
+
+ for (BasicBlock* const block : Blocks())
+ {
+ JITDUMP("\n\n===> " FMT_BB "\n", block->bbNum);
+ changed |= fgForwardSubBlock(block);
+ }
+
+ return changed ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
+}
+
+//------------------------------------------------------------------------
+// fgForwardSubBlock: run forward substitution in this block
+//
+// Arguments:
+// block -- block to process
+//
+// Returns:
+// true if any IR was modified
+//
+bool Compiler::fgForwardSubBlock(BasicBlock* block)
+{
+ Statement* stmt = block->firstStmt();
+ Statement* lastStmt = block->lastStmt();
+ bool changed = false;
+
+ while (stmt != lastStmt)
+ {
+ Statement* const prevStmt = stmt->GetPrevStmt();
+ Statement* const nextStmt = stmt->GetNextStmt();
+ bool const substituted = fgForwardSubStatement(stmt);
+
+ if (substituted)
+ {
+ fgRemoveStmt(block, stmt);
+ changed = true;
+ }
+
+ // Try backtracking if we substituted.
+ //
+ if (substituted && (prevStmt != lastStmt) && prevStmt->GetRootNode()->OperIs(GT_ASG))
+ {
+ // Yep, bactrack.
+ //
+ stmt = prevStmt;
+ }
+ else
+ {
+ // Move on to the next.
+ //
+ stmt = nextStmt;
+ }
+ }
+
+ return changed;
+}
+
+//------------------------------------------------------------------------
+// ForwardSubVisitor: tree visitor to locate uses of a local in a tree
+//
+// Also computes the set of side effects that happen "before" the use,
+// and counts the size of the tree.
+//
+// Effects accounting is complicated by missing flags and by the need
+// to avoid introducing interfering call args.
+//
+class ForwardSubVisitor final : public GenTreeVisitor
+{
+public:
+ enum
+ {
+ ComputeStack = true,
+ DoPostOrder = true,
+ UseExecutionOrder = true
+ };
+
+ ForwardSubVisitor(Compiler* compiler, unsigned lclNum)
+ : GenTreeVisitor(compiler)
+ , m_use(nullptr)
+ , m_node(nullptr)
+ , m_parentNode(nullptr)
+ , m_callAncestor(nullptr)
+ , m_lclNum(lclNum)
+ , m_useCount(0)
+ , m_useFlags(GTF_EMPTY)
+ , m_accumulatedFlags(GTF_EMPTY)
+ , m_treeSize(0)
+ {
+ }
+
+ Compiler::fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
+ {
+ m_treeSize++;
+ GenTree* const node = *use;
+
+ if (node->OperIs(GT_LCL_VAR))
+ {
+ unsigned const lclNum = node->AsLclVarCommon()->GetLclNum();
+
+ if (lclNum == m_lclNum)
+ {
+ m_useCount++;
+
+ // Screen out contextual "uses"
+ //
+ GenTree* const parent = m_ancestors.Top(1);
+ bool const isDef = parent->OperIs(GT_ASG) && (parent->gtGetOp1() == node);
+ bool const isAddr = parent->OperIs(GT_ADDR);
+
+ bool isCallTarget = false;
+
+ // Quirk:
+ //
+ // fgGetStubAddrArg cannot handle complex trees (it calls gtClone)
+ //
+ if (parent->IsCall())
+ {
+ GenTreeCall* const parentCall = parent->AsCall();
+ isCallTarget = (parentCall->gtCallType == CT_INDIRECT) && (parentCall->gtCallAddr == node);
+ }
+
+ if (!isDef && !isAddr && !isCallTarget)
+ {
+ m_node = node;
+ m_use = use;
+ m_useFlags = m_accumulatedFlags;
+ m_parentNode = parent;
+
+ // If this use contributes to a call arg we need to
+ // remember the call and handle it specially when we
+ // see it later in the postorder walk.
+ //
+ for (int i = 1; i < m_ancestors.Height(); i++)
+ {
+ if (m_ancestors.Top(i)->IsCall())
+ {
+ m_callAncestor = m_ancestors.Top(i)->AsCall();
+ break;
+ }
+ }
+ }
+ }
+
+ // Uses of address-exposed locals are modelled as global refs.
+ //
+ LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum);
+
+ if (varDsc->IsAddressExposed())
+ {
+ m_accumulatedFlags |= GTF_GLOB_REF;
+ }
+ }
+
+ // Is this the use's call ancestor?
+ //
+ if ((m_callAncestor != nullptr) && (node == m_callAncestor))
+ {
+ // To be conservative and avoid issues with morph
+ // reordering call args, we merge in effects of all args
+ // to this call.
+ //
+ // Remove this if/when morph's arg sorting is fixed.
+ //
+ GenTreeFlags oldUseFlags = m_useFlags;
+
+ if (m_callAncestor->gtCallThisArg != nullptr)
+ {
+ m_useFlags |= (m_callAncestor->gtCallThisArg->GetNode()->gtFlags & GTF_GLOB_EFFECT);
+ }
+
+ for (GenTreeCall::Use& use : m_callAncestor->Args())
+ {
+ m_useFlags |= (use.GetNode()->gtFlags & GTF_GLOB_EFFECT);
+ }
+
+ if (oldUseFlags != m_useFlags)
+ {
+ JITDUMP(" [added other call arg use flags: 0x%x]", m_useFlags & ~oldUseFlags);
+ }
+ }
+
+ m_accumulatedFlags |= (node->gtFlags & GTF_GLOB_EFFECT);
+
+ return fgWalkResult::WALK_CONTINUE;
+ }
+
+ unsigned GetUseCount() const
+ {
+ return m_useCount;
+ }
+
+ GenTree* GetNode() const
+ {
+ return m_node;
+ }
+
+ GenTree** GetUse() const
+ {
+ return m_use;
+ }
+
+ GenTree* GetParentNode() const
+ {
+ return m_parentNode;
+ }
+
+ GenTreeFlags GetFlags() const
+ {
+ return m_useFlags;
+ }
+
+ bool IsCallArg() const
+ {
+ return m_parentNode->IsCall();
+ }
+
+ unsigned GetComplexity() const
+ {
+ return m_treeSize;
+ }
+
+private:
+ GenTree** m_use;
+ GenTree* m_node;
+ GenTree* m_parentNode;
+ GenTreeCall* m_callAncestor;
+ unsigned m_lclNum;
+ unsigned m_useCount;
+ GenTreeFlags m_useFlags;
+ GenTreeFlags m_accumulatedFlags;
+ unsigned m_treeSize;
+};
+
+//------------------------------------------------------------------------
+// EffectsVisitor: tree visitor to compute missing effects of a tree.
+//
+class EffectsVisitor final : public GenTreeVisitor
+{
+public:
+ enum
+ {
+ DoPostOrder = true,
+ UseExecutionOrder = true
+ };
+
+ EffectsVisitor(Compiler* compiler) : GenTreeVisitor(compiler), m_flags(GTF_EMPTY)
+ {
+ }
+
+ Compiler::fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
+ {
+ GenTree* const node = *use;
+ m_flags |= node->gtFlags & GTF_ALL_EFFECT;
+
+ if (node->OperIs(GT_LCL_VAR))
+ {
+ unsigned const lclNum = node->AsLclVarCommon()->GetLclNum();
+ LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum);
+
+ if (varDsc->IsAddressExposed())
+ {
+ m_flags |= GTF_GLOB_REF;
+ }
+ }
+
+ return fgWalkResult::WALK_CONTINUE;
+ }
+
+ GenTreeFlags GetFlags()
+ {
+ return m_flags;
+ }
+
+private:
+ GenTreeFlags m_flags;
+};
+
+//------------------------------------------------------------------------
+// fgForwardSubStatement: forward substitute this statement's
+// computation to the next statement, if legal and profitable
+//
+// arguments:
+// stmt - statement in question
+//
+// Returns:
+// true if statement computation was forwarded.
+// caller is responsible for removing the now-dead statement.
+//
+bool Compiler::fgForwardSubStatement(Statement* stmt)
+{
+ // Is this tree a def of a single use, unaliased local?
+ //
+ GenTree* const rootNode = stmt->GetRootNode();
+
+ if (!rootNode->OperIs(GT_ASG))
+ {
+ return false;
+ }
+
+ GenTree* const lhsNode = rootNode->gtGetOp1();
+
+ if (!lhsNode->OperIs(GT_LCL_VAR))
+ {
+ return false;
+ }
+
+ JITDUMP(" [%06u]: ", dspTreeID(rootNode))
+
+ unsigned const lclNum = lhsNode->AsLclVarCommon()->GetLclNum();
+ LclVarDsc* const varDsc = lvaGetDesc(lclNum);
+
+ // Leave pinned locals alone.
+ // This is just a perf opt -- we shouldn't find any uses.
+ //
+ if (varDsc->lvPinned)
+ {
+ JITDUMP(" pinned local\n");
+ return false;
+ }
+
+ // Only fwd sub if we expect no code duplication
+ // We expect one def and one use.
+ //
+ if (varDsc->lvRefCnt(RCS_EARLY) != 2)
+ {
+ JITDUMP(" not asg (single-use lcl)\n");
+ return false;
+ }
+
+ // And local is unalised
+ //
+ if (varDsc->IsAddressExposed())
+ {
+ JITDUMP(" not asg (unaliased single-use lcl)\n");
+ return false;
+ }
+
+ // Could handle this case --perhaps-- but we'd want to update ref counts.
+ //
+ if (lvaIsImplicitByRefLocal(lclNum))
+ {
+ JITDUMP(" implicit by-ref local\n");
+ return false;
+ }
+
+ // Check the tree to substitute.
+ //
+ // We could just extract the value portion and forward sub that,
+ // but cleanup would be more complicated.
+ //
+ GenTree* const rhsNode = rootNode->gtGetOp2();
+ GenTree* fwdSubNode = rhsNode;
+
+ // Can't substitute a qmark (unless the use is RHS of an assign... could check for this)
+ // Can't substitute GT_CATCH_ARG.
+ // Can't substitute GT_LCLHEAP.
+ //
+ // Don't substitute a no return call (trips up morph in some cases).
+ //
+ if (fwdSubNode->OperIs(GT_QMARK, GT_CATCH_ARG, GT_LCLHEAP))
+ {
+ JITDUMP(" tree to sub is qmark, catch arg, or lcl heap\n");
+ return false;
+ }
+
+ if (fwdSubNode->IsCall() && fwdSubNode->AsCall()->IsNoReturn())
+ {
+ JITDUMP(" tree to sub is a 'no return' call\n");
+ return false;
+ }
+
+ // Bail if sub node has embedded assignment.
+ //
+ if ((fwdSubNode->gtFlags & GTF_ASG) != 0)
+ {
+ JITDUMP(" tree to sub has effects\n");
+ return false;
+ }
+
+ // Bail if sub node has mismatched types.
+ // Might be able to tolerate these by retyping.
+ //
+ if (lhsNode->TypeGet() != fwdSubNode->TypeGet())
+ {
+ JITDUMP(" mismatched types (assignment)\n");
+ return false;
+ }
+
+ if (gtGetStructHandleIfPresent(fwdSubNode) != gtGetStructHandleIfPresent(lhsNode))
+ {
+ JITDUMP(" would change struct handle (assignment)\n");
+ return false;
+ }
+
+ // If lhs is mulit-reg, rhs must be too.
+ //
+ if (lhsNode->IsMultiRegNode() && !fwdSubNode->IsMultiRegNode())
+ {
+ JITDUMP(" would change multi-reg (assignment)\n");
+ return false;
+ }
+
+ // Don't fwd sub overly large trees.
+ // Size limit here is ad-hoc. Need to tune.
+ //
+ // Consider instead using the height of the fwdSubNode.
+ //
+ unsigned const nodeLimit = 16;
+
+ if (gtComplexityExceeds(&fwdSubNode, nodeLimit))
+ {
+ JITDUMP(" tree to sub has more than %u nodes\n", nodeLimit);
+ return false;
+ }
+
+ // Local and tree to substitute seem suitable.
+ // See if the next statement contains the one and only use.
+ //
+ Statement* const nextStmt = stmt->GetNextStmt();
+
+ // We often see stale flags, eg call flags after inlining.
+ // Try and clean these up.
+ //
+ gtUpdateStmtSideEffects(nextStmt);
+ gtUpdateStmtSideEffects(stmt);
+
+ // Scan for the (single) use.
+ //
+ ForwardSubVisitor fsv(this, lclNum);
+ fsv.WalkTree(nextStmt->GetRootNodePointer(), nullptr);
+
+ // LclMorph (via RCS_Early) said there was just one use.
+ // It had better have gotten this right.
+ //
+ assert(fsv.GetUseCount() <= 1);
+
+ if ((fsv.GetUseCount() == 0) || (fsv.GetNode() == nullptr))
+ {
+ JITDUMP(" no next stmt use\n");
+ return false;
+ }
+
+ JITDUMP(" [%06u] is only use of [%06u] (V%02u) ", dspTreeID(fsv.GetNode()), dspTreeID(lhsNode), lclNum);
+
+ // If next statement already has a large tree, hold off
+ // on making it even larger.
+ //
+ // We use total node count. Consider instead using the depth of the use and the
+ // height of the fwdSubNode.
+ //
+ unsigned const nextTreeLimit = 200;
+ if ((fsv.GetComplexity() > nextTreeLimit) && gtComplexityExceeds(&fwdSubNode, 1))
+ {
+ JITDUMP(" next stmt tree is too large (%u)\n", fsv.GetComplexity());
+ return false;
+ }
+
+ // Next statement seems suitable.
+ // See if we can forward sub without changing semantics.
+ //
+ GenTree* const nextRootNode = nextStmt->GetRootNode();
+
+ // Bail if types disagree.
+ // Might be able to tolerate these by retyping.
+ //
+ if (fsv.GetNode()->TypeGet() != fwdSubNode->TypeGet())
+ {
+ JITDUMP(" mismatched types (substitution)\n");
+ return false;
+ }
+
+ // We can forward sub if
+ //
+ // the value of the fwdSubNode can't change and its evaluation won't cause side effects,
+ //
+ // or,
+ //
+ // if the next tree can't change the value of fwdSubNode or be impacted by fwdSubNode effects
+ //
+ const bool fwdSubNodeInvariant = ((fwdSubNode->gtFlags & GTF_ALL_EFFECT) == 0);
+ const bool nextTreeIsPureUpToUse = ((fsv.GetFlags() & (GTF_EXCEPT | GTF_GLOB_REF | GTF_CALL)) == 0);
+ if (!fwdSubNodeInvariant && !nextTreeIsPureUpToUse)
+ {
+ // Fwd sub may impact global values and or reorder exceptions...
+ //
+ JITDUMP(" potentially interacting effects\n");
+ return false;
+ }
+
+ // If we're relying on purity of fwdSubNode for legality of forward sub,
+ // do some extra checks for global uses that might not be reflected in the flags.
+ //
+ // TODO: remove this once we can trust upstream phases and/or gtUpdateStmtSideEffects
+ // to set GTF_GLOB_REF properly.
+ //
+ if (fwdSubNodeInvariant && ((fsv.GetFlags() & (GTF_CALL | GTF_ASG)) != 0))
+ {
+ EffectsVisitor ev(this);
+ ev.WalkTree(&fwdSubNode, nullptr);
+
+ if ((ev.GetFlags() & GTF_GLOB_REF) != 0)
+ {
+ JITDUMP(" potentially interacting effects (AX locals)\n");
+ return false;
+ }
+ }
+
+ // Finally, profitability checks.
+ //
+ // These conditions can be checked earlier in the final version to save some throughput.
+ // Perhaps allowing for bypass with jit stress.
+ //
+ // If fwdSubNode is an address-exposed local, forwarding it may lose optimizations.
+ // (maybe similar for dner?)
+ //
+ if (fwdSubNode->OperIs(GT_LCL_VAR))
+ {
+ unsigned const fwdLclNum = fwdSubNode->AsLclVarCommon()->GetLclNum();
+ LclVarDsc* const fwdVarDsc = lvaGetDesc(fwdLclNum);
+
+ if (fwdVarDsc->IsAddressExposed())
+ {
+ JITDUMP(" V%02u is address exposed\n", fwdLclNum);
+ return false;
+ }
+ }
+
+ // Optimization:
+ //
+ // If we are about to substitute GT_OBJ, see if we can simplify it first.
+ // Not doing so can lead to regressions...
+ //
+ // Hold off on doing this for call args for now (per issue #51569).
+ //
+ if (fwdSubNode->OperIs(GT_OBJ) && !fsv.IsCallArg())
+ {
+ const bool destroyNodes = false;
+ GenTree* const optTree = fgMorphTryFoldObjAsLclVar(fwdSubNode->AsObj(), destroyNodes);
+ if (optTree != nullptr)
+ {
+ JITDUMP(" [folding OBJ(ADDR(LCL...))]");
+ fwdSubNode = optTree;
+ }
+ }
+
+ // Quirks:
+ //
+ // We may sometimes lose or change a type handle. Avoid substituting if so.
+ //
+ if (gtGetStructHandleIfPresent(fwdSubNode) != gtGetStructHandleIfPresent(fsv.GetNode()))
+ {
+ JITDUMP(" would change struct handle (substitution)\n");
+ return false;
+ }
+
+#ifdef FEATURE_SIMD
+ // Don't forward sub a SIMD call under a HW intrinsic node.
+ // LowerCallStruct is not prepared for this.
+ //
+ if (fwdSubNode->IsCall() && varTypeIsSIMD(fwdSubNode->TypeGet()) && fsv.GetParentNode()->OperIs(GT_HWINTRINSIC))
+ {
+ JITDUMP(" simd returning call; hw intrinsic\n");
+ return false;
+ }
+#endif // FEATURE_SIMD
+
+ // There are implicit assumptions downstream on where/how multi-reg ops
+ // can appear.
+ //
+ // Eg if fwdSubNode is a multi-reg call, parent node must be GT_ASG and the
+ // local being defined must be specially marked up.
+ //
+ if (fwdSubNode->IsMultiRegCall())
+ {
+ GenTree* const parentNode = fsv.GetParentNode();
+
+ if (!parentNode->OperIs(GT_ASG))
+ {
+ JITDUMP(" multi-reg call, parent not asg\n");
+ return false;
+ }
+
+ GenTree* const parentNodeLHS = parentNode->gtGetOp1();
+
+ if (!parentNodeLHS->OperIs(GT_LCL_VAR))
+ {
+ JITDUMP(" multi-reg call, parent not asg(lcl, ...)\n");
+ return false;
+ }
+
+#if defined(TARGET_X86) || defined(TARGET_ARM)
+ if (fwdSubNode->TypeGet() == TYP_LONG)
+ {
+ JITDUMP(" TYP_LONG fwd sub node, target is x86/arm\n");
+ return false;
+ }
+#endif // defined(TARGET_X86) || defined(TARGET_ARM)
+
+ GenTreeLclVar* const parentNodeLHSLocal = parentNodeLHS->AsLclVar();
+
+ unsigned const lhsLclNum = parentNodeLHSLocal->GetLclNum();
+ LclVarDsc* const lhsVarDsc = lvaGetDesc(lhsLclNum);
+
+ JITDUMP(" [marking V%02u as multi-reg-ret]", lhsLclNum);
+ lhsVarDsc->lvIsMultiRegRet = true;
+ parentNodeLHSLocal->SetMultiReg();
+ }
+
+ // If a method returns a multi-reg type, only forward sub locals,
+ // and ensure the local and operand have the required markup.
+ //
+ // (see eg impFixupStructReturnType)
+ //
+ if (compMethodReturnsMultiRegRetType() && fsv.GetParentNode()->OperIs(GT_RETURN))
+ {
+ if (!fwdSubNode->OperIs(GT_LCL_VAR))
+ {
+ JITDUMP(" parent is return, fwd sub node is not lcl var\n");
+ return false;
+ }
+
+#if defined(TARGET_X86) || defined(TARGET_ARM)
+ if (fwdSubNode->TypeGet() == TYP_LONG)
+ {
+ JITDUMP(" TYP_LONG fwd sub node, target is x86/arm\n");
+ return false;
+ }
+#endif // defined(TARGET_X86) || defined(TARGET_ARM)
+
+ GenTreeLclVar* const fwdSubNodeLocal = fwdSubNode->AsLclVar();
+
+ unsigned const fwdLclNum = fwdSubNodeLocal->GetLclNum();
+ LclVarDsc* const fwdVarDsc = lvaGetDesc(fwdLclNum);
+
+ JITDUMP(" [marking V%02u as multi-reg-ret]", fwdLclNum);
+ fwdVarDsc->lvIsMultiRegRet = true;
+ fwdSubNodeLocal->SetMultiReg();
+ fwdSubNodeLocal->gtFlags |= GTF_DONT_CSE;
+ }
+
+ // If the use is a multi-reg arg, don't forward sub non-locals.
+ //
+ if (fsv.GetNode()->IsMultiRegNode() && !fwdSubNode->IsMultiRegNode())
+ {
+ JITDUMP(" would change multi-reg (substitution)\n");
+ return false;
+ }
+
+ // If the intial has truncate on store semantics, we need to replicate
+ // that here with a cast.
+ //
+ if (varDsc->lvNormalizeOnStore() && fgCastNeeded(fwdSubNode, varDsc->TypeGet()))
+ {
+ JITDUMP(" [adding cast for normalize on store]");
+ fwdSubNode = gtNewCastNode(TYP_INT, fwdSubNode, false, varDsc->TypeGet());
+ }
+
+ // Looks good, forward sub!
+ //
+ GenTree** use = fsv.GetUse();
+ *use = fwdSubNode;
+
+ if (!fwdSubNodeInvariant)
+ {
+ gtUpdateStmtSideEffects(nextStmt);
+ }
+
+ JITDUMP(" -- fwd subbing [%06u]; new next stmt is\n", dspTreeID(fwdSubNode));
+ DISPSTMT(nextStmt);
+
+ return true;
+}
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 35b9d2d829ca42..1b99f5171cef08 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -2415,8 +2415,9 @@ unsigned Compiler::gtSetMultiOpOrder(GenTreeMultiOp* multiOp)
costEx = IND_COST_EX;
costSz = 2;
- GenTree* addr = hwTree->Op(1)->gtEffectiveVal();
- level = gtSetEvalOrder(addr);
+ GenTree* const addrNode = hwTree->Op(1);
+ level = gtSetEvalOrder(addrNode);
+ GenTree* const addr = addrNode->gtEffectiveVal();
// See if we can form a complex addressing mode.
if (addr->OperIs(GT_ADD) && gtMarkAddrMode(addr, &costEx, &costSz, hwTree->TypeGet()))
@@ -5793,6 +5794,12 @@ GenTree* Compiler::gtNewStringLiteralNode(InfoAccessType iat, void* pValue)
//
GenTreeIntCon* Compiler::gtNewStringLiteralLength(GenTreeStrCon* node)
{
+ if (node->IsStringEmptyField())
+ {
+ JITDUMP("Folded String.Empty.Length to 0\n");
+ return gtNewIconNode(0);
+ }
+
int length = -1;
const char16_t* str = info.compCompHnd->getStringLiteral(node->gtScpHnd, node->gtSconCPX, &length);
if (length >= 0)
@@ -5802,11 +5809,11 @@ GenTreeIntCon* Compiler::gtNewStringLiteralLength(GenTreeStrCon* node)
// str can be NULL for dynamic context
if (str != nullptr)
{
- JITDUMP("String '\"%ws\".Length' is '%d'\n", str, length)
+ JITDUMP("Folded '\"%ws\".Length' to '%d'\n", str, length)
}
else
{
- JITDUMP("String 'CNS_STR.Length' is '%d'\n", length)
+ JITDUMP("Folded 'CNS_STR.Length' to '%d'\n", length)
}
return iconNode;
}
@@ -11685,11 +11692,34 @@ GenTree* Compiler::gtFoldExprCompare(GenTree* tree)
return tree;
}
- /* Currently we can only fold when the two subtrees exactly match */
+ // Currently we can only fold when the two subtrees exactly match
+ // and everything is side effect free.
+ //
+ if (((tree->gtFlags & GTF_SIDE_EFFECT) != 0) || !GenTree::Compare(op1, op2, true))
+ {
+ // No folding.
+ //
+ return tree;
+ }
- if ((tree->gtFlags & GTF_SIDE_EFFECT) || GenTree::Compare(op1, op2, true) == false)
+ // GTF_ORDER_SIDEEFF here may indicate volatile subtrees.
+ // Or it may indicate a non-null assertion prop into an indir subtree.
+ //
+ // Check the operands.
+ //
+ if ((tree->gtFlags & GTF_ORDER_SIDEEFF) != 0)
{
- return tree; /* return unfolded tree */
+ // If op1 is "volatle" and op2 is not, we can still fold.
+ //
+ const bool op1MayBeVolatile = (op1->gtFlags & GTF_ORDER_SIDEEFF) != 0;
+ const bool op2MayBeVolatile = (op2->gtFlags & GTF_ORDER_SIDEEFF) != 0;
+
+ if (!op1MayBeVolatile || op2MayBeVolatile)
+ {
+ // No folding.
+ //
+ return tree;
+ }
}
GenTree* cons;
@@ -15917,6 +15947,9 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeqNode** pF
// will effectively treat such cases ("possible" in unsafe code) as undefined behavior.
if (comp->eeIsFieldStatic(fldSeq->GetFieldHandle()))
{
+ // TODO-VNTypes: this code is out of sync w.r.t. boxed statics that are numbered with
+ // VNF_PtrToStatic and treated as "simple" while here we treat them as "complex".
+
// 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.
diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h
index 085bc17a1e5107..b023c2bb8c52d4 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -3240,11 +3240,19 @@ struct GenTreeDblCon : public GenTree
/* gtStrCon -- string constant (GT_CNS_STR) */
+#define EMPTY_STRING_SCON (unsigned)-1
+
struct GenTreeStrCon : public GenTree
{
unsigned gtSconCPX;
CORINFO_MODULE_HANDLE gtScpHnd;
+ // Returns true if this GT_CNS_STR was imported for String.Empty field
+ bool IsStringEmptyField()
+ {
+ return gtSconCPX == EMPTY_STRING_SCON && gtScpHnd == nullptr;
+ }
+
// Because this node can come from an inlined method we need to
// have the scope handle, since it will become a helper call.
GenTreeStrCon(unsigned sconCPX, CORINFO_MODULE_HANDLE mod DEBUGARG(bool largeNode = false))
@@ -6420,7 +6428,6 @@ struct Statement
, m_lastILOffset(BAD_IL_OFFSET)
, m_stmtID(stmtID)
#endif
- , m_compilerAdded(false)
{
}
@@ -6507,16 +6514,6 @@ struct Statement
m_prev = prevStmt;
}
- bool IsCompilerAdded() const
- {
- return m_compilerAdded;
- }
-
- void SetCompilerAdded()
- {
- m_compilerAdded = true;
- }
-
bool IsPhiDefnStmt() const
{
return m_rootNode->IsPhiDefn();
@@ -6553,8 +6550,6 @@ struct Statement
IL_OFFSET m_lastILOffset; // The instr offset at the end of this statement.
unsigned m_stmtID;
#endif
-
- bool m_compilerAdded; // Was the statement created by optimizer?
};
// StatementList: adapter class for forward iteration of the statement linked list using range-based `for`,
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index b9cc2ff883d64a..ac361b08e8eb5f 100644
--- a/src/coreclr/jit/importer.cpp
+++ b/src/coreclr/jit/importer.cpp
@@ -8645,9 +8645,6 @@ var_types Compiler::impImportCall(OPCODE opcode,
opcodeNames[opcode], callInfo->kind, varTypeName(callRetTyp), structSize);
}
#endif
- // This should be checked in impImportBlockCode.
- assert(!compIsForInlining() || !(impInlineInfo->inlineCandidateInfo->dwRestrictions & INLINE_RESPECT_BOUNDARY));
-
sig = &calliSig;
}
else // (opcode != CEE_CALLI)
@@ -8677,14 +8674,6 @@ var_types Compiler::impImportCall(OPCODE opcode,
#endif
if (compIsForInlining())
{
- /* Does this call site have security boundary restrictions? */
-
- if (impInlineInfo->inlineCandidateInfo->dwRestrictions & INLINE_RESPECT_BOUNDARY)
- {
- compInlineResult->NoteFatal(InlineObservation::CALLSITE_CROSS_BOUNDARY_SECURITY);
- return TYP_UNDEF;
- }
-
/* Does the inlinee use StackCrawlMark */
if (mflags & CORINFO_FLG_DONT_INLINE_CALLER)
@@ -12216,20 +12205,9 @@ void Compiler::impImportBlockCode(BasicBlock* block)
break;
case CEE_LDSTR:
-
- if (compIsForInlining())
- {
- if (impInlineInfo->inlineCandidateInfo->dwRestrictions & INLINE_NO_CALLEE_LDSTR)
- {
- compInlineResult->NoteFatal(InlineObservation::CALLSITE_HAS_LDSTR_RESTRICTION);
- return;
- }
- }
-
val = getU4LittleEndian(codeAddr);
JITDUMP(" %08X", val);
impPushOnStack(gtNewSconNode(val, info.compScopeHnd), tiRetVal);
-
break;
case CEE_LDARG:
@@ -14460,16 +14438,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
eeGetCallInfo(&resolvedToken, nullptr /* constraint typeRef*/,
combine(CORINFO_CALLINFO_SECURITYCHECKS, CORINFO_CALLINFO_ALLOWINSTPARAM), &callInfo);
- if (compIsForInlining())
- {
- if (impInlineInfo->inlineCandidateInfo->dwRestrictions & INLINE_RESPECT_BOUNDARY)
- {
- // Check to see if this call violates the boundary.
- compInlineResult->NoteFatal(InlineObservation::CALLSITE_CROSS_BOUNDARY_SECURITY);
- return;
- }
- }
-
mflags = callInfo.methodFlags;
if ((mflags & (CORINFO_FLG_STATIC | CORINFO_FLG_ABSTRACT)) != 0)
@@ -14659,16 +14627,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
/* CALLI does not respond to CONSTRAINED */
prefixFlags &= ~PREFIX_CONSTRAINED;
- if (compIsForInlining())
- {
- // CALLI doesn't have a method handle, so assume the worst.
- if (impInlineInfo->inlineCandidateInfo->dwRestrictions & INLINE_RESPECT_BOUNDARY)
- {
- compInlineResult->NoteFatal(InlineObservation::CALLSITE_CROSS_BOUNDARY_CALLI);
- return;
- }
- }
-
FALLTHROUGH;
case CEE_CALLVIRT:
@@ -15115,9 +15073,8 @@ void Compiler::impImportBlockCode(BasicBlock* block)
{
assert(aflags & CORINFO_ACCESS_GET);
- LPVOID pValue;
- InfoAccessType iat = info.compCompHnd->emptyStringLiteral(&pValue);
- op1 = gtNewStringLiteralNode(iat, pValue);
+ // Import String.Empty as "" (GT_CNS_STR with a fake SconCPX = 0)
+ op1 = gtNewSconNode(EMPTY_STRING_SCON, nullptr);
goto FIELD_DONE;
}
break;
@@ -19063,7 +19020,6 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
bool success = eeRunWithErrorTrap(
[](Param* pParam) {
- uint32_t dwRestrictions = 0;
CorInfoInitClassResult initClassResult;
#ifdef DEBUG
@@ -19119,8 +19075,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
/* VM Inline check also ensures that the method is verifiable if needed */
CorInfoInline vmResult;
- vmResult = pParam->pThis->info.compCompHnd->canInline(pParam->pThis->info.compMethodHnd, pParam->fncHandle,
- &dwRestrictions);
+ vmResult = pParam->pThis->info.compCompHnd->canInline(pParam->pThis->info.compMethodHnd, pParam->fncHandle);
if (vmResult == INLINE_FAIL)
{
@@ -19138,21 +19093,6 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
goto _exit;
}
- // check for unsupported inlining restrictions
- assert((dwRestrictions & ~(INLINE_RESPECT_BOUNDARY | INLINE_NO_CALLEE_LDSTR | INLINE_SAME_THIS)) == 0);
-
- if (dwRestrictions & INLINE_SAME_THIS)
- {
- GenTree* thisArg = pParam->call->AsCall()->gtCallThisArg->GetNode();
- assert(thisArg);
-
- if (!pParam->pThis->impIsThis(thisArg))
- {
- pParam->result->NoteFatal(InlineObservation::CALLSITE_REQUIRES_SAME_THIS);
- goto _exit;
- }
- }
-
/* Get the method properties */
CORINFO_CLASS_HANDLE clsHandle;
@@ -19204,7 +19144,6 @@ void Compiler::impCheckCanInline(GenTreeCall* call,
pInfo->clsHandle = clsHandle;
pInfo->exactContextHnd = pParam->exactContextHnd;
pInfo->retExpr = nullptr;
- pInfo->dwRestrictions = dwRestrictions;
pInfo->preexistingSpillTemp = BAD_VAR_NUM;
pInfo->clsAttr = clsAttr;
pInfo->methAttr = pParam->methAttr;
diff --git a/src/coreclr/jit/inline.def b/src/coreclr/jit/inline.def
index a519471a3caec2..a4f84552edd98d 100644
--- a/src/coreclr/jit/inline.def
+++ b/src/coreclr/jit/inline.def
@@ -132,14 +132,11 @@ INLINE_OBSERVATION(CANT_EMBED_VARARGS_COOKIE, bool, "can't embed varargs cooki
INLINE_OBSERVATION(CANT_CLASS_INIT, bool, "can't class init", FATAL, CALLSITE)
INLINE_OBSERVATION(COMPILATION_ERROR, bool, "compilation error", FATAL, CALLSITE)
INLINE_OBSERVATION(COMPILATION_FAILURE, bool, "failed to compile", FATAL, CALLSITE)
-INLINE_OBSERVATION(CROSS_BOUNDARY_CALLI, bool, "cross-boundary calli", FATAL, CALLSITE)
-INLINE_OBSERVATION(CROSS_BOUNDARY_SECURITY, bool, "cross-boundary security check", FATAL, CALLSITE)
INLINE_OBSERVATION(EXCEEDS_THRESHOLD, bool, "exceeds profit threshold", FATAL, CALLSITE)
INLINE_OBSERVATION(EXPLICIT_TAIL_PREFIX, bool, "explicit tail prefix", FATAL, CALLSITE)
INLINE_OBSERVATION(GENERIC_DICTIONARY_LOOKUP, bool, "runtime dictionary lookup", FATAL, CALLSITE)
INLINE_OBSERVATION(HAS_CALL_VIA_LDVIRTFTN, bool, "call via ldvirtftn", FATAL, CALLSITE)
INLINE_OBSERVATION(HAS_COMPLEX_HANDLE, bool, "complex handle access", FATAL, CALLSITE)
-INLINE_OBSERVATION(HAS_LDSTR_RESTRICTION, bool, "has ldstr VM restriction", FATAL, CALLSITE)
INLINE_OBSERVATION(IMPLICIT_REC_TAIL_CALL, bool, "implicit recursive tail call", FATAL, CALLSITE)
INLINE_OBSERVATION(IS_CALL_TO_HELPER, bool, "target is helper", FATAL, CALLSITE)
INLINE_OBSERVATION(IS_NOT_DIRECT, bool, "target not direct", FATAL, CALLSITE)
@@ -162,7 +159,6 @@ INLINE_OBSERVATION(OVER_BUDGET, bool, "inline exceeds budget",
INLINE_OBSERVATION(OVER_INLINE_LIMIT, bool, "limited by JitInlineLimit", FATAL, CALLSITE)
INLINE_OBSERVATION(PIN_IN_TRY_REGION, bool, "within try region, pinned", FATAL, CALLSITE)
INLINE_OBSERVATION(RANDOM_REJECT, bool, "random reject", FATAL, CALLSITE)
-INLINE_OBSERVATION(REQUIRES_SAME_THIS, bool, "requires same this", FATAL, CALLSITE)
INLINE_OBSERVATION(RETURN_TYPE_MISMATCH, bool, "return type mismatch", FATAL, CALLSITE)
INLINE_OBSERVATION(STFLD_NEEDS_HELPER, bool, "stfld needs helper", FATAL, CALLSITE)
INLINE_OBSERVATION(TOO_MANY_LOCALS, bool, "too many locals", FATAL, CALLSITE)
diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h
index 9eacfb34a15138..7182bdf78fa92a 100644
--- a/src/coreclr/jit/inline.h
+++ b/src/coreclr/jit/inline.h
@@ -581,7 +581,6 @@ struct InlineCandidateInfo : public GuardedDevirtualizationCandidateInfo
CORINFO_CLASS_HANDLE clsHandle;
CORINFO_CONTEXT_HANDLE exactContextHnd;
GenTree* retExpr;
- DWORD dwRestrictions;
unsigned preexistingSpillTemp;
unsigned clsAttr;
unsigned methAttr;
diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp
index 1cbe07cb69b1c3..e0ecfeab9f0847 100644
--- a/src/coreclr/jit/instr.cpp
+++ b/src/coreclr/jit/instr.cpp
@@ -2159,8 +2159,10 @@ void CodeGen::instGen_Set_Reg_To_Zero(emitAttr size, regNumber reg, insFlags fla
{
#if defined(TARGET_XARCH)
GetEmitter()->emitIns_R_R(INS_xor, size, reg, reg);
-#elif defined(TARGET_ARMARCH)
+#elif defined(TARGET_ARM)
GetEmitter()->emitIns_R_I(INS_mov, size, reg, 0 ARM_ARG(flags));
+#elif defined(TARGET_ARM64)
+ GetEmitter()->emitIns_Mov(INS_mov, size, reg, REG_ZR, /* canSkip */ true);
#else
#error "Unknown TARGET"
#endif
diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h
index 08d4c4a8c8675d..abb2ac86ef99cb 100644
--- a/src/coreclr/jit/instrsxarch.h
+++ b/src/coreclr/jit/instrsxarch.h
@@ -592,7 +592,7 @@ INST3(LAST_AVXVNNI_INSTRUCTION, "LAST_AVXVNNI_INSTRUCTION", IUM_WR, BAD_CODE, BA
// BMI1
INST3(FIRST_BMI_INSTRUCTION, "FIRST_BMI_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_FLAGS_None)
-INST3(andn, "andn", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF2), INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND NOT
+INST3(andn, "andn", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF2), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Resets_CF | 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), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Reset Lowest Set Bit
diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h
index 1346c2069da170..b53588a6937217 100644
--- a/src/coreclr/jit/jitconfigvalues.h
+++ b/src/coreclr/jit/jitconfigvalues.h
@@ -118,6 +118,7 @@ CONFIG_INTEGER(JitNoCSE2, W("JitNoCSE2"), 0)
CONFIG_INTEGER(JitNoForceFallback, W("JitNoForceFallback"), 0) // Set to non-zero to prevent NOWAY assert testing.
// Overrides COMPlus_JitForceFallback and JIT stress
// flags.
+CONFIG_INTEGER(JitNoForwardSub, W("JitNoForwardSub"), 0) // Disables forward sub
CONFIG_INTEGER(JitNoHoist, W("JitNoHoist"), 0)
CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) // Disables inlining of all methods
CONFIG_INTEGER(JitNoMemoryBarriers, W("JitNoMemoryBarriers"), 0) // If 1, don't generate memory barriers
diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp
index 66684e38e1a3bb..999a904c3b338f 100644
--- a/src/coreclr/jit/lclmorph.cpp
+++ b/src/coreclr/jit/lclmorph.cpp
@@ -442,14 +442,15 @@ class LocalAddressVisitor final : public GenTreeVisitor
#endif // DEBUG
}
- // Morph promoted struct fields and count implicit byref argument occurrences.
+ // Morph promoted struct fields and count local occurrences.
+ //
// Also create and push the value produced by the visited node. This is done here
// rather than in PostOrderVisit because it makes it easy to handle nodes with an
// arbitrary number of operands - just pop values until the value corresponding
// to the visited node is encountered.
fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
{
- GenTree* node = *use;
+ GenTree* const node = *use;
if (node->OperIs(GT_FIELD))
{
@@ -462,19 +463,29 @@ class LocalAddressVisitor final : public GenTreeVisitor
if (node->OperIsLocal())
{
- unsigned lclNum = node->AsLclVarCommon()->GetLclNum();
+ unsigned const lclNum = node->AsLclVarCommon()->GetLclNum();
+ LclVarDsc* const varDsc = m_compiler->lvaGetDesc(lclNum);
+
+ UpdateEarlyRefCount(lclNum);
- LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum);
if (varDsc->lvIsStructField)
{
- // Promoted field, increase counter for the parent lclVar.
+ // Promoted field, increase count for the parent lclVar.
+ //
assert(!m_compiler->lvaIsImplicitByRefLocal(lclNum));
unsigned parentLclNum = varDsc->lvParentLcl;
- UpdateEarlyRefCountForImplicitByRef(parentLclNum);
+ UpdateEarlyRefCount(parentLclNum);
}
- else
+
+ if (varDsc->lvPromoted)
{
- UpdateEarlyRefCountForImplicitByRef(lclNum);
+ // Promoted struct, increase count for each promoted field.
+ //
+ for (unsigned childLclNum = varDsc->lvFieldLclStart;
+ childLclNum < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++childLclNum)
+ {
+ UpdateEarlyRefCount(childLclNum);
+ }
}
}
@@ -1162,7 +1173,7 @@ class LocalAddressVisitor final : public GenTreeVisitor
}
//------------------------------------------------------------------------
- // UpdateEarlyRefCountForImplicitByRef: updates the ref count for implicit byref params.
+ // UpdateEarlyRefCount: updates the ref count for locals
//
// Arguments:
// lclNum - the local number to update the count for.
@@ -1171,19 +1182,24 @@ class LocalAddressVisitor final : public GenTreeVisitor
// fgMakeOutgoingStructArgCopy checks the ref counts for implicit byref params when it decides
// if it's legal to elide certain copies of them;
// fgRetypeImplicitByRefArgs checks the ref counts when it decides to undo promotions.
+ // fgForwardSub uses ref counts to decide when to forward sub.
//
- void UpdateEarlyRefCountForImplicitByRef(unsigned lclNum)
+ void UpdateEarlyRefCount(unsigned lclNum)
{
+ LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum);
+
+ // Note we don't need accurate counts when the values are large.
+ //
+ if (varDsc->lvRefCnt(RCS_EARLY) < USHRT_MAX)
+ {
+ varDsc->incLvRefCnt(1, RCS_EARLY);
+ }
+
if (!m_compiler->lvaIsImplicitByRefLocal(lclNum))
{
return;
}
- LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum);
- JITDUMP("LocalAddressVisitor incrementing ref count from %d to %d for implicit by-ref V%02d\n",
- varDsc->lvRefCnt(RCS_EARLY), varDsc->lvRefCnt(RCS_EARLY) + 1, lclNum);
- varDsc->incLvRefCnt(1, RCS_EARLY);
-
// See if this struct is an argument to a call. This information is recorded
// via the weighted early ref count for the local, and feeds the undo promotion
// heuristic.
diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp
index 81d03b93f7b347..2f5b762214ef17 100644
--- a/src/coreclr/jit/lir.cpp
+++ b/src/coreclr/jit/lir.cpp
@@ -1338,7 +1338,10 @@ class CheckLclVarSemanticsHelper
CheckLclVarSemanticsHelper(Compiler* compiler,
const LIR::Range* range,
SmallHashTable& unusedDefs)
- : compiler(compiler), range(range), unusedDefs(unusedDefs), unusedLclVarReads(compiler->getAllocator())
+ : compiler(compiler)
+ , range(range)
+ , unusedDefs(unusedDefs)
+ , unusedLclVarReads(compiler->getAllocator(CMK_DebugOnly))
{
}
@@ -1358,13 +1361,45 @@ class CheckLclVarSemanticsHelper
AliasSet::NodeInfo nodeInfo(compiler, node);
if (nodeInfo.IsLclVarRead() && !unusedDefs.Contains(node))
{
- int count = 0;
- unusedLclVarReads.TryGetValue(nodeInfo.LclNum(), &count);
- unusedLclVarReads.AddOrUpdate(nodeInfo.LclNum(), count + 1);
+ jitstd::list* reads;
+ if (!unusedLclVarReads.TryGetValue(nodeInfo.LclNum(), &reads))
+ {
+ reads = new (compiler, CMK_DebugOnly) jitstd::list(compiler->getAllocator(CMK_DebugOnly));
+ unusedLclVarReads.AddOrUpdate(nodeInfo.LclNum(), reads);
+ }
+
+ reads->push_back(node);
}
- // If this node is a lclVar write, it must be to a lclVar that does not have an outstanding read.
- assert(!nodeInfo.IsLclVarWrite() || !unusedLclVarReads.Contains(nodeInfo.LclNum()));
+ if (nodeInfo.IsLclVarWrite())
+ {
+ // If this node is a lclVar write, it must be not alias a lclVar with an outstanding read
+ jitstd::list* reads;
+ if (unusedLclVarReads.TryGetValue(nodeInfo.LclNum(), &reads))
+ {
+ for (GenTree* read : *reads)
+ {
+ AliasSet::NodeInfo readInfo(compiler, read);
+ assert(readInfo.IsLclVarRead() && readInfo.LclNum() == nodeInfo.LclNum());
+ unsigned readStart = readInfo.LclOffs();
+ unsigned readEnd = readStart + genTypeSize(read->TypeGet());
+ unsigned writeStart = nodeInfo.LclOffs();
+ unsigned writeEnd = writeStart + genTypeSize(node->TypeGet());
+ if ((readEnd > writeStart) && (writeEnd > readStart))
+ {
+ JITDUMP(
+ "Write to unaliased local overlaps outstanding read (write: %u..%u, read: %u..%u)\n",
+ writeStart, writeEnd, readStart, readEnd);
+ JITDUMP("Read:\n");
+ DISPTREERANGE(const_cast(*range), read);
+ JITDUMP("Write:\n");
+ DISPTREERANGE(const_cast(*range), node);
+ assert(!"Write to unaliased local overlaps outstanding read");
+ break;
+ }
+ }
+ }
+ }
}
return true;
@@ -1393,14 +1428,22 @@ class CheckLclVarSemanticsHelper
AliasSet::NodeInfo operandInfo(compiler, operand);
if (operandInfo.IsLclVarRead())
{
- int count;
- const bool removed = unusedLclVarReads.TryRemove(operandInfo.LclNum(), &count);
- assert(removed);
+ jitstd::list* reads;
+ const bool foundList = unusedLclVarReads.TryGetValue(operandInfo.LclNum(), &reads);
+ assert(foundList);
- if (count > 1)
+ bool found = false;
+ for (jitstd::list::iterator it = reads->begin(); it != reads->end(); ++it)
{
- unusedLclVarReads.AddOrUpdate(operandInfo.LclNum(), count - 1);
+ if (*it == operand)
+ {
+ reads->erase(it);
+ found = true;
+ break;
+ }
}
+
+ assert(found || !"Could not find consumed local in unusedLclVarReads");
}
}
}
@@ -1408,8 +1451,8 @@ class CheckLclVarSemanticsHelper
private:
Compiler* compiler;
const LIR::Range* range;
- SmallHashTable& unusedDefs;
- SmallHashTable unusedLclVarReads;
+ SmallHashTable& unusedDefs;
+ SmallHashTable*, 16U> unusedLclVarReads;
};
//------------------------------------------------------------------------
diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index b111d73db6a995..2697a9892dca3b 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 LowerBinaryArithmeticCommon(node->AsOp());
+ return LowerBinaryArithmetic(node->AsOp());
case GT_MUL:
case GT_MULHI:
@@ -5133,53 +5133,6 @@ GenTree* Lowering::LowerAdd(GenTreeOp* node)
return nullptr;
}
-//------------------------------------------------------------------------
-// LowerBinaryArithmeticCommon: lowers the given binary arithmetic node.
-//
-// Recognizes opportunities for using target-independent "combined" nodes
-// (currently AND_NOT on ARMArch). Performs containment checks.
-//
-// Arguments:
-// node - the arithmetic node to lower
-//
-// Returns:
-// The next node to lower.
-//
-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() && binOp->OperIs(GT_AND))
- {
- GenTree* opNode = nullptr;
- GenTree* notNode = nullptr;
- if (binOp->gtGetOp1()->OperIs(GT_NOT))
- {
- notNode = binOp->gtGetOp1();
- opNode = binOp->gtGetOp2();
- }
- else if (binOp->gtGetOp2()->OperIs(GT_NOT))
- {
- notNode = binOp->gtGetOp2();
- opNode = binOp->gtGetOp1();
- }
-
- if (notNode != nullptr)
- {
- binOp->gtOp1 = opNode;
- binOp->gtOp2 = notNode->AsUnOp()->gtGetOp1();
- binOp->ChangeOper(GT_AND_NOT);
- BlockRange().Remove(notNode);
- }
- }
-#endif
-
- return LowerBinaryArithmetic(binOp);
-}
-
//------------------------------------------------------------------------
// LowerUnsignedDivOrMod: Lowers a GT_UDIV/GT_UMOD node.
//
diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h
index 95843b6bded47e..b6a6c178f7e544 100644
--- a/src/coreclr/jit/lower.h
+++ b/src/coreclr/jit/lower.h
@@ -297,7 +297,6 @@ class Lowering final : public Phase
void LowerStoreIndir(GenTreeStoreInd* node);
GenTree* LowerAdd(GenTreeOp* node);
GenTree* LowerMul(GenTreeOp* mul);
- GenTree* LowerBinaryArithmeticCommon(GenTreeOp* binOp);
GenTree* LowerBinaryArithmetic(GenTreeOp* binOp);
bool LowerUnsignedDivOrMod(GenTreeOp* divMod);
GenTree* LowerConstIntDivOrMod(GenTree* node);
@@ -344,7 +343,8 @@ class Lowering final : public Phase
void LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node);
void LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node);
void LowerHWIntrinsicWithElement(GenTreeHWIntrinsic* node);
- GenTree* TryLowerAndOpToResetLowestSetBit(GenTreeOp* binOp);
+ GenTree* TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode);
+ GenTree* TryLowerAndOpToAndNot(GenTreeOp* andNode);
#elif defined(TARGET_ARM64)
bool IsValidConstForMovImm(GenTreeHWIntrinsic* node);
void LowerHWIntrinsicFusedMultiplyAddScalar(GenTreeHWIntrinsic* node);
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index 67e1269dfd429a..41b80fbee67233 100644
--- a/src/coreclr/jit/lowerarmarch.cpp
+++ b/src/coreclr/jit/lowerarmarch.cpp
@@ -292,6 +292,30 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul)
//
GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp)
{
+ if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND))
+ {
+ GenTree* opNode = nullptr;
+ GenTree* notNode = nullptr;
+ if (binOp->gtGetOp1()->OperIs(GT_NOT))
+ {
+ notNode = binOp->gtGetOp1();
+ opNode = binOp->gtGetOp2();
+ }
+ else if (binOp->gtGetOp2()->OperIs(GT_NOT))
+ {
+ notNode = binOp->gtGetOp2();
+ opNode = binOp->gtGetOp1();
+ }
+
+ if (notNode != nullptr)
+ {
+ binOp->gtOp1 = opNode;
+ binOp->gtOp2 = notNode->AsUnOp()->gtGetOp1();
+ binOp->ChangeOper(GT_AND_NOT);
+ BlockRange().Remove(notNode);
+ }
+ }
+
ContainCheckBinary(binOp);
return binOp->gtNext;
diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp
index 37459907558a0b..266d642014fd02 100644
--- a/src/coreclr/jit/lowerxarch.cpp
+++ b/src/coreclr/jit/lowerxarch.cpp
@@ -162,6 +162,9 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul)
//------------------------------------------------------------------------
// LowerBinaryArithmetic: lowers the given binary arithmetic node.
//
+// Recognizes opportunities for using target-independent "combined" nodes
+// Performs containment checks.
+//
// Arguments:
// node - the arithmetic node to lower
//
@@ -173,10 +176,16 @@ 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)
+ GenTree* replacementNode = TryLowerAndOpToAndNot(binOp);
+ if (replacementNode != nullptr)
+ {
+ return replacementNode->gtNext;
+ }
+
+ replacementNode = TryLowerAndOpToResetLowestSetBit(binOp);
+ if (replacementNode != nullptr)
{
- return blsrNode->gtNext;
+ return replacementNode->gtNext;
}
}
#endif
@@ -3726,7 +3735,7 @@ void Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node)
}
//----------------------------------------------------------------------------------------------
-// Lowering::TryLowerAndOpToResetLowestSetBit: Lowers a tree AND(X, ADD(X, -1) to HWIntrinsic::ResetLowestSetBit
+// Lowering::TryLowerAndOpToResetLowestSetBit: Lowers a tree AND(X, ADD(X, -1)) to HWIntrinsic::ResetLowestSetBit
//
// Arguments:
// andNode - GT_AND node of integral type
@@ -3734,6 +3743,8 @@ void Lowering::LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node)
// Return Value:
// Returns the replacement node if one is created else nullptr indicating no replacement
//
+// Notes:
+// Performs containment checks on the replacement node if one is created
GenTree* Lowering::TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode)
{
assert(andNode->OperIs(GT_AND) && varTypeIsIntegral(andNode));
@@ -3802,6 +3813,86 @@ GenTree* Lowering::TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode)
return blsrNode;
}
+//----------------------------------------------------------------------------------------------
+// Lowering::TryLowerAndOpToAndNot: Lowers a tree AND(X, NOT(Y)) to HWIntrinsic::AndNot
+//
+// Arguments:
+// andNode - GT_AND node of integral type
+//
+// Return Value:
+// Returns the replacement node if one is created else nullptr indicating no replacement
+//
+// Notes:
+// Performs containment checks on the replacement node if one is created
+GenTree* Lowering::TryLowerAndOpToAndNot(GenTreeOp* andNode)
+{
+ assert(andNode->OperIs(GT_AND) && varTypeIsIntegral(andNode));
+
+ GenTree* opNode = nullptr;
+ GenTree* notNode = nullptr;
+ if (andNode->gtGetOp1()->OperIs(GT_NOT))
+ {
+ notNode = andNode->gtGetOp1();
+ opNode = andNode->gtGetOp2();
+ }
+ else if (andNode->gtGetOp2()->OperIs(GT_NOT))
+ {
+ notNode = andNode->gtGetOp2();
+ opNode = andNode->gtGetOp1();
+ }
+
+ if (opNode == nullptr)
+ {
+ return nullptr;
+ }
+
+ // We want to avoid using "andn" when one of the operands is both a source and the destination and is also coming
+ // from memory. In this scenario, we will get smaller and likely faster code by using the RMW encoding of `and`
+ if (IsBinOpInRMWStoreInd(andNode))
+ {
+ return nullptr;
+ }
+
+ NamedIntrinsic intrinsic;
+ if (andNode->TypeIs(TYP_LONG) && comp->compOpportunisticallyDependsOn(InstructionSet_BMI1_X64))
+ {
+ intrinsic = NamedIntrinsic::NI_BMI1_X64_AndNot;
+ }
+ else if (comp->compOpportunisticallyDependsOn(InstructionSet_BMI1))
+ {
+ intrinsic = NamedIntrinsic::NI_BMI1_AndNot;
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ LIR::Use use;
+ if (!BlockRange().TryGetUse(andNode, &use))
+ {
+ return nullptr;
+ }
+
+ // note that parameter order for andn is ~y, x so these are purposefully reversed when creating the node
+ GenTreeHWIntrinsic* andnNode =
+ comp->gtNewScalarHWIntrinsicNode(andNode->TypeGet(), notNode->AsUnOp()->gtGetOp1(), opNode, intrinsic);
+
+ JITDUMP("Lower: optimize AND(X, NOT(Y)))\n");
+ DISPNODE(andNode);
+ JITDUMP("to:\n");
+ DISPNODE(andnNode);
+
+ use.ReplaceWith(andnNode);
+
+ BlockRange().InsertBefore(andNode, andnNode);
+ BlockRange().Remove(andNode);
+ BlockRange().Remove(notNode);
+
+ ContainCheckHWIntrinsic(andnNode);
+
+ return andnNode;
+}
+
#endif // FEATURE_HW_INTRINSICS
//----------------------------------------------------------------------------------------------
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index f07fe3ca9ed02b..b3e9e8fa82977f 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -5184,7 +5184,9 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
noway_assert(elemTyp != TYP_STRUCT || elemStructType != nullptr);
// Fold "cns_str"[cns_index] to ushort constant
- if (opts.OptimizationEnabled() && asIndex->Arr()->OperIs(GT_CNS_STR) && asIndex->Index()->IsIntCnsFitsInI32())
+ // NOTE: don't do it for empty string, the operation will fail anyway
+ if (opts.OptimizationEnabled() && asIndex->Arr()->OperIs(GT_CNS_STR) &&
+ !asIndex->Arr()->AsStrCon()->IsStringEmptyField() && asIndex->Index()->IsIntCnsFitsInI32())
{
const int cnsIndex = static_cast(asIndex->Index()->AsIntConCommon()->IconValue());
if (cnsIndex >= 0)
@@ -6265,20 +6267,32 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
FieldSeqNode* fldSeq =
!isBoxedStatic ? GetFieldSeqStore()->CreateSingleton(symHnd) : FieldSeqStore::NotAField();
-#ifdef TARGET_64BIT
+ // TODO-CQ: enable this optimization for 32 bit targets.
bool isStaticReadOnlyInited = false;
- bool plsSpeculative = true;
- if (info.compCompHnd->getStaticFieldCurrentClass(symHnd, &plsSpeculative) != NO_CLASS_HANDLE)
+#ifdef TARGET_64BIT
+ if (tree->TypeIs(TYP_REF) && !isBoxedStatic)
{
- isStaticReadOnlyInited = !plsSpeculative;
+ bool pIsSpeculative = true;
+ if (info.compCompHnd->getStaticFieldCurrentClass(symHnd, &pIsSpeculative) != NO_CLASS_HANDLE)
+ {
+ isStaticReadOnlyInited = !pIsSpeculative;
+ }
}
+#endif // TARGET_64BIT
+
+ // TODO: choices made below have mostly historical reasons and
+ // should be unified to always use the IND() form.
+ CLANG_FORMAT_COMMENT_ANCHOR;
- // even if RelocTypeHint is REL32 let's still prefer IND over GT_CLS_VAR
- // for static readonly fields of statically initialized classes - thus we can
- // apply GTF_IND_INVARIANT flag and make it hoistable/CSE-friendly
- if (isStaticReadOnlyInited || (IMAGE_REL_BASED_REL32 != eeGetRelocTypeHint(fldAddr)))
+#ifdef TARGET_64BIT
+ bool preferIndir =
+ isBoxedStatic || isStaticReadOnlyInited || (IMAGE_REL_BASED_REL32 != eeGetRelocTypeHint(fldAddr));
+#else // !TARGET_64BIT
+ bool preferIndir = isBoxedStatic;
+#endif // !TARGET_64BIT
+
+ if (preferIndir)
{
- // The address is not directly addressible, so force it into a constant, so we handle it properly.
GenTreeFlags handleKind = GTF_EMPTY;
if (isBoxedStatic)
{
@@ -6321,7 +6335,6 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
return fgMorphSmpOp(tree);
}
else
-#endif // TARGET_64BIT
{
// Only volatile or classinit could be set, and they map over
noway_assert((tree->gtFlags & ~(GTF_FLD_VOLATILE | GTF_FLD_INITCLASS | GTF_COMMON_MASK)) == 0);
@@ -9422,11 +9435,18 @@ GenTree* Compiler::fgMorphConst(GenTree* tree)
tree->gtFlags &= ~(GTF_ALL_EFFECT | GTF_REVERSE_OPS);
- if (tree->OperGet() != GT_CNS_STR)
+ if (!tree->OperIs(GT_CNS_STR))
{
return tree;
}
+ if (tree->AsStrCon()->IsStringEmptyField())
+ {
+ LPVOID pValue;
+ InfoAccessType iat = info.compCompHnd->emptyStringLiteral(&pValue);
+ return fgMorphTree(gtNewStringLiteralNode(iat, pValue));
+ }
+
// TODO-CQ: Do this for compCurBB->isRunRarely(). Doing that currently will
// guarantee slow performance for that block. Instead cache the return value
// of CORINFO_HELP_STRCNS and go to cache first giving reasonable perf.
@@ -9482,6 +9502,7 @@ GenTree* Compiler::fgMorphConst(GenTree* tree)
//
// Arguments:
// obj - the obj node.
+// destroyNodes -- destroy nodes that are optimized away
//
// Return value:
// GenTreeLclVar if the obj can be replaced by it, null otherwise.
@@ -9492,7 +9513,7 @@ GenTree* Compiler::fgMorphConst(GenTree* tree)
// for some platforms does not expect struct `LCL_VAR` as a source, so
// it needs more work.
//
-GenTreeLclVar* Compiler::fgMorphTryFoldObjAsLclVar(GenTreeObj* obj)
+GenTreeLclVar* Compiler::fgMorphTryFoldObjAsLclVar(GenTreeObj* obj, bool destroyNodes)
{
if (opts.OptimizationEnabled())
{
@@ -9525,8 +9546,12 @@ GenTreeLclVar* Compiler::fgMorphTryFoldObjAsLclVar(GenTreeObj* obj)
lclVar->gtFlags &= ~GTF_DONT_CSE;
lclVar->gtFlags |= (obj->gtFlags & GTF_DONT_CSE);
- DEBUG_DESTROY_NODE(obj);
- DEBUG_DESTROY_NODE(addr);
+ if (destroyNodes)
+ {
+ DEBUG_DESTROY_NODE(obj);
+ DEBUG_DESTROY_NODE(addr);
+ }
+
return lclVar;
}
}
@@ -11535,6 +11560,24 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
case GT_PUTARG_TYPE:
return fgMorphTree(tree->AsUnOp()->gtGetOp1());
+ case GT_NULLCHECK:
+ {
+ op1 = tree->AsUnOp()->gtGetOp1();
+ if (op1->IsCall())
+ {
+ GenTreeCall* const call = op1->AsCall();
+ if (call->IsHelperCall() && s_helperCallProperties.NonNullReturn(eeGetHelperNum(call->gtCallMethHnd)))
+ {
+ JITDUMP("\nNULLCHECK on [%06u] will always succeed\n", dspTreeID(call));
+
+ // TODO: Can we also remove the call?
+ //
+ return fgMorphTree(call);
+ }
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp
index dd2f3a8246ede1..64b0675c045e1d 100644
--- a/src/coreclr/jit/optimizer.cpp
+++ b/src/coreclr/jit/optimizer.cpp
@@ -1159,7 +1159,7 @@ bool Compiler::optExtractInitTestIncr(
noway_assert(initStmt != nullptr && (initStmt->GetNextStmt() == nullptr));
// If it is a duplicated loop condition, skip it.
- if (initStmt->IsCompilerAdded())
+ if (initStmt->GetRootNode()->OperIs(GT_JTRUE))
{
bool doGetPrev = true;
#ifdef DEBUG
@@ -3771,10 +3771,9 @@ PhaseStatus Compiler::optUnrollLoops()
Statement* incrStmt = testStmt->GetPrevStmt();
noway_assert(incrStmt != nullptr);
- if (initStmt->IsCompilerAdded())
+ if (initStmt->GetRootNode()->OperIs(GT_JTRUE))
{
// Must be a duplicated loop condition.
- noway_assert(initStmt->GetRootNode()->gtOper == GT_JTRUE);
dupCond = true;
initStmt = initStmt->GetPrevStmt();
@@ -4601,8 +4600,6 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block)
{
clonedStmt->SetDebugInfo(stmt->GetDebugInfo());
}
-
- clonedStmt->SetCompilerAdded();
}
assert(foundCondTree);
@@ -5835,12 +5832,9 @@ void Compiler::optPerformHoistExpr(GenTree* origExpr, BasicBlock* exprBb, unsign
preHead->bbFlags |= (exprBb->bbFlags & (BBF_HAS_IDX_LEN | BBF_HAS_NULLCHECK));
Statement* hoistStmt = gtNewStmt(hoist);
- hoistStmt->SetCompilerAdded();
-
- /* simply append the statement at the end of the preHead's list */
+ // Simply append the statement at the end of the preHead's list.
Statement* firstStmt = preHead->firstStmt();
-
if (firstStmt != nullptr)
{
/* append after last statement */
diff --git a/src/coreclr/jit/phase.cpp b/src/coreclr/jit/phase.cpp
index 5f2e2172c6f4a5..8d002dfe08c614 100644
--- a/src/coreclr/jit/phase.cpp
+++ b/src/coreclr/jit/phase.cpp
@@ -180,6 +180,7 @@ void Phase::PostPhase(PhaseStatus status)
PHASE_MERGE_FINALLY_CHAINS,
PHASE_CLONE_FINALLY,
PHASE_MERGE_THROWS,
+ PHASE_FWD_SUB,
PHASE_MORPH_GLOBAL,
PHASE_INVERT_LOOPS,
PHASE_OPTIMIZE_LAYOUT,
diff --git a/src/coreclr/jit/sideeffects.cpp b/src/coreclr/jit/sideeffects.cpp
index b7c896d14098fd..fe6a8a7d6064c5 100644
--- a/src/coreclr/jit/sideeffects.cpp
+++ b/src/coreclr/jit/sideeffects.cpp
@@ -136,7 +136,7 @@ AliasSet::AliasSet()
// node - The node in question.
//
AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
- : m_compiler(compiler), m_node(node), m_flags(0), m_lclNum(0)
+ : m_compiler(compiler), m_node(node), m_flags(0), m_lclNum(0), m_lclOffs(0)
{
if (node->IsCall())
{
@@ -174,6 +174,7 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
bool isMemoryAccess = false;
bool isLclVarAccess = false;
unsigned lclNum = 0;
+ unsigned lclOffs = 0;
if (node->OperIsIndir())
{
// If the indirection targets a lclVar, we can be more precise with regards to aliasing by treating the
@@ -183,6 +184,7 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
{
isLclVarAccess = true;
lclNum = address->AsLclVarCommon()->GetLclNum();
+ lclOffs = address->AsLclVarCommon()->GetLclOffs();
}
else
{
@@ -197,6 +199,7 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
{
isLclVarAccess = true;
lclNum = node->AsLclVarCommon()->GetLclNum();
+ lclOffs = node->AsLclVarCommon()->GetLclOffs();
}
else
{
@@ -221,7 +224,8 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
if (isLclVarAccess)
{
m_flags |= ALIAS_READS_LCL_VAR;
- m_lclNum = lclNum;
+ m_lclNum = lclNum;
+ m_lclOffs = lclOffs;
}
}
else
@@ -234,7 +238,8 @@ AliasSet::NodeInfo::NodeInfo(Compiler* compiler, GenTree* node)
if (isLclVarAccess)
{
m_flags |= ALIAS_WRITES_LCL_VAR;
- m_lclNum = lclNum;
+ m_lclNum = lclNum;
+ m_lclOffs = lclOffs;
}
}
}
diff --git a/src/coreclr/jit/sideeffects.h b/src/coreclr/jit/sideeffects.h
index 8e2fe1cd788b4b..e7ffdb0a7311b8 100644
--- a/src/coreclr/jit/sideeffects.h
+++ b/src/coreclr/jit/sideeffects.h
@@ -72,6 +72,7 @@ class AliasSet final
GenTree* m_node;
unsigned m_flags;
unsigned m_lclNum;
+ unsigned m_lclOffs;
public:
NodeInfo(Compiler* compiler, GenTree* node);
@@ -112,6 +113,12 @@ class AliasSet final
return m_lclNum;
}
+ inline unsigned LclOffs() const
+ {
+ assert(IsLclVarRead() || IsLclVarWrite());
+ return m_lclOffs;
+ }
+
inline bool WritesAnyLocation() const
{
return (m_flags & (ALIAS_WRITES_ADDRESSABLE_LOCATION | ALIAS_WRITES_LCL_VAR)) != 0;
diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index 947f774fbdac05..4be6e1a93a4cdb 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -7802,8 +7802,24 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
GenTree* baseAddr = nullptr;
FieldSeqNode* fldSeq = nullptr;
+ if (argIsVNFunc && funcApp.m_func == VNF_PtrToStatic)
+ {
+ FieldSeqNode* fldSeq = vnStore->FieldSeqVNToFieldSeq(funcApp.m_args[1]);
+ assert(fldSeq != nullptr); // We should never see an empty sequence here.
+
+ if (fldSeq != FieldSeqStore::NotAField())
+ {
+ ValueNum newHeapVN = vnStore->VNApplySelectorsAssign(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq,
+ rhsVNPair.GetLiberal(), lhs->TypeGet());
+ recordGcHeapStore(tree, newHeapVN DEBUGARG("static field store"));
+ }
+ else
+ {
+ fgMutateGcHeap(tree DEBUGARG("indirect store at NotAField PtrToStatic address"));
+ }
+ }
// Is the LHS an array index expression?
- if (argIsVNFunc && funcApp.m_func == VNF_PtrToArrElem)
+ else if (argIsVNFunc && funcApp.m_func == VNF_PtrToArrElem)
{
CORINFO_CLASS_HANDLE elemTypeEq =
CORINFO_CLASS_HANDLE(vnStore->ConstantValue(funcApp.m_args[0]));
@@ -8002,370 +8018,223 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree)
GenTree* lhs = tree->gtGetOp1();
GenTree* rhs = tree->gtGetOp2();
- if (tree->OperIsInitBlkOp())
+ GenTreeLclVarCommon* lclVarTree;
+ bool isEntire;
+ if (tree->DefinesLocal(this, &lclVarTree, &isEntire))
{
- GenTreeLclVarCommon* lclVarTree;
- bool isEntire;
+ assert(lclVarTree->gtFlags & GTF_VAR_DEF);
+ // Should not have been recorded as updating the GC heap.
+ assert(!GetMemorySsaMap(GcHeap)->Lookup(tree));
- if (tree->DefinesLocal(this, &lclVarTree, &isEntire))
- {
- assert(lclVarTree->gtFlags & GTF_VAR_DEF);
- // Should not have been recorded as updating the GC heap.
- assert(!GetMemorySsaMap(GcHeap)->Lookup(tree));
+ unsigned lhsLclNum = lclVarTree->GetLclNum();
+ unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
- unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
+ // Ignore vars that we excluded from SSA (for example, because they're address-exposed). They don't have
+ // SSA names in which to store VN's on defs. We'll yield unique VN's when we read from them.
+ if (lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
+ {
+ FieldSeqNode* lhsFldSeq = nullptr;
+ LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclNum);
- // Ignore vars that we excluded from SSA (for example, because they're address-exposed). They don't have
- // SSA names in which to store VN's on defs. We'll yield unique VN's when we read from them.
- if (lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
+ if (lhs->IsLocalExpr(this, &lclVarTree, &lhsFldSeq))
{
- LclVarDsc* lclVarDsc = lvaGetDesc(lclVarTree);
+ noway_assert(lclVarTree->GetLclNum() == lhsLclNum);
+ }
+ else
+ {
+ GenTree* lhsAddr = lhs->AsIndir()->Addr();
- // Should not have been recorded as updating ByrefExposed.
- assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree));
+ // For addr-of-local expressions, lib/cons shouldn't matter.
+ assert(lhsAddr->gtVNPair.BothEqual());
+ ValueNum lhsAddrVN = lhsAddr->GetVN(VNK_Liberal);
+
+ // Unpack the PtrToLoc value number of the address.
+ assert(vnStore->IsVNFunc(lhsAddrVN));
+
+ VNFuncApp lhsAddrFuncApp;
+ vnStore->GetVNFunc(lhsAddrVN, &lhsAddrFuncApp);
+
+ assert(lhsAddrFuncApp.m_func == VNF_PtrToLoc);
+ assert(vnStore->IsVNConstant(lhsAddrFuncApp.m_args[0]) &&
+ vnStore->ConstantValue(lhsAddrFuncApp.m_args[0]) == lhsLclNum);
+ lhsFldSeq = vnStore->FieldSeqVNToFieldSeq(lhsAddrFuncApp.m_args[1]);
+ }
+
+ bool isNewUniq = false;
+ ValueNumPair newLhsLclVNPair = ValueNumPair();
+ if (tree->OperIsInitBlkOp())
+ {
ValueNum lclVarVN = ValueNumStore::NoVN;
if (isEntire && rhs->IsIntegralConst(0))
{
// Note that it is possible to see pretty much any kind of type for the local
// (not just TYP_STRUCT) here because of the ASG(BLK(ADDR(LCL_VAR/FLD)), 0) form.
- lclVarVN = (lclVarDsc->TypeGet() == TYP_STRUCT) ? vnStore->VNForZeroObj(lclVarDsc->GetStructHnd())
- : vnStore->VNZeroForType(lclVarDsc->TypeGet());
+ lclVarVN = (lhsVarDsc->TypeGet() == TYP_STRUCT) ? vnStore->VNForZeroObj(lhsVarDsc->GetStructHnd())
+ : vnStore->VNZeroForType(lhsVarDsc->TypeGet());
}
else
{
// Non-zero block init is very rare so we'll use a simple, unique VN here.
- lclVarVN = vnStore->VNForExpr(compCurBB, lclVarDsc->TypeGet());
+ lclVarVN = vnStore->VNForExpr(compCurBB, lhsVarDsc->TypeGet());
+ isNewUniq = true;
}
- lclVarDsc->GetPerSsaData(lclDefSsaNum)->m_vnPair.SetBoth(lclVarVN);
-#ifdef DEBUG
- if (verbose)
- {
- printf("Tree ");
- Compiler::printTreeID(tree);
- printf(" assigned VN to local var V%02u/%d: ", lclVarTree->GetLclNum(), lclDefSsaNum);
- vnPrint(lclVarVN, 1);
- printf("\n");
- }
-#endif // DEBUG
- }
- else if (lvaVarAddrExposed(lclVarTree->GetLclNum()))
- {
- fgMutateAddressExposedLocal(tree DEBUGARG("INITBLK - address-exposed local"));
+ newLhsLclVNPair.SetBoth(lclVarVN);
}
- }
- else
- {
- // For now, arbitrary side effect on GcHeap/ByrefExposed.
- // TODO-CQ: Why not be complete, and get this case right?
- fgMutateGcHeap(tree DEBUGARG("INITBLK - non local"));
- }
- // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we
- // want to be able to give VN's to.
- tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid());
- }
- else
- {
- assert(tree->OperIsCopyBlkOp());
- // TODO-Cleanup: We should factor things so that we uniformly rely on "PtrTo" VN's, and
- // the memory cases can be shared with assignments.
- GenTreeLclVarCommon* lclVarTree = nullptr;
- bool isEntire = false;
- // Note that we don't care about exceptions here, since we're only using the values
- // to perform an assignment (which happens after any exceptions are raised...)
-
- if (tree->DefinesLocal(this, &lclVarTree, &isEntire))
- {
- // Should not have been recorded as updating the GC heap.
- assert(!GetMemorySsaMap(GcHeap)->Lookup(tree));
-
- unsigned lhsLclNum = lclVarTree->GetLclNum();
- FieldSeqNode* lhsFldSeq = nullptr;
- unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree);
- LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclNum);
- // If it's excluded from SSA, don't need to do anything.
- if (lvaInSsa(lhsLclNum) && lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM)
+ else
{
- // Should not have been recorded as updating ByrefExposed.
- assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree));
-
- if (lhs->IsLocalExpr(this, &lclVarTree, &lhsFldSeq))
- {
- noway_assert(lclVarTree->GetLclNum() == lhsLclNum);
- }
- else
- {
- GenTree* lhsAddr;
- if (lhs->OperIsBlk())
- {
- lhsAddr = lhs->AsBlk()->Addr();
- }
- else
- {
- assert(lhs->OperGet() == GT_IND);
- lhsAddr = lhs->AsOp()->gtOp1;
- }
-
- // For addr-of-local expressions, lib/cons shouldn't matter.
- assert(lhsAddr->gtVNPair.BothEqual());
- ValueNum lhsAddrVN = lhsAddr->GetVN(VNK_Liberal);
-
- // Unpack the PtrToLoc value number of the address.
- assert(vnStore->IsVNFunc(lhsAddrVN));
-
- VNFuncApp lhsAddrFuncApp;
- vnStore->GetVNFunc(lhsAddrVN, &lhsAddrFuncApp);
-
- assert(lhsAddrFuncApp.m_func == VNF_PtrToLoc);
- assert(vnStore->IsVNConstant(lhsAddrFuncApp.m_args[0]) &&
- vnStore->ConstantValue(lhsAddrFuncApp.m_args[0]) == lhsLclNum);
-
- lhsFldSeq = vnStore->FieldSeqVNToFieldSeq(lhsAddrFuncApp.m_args[1]);
- }
+ assert(tree->OperIsCopyBlkOp());
- // Now we need to get the proper RHS.
- GenTreeLclVarCommon* rhsLclVarTree = nullptr;
- LclVarDsc* rhsVarDsc = nullptr;
- FieldSeqNode* rhsFldSeq = nullptr;
- ValueNumPair rhsVNPair;
- bool isNewUniq = false;
- if (!rhs->OperIsIndir())
+ if (fgValueNumberBlockAssignmentTypeCheck(lhsVarDsc, lhsFldSeq, rhs))
{
- if (rhs->IsLocalExpr(this, &rhsLclVarTree, &rhsFldSeq))
- {
- unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
- rhsVarDsc = lvaGetDesc(rhsLclNum);
- if (!lvaInSsa(rhsLclNum) || !rhsLclVarTree->HasSsaName() ||
- rhsFldSeq == FieldSeqStore::NotAField())
- {
- rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, rhsLclVarTree->TypeGet()));
- isNewUniq = true;
- }
- else
- {
- rhsVNPair = rhsVarDsc->GetPerSsaData(rhsLclVarTree->GetSsaNum())->m_vnPair;
- var_types indType = rhsLclVarTree->TypeGet();
-
- rhsVNPair = vnStore->VNPairApplySelectors(rhsVNPair, rhsFldSeq, indType);
- }
- }
- else
- {
- isNewUniq = true;
- }
+ ValueNumPair rhsVNPair = vnStore->VNPNormalPair(rhs->gtVNPair);
+ ValueNumPair oldLhsLclVNPair = lhsVarDsc->GetPerSsaData(lclVarTree->GetSsaNum())->m_vnPair;
+ newLhsLclVNPair =
+ vnStore->VNPairApplySelectorsAssign(oldLhsLclVNPair, lhsFldSeq, rhsVNPair, lhs->TypeGet());
}
else
{
- GenTree* srcAddr = rhs->AsIndir()->Addr();
- VNFuncApp srcAddrFuncApp;
- if (srcAddr->IsLocalAddrExpr(this, &rhsLclVarTree, &rhsFldSeq))
- {
- unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
- rhsVarDsc = lvaGetDesc(rhsLclNum);
- if (!lvaInSsa(rhsLclNum) || !rhsLclVarTree->HasSsaName() ||
- rhsFldSeq == FieldSeqStore::NotAField())
- {
- isNewUniq = true;
- }
- else
- {
- rhsVNPair = rhsVarDsc->GetPerSsaData(rhsLclVarTree->GetSsaNum())->m_vnPair;
- var_types indType = rhsLclVarTree->TypeGet();
-
- rhsVNPair = vnStore->VNPairApplySelectors(rhsVNPair, rhsFldSeq, indType);
- }
- }
- else if (vnStore->GetVNFunc(vnStore->VNLiberalNormalValue(srcAddr->gtVNPair), &srcAddrFuncApp))
- {
- if (srcAddrFuncApp.m_func == VNF_PtrToStatic)
- {
- var_types indType = lclVarTree->TypeGet();
- ValueNum fieldSeqVN = srcAddrFuncApp.m_args[1];
- FieldSeqNode* fldSeqForStaticVar = vnStore->FieldSeqVNToFieldSeq(fieldSeqVN);
-#ifdef DEBUG
- FieldSeqNode* zeroOffsetFldSeq = nullptr;
- if (GetZeroOffsetFieldMap()->Lookup(srcAddr, &zeroOffsetFldSeq))
- {
- // Check that the zero offset field seq was attached for `srcAddr`.
- assert(fldSeqForStaticVar->GetTail() == zeroOffsetFldSeq);
- }
-#endif
- if (fldSeqForStaticVar != FieldSeqStore::NotAField())
- {
- assert(fldSeqForStaticVar != nullptr);
-
- // We model statics as indices into GcHeap (which is a subset of ByrefExposed).
- ValueNum selectedStaticVar;
- size_t structSize = 0;
- selectedStaticVar = vnStore->VNApplySelectors(VNK_Liberal, fgCurMemoryVN[GcHeap],
- fldSeqForStaticVar, &structSize);
- selectedStaticVar =
- vnStore->VNApplySelectorsTypeCheck(selectedStaticVar, indType, structSize);
-
- rhsVNPair.SetLiberal(selectedStaticVar);
- rhsVNPair.SetConservative(vnStore->VNForExpr(compCurBB, indType));
- }
- else
- {
- JITDUMP(" *** Missing field sequence info for Src/RHS of COPYBLK\n");
- isNewUniq = true;
- }
- }
- else if (srcAddrFuncApp.m_func == VNF_PtrToArrElem)
- {
- ValueNum elemLib =
- fgValueNumberArrIndexVal(nullptr, &srcAddrFuncApp, vnStore->VNPForEmptyExcSet());
- rhsVNPair.SetLiberal(elemLib);
- rhsVNPair.SetConservative(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
- }
- else
- {
- isNewUniq = true;
- }
- }
- else
- {
- isNewUniq = true;
- }
- }
-
- if (lhsFldSeq == FieldSeqStore::NotAField())
- {
- // We don't have proper field sequence information for the lhs
- //
- JITDUMP(" *** Missing field sequence info for Dst/LHS of COPYBLK\n");
+ newLhsLclVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lhsVarDsc->TypeGet()));
isNewUniq = true;
}
+ }
- if (!isNewUniq && (lclVarTree != nullptr) && (rhsLclVarTree != nullptr))
- {
- isNewUniq = fgValueNumberIsStructReinterpretation(lclVarTree, rhsLclVarTree);
- }
+ lhsVarDsc->GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsLclVNPair;
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("Tree ");
+ Compiler::printTreeID(tree);
+ printf(" assigned VN to local var V%02u/%d: ", lhsLclNum, lclDefSsaNum);
if (isNewUniq)
{
- rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
- }
- else // We will assign rhsVNPair into a map[lhsFldSeq]
- {
- if (lhsFldSeq != nullptr && isEntire)
- {
- // This can occur for structs with one field, itself of a struct type.
- // We are assigning the one field and it is also the entire enclosing struct.
- //
- // Use an unique value number for the old map, as this is an an entire assignment
- // and we won't have any other values in the map
- ValueNumPair uniqueMap;
- uniqueMap.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet()));
- rhsVNPair =
- vnStore->VNPairApplySelectorsAssign(uniqueMap, lhsFldSeq, rhsVNPair, lclVarTree->TypeGet());
- }
- else
- {
- ValueNumPair oldLhsVNPair = lhsVarDsc->GetPerSsaData(lclVarTree->GetSsaNum())->m_vnPair;
- rhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lhsFldSeq, rhsVNPair,
- lclVarTree->TypeGet());
- }
+ printf("new uniq ");
}
-
- lhsVarDsc->GetPerSsaData(lclDefSsaNum)->m_vnPair = vnStore->VNPNormalPair(rhsVNPair);
-
-#ifdef DEBUG
- if (verbose)
- {
- printf("Tree ");
- Compiler::printTreeID(tree);
- printf(" assigned VN to local var V%02u/%d: ", lhsLclNum, lclDefSsaNum);
- if (isNewUniq)
- {
- printf("new uniq ");
- }
- vnpPrint(rhsVNPair, 1);
- printf("\n");
- }
-#endif // DEBUG
- }
- else if (lvaVarAddrExposed(lhsLclNum))
- {
- fgMutateAddressExposedLocal(tree DEBUGARG("COPYBLK - address-exposed local"));
- }
- else
- {
- JITDUMP("LHS V%02u not in ssa at [%06u], so no VN assigned\n", lhsLclNum, dspTreeID(lclVarTree));
+ vnpPrint(newLhsLclVNPair, 1);
+ printf("\n");
}
+#endif // DEBUG
+ }
+ else if (lvaVarAddrExposed(lhsLclNum))
+ {
+ fgMutateAddressExposedLocal(tree DEBUGARG("INITBLK/COPYBLK - address-exposed local"));
}
else
{
- // For now, arbitrary side effect on GcHeap/ByrefExposed.
- // TODO-CQ: Why not be complete, and get this case right?
- fgMutateGcHeap(tree DEBUGARG("COPYBLK - non local"));
+ JITDUMP("LHS V%02u not in ssa at [%06u], so no VN assigned\n", lhsLclNum, dspTreeID(lclVarTree));
}
- // Copyblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we want
- // to be able to give VN's to.
- tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid());
}
+ else
+ {
+ // For now, arbitrary side effect on GcHeap/ByrefExposed.
+ // TODO-CQ: Why not be complete, and get this case right?
+ fgMutateGcHeap(tree DEBUGARG("INITBLK/COPYBLK - non local"));
+ }
+
+ // Assignments produce no values so we give them the "Void" VN.
+ tree->gtVNPair = vnStore->VNPForVoid();
}
//------------------------------------------------------------------------
-// fgValueNumberIsStructReinterpretation: Checks if there is a struct reinterpretation that prevent VN propagation.
+// fgValueNumberBlockAssignmentTypeCheck: Checks if there is a struct reinterpretation that prevent VN propagation.
//
// Arguments:
-// lhsLclVarTree - a lcl var tree on the lhs of the asg;
-// rhsLclVarTree - a lcl var tree on the rhs of the asg;
+// dstVarDsc - the descriptor for the local being assigned to
+// dstFldSeq - the sequence of fields used for the assignment
+// src - the source of the assignment, i. e. the RHS
//
// Return Value:
-// True if the locals have different struct types and VN can't use rhs VN for lhs VN.
-// False if locals have the same struct type or if this ASG is not a struct ASG.
+// Whether "src"'s exact type matches that of the destination location.
+//
+// Notes:
+// Currently this method only handles local destinations, it should be expanded to support more
+// locations (static/instance fields, array elements) once/if "fgValueNumberBlockAssignment"
+// supports them.
//
-bool Compiler::fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree,
- GenTreeLclVarCommon* rhsLclVarTree)
+bool Compiler::fgValueNumberBlockAssignmentTypeCheck(LclVarDsc* dstVarDsc, FieldSeqNode* dstFldSeq, GenTree* src)
{
- assert(lhsLclVarTree != nullptr);
- assert(rhsLclVarTree != nullptr);
+ if (dstFldSeq == FieldSeqStore::NotAField())
+ {
+ // We don't have proper field sequence information for the lhs - assume arbitrary aliasing.
+ JITDUMP(" *** Missing field sequence info for Dst/LHS of COPYBLK\n");
+ return false;
+ }
- if (rhsLclVarTree->TypeGet() == TYP_STRUCT)
+ // With unsafe code or nested structs, we can end up with IR that has
+ // mismatched struct types on the LHS and RHS. We need to maintain the
+ // invariant that a node's VN corresponds exactly to its type. Failure
+ // to do so is a correctness problem. For example:
+ //
+ // S1 s1 = { ... }; // s1 = map
+ // S1.F0 = 0; // s1 = map[F0 := 0]
+ // S2 s2 = s1; // s2 = map[F0 := 0] (absent below checks)
+ // s2.F1 = 1; // s2 = map[F0 := 0][F1 := 1]
+ // s1 = s2; // s1 = map[F0 := 0][F1 := 1]
+ //
+ // int r = s1.F0; // map[F0 := 0][F1 := 1][F0] => map[F0 := 0][F0] => 0
+ //
+ // If F1 and F0 physically alias (exist at the same offset, say), the above
+ // represents an incorrect optimization.
+
+ var_types dstLocationType = TYP_UNDEF;
+ CORINFO_CLASS_HANDLE dstLocationStructHnd = NO_CLASS_HANDLE;
+ if (dstFldSeq == nullptr)
{
- if (rhsLclVarTree->TypeGet() == lhsLclVarTree->TypeGet())
+ dstLocationType = dstVarDsc->TypeGet();
+ if (dstLocationType == TYP_STRUCT)
{
- if (lhsLclVarTree->isLclField() || rhsLclVarTree->isLclField())
- {
- // Jit does not have a real support for `LCL_FLD struct [FldSeq]` because it can't determinate their
- // size
- // when the fieldSeq is `NotAField`, but by mistake we could have
- // `BLK(ADDR byref(LCL_FLD struct Fseq[]))` nowadays in out IR.
- // Generate a unique VN for now, it currently won't match the other side,
- // otherwise we would not have 'OBJ struct2 (ADDR(LCL_FLD struct1))` cast.
- return true;
- }
+ dstLocationStructHnd = dstVarDsc->GetStructHnd();
+ }
+ }
+ else
+ {
+ // Have to normalize as "eeGetFieldType" will return TYP_STRUCT for TYP_SIMD.
+ dstLocationType = eeGetFieldType(dstFldSeq->GetTail()->GetFieldHandle(), &dstLocationStructHnd);
+ if (dstLocationType == TYP_STRUCT)
+ {
+ dstLocationType = impNormStructType(dstLocationStructHnd);
+ }
+ }
- assert(lhsLclVarTree->OperIs(GT_LCL_VAR));
- assert(rhsLclVarTree->OperIs(GT_LCL_VAR));
+ // This method is meant to handle TYP_STRUCT mismatches, bail early for anything else.
+ if (dstLocationType != src->TypeGet())
+ {
+ JITDUMP(" *** Different types for Dst/Src of COPYBLK: %s != %s\n", varTypeName(dstLocationType),
+ varTypeName(src->TypeGet()));
+ return false;
+ }
- const LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclVarTree);
- const LclVarDsc* rhsVarDsc = lvaGetDesc(rhsLclVarTree);
- assert(rhsVarDsc->TypeGet() == TYP_STRUCT);
- assert(lhsVarDsc->TypeGet() == TYP_STRUCT);
+ // They're equal, and they're primitives. Allow, for now. TYP_SIMD is tentatively
+ // allowed here as well as, currently, there are no two vector types with public
+ // fields both that could reasonably alias each other.
+ if (dstLocationType != TYP_STRUCT)
+ {
+ return true;
+ }
- CORINFO_CLASS_HANDLE rhsStructHnd = rhsVarDsc->GetStructHnd();
- CORINFO_CLASS_HANDLE lhsStructHnd = lhsVarDsc->GetStructHnd();
+ // Figure out what the source's type really is. Note that this will miss
+ // struct fields of struct locals currently ("src" for them is an IND(struct)).
+ // Note as well that we're relying on the invariant that "node type == node's
+ // VN type" here (it would be expensive to recover the handle from "src"'s VN).
+ CORINFO_CLASS_HANDLE srcValueStructHnd = gtGetStructHandleIfPresent(src);
+ if (srcValueStructHnd == NO_CLASS_HANDLE)
+ {
+ JITDUMP(" *** Missing struct handle for Src of COPYBLK\n");
+ return false;
+ }
- if (rhsStructHnd != lhsStructHnd)
- {
- // This can occur for nested structs or for unsafe casts, when we have IR like
- // struct1 = struct2.
- // Use an unique value number for the old map, as we don't have information about
- // the dst field values using dst FIELD_HANDLE.
- // Note that other asignments, like struct1 = IND struct(ADDR(LCL_VAR long))
- // will be handled in `VNPairApplySelectorsAssign`, here we care only about
- // `LCL_VAR structX = (*)LCL_VAR structY` cases.
- JITDUMP(" *** Different struct handles for Dst/Src of COPYBLK\n");
- return true;
- }
- }
+ assert((dstLocationStructHnd != NO_CLASS_HANDLE) && (srcValueStructHnd != NO_CLASS_HANDLE));
+
+ if (dstLocationStructHnd != srcValueStructHnd)
+ {
+ JITDUMP(" *** Different struct handles for Dst/Src of COPYBLK: %s != %s\n",
+ eeGetClassName(dstLocationStructHnd), eeGetClassName(srcValueStructHnd));
+ return false;
}
- return false;
+ return true;
}
void Compiler::fgValueNumberTree(GenTree* tree)
@@ -8625,39 +8494,19 @@ void Compiler::fgValueNumberTree(GenTree* tree)
ValueNumPair clsVarVNPair;
GenTreeClsVar* clsVar = tree->AsClsVar();
FieldSeqNode* fldSeq = clsVar->gtFieldSeq;
- assert(fldSeq != nullptr); // We need to have one.
- CORINFO_FIELD_HANDLE fieldHnd = clsVar->gtClsVarHnd;
- assert(fieldHnd != NO_FIELD_HANDLE);
- ValueNum selectedStaticVar = ValueNumStore::NoVN;
+ assert((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField())); // We need to have one.
- if (fldSeq == FieldSeqStore::NotAField())
- {
- // This is the box for a "boxed static" - see "fgMorphField".
- assert(gtIsStaticFieldPtrToBoxedStruct(clsVar->TypeGet(), fieldHnd));
-
- // We will create an empty field sequence for VNF_PtrToStatic here. We will assume
- // the actual sequence will get appended later, when processing the TARGET_POINTER_SIZE
- // offset that is always added to this box to get to its payload.
-
- ValueNum fieldHndVN = vnStore->VNForHandle(ssize_t(fieldHnd), GTF_ICON_FIELD_HDL);
- ValueNum fieldSeqVN = vnStore->VNForFieldSeq(nullptr);
- clsVarVNPair.SetBoth(vnStore->VNForFunc(TYP_REF, VNF_PtrToStatic, fieldHndVN, fieldSeqVN));
- }
- else
- {
- // This is a reference to heap memory.
- // We model statics as indices into GcHeap (which is a subset of ByrefExposed).
+ // This is a reference to heap memory.
+ // We model statics as indices into GcHeap (which is a subset of ByrefExposed).
+ size_t structSize = 0;
+ ValueNum selectedStaticVar =
+ vnStore->VNApplySelectors(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq, &structSize);
+ selectedStaticVar =
+ vnStore->VNApplySelectorsTypeCheck(selectedStaticVar, tree->TypeGet(), structSize);
- size_t structSize = 0;
- selectedStaticVar =
- vnStore->VNApplySelectors(VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq, &structSize);
- selectedStaticVar =
- vnStore->VNApplySelectorsTypeCheck(selectedStaticVar, tree->TypeGet(), structSize);
-
- clsVarVNPair.SetLiberal(selectedStaticVar);
- // The conservative interpretation always gets a new, unique VN.
- clsVarVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
- }
+ clsVarVNPair.SetLiberal(selectedStaticVar);
+ // The conservative interpretation always gets a new, unique VN.
+ clsVarVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
// The ValueNum returned must represent the full-sized IL-Stack value
// If we need to widen this value then we need to introduce a VNF_Cast here to represent
@@ -8834,9 +8683,22 @@ void Compiler::fgValueNumberTree(GenTree* tree)
if (!wasNewobj)
{
+ // Indirections off of addresses for boxed statics represent bases for
+ // the address of the static itself. Here we will use "nullptr" for the
+ // field sequence and assume the actual static field will be appended to
+ // it later, as part of numbering the method table pointer offset addition.
+ if (addr->IsCnsIntOrI() && addr->IsIconHandle(GTF_ICON_STATIC_BOX_PTR))
+ {
+ assert(addrNvnp.BothEqual() && (addrXvnp == vnStore->VNPForEmptyExcSet()));
+ ValueNum boxAddrVN = addrNvnp.GetLiberal();
+ ValueNum fieldSeqVN = vnStore->VNForFieldSeq(nullptr);
+ ValueNum staticAddrVN =
+ vnStore->VNForFunc(tree->TypeGet(), VNF_PtrToStatic, boxAddrVN, fieldSeqVN);
+ tree->gtVNPair = ValueNumPair(staticAddrVN, staticAddrVN);
+ }
// Is this invariant indirect expected to always return a non-null value?
// TODO-VNTypes: non-null indirects should only be used for TYP_REFs.
- if ((tree->gtFlags & GTF_IND_NONNULL) != 0)
+ else if ((tree->gtFlags & GTF_IND_NONNULL) != 0)
{
assert(tree->gtFlags & GTF_IND_NONFAULTING);
tree->gtVNPair = vnStore->VNPairForFunc(tree->TypeGet(), VNF_NonNullIndirect, addrNvnp);
@@ -10614,8 +10476,19 @@ void Compiler::fgValueNumberAddExceptionSetForIndirection(GenTree* tree, GenTree
// The normal VN for base address is used to create the NullPtrExc
ValueNumPair vnpBaseNorm = vnStore->VNPNormalPair(baseVNP);
+ ValueNumPair excChkSet = vnStore->VNPForEmptyExcSet();
+
+ if (!vnStore->IsKnownNonNull(vnpBaseNorm.GetLiberal()))
+ {
+ excChkSet.SetLiberal(
+ vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm.GetLiberal())));
+ }
- ValueNumPair excChkSet = vnStore->VNPExcSetSingleton(vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm));
+ if (!vnStore->IsKnownNonNull(vnpBaseNorm.GetConservative()))
+ {
+ excChkSet.SetConservative(
+ vnStore->VNExcSetSingleton(vnStore->VNForFunc(TYP_REF, VNF_NullPtrExc, vnpBaseNorm.GetConservative())));
+ }
// Add the NullPtrExc to "tree"'s value numbers.
tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, excChkSet);
diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h
index fc10c05398cf03..f82c2ff603d07e 100644
--- a/src/coreclr/jit/valuenumfuncs.h
+++ b/src/coreclr/jit/valuenumfuncs.h
@@ -16,7 +16,7 @@ ValueNumFuncDef(NotAField, 0, false, false, false) // Value number function for
ValueNumFuncDef(PtrToLoc, 2, false, true, false) // Pointer (byref) to a local variable. Args: VN's of: 0: var num, 1: FieldSeq.
ValueNumFuncDef(PtrToArrElem, 4, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: FieldSeq.
ValueNumFuncDef(PtrToStatic, 2, false, true, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct).
- // Args: 0: (VN of) the field handle, 1: the field sequence, of which the first element is the static itself.
+ // Args: 0: (VN of) the box's address if the static is "boxed", 1: the field sequence, of which the first element is the static itself.
ValueNumFuncDef(Phi, 2, false, false, false) // A phi function. Only occurs as arg of PhiDef or PhiMemoryDef. Arguments are SSA numbers of var being defined.
ValueNumFuncDef(PhiDef, 3, false, false, false) // Args: 0: local var # (or -1 for memory), 1: SSA #, 2: VN of definition.
diff --git a/src/coreclr/jit/valuenumtype.h b/src/coreclr/jit/valuenumtype.h
index 1c991e5c05a971..5ed44e280f8f7e 100644
--- a/src/coreclr/jit/valuenumtype.h
+++ b/src/coreclr/jit/valuenumtype.h
@@ -96,6 +96,16 @@ struct ValueNumPair
m_conservative = vn;
}
+ bool operator==(const ValueNumPair& other) const
+ {
+ return (m_liberal == other.m_liberal) && (m_conservative == other.m_conservative);
+ }
+
+ bool operator!=(const ValueNumPair& other) const
+ {
+ return !(*this == other);
+ }
+
void operator=(const ValueNumPair& vn2)
{
m_liberal = vn2.m_liberal;
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props
index b49f24ea2bc38d..4e8bbecff72873 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props
@@ -90,7 +90,7 @@ The .NET Foundation licenses this file to you under the MIT license.
-
+
diff --git a/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs b/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs
index 9909556b183305..f684094f9084db 100644
--- a/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs
+++ b/src/coreclr/nativeaot/Common/src/System/Collections/Generic/LowLevelList.cs
@@ -40,7 +40,7 @@ internal class LowLevelList
{
private const int _defaultCapacity = 4;
- protected T?[] _items;
+ protected T[] _items;
protected int _size;
protected int _version;
@@ -447,7 +447,7 @@ public void RemoveAt(int index)
{
Array.Copy(_items, index + 1, _items, index, _size - index);
}
- _items[_size] = default(T);
+ _items[_size] = default!;
_version++;
}
@@ -549,7 +549,7 @@ public T Current
}
}
- object System.Collections.IEnumerator.Current
+ object? System.Collections.IEnumerator.Current
{
get
{
diff --git a/src/coreclr/nativeaot/Directory.Build.props b/src/coreclr/nativeaot/Directory.Build.props
index dddbec1ec7bfbd..9b732840b30907 100644
--- a/src/coreclr/nativeaot/Directory.Build.props
+++ b/src/coreclr/nativeaot/Directory.Build.props
@@ -31,7 +31,7 @@
$(NoWarn),0419,0649,CA2249,CA1830
- $(NoWarn);CS8600;CS8601;CS8602;CS8603;CS8604;CS8610;CS8618;CS8620;CS8625;CS8632;CS8765
+ $(NoWarn);CS8600;CS8602;CS8603;CS8604;CS8610;CS8618;CS8620;CS8625;CS8632;CS8765
$(NoWarn);CA1810;CA1823;CA1825;CA2208;SA1129;SA1205;SA1400;SA1517
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs
index 7e738b4f2d32c5..f6af798344b761 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs
@@ -1054,7 +1054,7 @@ public static unsafe bool AreTypesAssignableInternal(MethodTable* pSourceType, M
return true;
Key key = new Key(pSourceType, pTargetType, variation);
- Entry entry = LookupInCache(s_cache, ref key);
+ Entry? entry = LookupInCache(s_cache, ref key);
if (entry == null)
return CacheMiss(ref key, pVisited);
@@ -1072,7 +1072,7 @@ public static unsafe bool AreTypesAssignableInternal_SourceNotTarget_BoxedSource
{
Debug.Assert(pSourceType != pTargetType, "target is source");
Key key = new Key(pSourceType, pTargetType, AssignmentVariation.BoxedSource);
- Entry entry = LookupInCache(s_cache, ref key);
+ Entry? entry = LookupInCache(s_cache, ref key);
if (entry == null)
return CacheMiss(ref key, pVisited);
@@ -1113,7 +1113,7 @@ private static unsafe bool CacheMiss(ref Key key, EETypePairList* pVisited)
Entry[] previousCache = Unsafe.As(s_previousCache.Target);
if (previousCache != null)
{
- Entry previousEntry = LookupInCache(previousCache, ref key);
+ Entry? previousEntry = LookupInCache(previousCache, ref key);
if (previousEntry != null)
{
result = previousEntry.Result;
@@ -1140,7 +1140,7 @@ private static unsafe bool CacheMiss(ref Key key, EETypePairList* pVisited)
try
{
// Avoid duplicate entries
- Entry existingEntry = LookupInCache(s_cache, ref key);
+ Entry? existingEntry = LookupInCache(s_cache, ref key);
if (existingEntry != null)
return existingEntry.Result;
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index 7379e9ed471581..0059de15e5d9de 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -2,14 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection;
+using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Text;
using System.Threading;
+using Internal.Runtime;
using Internal.Runtime.Augments;
namespace Internal.Runtime.CompilerHelpers
@@ -337,7 +340,7 @@ internal static unsafe void FixupModuleCell(ModuleFixupCell* pCell)
if (hModule == IntPtr.Zero)
{
// Built-in rules didn't resolve the library. Use AssemblyLoadContext as a last chance attempt.
- AssemblyLoadContext loadContext = AssemblyLoadContext.GetLoadContext(callingAssembly);
+ AssemblyLoadContext? loadContext = AssemblyLoadContext.GetLoadContext(callingAssembly);
hModule = loadContext.GetResolvedUnmanagedDll(callingAssembly, moduleName);
}
@@ -591,6 +594,32 @@ internal static unsafe void CleanupVariant(IntPtr pDstNativeVariant)
#endif
}
+ public static unsafe object InitializeCustomMarshaller(RuntimeTypeHandle pParameterType, RuntimeTypeHandle pMarshallerType, string cookie, delegate* getInstanceMethod)
+ {
+ if (getInstanceMethod == null)
+ {
+ throw new ApplicationException();
+ }
+
+ if (!RuntimeImports.AreTypesAssignable(pMarshallerType.ToEETypePtr(), EETypePtr.EETypePtrOf()))
+ {
+ throw new ApplicationException();
+ }
+
+ var marshaller = CustomMarshallerTable.s_customMarshallersTable.GetOrAdd(new CustomMarshallerKey(pParameterType, pMarshallerType, cookie, getInstanceMethod));
+ if (marshaller == null)
+ {
+ throw new ApplicationException();
+ }
+
+ if (!RuntimeImports.AreTypesAssignable(marshaller.EETypePtr, EETypePtr.EETypePtrOf()))
+ {
+ throw new ApplicationException();
+ }
+
+ return marshaller;
+ }
+
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ModuleFixupCell
{
@@ -608,5 +637,52 @@ internal unsafe struct MethodFixupCell
public ModuleFixupCell* Module;
public CharSet CharSetMangling;
}
+
+ internal unsafe struct CustomMarshallerKey : IEquatable
+ {
+ public CustomMarshallerKey(RuntimeTypeHandle pParameterType, RuntimeTypeHandle pMarshallerType, string cookie, delegate* getInstanceMethod)
+ {
+ ParameterType = pParameterType;
+ MarshallerType = pMarshallerType;
+ Cookie = cookie;
+ GetInstanceMethod = getInstanceMethod;
+ }
+
+ public RuntimeTypeHandle ParameterType { get; }
+ public RuntimeTypeHandle MarshallerType { get; }
+ public string Cookie { get; }
+ public delegate* GetInstanceMethod { get; }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is CustomMarshallerKey other))
+ return false;
+ return Equals(other);
+ }
+
+ public bool Equals(CustomMarshallerKey other)
+ {
+ return ParameterType.Equals(other.ParameterType)
+ && MarshallerType.Equals(other.MarshallerType)
+ && Cookie.Equals(other.Cookie);
+ }
+
+ public override int GetHashCode()
+ {
+ return ParameterType.GetHashCode()
+ ^ MarshallerType.GetHashCode()
+ ^ Cookie.GetHashCode();
+ }
+ }
+
+ internal sealed class CustomMarshallerTable : ConcurrentUnifier
+ {
+ internal static CustomMarshallerTable s_customMarshallersTable = new CustomMarshallerTable();
+
+ protected unsafe override object Factory(CustomMarshallerKey key)
+ {
+ return key.GetInstanceMethod(key.Cookie);
+ }
+ }
}
}
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 2284e13f661357..57ba9e2a3ab29c 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
@@ -445,7 +445,7 @@
-
+
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Exception.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Exception.CoreRT.cs
index 10fadea9d090be..c9239b10f4de87 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Exception.CoreRT.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Exception.CoreRT.cs
@@ -180,7 +180,7 @@ internal DispatchState CaptureDispatchState()
internal void RestoreDispatchState(DispatchState DispatchState)
{
- IntPtr[] stackTrace = DispatchState.StackTrace;
+ IntPtr[]? stackTrace = DispatchState.StackTrace;
int idxFirstFreeStackTraceEntry = 0;
if (stackTrace != null)
{
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/GC.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/GC.cs
index a01d78f9f07b07..c9578dfee08036 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/GC.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/GC.cs
@@ -83,7 +83,7 @@ public static int GetGeneration(WeakReference wo)
{
// note - this throws an NRE if given a null weak reference. This isn't
// documented, but it's the behavior of Desktop and CoreCLR.
- object handleRef = RuntimeImports.RhHandleGet(wo.m_handle);
+ object? handleRef = RuntimeImports.RhHandleGet(wo.m_handle);
if (handleRef == null)
{
throw new ArgumentNullException(nameof(wo));
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs
index eda6c45aa296cb..b05af345fe2960 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs
@@ -31,7 +31,7 @@ protected MulticastDelegate([DynamicallyAccessedMembers(DynamicallyAccessedMembe
private bool InvocationListEquals(MulticastDelegate d)
{
- Delegate[] invocationList = m_helperObject as Delegate[];
+ Delegate[] invocationList = (Delegate[])m_helperObject;
if (d.m_extraFunctionPointerOrData != m_extraFunctionPointerOrData)
return false;
@@ -39,7 +39,7 @@ private bool InvocationListEquals(MulticastDelegate d)
for (int i = 0; i < invocationCount; i++)
{
Delegate dd = invocationList[i];
- Delegate[] dInvocationList = d.m_helperObject as Delegate[];
+ Delegate[] dInvocationList = (Delegate[])d.m_helperObject;
if (!dd.Equals(dInvocationList[i]))
return false;
}
@@ -65,9 +65,10 @@ public override sealed bool Equals([NotNullWhen(true)] object? obj)
// 1- Multicast (m_helperObject is Delegate[])
// 2- Single-cast delegate, which can be compared with a structural comparision
- if (m_functionPointer == GetThunk(MulticastThunk))
+ IntPtr multicastThunk = GetThunk(MulticastThunk);
+ if (m_functionPointer == multicastThunk)
{
- return InvocationListEquals(d);
+ return d.m_functionPointer == multicastThunk && InvocationListEquals(d);
}
else
{
@@ -280,7 +281,7 @@ protected sealed override Delegate CombineImpl(Delegate? follow)
private Delegate[] DeleteFromInvocationList(Delegate[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
{
- Delegate[] thisInvocationList = m_helperObject as Delegate[];
+ Delegate[] thisInvocationList = (Delegate[])m_helperObject;
int allocCount = thisInvocationList.Length;
while (allocCount / 2 >= invocationCount - deleteCount)
allocCount /= 2;
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreRT.cs
index bcadaa56b04a05..02ebc1dfaff96c 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreRT.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreRT.cs
@@ -9,8 +9,8 @@ public partial struct GCHandle
private static void InternalFree(IntPtr handle) => RuntimeImports.RhHandleFree(handle);
- private static object InternalGet(IntPtr handle) => RuntimeImports.RhHandleGet(handle);
+ private static object? InternalGet(IntPtr handle) => RuntimeImports.RhHandleGet(handle);
- private static void InternalSet(IntPtr handle, object value) => RuntimeImports.RhHandleSet(handle, value);
+ private static void InternalSet(IntPtr handle, object? value) => RuntimeImports.RhHandleSet(handle, value);
}
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
index be104462e5aeb4..57a2a7c8375ef5 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
@@ -185,7 +185,7 @@ private static PInvokeDelegateThunk AllocateThunk(Delegate del)
///
/// Retrieve the corresponding P/invoke instance from the stub
///
- public static unsafe Delegate GetDelegateForFunctionPointer(IntPtr ptr, RuntimeTypeHandle delegateType)
+ public static unsafe Delegate? GetDelegateForFunctionPointer(IntPtr ptr, RuntimeTypeHandle delegateType)
{
if (ptr == IntPtr.Zero)
return null;
@@ -367,7 +367,7 @@ public static unsafe void AnsiStringToStringBuilder(byte* newBuffer, System.Text
/// Input assumed to be zero terminated. Generates String.Empty for zero length string.
/// This version is more efficient than ConvertToUnicode in src\Interop\System\Runtime\InteropServices\Marshal.cs in that it can skip calling
/// MultiByteToWideChar for ASCII string, and it does not need another char[] buffer
- public static unsafe string AnsiStringToString(byte* pchBuffer)
+ public static unsafe string? AnsiStringToString(byte* pchBuffer)
{
if (pchBuffer == null)
{
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 a7edbf10d819af..b0d2fad5792f37 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
@@ -245,15 +245,15 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary)
// Get object reference from handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhHandleGet")]
- private static extern object _RhHandleGet(IntPtr handle);
+ private static extern object? _RhHandleGet(IntPtr handle);
- internal static unsafe object RhHandleGet(IntPtr handle)
+ internal static unsafe object? RhHandleGet(IntPtr handle)
{
#if DEBUG
// The runtime performs additional checks in debug builds
return _RhHandleGet(handle);
#else
- return Unsafe.As(ref *(IntPtr*)(nint)handle);
+ return Unsafe.As(ref *(IntPtr*)(nint)handle);
#endif
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs
index f56a1cc1bfb913..9c3985b08cbe45 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs
@@ -9,7 +9,7 @@ namespace System
// Base class for runtime implemented Type
public abstract class RuntimeType : TypeInfo
{
- public sealed override string GetEnumName(object value)
+ public sealed override string? GetEnumName(object value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/WeakReference.CoreRT.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/WeakReference.CoreRT.cs
index 41e765934c3013..5fc7acd35b6177 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/WeakReference.CoreRT.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/WeakReference.CoreRT.cs
@@ -80,7 +80,7 @@ public virtual object? Target
if (default(IntPtr) == h)
return null;
- object o = RuntimeImports.RhHandleGet(h);
+ object? o = RuntimeImports.RhHandleGet(h);
if (o == null)
{
diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp
index 21ef333d437082..49ee360c4a323e 100644
--- a/src/coreclr/pal/src/map/map.cpp
+++ b/src/coreclr/pal/src/map/map.cpp
@@ -1604,7 +1604,7 @@ static PAL_ERROR MAPGrowLocalFile( INT UnixFD, off_t NewSize )
TruncateRetVal = ftruncate( UnixFD, NewSize );
fstat( UnixFD, &FileInfo );
- if ( TruncateRetVal != 0 || FileInfo.st_size != (int) NewSize )
+ if ( TruncateRetVal != 0 || FileInfo.st_size != NewSize )
{
INT OrigSize;
CONST UINT BUFFER_SIZE = 128;
diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp
index 8f935b3e3ea1a8..19f9c86fd451cc 100644
--- a/src/coreclr/pal/src/misc/sysinfo.cpp
+++ b/src/coreclr/pal/src/misc/sysinfo.cpp
@@ -613,9 +613,15 @@ PAL_GetLogicalProcessorCacheSizeFromOS()
{
int64_t cacheSizeFromSysctl = 0;
size_t sz = sizeof(cacheSizeFromSysctl);
- const bool success = sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
+ const bool success = false
+ // macOS-arm64: Since macOS 12.0, Apple added ".perflevelX." to determinate cache sizes for efficiency
+ // and performance cores separetely. "perflevel0" stands for "performance"
+ || sysctlbyname("hw.perflevel0.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
+ // macOS-arm64: these report cache sizes for efficiency cores only:
+ || sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
|| sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0
|| sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0;
+
if (success)
{
_ASSERTE(cacheSizeFromSysctl > 0);
diff --git a/src/coreclr/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp b/src/coreclr/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp
index 96962eda3983a7..d9e354d0f7eaea 100644
--- a/src/coreclr/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp
+++ b/src/coreclr/pal/tests/palsuite/file_io/ReadFile/test2/ReadFile.cpp
@@ -14,13 +14,11 @@
** WriteFile
** GetLastError
**
-**
**===================================================================*/
#include
-
#define szStringTest "The quick fox jumped over the lazy dog's back.\0"
#define szEmptyString ""
#define szReadableFile "Readable.txt"
@@ -29,7 +27,6 @@
//Previously number of tests was 6, now 4 refer VSW 312690
#define NOOFTESTS 4
-const int PAGESIZE = 4096;
char *readBuffer_ReadFile_test2;
BOOL validateResults_ReadFile_test2(const char* szString, // string read
@@ -66,9 +63,9 @@ BOOL readTest_ReadFile_test2(DWORD dwByteCount, char cResult)
HANDLE hFile = NULL;
DWORD dwBytesRead;
BOOL bRc = FALSE;
-
- // open the test file
- hFile = CreateFile(szReadableFile,
+
+ // open the test file
+ hFile = CreateFile(szReadableFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
@@ -77,12 +74,15 @@ BOOL readTest_ReadFile_test2(DWORD dwByteCount, char cResult)
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
- Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n",
+ Trace("ReadFile: ERROR -> Unable to open file \"%s\".\n",
szReadableFile);
return FALSE;
}
- memset(readBuffer_ReadFile_test2, 0, PAGESIZE);
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+ long pageSize = sysInfo.dwPageSize;
+ memset(readBuffer_ReadFile_test2, 0, pageSize);
bRc = ReadFile(hFile, readBuffer_ReadFile_test2, dwByteCount, &dwBytesRead, NULL);
@@ -94,7 +94,7 @@ BOOL readTest_ReadFile_test2(DWORD dwByteCount, char cResult)
Trace("\nbRc = %d\n", bRc);
Trace("readBuffer = [%s] dwByteCount = %d dwBytesRead = %d\n", readBuffer_ReadFile_test2, dwByteCount, dwBytesRead);
Trace("cresult = 1\n");
- Trace("getlasterror = %d\n", GetLastError());
+ Trace("getlasterror = %d\n", GetLastError());
CloseHandle(hFile);
return FALSE;
}
@@ -121,51 +121,55 @@ BOOL readTest_ReadFile_test2(DWORD dwByteCount, char cResult)
PALTEST(file_io_ReadFile_test2_paltest_readfile_test2, "file_io/ReadFile/test2/paltest_readfile_test2")
{
HANDLE hFile = NULL;
- const int BUFFER_SIZE = 2 * PAGESIZE;
- DWORD dwByteCount[] = { 0,
- 10,
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+ long pageSize = sysInfo.dwPageSize;
+ long bufferSize = 2 * pageSize;
+
+ DWORD dwByteCount[] = { 0,
+ 10,
strlen(szStringTest),
- PAGESIZE
+ pageSize
// Commented out two negative test cases : Refer VSW 312690
- // 2 * PAGESIZE,
+ // 2 * pageSize,
// -1
};
DWORD oldProt;
- char szResults[] = "1111"; // Was "111100": Refer VSW 312690
+ char szResults[] = "1111"; // Was "111100": Refer VSW 312690
int i;
BOOL bRc = FALSE;
DWORD dwBytesWritten = 0;
-
+
if (0 != PAL_Initialize(argc,argv))
{
return FAIL;
}
/* allocate read-write memery for readBuffer */
- if (!(readBuffer_ReadFile_test2 = (char*) VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE)))
+ if (!(readBuffer_ReadFile_test2 = (char*) VirtualAlloc(NULL, bufferSize, MEM_COMMIT, PAGE_READWRITE)))
{
Fail("VirtualAlloc failed: GetLastError returns %d\n", GetLastError());
return FAIL;
}
-
+
/* write protect the second page of readBuffer */
- if (!VirtualProtect(&readBuffer_ReadFile_test2[PAGESIZE], PAGESIZE, PAGE_NOACCESS, &oldProt))
+ if (!VirtualProtect(&readBuffer_ReadFile_test2[pageSize], pageSize, PAGE_NOACCESS, &oldProt))
{
Fail("VirtualProtect failed: GetLastError returns %d\n", GetLastError());
return FAIL;
}
- // create the test file
- hFile = CreateFile(szReadableFile,
+ // create the test file
+ hFile = CreateFile(szReadableFile,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
-
+
if(hFile == INVALID_HANDLE_VALUE)
{
Fail("ReadFile: ERROR -> Unable to create file \"%s\" (%d).\n",
@@ -175,7 +179,7 @@ PALTEST(file_io_ReadFile_test2_paltest_readfile_test2, "file_io/ReadFile/test2/p
bRc = WriteFile(hFile, szStringTest, strlen(szStringTest), &dwBytesWritten, NULL);
CloseHandle(hFile);
-
+
for (i = 0; i< NOOFTESTS; i++)
{
bRc = readTest_ReadFile_test2(dwByteCount[i], szResults[i]);
@@ -184,9 +188,8 @@ PALTEST(file_io_ReadFile_test2_paltest_readfile_test2, "file_io/ReadFile/test2/p
Fail("ReadFile: ERROR -> Failed on test[%d]\n", i);
}
}
-
- VirtualFree(readBuffer_ReadFile_test2, BUFFER_SIZE, MEM_RELEASE);
+
+ VirtualFree(readBuffer_ReadFile_test2, bufferSize, MEM_RELEASE);
PAL_Terminate();
return PASS;
}
-
diff --git a/src/coreclr/pal/tests/palsuite/issues.targets b/src/coreclr/pal/tests/palsuite/issues.targets
index 6b0e8ae55667ad..2ed7e5b303bfca 100644
--- a/src/coreclr/pal/tests/palsuite/issues.targets
+++ b/src/coreclr/pal/tests/palsuite/issues.targets
@@ -31,10 +31,6 @@
-
-
- https://github.com/dotnet/runtime/issues/48783
-
https://github.com/dotnet/runtime/issues/48783
diff --git a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp
index d226ff5cf8d82d..ff5078f85209f3 100644
--- a/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp
+++ b/src/coreclr/pal/tests/palsuite/threading/NamedMutex/test1/nopal.cpp
@@ -14,9 +14,6 @@
#include
#include
-#undef PAGE_SIZE
-#define PAGE_SIZE (4096)
-
auto test_strcpy = strcpy;
auto test_strcmp = strcmp;
auto test_strlen = strlen;
@@ -50,7 +47,7 @@ bool WriteHeaderInfo(const char *path, char sharedMemoryType, char version, int
if (fd == -1)
return false;
*fdRef = fd;
- if (ftruncate(fd, PAGE_SIZE) != 0)
+ if (ftruncate(fd, getpagesize()) != 0)
return false;
if (lseek(fd, 0, SEEK_SET) != 0)
return false;
diff --git a/src/coreclr/scripts/jitutil.py b/src/coreclr/scripts/jitutil.py
index 5df464da5fc0cb..1f4306b9c34ebe 100644
--- a/src/coreclr/scripts/jitutil.py
+++ b/src/coreclr/scripts/jitutil.py
@@ -92,23 +92,22 @@ def set_pipeline_variable(name, value):
##
################################################################################
-def decode_string(str_to_decode):
+def decode_and_print(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.
+ String output. If there any encoding/decoding errors, it will not print anything
+ and return an empty string.
"""
+ output = ''
try:
output = str_to_decode.decode("utf-8", errors='replace')
- except UnicodeEncodeError:
- output = "UnicodeEncodeError"
- except UnicodeDecodeError:
- output = "UnicodeDecodeError"
- return output
+ print(output)
+ finally:
+ return output
def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None):
""" Runs the command.
@@ -138,15 +137,14 @@ 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 = decode_string(output.strip())
- print(output_str)
+ output_str = decode_and_print(output.strip())
of.write(output_str + "\n")
else:
command_stdout, command_stderr = proc.communicate()
if len(command_stdout) > 0:
- print(decode_string(command_stdout))
+ decode_and_print(command_stdout)
if len(command_stderr) > 0:
- print(decode_string(command_stderr))
+ decode_and_print(command_stderr)
return_code = proc.returncode
if _exit_on_fail and return_code != 0:
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
index 006409bdbb5338..858afde75164e2 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
@@ -86,12 +86,12 @@ static byte _getMethodInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHO
}
[UnmanagedCallersOnly]
- static CorInfoInline _canInline(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd, uint* pRestrictions)
+ static CorInfoInline _canInline(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
{
var _this = GetThis(thisHandle);
try
{
- return _this.canInline(callerHnd, calleeHnd, ref *pRestrictions);
+ return _this.canInline(callerHnd, calleeHnd);
}
catch (Exception ex)
{
@@ -2559,7 +2559,7 @@ static IntPtr GetUnmanagedCallbacks()
callbacks[2] = (delegate* unmanaged)&_setMethodAttribs;
callbacks[3] = (delegate* unmanaged)&_getMethodSig;
callbacks[4] = (delegate* unmanaged)&_getMethodInfo;
- callbacks[5] = (delegate* unmanaged)&_canInline;
+ callbacks[5] = (delegate* unmanaged)&_canInline;
callbacks[6] = (delegate* unmanaged)&_reportInliningDecision;
callbacks[7] = (delegate* unmanaged)&_canTailCall;
callbacks[8] = (delegate* unmanaged)&_reportTailCallDecision;
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index cd464db7955341..41c4663ed720e2 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -1159,7 +1159,7 @@ private bool getMethodInfo(CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_INFO* inf
return Get_CORINFO_METHOD_INFO(method, methodIL, info);
}
- private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd, ref uint pRestrictions)
+ private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd)
{
MethodDesc callerMethod = HandleToObject(callerHnd);
MethodDesc calleeMethod = HandleToObject(calleeHnd);
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
index 4a7d254d583fcf..3e348263103855 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
@@ -498,16 +498,6 @@ public enum CorInfoInlineTypeCheckSource
CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN = 0x00000001, // Type handle comes from an ldtoken
}
- public enum CorInfoInlineRestrictions
- {
- INLINE_RESPECT_BOUNDARY = 0x00000001, // You can inline if there are no calls from the method being inlined
- INLINE_NO_CALLEE_LDSTR = 0x00000002, // You can inline only if you guarantee that if inlinee does an ldstr
- // inlinee's module will never see that string (by any means).
- // This is due to how we implement the NoStringInterningAttribute
- // (by reusing the fixup table).
- INLINE_SAME_THIS = 0x00000004, // You can inline only if the callee is on the same this reference as caller
- }
-
// If you add more values here, keep it in sync with TailCallTypeMap in ..\vm\ClrEtwAll.man
// and the string enum in CEEInfo::reportTailCallDecision in ..\vm\JITInterface.cpp
public enum CorInfoTailCall
diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
index 92bc30aaf2570b..7cccae04c4151c 100644
--- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
+++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
@@ -158,7 +158,7 @@ FUNCTIONS
void setMethodAttribs( CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs );
void getMethodSig( CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig, CORINFO_CLASS_HANDLE memberParent );
bool getMethodInfo( CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info );
- CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, uint32_t* pRestrictions );
+ CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd);
void reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char * reason);
bool canTailCall( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE declaredCalleeHnd, CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix );
void reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char * reason);
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs
index e915f9518ad043..c36e39f224859a 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/LockFreeReaderHashtable.cs
@@ -540,7 +540,7 @@ private void WriteAbortNullToLocation(TValue[] hashTableLocal, int tableIndex)
// Add to hash, use a volatile write to ensure that
// the contents of the value are fully published to all
// threads before adding to the hashtable
- Volatile.Write(ref hashTableLocal[tableIndex], null);
+ Volatile.Write(ref hashTableLocal[tableIndex], default(TValue)!);
}
[MethodImpl(MethodImplOptions.NoInlining)]
diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs
index 537b494b0d6f9d..2247f551fc29d1 100644
--- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs
@@ -535,6 +535,8 @@ public MarshalAsDescriptor ParseMarshalAsDescriptor()
NativeTypeKind type = (NativeTypeKind)_reader.ReadByte();
NativeTypeKind arraySubType = NativeTypeKind.Default;
uint? paramNum = null, numElem = null;
+ string cookie = null;
+ TypeDesc marshallerType = null;
switch (type)
{
@@ -607,9 +609,6 @@ public MarshalAsDescriptor ParseMarshalAsDescriptor()
break;
case NativeTypeKind.CustomMarshaler:
{
- // There's nobody to consume CustomMarshaller, so let's just parse the data
- // to avoid asserting later.
-
// Read typelib guid
_reader.ReadSerializedString();
@@ -617,10 +616,11 @@ public MarshalAsDescriptor ParseMarshalAsDescriptor()
_reader.ReadSerializedString();
// Read managed marshaler name
- _reader.ReadSerializedString();
+ var customMarshallerTypeName = _reader.ReadSerializedString();
+ marshallerType = _ecmaModule.GetTypeByCustomAttributeTypeName(customMarshallerTypeName, true);
// Read cookie
- _reader.ReadSerializedString();
+ cookie = _reader.ReadSerializedString();
}
break;
default:
@@ -629,7 +629,7 @@ public MarshalAsDescriptor ParseMarshalAsDescriptor()
Debug.Assert(_reader.RemainingBytes == 0);
- return new MarshalAsDescriptor(type, arraySubType, paramNum, numElem);
+ return new MarshalAsDescriptor(type, arraySubType, paramNum, numElem, marshallerType, cookie);
}
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
index d37f44971968b7..e9a889f8233e10 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
@@ -173,6 +173,9 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type,
#if !READYTORUN
case MarshallerKind.Variant:
return InteropTypes.GetVariant(context);
+
+ case MarshallerKind.CustomMarshaler:
+ return context.GetWellKnownType(WellKnownType.IntPtr);
#endif
case MarshallerKind.OleCurrency:
@@ -249,6 +252,14 @@ internal static MarshallerKind GetMarshallerKind(
if (marshalAs != null)
nativeType = marshalAs.Type;
+ if (nativeType == NativeTypeKind.CustomMarshaler)
+ {
+ if (isField)
+ return MarshallerKind.FailedTypeLoad;
+ else
+ return MarshallerKind.CustomMarshaler;
+ }
+
//
// Determine MarshalerKind
//
@@ -574,6 +585,9 @@ internal static MarshallerKind GetMarshallerKind(
case NativeTypeKind.AnsiBStr:
return MarshallerKind.AnsiBSTRString;
+ case NativeTypeKind.CustomMarshaler:
+ return MarshallerKind.CustomMarshaler;
+
case NativeTypeKind.Default:
if (isAnsi)
return MarshallerKind.AnsiString;
@@ -663,7 +677,9 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Invalid;
}
else
+ {
return MarshallerKind.Invalid;
+ }
}
private static MarshallerKind GetArrayElementMarshallerKind(
@@ -834,6 +850,8 @@ private static MarshallerKind GetArrayElementMarshallerKind(
return MarshallerKind.BSTRString;
case NativeTypeKind.AnsiBStr:
return MarshallerKind.AnsiBSTRString;
+ case NativeTypeKind.CustomMarshaler:
+ return MarshallerKind.CustomMarshaler;
default:
return MarshallerKind.Invalid;
}
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 01b27026152389..cd1395d9115b56 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
@@ -90,6 +90,8 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind)
return new FailedTypeLoadMarshaller();
case MarshallerKind.Variant:
return new VariantMarshaller();
+ case MarshallerKind.CustomMarshaler:
+ return new CustomTypeMarshaller();
default:
// ensures we don't throw during create marshaller. We will throw NSE
// during EmitIL which will be handled and an Exception method body
@@ -1144,4 +1146,136 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)
codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));
}
}
+
+ class CustomTypeMarshaller : Marshaller
+ {
+ private ILLocalVariable MarshallerLocalVariable = (ILLocalVariable)(-1);
+
+ private ILLocalVariable InitializeMarshallerVariable()
+ {
+ if (MarshallerLocalVariable != (ILLocalVariable)(-1))
+ {
+ return MarshallerLocalVariable;
+ }
+
+ var marshallerType = MarshalAsDescriptor.MarshallerType;
+ if (marshallerType.IsGenericDefinition)
+ {
+ ThrowHelper.ThrowTypeLoadException(marshallerType);
+ }
+
+ var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
+ var getInstanceMethod = marshallerType.GetMethod(
+ "GetInstance",
+ new MethodSignature(MethodSignatureFlags.Static, 0, customMarshallerType, new[] { Context.GetWellKnownType(WellKnownType.String) }));
+ if (ManagedType.IsValueType || ManagedType.IsPointer || ManagedType.IsFunctionPointer)
+ {
+ ThrowHelper.ThrowMarshalDirectiveException();
+ }
+
+ var initializeCustomMarshallerMethod = Context.GetHelperEntryPoint("InteropHelpers", "InitializeCustomMarshaller");
+
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+ MarshallerLocalVariable = emitter.NewLocal(customMarshallerType);
+ var cookie = MarshalAsDescriptor.Cookie;
+
+ // Custom marshaller initialization should not be catched, so initialize early
+ ILCodeStream fnptrLoadStream = _ilCodeStreams.FunctionPointerLoadStream;
+ fnptrLoadStream.Emit(ILOpcode.ldtoken, emitter.NewToken(ManagedType));
+ fnptrLoadStream.Emit(ILOpcode.ldtoken, emitter.NewToken(marshallerType));
+ fnptrLoadStream.Emit(ILOpcode.ldstr, emitter.NewToken(cookie));
+ if (getInstanceMethod != null)
+ {
+ fnptrLoadStream.Emit(ILOpcode.ldftn, emitter.NewToken(getInstanceMethod));
+ }
+ else
+ {
+ fnptrLoadStream.EmitLdc(0);
+ fnptrLoadStream.Emit(ILOpcode.conv_i);
+ }
+
+ fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(initializeCustomMarshallerMethod));
+ fnptrLoadStream.EmitStLoc(MarshallerLocalVariable);
+ return MarshallerLocalVariable;
+ }
+
+ protected override void TransformManagedToNative(ILCodeStream codeStream)
+ {
+ var lMarshaller = InitializeMarshallerVariable();
+
+ var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+ var manageToNativeMethod = customMarshallerType.GetKnownMethod(
+ "MarshalManagedToNative",
+ new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.IntPtr), new[] { Context.GetWellKnownType(WellKnownType.Object) }));
+
+ codeStream.EmitLdLoc(lMarshaller);
+ LoadManagedValue(codeStream);
+ codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(manageToNativeMethod));
+ StoreNativeValue(codeStream);
+ if (MarshalDirection == MarshalDirection.Forward)
+ {
+ if (In && Out)
+ {
+ EmitCleanUpManagedData(codeStream);
+ }
+
+ EmitCleanUpNativeData(_ilCodeStreams.CleanupCodeStream);
+ }
+ else
+ {
+ EmitCleanUpManagedData(codeStream);
+ }
+ }
+
+ protected override void TransformNativeToManaged(ILCodeStream codeStream)
+ {
+ var lMarshaller = InitializeMarshallerVariable();
+
+ var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+ var marshalNativeToManagedMethod = customMarshallerType.GetKnownMethod(
+ "MarshalNativeToManaged",
+ new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Object), new[] { Context.GetWellKnownType(WellKnownType.IntPtr) }));
+
+ codeStream.EmitLdLoc(lMarshaller);
+ LoadNativeValue(codeStream);
+ codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(marshalNativeToManagedMethod));
+ StoreManagedValue(codeStream);
+ }
+
+ protected void EmitCleanUpManagedData(ILCodeStream codeStream)
+ {
+ var lMarshaller = InitializeMarshallerVariable();
+
+ var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+
+ // Call CleanUpManagedData on cleanup code stream.
+ var cleanupManagedDataMethod = customMarshallerType.GetKnownMethod(
+ "CleanUpManagedData",
+ new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), new[] { Context.GetWellKnownType(WellKnownType.Object) }));
+
+ codeStream.EmitLdLoc(lMarshaller);
+ LoadManagedValue(codeStream);
+ codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(cleanupManagedDataMethod));
+ }
+
+ protected void EmitCleanUpNativeData(ILCodeStream codeStream)
+ {
+ var lMarshaller = InitializeMarshallerVariable();
+
+ var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+
+ // Call CleanUpNativeData on cleanup code stream.
+ var cleanupNativeDataMethod = customMarshallerType.GetKnownMethod(
+ "CleanUpNativeData",
+ new MethodSignature(MethodSignatureFlags.None, 0, Context.GetWellKnownType(WellKnownType.Void), new[] { Context.GetWellKnownType(WellKnownType.IntPtr) }));
+
+ codeStream.EmitLdLoc(lMarshaller);
+ LoadNativeValue(codeStream);
+ codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(cleanupNativeDataMethod));
+ }
+ }
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs
index 888a174ff38fcc..8d4fb58a45d191 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshallerKind.cs
@@ -48,6 +48,7 @@ enum MarshallerKind
FailedTypeLoad,
ComInterface,
BlittableValueClassWithCopyCtor,
+ CustomMarshaler,
Invalid
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs
index 91f3c9d2fe0773..c76e2cf469350d 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/MarshalAsDescriptor.cs
@@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
using System;
+using System.Diagnostics;
namespace Internal.TypeSystem
{
@@ -48,17 +49,39 @@ public enum NativeTypeKind : byte
public class MarshalAsDescriptor
{
+ private TypeDesc _marshallerType;
+ private string _cookie;
+
public NativeTypeKind Type { get; }
public NativeTypeKind ArraySubType { get; }
public uint? SizeParamIndex { get; }
public uint? SizeConst { get; }
+ public TypeDesc MarshallerType
+ {
+ get
+ {
+ Debug.Assert(Type == NativeTypeKind.CustomMarshaler, "Marshaller type can be set only when using for CustomMarshaller");
+ return _marshallerType;
+ }
+ }
+
+ public string Cookie
+ {
+ get
+ {
+ Debug.Assert(Type == NativeTypeKind.CustomMarshaler, "Cookie can be set only when using for CustomMarshaller");
+ return _cookie;
+ }
+ }
- public MarshalAsDescriptor(NativeTypeKind type, NativeTypeKind arraySubType, uint? sizeParamIndex, uint? sizeConst)
+ public MarshalAsDescriptor(NativeTypeKind type, NativeTypeKind arraySubType, uint? sizeParamIndex, uint? sizeConst, TypeDesc customMarshallerType, string cookie)
{
Type = type;
ArraySubType = arraySubType;
SizeParamIndex = sizeParamIndex;
SizeConst = sizeConst;
+ _marshallerType = customMarshallerType;
+ _cookie = cookie;
}
}
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
index 1f462113d8e0c4..44eada8ff9ae68 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
@@ -142,7 +142,6 @@ protected override void EmitCode(NodeFactory factory, ref ARMEmitter encoder, bo
}
else
{
- ISymbolNode targetMethodNode = target.GetTargetNode(factory);
encoder.EmitMOV(encoder.TargetRegister.Arg2, target.GetTargetNode(factory));
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs
index 0b9068e3a13f24..3574e998d8fa1d 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs
@@ -147,7 +147,6 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder,
}
else
{
- ISymbolNode targetMethodNode = target.GetTargetNode(factory);
encoder.EmitMOV(encoder.TargetRegister.Arg2, target.GetTargetNode(factory));
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
index 07ab13b13d2c70..2c80e0b0faafba 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
@@ -150,7 +150,6 @@ protected override void EmitCode(NodeFactory factory, ref X64Emitter encoder, bo
}
else
{
- ISymbolNode targetMethodNode = target.GetTargetNode(factory);
encoder.EmitLEAQ(encoder.TargetRegister.Arg2, target.GetTargetNode(factory));
}
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
index ae9e60343dfb42..23a2af0219da7c 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
@@ -270,7 +270,7 @@ internal override VTableSliceNode GetSlice(TypeDesc type)
{
if (!_vtableSlices.TryGetValue(type, out IReadOnlyList slots))
{
- // If we couln't find the vtable slice information for this type, it's because the scanner
+ // If we couldn't find the vtable slice information for this type, it's because the scanner
// didn't correctly predict what will be needed.
// To troubleshoot, compare the dependency graph of the scanner and the compiler.
// Follow the path from the node that requested this node to the root.
@@ -318,7 +318,7 @@ private DictionaryLayoutNode GetPrecomputedLayout(TypeSystemEntity methodOrType)
{
if (!_layouts.TryGetValue(methodOrType, out IEnumerable layout))
{
- // If we couln't find the dictionary layout information for this, it's because the scanner
+ // If we couldn't find the dictionary layout information for this, it's because the scanner
// didn't correctly predict what will be needed.
// To troubleshoot, compare the dependency graph of the scanner and the compiler.
// Follow the path from the node that requested this node to the root.
diff --git a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Type.cs b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Type.cs
index ca81bd42d8e4c2..6ce9159a12dafd 100644
--- a/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Type.cs
+++ b/src/coreclr/tools/aot/ILCompiler.MetadataTransform/ILCompiler/Metadata/Transform.Type.cs
@@ -261,17 +261,43 @@ private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record)
record.PackingSize = checked((ushort)layoutMetadata.PackingSize);
record.Flags = GetTypeAttributes(entity);
- if (entity.HasBaseType)
+ try
{
- record.BaseType = HandleType(entity.BaseType);
+ if (entity.HasBaseType)
+ {
+ record.BaseType = HandleType(entity.BaseType);
+ }
+ }
+ catch (Cts.TypeSystemException) when (HasNestedTypes(entity))
+ {
+ // We might have been forced to generate metadata for a type
+ // that wasn't looked at during code generation because it's an owning
+ // type of a type we did look at. Allow those to generate incomplete
+ // metadata. The ultimate fix is to rewrite metadata generation to be
+ // System.Reflection.Metadata-based as opposed to type system based.
+ // If there's no nested types, this is a bug and should tear down
+ // the compiler at this point.
}
- record.Interfaces.Capacity = entity.ExplicitlyImplementedInterfaces.Length;
- foreach (var interfaceType in entity.ExplicitlyImplementedInterfaces)
+ try
+ {
+ record.Interfaces.Capacity = entity.ExplicitlyImplementedInterfaces.Length;
+ foreach (var interfaceType in entity.ExplicitlyImplementedInterfaces)
+ {
+ if (IsBlocked(interfaceType))
+ continue;
+ record.Interfaces.Add(HandleType(interfaceType));
+ }
+ }
+ catch (Cts.TypeSystemException) when (HasNestedTypes(entity))
{
- if (IsBlocked(interfaceType))
- continue;
- record.Interfaces.Add(HandleType(interfaceType));
+ // We might have been forced to generate metadata for a type
+ // that wasn't looked at during code generation because it's an owning
+ // type of a type we did look at. Allow those to generate incomplete
+ // metadata. The ultimate fix is to rewrite metadata generation to be
+ // System.Reflection.Metadata-based as opposed to type system based.
+ // If there's no nested types, this is a bug and should tear down
+ // the compiler at this point.
}
if (entity.HasInstantiation)
@@ -346,6 +372,9 @@ private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record)
record.MethodImpls.Add(methodImplRecord);
}*/
}
+
+ static bool HasNestedTypes(Cts.MetadataType entity)
+ => entity.GetNestedTypes().GetEnumerator().MoveNext();
}
private TypeAttributes GetTypeAttributes(Cts.MetadataType type)
diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
index 4eab54b43b8628..c732d55ef2546a 100644
--- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
@@ -1072,7 +1072,12 @@ private void ParsePgoMethods()
PgoInfoKey key = new PgoInfoKey(mdReader, owningType, methodHandle, methodTypeArgs);
PgoInfo info = new PgoInfo(key, this, pgoFormatVersion, Image, pgoOffset);
- _pgoInfos.Add(key, info);
+
+ // Since we do non-assembly qualified name based matching for generic instantiations, we can have conflicts.
+ // This is rare, so the current strategy is to just ignore them. This will allow the tooling to work, although
+ // the text output for PGO will be slightly wrong.
+ if (!_pgoInfos.ContainsKey(key))
+ _pgoInfos.Add(key, info);
curParser = allEntriesEnum.GetNext();
}
diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs
index 7e2b624a3131fc..839626e6d5d9e8 100644
--- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs
+++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs
@@ -210,7 +210,7 @@ private void CompileSingleMethod(CorInfoImpl corInfo, MethodCodeNode methodCodeN
Logger.LogWarning(method, DiagnosticId.COMInteropNotSupportedInFullAOT);
}
if ((_compilationOptions & RyuJitCompilationOptions.UseResilience) != 0)
- Logger.LogMessage($"Ignoring unresolved method {method}, because: {exception.Message}");
+ Logger.LogMessage($"Method '{method}' will always throw because: {exception.Message}");
else
Logger.LogError($"Method will always throw because: {exception.Message}", 1005, method, MessageSubCategory.AotAnalysis);
}
diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs
index a1446f9d3ff274..bc29c680363f04 100644
--- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs
+++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs
@@ -22,6 +22,7 @@ public sealed class RyuJitCompilationBuilder : CompilationBuilder
private KeyValuePair[] _ryujitOptions = Array.Empty>();
private ILProvider _ilProvider = new CoreRTILProvider();
private ProfileDataManager _profileDataManager;
+ private string _jitPath;
public RyuJitCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
: base(context, group,
@@ -35,6 +36,12 @@ public RyuJitCompilationBuilder UseProfileData(IEnumerable mibcFiles)
return this;
}
+ public RyuJitCompilationBuilder UseJitPath(string jitPath)
+ {
+ _jitPath = jitPath;
+ return this;
+ }
+
public override CompilationBuilder UseBackendOptions(IEnumerable options)
{
var builder = new ArrayBuilder>();
@@ -118,7 +125,7 @@ public override ICompilation ToCompilation()
var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, _interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider, GetPreinitializationManager());
- JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions);
+ JitConfigProvider.Initialize(_context.Target, jitFlagBuilder.ToArray(), _ryujitOptions, _jitPath);
DependencyAnalyzerBase graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer()));
return new RyuJitCompilation(graph, factory, _compilationRoots, _ilProvider, _debugInformationProvider, _logger, _devirtualizationManager, _inliningPolicy ?? _compilationGroup, _instructionSetSupport, _profileDataManager, _methodImportationErrorProvider, options, _parallelism);
}
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 1b1fbdf550777d..4706aaa7f7901c 100644
--- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
+++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
@@ -748,8 +748,17 @@ private bool canTailCall(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUC
private InfoAccessType constructStringLiteral(CORINFO_MODULE_STRUCT_* module, mdToken metaTok, ref void* ppValue)
{
MethodIL methodIL = (MethodIL)HandleToObject((IntPtr)module);
- object literal = methodIL.GetObject((int)metaTok);
- ISymbolNode stringObject = _compilation.NodeFactory.SerializedStringObject((string)literal);
+
+ ISymbolNode stringObject;
+ if (metaTok == (mdToken)CorConstants.CorTokenType.mdtString)
+ {
+ stringObject = _compilation.NodeFactory.SerializedStringObject("");
+ }
+ else
+ {
+ object literal = methodIL.GetObject((int)metaTok);
+ stringObject = _compilation.NodeFactory.SerializedStringObject((string)literal);
+ }
ppValue = (void*)ObjectToHandle(stringObject);
return stringObject.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE;
}
diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs
index 51400a9e939be0..94bfbcc86e848a 100644
--- a/src/coreclr/tools/aot/ILCompiler/Program.cs
+++ b/src/coreclr/tools/aot/ILCompiler/Program.cs
@@ -62,6 +62,7 @@ internal class Program
private string _guard;
private int _maxGenericCycle = CompilerTypeSystemContext.DefaultGenericCycleCutoffPoint;
private bool _useDwarf5;
+ private string _jitPath;
private string _singleMethodTypeName;
private string _singleMethodName;
@@ -230,6 +231,7 @@ private ArgumentSyntax ParseCommandLine(string[] args)
syntax.DefineOption("targetarch", ref _targetArchitectureStr, "Target architecture for cross compilation");
syntax.DefineOption("targetos", ref _targetOSStr, "Target OS for cross compilation");
+ syntax.DefineOption("jitpath", ref _jitPath, "Path to JIT compiler library");
syntax.DefineOption("singlemethodtypename", ref _singleMethodTypeName, "Single method compilation: assembly-qualified name of the owning type");
syntax.DefineOption("singlemethodname", ref _singleMethodName, "Single method compilation: name of the method");
@@ -642,6 +644,8 @@ static string ILLinkify(string rootedAssembly)
if (_mibcFilePaths.Count > 0)
((RyuJitCompilationBuilder)builder).UseProfileData(_mibcFilePaths);
+ if (!String.IsNullOrEmpty(_jitPath))
+ ((RyuJitCompilationBuilder)builder).UseJitPath(_jitPath);
PInvokeILEmitterConfiguration pinvokePolicy = new ConfigurablePInvokePolicy(typeSystemContext.Target, _directPInvokes, _directPInvokeLists);
diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h
index 14286588063b23..9f802bdb461836 100644
--- a/src/coreclr/tools/aot/jitinterface/jitinterface.h
+++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h
@@ -16,7 +16,7 @@ struct JitInterfaceCallbacks
void (* setMethodAttribs)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs);
void (* getMethodSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent);
bool (* getMethodInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info);
- CorInfoInline (* canInline)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, uint32_t* pRestrictions);
+ CorInfoInline (* canInline)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd);
void (* reportInliningDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char* reason);
bool (* canTailCall)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE declaredCalleeHnd, CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix);
void (* reportTailCallDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char* reason);
@@ -247,11 +247,10 @@ class JitInterfaceWrapper : public ICorJitInfo
virtual CorInfoInline canInline(
CORINFO_METHOD_HANDLE callerHnd,
- CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions)
+ CORINFO_METHOD_HANDLE calleeHnd)
{
CorInfoExceptionClass* pException = nullptr;
- CorInfoInline temp = _callbacks->canInline(_thisHandle, &pException, callerHnd, calleeHnd, pRestrictions);
+ CorInfoInline temp = _callbacks->canInline(_thisHandle, &pException, callerHnd, calleeHnd);
if (pException != nullptr) throw pException;
return temp;
}
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
index fd2a35093c7dec..1cd8a06b0aa277 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
@@ -66,7 +66,6 @@ struct DLDL
struct Agnostic_CanInline
{
- DWORD Restrictions;
DWORD result;
DWORD exceptionCode;
};
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
index ab8717dae42e80..21526c49fb5f4d 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
@@ -1293,7 +1293,6 @@ LPCWSTR MethodContext::repGetJitTimeLogFilename()
void MethodContext::recCanInline(CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions,
CorInfoInline response,
DWORD exceptionCode)
{
@@ -1306,10 +1305,6 @@ void MethodContext::recCanInline(CORINFO_METHOD_HANDLE callerHnd,
key.B = CastHandle(calleeHnd);
Agnostic_CanInline value;
- if (pRestrictions != nullptr)
- value.Restrictions = (DWORD)*pRestrictions;
- else
- value.Restrictions = (DWORD)0;
value.result = (DWORD)response;
value.exceptionCode = (DWORD)exceptionCode;
@@ -1318,12 +1313,11 @@ void MethodContext::recCanInline(CORINFO_METHOD_HANDLE callerHnd,
}
void MethodContext::dmpCanInline(DLDL key, const Agnostic_CanInline& value)
{
- printf("CanInline key - callerHnd-%016llX calleeHnd-%016llX, value pRestrictions-%u result-%u exceptionCode-%08X",
- key.A, key.B, value.Restrictions, value.result, value.exceptionCode);
+ printf("CanInline key - callerHnd-%016llX calleeHnd-%016llX, value result-%u exceptionCode-%08X",
+ key.A, key.B, value.result, value.exceptionCode);
}
CorInfoInline MethodContext::repCanInline(CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions,
DWORD* exceptionCode)
{
DLDL key;
@@ -1347,8 +1341,6 @@ CorInfoInline MethodContext::repCanInline(CORINFO_METHOD_HANDLE callerHnd,
*exceptionCode = value.exceptionCode;
- if (pRestrictions != nullptr)
- *pRestrictions = (DWORD)value.Restrictions;
CorInfoInline response = (CorInfoInline)value.result;
return response;
}
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
index d18c531dd86483..dc2e733e343fe7 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
@@ -193,13 +193,11 @@ class MethodContext
void recCanInline(CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions,
CorInfoInline response,
DWORD exceptionCode);
void dmpCanInline(DLDL key, const Agnostic_CanInline& value);
CorInfoInline repCanInline(CORINFO_METHOD_HANDLE callerHnd,
CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions,
DWORD* exceptionCode);
void recResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, DWORD exceptionCode);
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
index 061d3d6a77b927..f347a616f96f4c 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
@@ -89,17 +89,14 @@ bool interceptor_ICJI::getMethodInfo(CORINFO_METHOD_HANDLE ftn, /* IN */
}
// Decides if you have any limitations for inlining. If everything's OK, it will return
-// INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
-// function must respect. If caller passes pRestrictions = nullptr, if there are any restrictions
-// INLINE_FAIL will be returned
+// INLINE_PASS.
//
// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
//
// The inlined method need not be verified
CorInfoInline interceptor_ICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* IN */
- CORINFO_METHOD_HANDLE calleeHnd, /* IN */
- uint32_t* pRestrictions /* OUT */
+ CORINFO_METHOD_HANDLE calleeHnd /* IN */
)
{
CorInfoInline temp = INLINE_NEVER;
@@ -108,11 +105,11 @@ CorInfoInline interceptor_ICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /*
[&]()
{
mc->cr->AddCall("canInline");
- temp = original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
+ temp = original_ICorJitInfo->canInline(callerHnd, calleeHnd);
},
[&](DWORD exceptionCode)
{
- this->mc->recCanInline(callerHnd, calleeHnd, pRestrictions, temp, exceptionCode);
+ this->mc->recCanInline(callerHnd, calleeHnd, temp, exceptionCode);
});
return temp;
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp
index 657575cce71fe3..66f792968885d8 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp
@@ -53,11 +53,10 @@ bool interceptor_ICJI::getMethodInfo(
CorInfoInline interceptor_ICJI::canInline(
CORINFO_METHOD_HANDLE callerHnd,
- CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions)
+ CORINFO_METHOD_HANDLE calleeHnd)
{
mcs->AddCall("canInline");
- return original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
+ return original_ICorJitInfo->canInline(callerHnd, calleeHnd);
}
void interceptor_ICJI::reportInliningDecision(
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
index 294750ccde5c1a..cd38c2c7759390 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp
@@ -48,10 +48,9 @@ bool interceptor_ICJI::getMethodInfo(
CorInfoInline interceptor_ICJI::canInline(
CORINFO_METHOD_HANDLE callerHnd,
- CORINFO_METHOD_HANDLE calleeHnd,
- uint32_t* pRestrictions)
+ CORINFO_METHOD_HANDLE calleeHnd)
{
- return original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
+ return original_ICorJitInfo->canInline(callerHnd, calleeHnd);
}
void interceptor_ICJI::reportInliningDecision(
diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
index 16c66a6a398476..d90f0b5e097068 100644
--- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
@@ -81,23 +81,20 @@ bool MyICJI::getMethodInfo(CORINFO_METHOD_HANDLE ftn, /* IN */
}
// Decides if you have any limitations for inlining. If everything's OK, it will return
-// INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
-// function must respect. If caller passes pRestrictions = nullptr, if there are any restrictions
-// INLINE_FAIL will be returned
+// INLINE_PASS.
//
// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
//
// The inlined method need not be verified
CorInfoInline MyICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* IN */
- CORINFO_METHOD_HANDLE calleeHnd, /* IN */
- uint32_t* pRestrictions /* OUT */
+ CORINFO_METHOD_HANDLE calleeHnd /* IN */
)
{
jitInstance->mc->cr->AddCall("canInline");
DWORD exceptionCode = 0;
- CorInfoInline result = jitInstance->mc->repCanInline(callerHnd, calleeHnd, pRestrictions, &exceptionCode);
+ CorInfoInline result = jitInstance->mc->repCanInline(callerHnd, calleeHnd, &exceptionCode);
if (exceptionCode != 0)
ThrowException(exceptionCode);
return result;
diff --git a/src/coreclr/utilcode/stresslog.cpp b/src/coreclr/utilcode/stresslog.cpp
index 5d13b2ec7695ca..0d6f4cd53c93f0 100644
--- a/src/coreclr/utilcode/stresslog.cpp
+++ b/src/coreclr/utilcode/stresslog.cpp
@@ -965,6 +965,19 @@ void* __cdecl ThreadStressLog::operator new(size_t n, const NoThrow&) NOEXCEPT
return malloc(n);
#endif //HOST_WINDOWS
}
+
+void __cdecl ThreadStressLog::operator delete(void* p)
+{
+ if (StressLogChunk::s_memoryMapped)
+ return; // Giving up, we will just leak it instead of building a sophisticated allocator
+#ifdef HOST_WINDOWS
+ _ASSERTE(StressLogChunk::s_LogChunkHeap);
+ HeapFree(StressLogChunk::s_LogChunkHeap, 0, p);
+#else
+ free(p);
+#endif //HOST_WINDOWS
+}
+
#endif //MEMORY_MAPPED_STRESSLOG
#endif // STRESS_LOG
diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp
index c25b7aa19cc9d1..5344eb22dc9144 100644
--- a/src/coreclr/vm/ceeload.cpp
+++ b/src/coreclr/vm/ceeload.cpp
@@ -432,7 +432,7 @@ void Module::SetNativeMetadataAssemblyRefInCache(DWORD rid, PTR_Assembly pAssemb
_ASSERTE(m_NativeMetadataAssemblyRefMap != NULL);
_ASSERTE(rid <= GetNativeMetadataAssemblyCount());
- m_NativeMetadataAssemblyRefMap[rid - 1] = pAssembly;
+ VolatileStore(&m_NativeMetadataAssemblyRefMap[rid - 1], pAssembly);
}
// Module initialization occurs in two phases: the constructor phase and the Initialize phase.
@@ -1596,75 +1596,6 @@ InstrumentedILOffsetMapping Module::GetInstrumentedILOffsetMapping(mdMethodDef t
#ifndef DACCESS_COMPILE
-
-BOOL Module::IsNoStringInterning()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACTL_END
-
- if (!(m_dwPersistedFlags & COMPUTED_STRING_INTERNING))
- {
- // Default is string interning
- BOOL fNoStringInterning = FALSE;
-
- HRESULT hr;
-
- IMDInternalImport *mdImport = GetAssembly()->GetMDImport();
- _ASSERTE(mdImport);
-
- mdToken token;
- IfFailThrow(mdImport->GetAssemblyFromScope(&token));
-
- const BYTE *pVal;
- ULONG cbVal;
-
- hr = mdImport->GetCustomAttributeByName(token,
- COMPILATIONRELAXATIONS_TYPE,
- (const void**)&pVal, &cbVal);
-
- // Parse the attribute
- if (hr == S_OK)
- {
- CustomAttributeParser cap(pVal, cbVal);
- IfFailThrow(cap.SkipProlog());
-
- // Get Flags
- UINT32 flags;
- IfFailThrow(cap.GetU4(&flags));
-
- if (flags & CompilationRelaxations_NoStringInterning)
- {
- fNoStringInterning = TRUE;
- }
- }
-
-#ifdef _DEBUG
- static ConfigDWORD g_NoStringInterning;
- DWORD dwOverride = g_NoStringInterning.val(CLRConfig::INTERNAL_NoStringInterning);
-
- if (dwOverride == 0)
- {
- // Disabled
- fNoStringInterning = FALSE;
- }
- else if (dwOverride == 2)
- {
- // Always true (testing)
- fNoStringInterning = TRUE;
- }
-#endif // _DEBUG
-
- FastInterlockOr(&m_dwPersistedFlags, COMPUTED_STRING_INTERNING |
- (fNoStringInterning ? NO_STRING_INTERNING : 0));
- }
-
- return !!(m_dwPersistedFlags & NO_STRING_INTERNING);
-}
-
BOOL Module::HasDefaultDllImportSearchPathsAttribute()
{
CONTRACTL
@@ -3102,7 +3033,7 @@ void Module::InitializeStringData(DWORD token, EEStringData *pstrData, CQuickByt
}
-OBJECTHANDLE Module::ResolveStringRef(DWORD token, BaseDomain *pDomain, bool bNeedToSyncWithFixups)
+OBJECTHANDLE Module::ResolveStringRef(DWORD token, BaseDomain *pDomain)
{
CONTRACTL
{
diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h
index d9cd6742cb6c0e..a97be226fb9fba 100644
--- a/src/coreclr/vm/ceeload.h
+++ b/src/coreclr/vm/ceeload.h
@@ -805,9 +805,8 @@ class Module
// unused = 0x00000001,
COMPUTED_GLOBAL_CLASS = 0x00000002,
- // This flag applies to assembly, but it is stored so it can be cached in ngen image
- COMPUTED_STRING_INTERNING = 0x00000004,
- NO_STRING_INTERNING = 0x00000008,
+ // unused = 0x00000004,
+ // unused = 0x00000008,
// This flag applies to assembly, but it is stored so it can be cached in ngen image
COMPUTED_WRAP_EXCEPTIONS = 0x00000010,
@@ -1400,7 +1399,7 @@ class Module
void InitializeStringData(DWORD token, EEStringData *pstrData, CQuickBytes *pqb);
// Resolving
- OBJECTHANDLE ResolveStringRef(DWORD Token, BaseDomain *pDomain, bool bNeedToSyncWithFixups);
+ OBJECTHANDLE ResolveStringRef(DWORD Token, BaseDomain *pDomain);
CHECK CheckStringRef(RVA rva);
@@ -2024,13 +2023,6 @@ class Module
public:
- //-----------------------------------------------------------------------------------------
- // If true, strings only need to be interned at a per module basis, instead of at a
- // per appdomain basis, which is the default. Use the module accessor so you don't need
- // to touch the metadata in the ngen case
- //-----------------------------------------------------------------------------------------
- BOOL IsNoStringInterning();
-
//-----------------------------------------------------------------------------------------
// Returns a BOOL to indicate if we have computed whether compiler has instructed us to
// wrap the non-CLS compliant exceptions or not.
diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h
index c2fff3f9c9a961..eb37c0a0cac94b 100644
--- a/src/coreclr/vm/common.h
+++ b/src/coreclr/vm/common.h
@@ -119,7 +119,7 @@ typedef DPTR(class ComCallMethodDesc) PTR_ComCallMethodDesc;
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 DPTR(class DomainAssembly) PTR_DomainAssembly;
typedef DPTR(struct FailedAssembly) PTR_FailedAssembly;
typedef VPTR(class EditAndContinueModule) PTR_EditAndContinueModule;
typedef DPTR(class EEClass) PTR_EEClass;
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 919a5352c1bb0a..54f17064fcad43 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -113,13 +113,6 @@ DEFINE_FIELD(ARRAY_WITH_OFFSET, M_ARRAY, m_array)
DEFINE_FIELD(ARRAY_WITH_OFFSET, M_OFFSET, m_offset)
DEFINE_FIELD(ARRAY_WITH_OFFSET, M_COUNT, m_count)
-
-DEFINE_CLASS(ASSEMBLY_BUILDER, ReflectionEmit, AssemblyBuilder)
-DEFINE_CLASS(INTERNAL_ASSEMBLY_BUILDER, ReflectionEmit, InternalAssemblyBuilder)
-#if FOR_ILLINK
-DEFINE_METHOD(INTERNAL_ASSEMBLY_BUILDER, CTOR, .ctor, IM_RetVoid)
-#endif
-
DEFINE_CLASS(ASSEMBLY_HASH_ALGORITHM, Assemblies, AssemblyHashAlgorithm)
DEFINE_CLASS(PORTABLE_EXECUTABLE_KINDS, Reflection, PortableExecutableKinds)
DEFINE_CLASS(IMAGE_FILE_MACHINE, Reflection, ImageFileMachine)
@@ -582,10 +575,6 @@ DEFINE_FIELD_U(m_pFields, ReflectModuleBaseObject, m_pGloba
DEFINE_CLASS(MODULE, Reflection, RuntimeModule)
DEFINE_FIELD(MODULE, DATA, m_pData)
-DEFINE_CLASS(MODULE_BUILDER, ReflectionEmit, InternalModuleBuilder)
-#if FOR_ILLINK
-DEFINE_METHOD(MODULE_BUILDER, CTOR, .ctor, IM_RetVoid)
-#endif
DEFINE_CLASS(TYPE_BUILDER, ReflectionEmit, TypeBuilder)
DEFINE_CLASS(ENUM_BUILDER, ReflectionEmit, EnumBuilder)
diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp
index 458f988280b02d..b8b19bb08b1694 100644
--- a/src/coreclr/vm/domainassembly.cpp
+++ b/src/coreclr/vm/domainassembly.cpp
@@ -353,14 +353,7 @@ OBJECTREF DomainAssembly::GetExposedModuleObject()
GCPROTECT_BEGIN(refClass);
- if (GetPEAssembly()->IsDynamic())
- {
- refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE_BUILDER));
- }
- else
- {
- refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE));
- }
+ refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE));
refClass->SetModule(m_pModule);
// Attach the reference to the assembly to keep the LoaderAllocator for this collectible type
@@ -672,18 +665,8 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject()
{
ASSEMBLYREF assemblyObj = NULL;
MethodTable * pMT;
- if (GetPEAssembly()->IsDynamic())
- {
- // This is unnecessary because the managed InternalAssemblyBuilder object
- // should have already been created at the time of DefineDynamicAssembly
- OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
- pMT = CoreLibBinder::GetClass(CLASS__INTERNAL_ASSEMBLY_BUILDER);
- }
- else
- {
- OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
- pMT = CoreLibBinder::GetClass(CLASS__ASSEMBLY);
- }
+
+ pMT = CoreLibBinder::GetClass(CLASS__ASSEMBLY);
// Will be TRUE only if LoaderAllocator managed object was already collected and therefore we should
// return NULL
diff --git a/src/coreclr/vm/field.cpp b/src/coreclr/vm/field.cpp
index 3855f4a22c0df7..31d858814d020c 100644
--- a/src/coreclr/vm/field.cpp
+++ b/src/coreclr/vm/field.cpp
@@ -97,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;
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/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp
index 27d2452491e2a1..cd8ab0933e9229 100644
--- a/src/coreclr/vm/jithelpers.cpp
+++ b/src/coreclr/vm/jithelpers.cpp
@@ -2433,7 +2433,7 @@ OBJECTHANDLE ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken meta
_ASSERTE(TypeFromToken(metaTok) == mdtString);
Module* module = GetModule(scopeHnd);
- return module->ResolveStringRef(metaTok, module->GetAssembly()->Parent(), false);
+ return module->ResolveStringRef(metaTok, module->GetAssembly()->Parent());
}
/*********************************************************************/
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index 3a9f5c0207a6bb..69a0abdfcb1efb 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -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;
}
@@ -7523,8 +7523,7 @@ bool containsStackCrawlMarkLocal(MethodDesc* ftn)
*************************************************************/
CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
- CORINFO_METHOD_HANDLE hCallee,
- uint32_t* pRestrictions)
+ CORINFO_METHOD_HANDLE hCallee)
{
CONTRACTL {
THROWS;
@@ -7534,7 +7533,6 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
CorInfoInline result = INLINE_PASS; // By default we pass.
// Do not set pass in the rest of the method.
- DWORD dwRestrictions = 0; // By default, no restrictions
const char * szFailReason = NULL; // for reportInlineDecision
JIT_TO_EE_TRANSITION();
@@ -7609,23 +7607,6 @@ CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
}
}
- //
- // Perform the Cross-Assembly inlining checks
- //
- {
- Module * pCalleeModule = pCallee->GetModule();
-
- // TODO: We can probably be smarter here if the caller is jitted, as we will
- // know for sure if the inlinee has really no string interning active (currently
- // it's only on in the ngen case (besides requiring the attribute)), but this is getting
- // too subtle. Will only do if somebody screams about it, as bugs here are going to
- // be tough to find
- if ((pOrigCallerModule != pCalleeModule) && pCalleeModule->IsNoStringInterning())
- {
- dwRestrictions |= INLINE_NO_CALLEE_LDSTR;
- }
- }
-
#ifdef PROFILING_SUPPORTED
if (CORProfilerPresent())
{
@@ -7699,28 +7680,6 @@ exit: ;
EE_TO_JIT_TRANSITION();
- if (result == INLINE_PASS && dwRestrictions)
- {
- if (pRestrictions)
- {
- *pRestrictions = dwRestrictions;
- }
- else
- {
- // If the jitter didn't want to know about restrictions, it shouldn't be inlining
- result = INLINE_FAIL;
- szFailReason = "Inlinee has restrictions the JIT doesn't want";
- }
- }
- else
- {
- if (pRestrictions)
- {
- // Denied inlining, makes no sense to pass out restrictions,
- *pRestrictions = 0;
- }
- }
-
if (dontInline(result))
{
// If you hit this assert, it means you added a new way to prevent inlining
@@ -13186,12 +13145,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule,
return TRUE;
}
- // For generic instantiations compiled into the ngen image of some other
- // client assembly, we need to ensure that we intern the string
- // in the defining assembly.
- bool mayNeedToSyncWithFixups = pInfoModule != currentModule;
-
- result = (size_t) pInfoModule->ResolveStringRef(TokenFromRid(rid, mdtString), currentModule->GetDomain(), mayNeedToSyncWithFixups);
+ result = (size_t) pInfoModule->ResolveStringRef(TokenFromRid(rid, mdtString), currentModule->GetDomain());
}
}
break;
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index 59566e2e717179..19a63dd9255443 100644
--- a/src/coreclr/vm/methodtablebuilder.cpp
+++ b/src/coreclr/vm/methodtablebuilder.cpp
@@ -3991,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);
@@ -4067,6 +4066,8 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
// 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)
{
@@ -8390,7 +8391,6 @@ MethodTableBuilder::HandleExplicitLayout(
{
STANDARD_VM_CONTRACT;
-
// Instance slice size is the total size of an instance, and is calculated as
// the field whose offset and size add to the greatest number.
UINT instanceSliceSize = 0;
@@ -8425,13 +8425,13 @@ MethodTableBuilder::HandleExplicitLayout(
pFieldLayout[i] = empty;
}
- // go through each field and look for invalid layout
+ // Go through each field and look for invalid layout.
// (note that we are more permissive than what Ecma allows. We only disallow the minimum set necessary to
// close security holes.)
//
- // This is what we implment:
+ // This is what we implement:
//
- // 1. Verify that every OREF is on a valid alignment
+ // 1. Verify that every OREF or BYREF is on a valid alignment.
// 2. Verify that OREFs only overlap with other OREFs.
// 3. If an OREF does overlap with another OREF, the class is marked unverifiable.
// 4. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()).
@@ -8444,7 +8444,6 @@ MethodTableBuilder::HandleExplicitLayout(
isObject[i] = oref;
}
-
ExplicitClassTrust explicitClassTrust;
UINT valueClassCacheIndex = ((UINT)(-1));
@@ -8480,7 +8479,8 @@ MethodTableBuilder::HandleExplicitLayout(
// "i" indexes all fields, valueClassCacheIndex indexes non-static fields only. Don't get them confused!
valueClassCacheIndex++;
- if (CorTypeInfo::IsObjRef(pFD->GetFieldType()))
+ CorElementType type = pFD->GetFieldType();
+ if (CorTypeInfo::IsObjRef(type) || CorTypeInfo::IsByRef(type))
{
// Check that the ref offset is pointer aligned
if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0)
@@ -8488,9 +8488,13 @@ MethodTableBuilder::HandleExplicitLayout(
badOffset = pFD->GetOffset_NoLogging();
fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
- // If we got here, OREF field was not pointer aligned. THROW.
+ // If we got here, OREF or BYREF field was not pointer aligned. THROW.
break;
}
+ }
+
+ if (CorTypeInfo::IsObjRef(type))
+ {
// check if overlaps another object
if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)isObject, sizeof(isObject)) == 0)
{
diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp
index 2664a44ad2d18b..37ed957032f303 100644
--- a/src/coreclr/vm/nativeimage.cpp
+++ b/src/coreclr/vm/nativeimage.cpp
@@ -123,7 +123,15 @@ NativeImage *NativeImage::Open(
if (pExistingImage != nullptr)
{
*isNewNativeImage = false;
- return pExistingImage->GetAssemblyBinder() == pAssemblyBinder ? pExistingImage : nullptr;
+ if (pExistingImage->GetAssemblyBinder() == pAssemblyBinder)
+ {
+ pExistingImage->AddComponentAssemblyToCache(componentModule->GetAssembly());
+ return pExistingImage;
+ }
+ else
+ {
+ return nullptr;
+ }
}
SString path = componentModule->GetPath();
@@ -237,11 +245,33 @@ NativeImage *NativeImage::Open(
// No pre-existing image, new image has been stored in the map
*isNewNativeImage = true;
amTracker.SuppressRelease();
+ image->AddComponentAssemblyToCache(componentModule->GetAssembly());
return image.Extract();
}
// Return pre-existing image if it was loaded into the same ALC, null otherwise
*isNewNativeImage = false;
- return (pExistingImage->GetAssemblyBinder() == pAssemblyBinder ? pExistingImage : nullptr);
+ if (pExistingImage->GetAssemblyBinder() == pAssemblyBinder)
+ {
+ pExistingImage->AddComponentAssemblyToCache(componentModule->GetAssembly());
+ return pExistingImage;
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+#endif
+
+#ifndef DACCESS_COMPILE
+void NativeImage::AddComponentAssemblyToCache(Assembly *assembly)
+{
+ STANDARD_VM_CONTRACT;
+
+ const AssemblyNameIndex *assemblyNameIndex = m_assemblySimpleNameToIndexMap.LookupPtr(assembly->GetSimpleName());
+ if (assemblyNameIndex != nullptr)
+ {
+ VolatileStore(&m_pNativeMetadataAssemblyRefMap[assemblyNameIndex->Index], assembly);
+ }
}
#endif
diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h
index 4774365197f2be..b9c1e8f6b81180 100644
--- a/src/coreclr/vm/nativeimage.h
+++ b/src/coreclr/vm/nativeimage.h
@@ -93,6 +93,7 @@ class NativeImage
private:
NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *peImageLayout, LPCUTF8 imageFileName);
+ void AddComponentAssemblyToCache(Assembly *assembly);
protected:
void Initialize(READYTORUN_HEADER *header, LoaderAllocator *loaderAllocator, AllocMemTracker *pamTracker);
diff --git a/src/coreclr/vm/object.cpp b/src/coreclr/vm/object.cpp
index 4a0ac960e9ace9..9cb54ede586a80 100644
--- a/src/coreclr/vm/object.cpp
+++ b/src/coreclr/vm/object.cpp
@@ -1917,6 +1917,13 @@ void ExceptionObject::SetStackTrace(I1ARRAYREF stackTrace, PTRARRAYREF dynamicMe
}
CONTRACTL_END;
+#ifdef STRESS_LOG
+ if (StressLog::StressLogOn(~0u, 0))
+ {
+ StressLog::CreateThreadStressLog();
+ }
+#endif
+
SpinLock::AcquireLock(&g_StackTraceArrayLock);
SetObjectReference((OBJECTREF*)&_stackTrace, (OBJECTREF)stackTrace);
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.h b/src/coreclr/vm/peassembly.h
index 8cb12f986c8bb3..a051343f2e1fd9 100644
--- a/src/coreclr/vm/peassembly.h
+++ b/src/coreclr/vm/peassembly.h
@@ -44,7 +44,7 @@ class EditAndContinueModule;
class PEAssembly;
class SimpleRWLock;
-typedef VPTR(PEAssembly) PTR_PEAssembly;
+typedef DPTR(PEAssembly) PTR_PEAssembly;
// --------------------------------------------------------------------------------
// Types
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/spinlock.cpp b/src/coreclr/vm/spinlock.cpp
index c9173198f620fa..70ad06459777f9 100644
--- a/src/coreclr/vm/spinlock.cpp
+++ b/src/coreclr/vm/spinlock.cpp
@@ -283,6 +283,7 @@ void SpinLock::dbg_PreEnterLock()
// SpinLock can not be nested.
_ASSERTE ((pThread->m_StateNC & Thread::TSNC_OwnsSpinLock) == 0);
+ IncCantAllocCount();
pThread->SetThreadStateNC(Thread::TSNC_OwnsSpinLock);
if (!pThread->PreemptiveGCDisabled())
@@ -321,6 +322,7 @@ void SpinLock::dbg_LeaveLock()
if (pThread)
{
_ASSERTE ((pThread->m_StateNC & Thread::TSNC_OwnsSpinLock) != 0);
+ DecCantAllocCount();
pThread->ResetThreadStateNC(Thread::TSNC_OwnsSpinLock);
INCONTRACT(pThread->EndNoTriggerGC());
}
diff --git a/src/coreclr/vm/zapsig.cpp b/src/coreclr/vm/zapsig.cpp
index b66c7b10571384..6dede7725e291a 100644
--- a/src/coreclr/vm/zapsig.cpp
+++ b/src/coreclr/vm/zapsig.cpp
@@ -654,31 +654,35 @@ Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule,
else
{
index -= assemblyRefMax;
- tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
- IMDInternalImport * pMDImportOverride = (nativeImage != NULL
- ? nativeImage->GetManifestMetadata() : fromModule->GetNativeAssemblyImport(FALSE));
- if (pMDImportOverride != NULL)
+ pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index);
+ if (pAssembly == NULL)
{
- BOOL fValidAssemblyRef = TRUE;
- LPCSTR pAssemblyName;
- DWORD dwFlags;
- if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef,
- NULL,
- NULL,
- &pAssemblyName,
- NULL,
- NULL,
- NULL,
- &dwFlags)))
- { // Unexpected failure reading MetaData
- fValidAssemblyRef = FALSE;
- }
-
- if (fValidAssemblyRef)
+ tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
+ IMDInternalImport * pMDImportOverride = (nativeImage != NULL
+ ? nativeImage->GetManifestMetadata() : fromModule->GetNativeAssemblyImport(FALSE));
+ if (pMDImportOverride != NULL)
{
- pAssembly = fromModule->GetAssemblyIfLoaded(
- tkAssemblyRef,
- pMDImportOverride);
+ BOOL fValidAssemblyRef = TRUE;
+ LPCSTR pAssemblyName;
+ DWORD dwFlags;
+ if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef,
+ NULL,
+ NULL,
+ &pAssemblyName,
+ NULL,
+ NULL,
+ NULL,
+ &dwFlags)))
+ { // Unexpected failure reading MetaData
+ fValidAssemblyRef = FALSE;
+ }
+
+ if (fValidAssemblyRef)
+ {
+ pAssembly = fromModule->GetAssemblyIfLoaded(
+ tkAssemblyRef,
+ pMDImportOverride);
+ }
}
}
}
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index f122fd1fcf526d..e94c73bb92386f 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -235,6 +235,7 @@
+
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 true;
#endif
+ [UnsupportedOSPlatformGuard("browser")]
+ internal static bool HasMD5 { get; } =
+#if NET5_0_OR_GREATER
+ !OperatingSystem.IsBrowser();
+#else
+ true;
+#endif
+
[return: NotNullIfNotNull("src")]
public static byte[]? CloneByteArray(this byte[]? src)
{
diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs
index 39c980bdfab125..8de978aea5df30 100644
--- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs
+++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs
@@ -64,7 +64,15 @@ internal static void CipherSetNonceLength(SafeEvpCipherCtxHandle ctx, int nonceL
[GeneratedDllImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_CipherReset")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal static partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx);
+ private static unsafe partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, byte* pIv, int cIv);
+
+ internal static unsafe bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, ReadOnlySpan iv)
+ {
+ fixed (byte* pIv = &MemoryMarshal.GetReference(iv))
+ {
+ return EvpCipherReset(ctx, pIv, iv.Length);
+ }
+ }
[GeneratedDllImport(Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_CipherCtxSetPadding")]
[return: MarshalAs(UnmanagedType.Bool)]
diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
index 68d18a56983d41..b9496982622504 100644
--- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
+++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs
@@ -76,7 +76,15 @@ internal static void EvpCipherSetCcmNonceLength(SafeEvpCipherCtxHandle ctx, int
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherReset")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal static partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx);
+ private static unsafe partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, byte* pIv, int cIv);
+
+ internal static unsafe bool EvpCipherReset(SafeEvpCipherCtxHandle ctx, ReadOnlySpan iv)
+ {
+ fixed (byte* pIv = &MemoryMarshal.GetReference(iv))
+ {
+ return EvpCipherReset(ctx, pIv, iv.Length);
+ }
+ }
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCtxSetPadding")]
[return: MarshalAs(UnmanagedType.Bool)]
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 12b75443f74723..22e7d9bd1e2b62 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
@@ -356,13 +356,12 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia
internal static SecurityStatusPal SslRenegotiate(SafeSslHandle sslContext, out byte[]? outputBuffer)
{
- int ret = Interop.Ssl.SslRenegotiate(sslContext);
+ int ret = Interop.Ssl.SslRenegotiate(sslContext, out Ssl.SslErrorCode errorCode);
outputBuffer = Array.Empty();
if (ret != 1)
{
- GetSslError(sslContext, ret, out Exception? exception);
- return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exception);
+ return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, GetSslError(ret, errorCode));
}
return new SecurityStatusPal(SecurityStatusPalErrorCode.OK);
}
@@ -382,23 +381,21 @@ internal static SecurityStatusPalErrorCode DoSslHandshake(SafeSslHandle context,
}
}
- int retVal = Ssl.SslDoHandshake(context);
+ int retVal = Ssl.SslDoHandshake(context, out Ssl.SslErrorCode errorCode);
if (retVal != 1)
{
- Exception? innerError;
- Ssl.SslErrorCode error = GetSslError(context, retVal, out innerError);
-
- if (error == Ssl.SslErrorCode.SSL_ERROR_WANT_X509_LOOKUP)
+ if (errorCode == Ssl.SslErrorCode.SSL_ERROR_WANT_X509_LOOKUP)
{
return SecurityStatusPalErrorCode.CredentialsNeeded;
}
- if ((retVal != -1) || (error != Ssl.SslErrorCode.SSL_ERROR_WANT_READ))
+ if ((retVal != -1) || (errorCode != Ssl.SslErrorCode.SSL_ERROR_WANT_READ))
{
+ Exception? innerError = GetSslError(retVal, errorCode);
+
// Handshake failed, but even if the handshake does not need to read, there may be an Alert going out.
// To handle that we will fall-through the block below to pull it out, and we will fail after.
- handshakeException = new SslException(SR.Format(SR.net_ssl_handshake_failed_error, error), innerError);
- Crypto.ErrClearError();
+ handshakeException = new SslException(SR.Format(SR.net_ssl_handshake_failed_error, errorCode), innerError);
}
}
@@ -447,17 +444,7 @@ internal static int Encrypt(SafeSslHandle context, ReadOnlySpan input, ref
ulong assertNoError = Crypto.ErrPeekError();
Debug.Assert(assertNoError == 0, $"OpenSsl error queue is not empty, run: 'openssl errstr {assertNoError:X}' for original error.");
#endif
- errorCode = Ssl.SslErrorCode.SSL_ERROR_NONE;
-
- int retVal;
- Exception? innerError = null;
-
- retVal = Ssl.SslWrite(context, ref MemoryMarshal.GetReference(input), input.Length);
-
- if (retVal != input.Length)
- {
- errorCode = GetSslError(context, retVal, out innerError);
- }
+ int retVal = Ssl.SslWrite(context, ref MemoryMarshal.GetReference(input), input.Length, out errorCode);
if (retVal != input.Length)
{
@@ -471,7 +458,7 @@ internal static int Encrypt(SafeSslHandle context, ReadOnlySpan input, ref
break;
default:
- throw new SslException(SR.Format(SR.net_ssl_encrypt_failed, errorCode), innerError);
+ throw new SslException(SR.Format(SR.net_ssl_encrypt_failed, errorCode), GetSslError(retVal, errorCode));
}
}
else
@@ -501,17 +488,14 @@ internal static int Decrypt(SafeSslHandle context, Span buffer, out Ssl.Ss
ulong assertNoError = Crypto.ErrPeekError();
Debug.Assert(assertNoError == 0, $"OpenSsl error queue is not empty, run: 'openssl errstr {assertNoError:X}' for original error.");
#endif
- errorCode = Ssl.SslErrorCode.SSL_ERROR_NONE;
-
BioWrite(context.InputBio!, buffer);
- int retVal = Ssl.SslRead(context, ref MemoryMarshal.GetReference(buffer), buffer.Length);
+ int retVal = Ssl.SslRead(context, ref MemoryMarshal.GetReference(buffer), buffer.Length, out errorCode);
if (retVal > 0)
{
return retVal;
}
- errorCode = GetSslError(context, retVal, out Exception? innerError);
switch (errorCode)
{
// indicate end-of-file
@@ -526,7 +510,7 @@ internal static int Decrypt(SafeSslHandle context, Span buffer, out Ssl.Ss
break;
default:
- throw new SslException(SR.Format(SR.net_ssl_decrypt_failed, errorCode), innerError);
+ throw new SslException(SR.Format(SR.net_ssl_decrypt_failed, errorCode), GetSslError(retVal, errorCode));
}
return 0;
@@ -647,14 +631,13 @@ private static void BioWrite(SafeBioHandle bio, ReadOnlySpan buffer)
}
}
- private static Ssl.SslErrorCode GetSslError(SafeSslHandle context, int result, out Exception? innerError)
+ private static Exception? GetSslError(int result, Ssl.SslErrorCode retVal)
{
- ErrorInfo lastErrno = Sys.GetLastErrorInfo(); // cache it before we make more P/Invoke calls, just in case we need it
-
- Ssl.SslErrorCode retVal = Ssl.SslGetError(context, result);
+ Exception? innerError;
switch (retVal)
{
case Ssl.SslErrorCode.SSL_ERROR_SYSCALL:
+ ErrorInfo lastErrno = Sys.GetLastErrorInfo();
// Some I/O error occurred
innerError =
Crypto.ErrPeekError() != 0 ? Crypto.CreateOpenSslCryptographicException() : // crypto error queue not empty
@@ -673,7 +656,8 @@ private static Ssl.SslErrorCode GetSslError(SafeSslHandle context, int result, o
innerError = null;
break;
}
- return retVal;
+
+ return innerError;
}
private static void SetSslCertificate(SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr)
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 379ab7586ed38c..6ccb1307886f71 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
@@ -75,13 +75,13 @@ internal static partial class Ssl
}
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslWrite", SetLastError = true)]
- internal static partial int SslWrite(SafeSslHandle ssl, ref byte buf, int num);
+ internal static partial int SslWrite(SafeSslHandle ssl, ref byte buf, int num, out SslErrorCode error);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRead", SetLastError = true)]
- internal static partial int SslRead(SafeSslHandle ssl, ref byte buf, int num);
+ internal static partial int SslRead(SafeSslHandle ssl, ref byte buf, int num, out SslErrorCode error);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRenegotiate")]
- internal static partial int SslRenegotiate(SafeSslHandle ssl);
+ internal static partial int SslRenegotiate(SafeSslHandle ssl, out SslErrorCode error);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslRenegotiatePending")]
[return: MarshalAs(UnmanagedType.Bool)]
@@ -97,7 +97,7 @@ internal static partial class Ssl
internal static partial void SslSetBio(SafeSslHandle ssl, SafeBioHandle rbio, SafeBioHandle wbio);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslDoHandshake", SetLastError = true)]
- internal static partial int SslDoHandshake(SafeSslHandle ssl);
+ internal static partial int SslDoHandshake(SafeSslHandle ssl, out SslErrorCode error);
[GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslStateOK")]
[return: MarshalAs(UnmanagedType.Bool)]
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..94e650df6362ae 100644
--- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs
+++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs
@@ -16,28 +16,42 @@ internal static unsafe SafeKeyHandle BCryptImportKey(SafeAlgorithmHandle hAlg, R
const string BCRYPT_KEY_DATA_BLOB = "KeyDataBlob";
int keySize = key.Length;
int blobSize = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + keySize;
- byte[] blob = new byte[blobSize];
+
+ // 64 is large enough to hold a BCRYPT_KEY_DATA_BLOB_HEADER and an AES-256 key with room to spare.
+ int MaxStackKeyBlob = 64;
+ Span blob = stackalloc byte[MaxStackKeyBlob];
+
+ if (blobSize > MaxStackKeyBlob)
+ {
+ blob = new byte[blobSize];
+ }
+ else
+ {
+ blob.Clear();
+ }
+
fixed (byte* pbBlob = blob)
{
BCRYPT_KEY_DATA_BLOB_HEADER* pBlob = (BCRYPT_KEY_DATA_BLOB_HEADER*)pbBlob;
pBlob->dwMagic = BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_MAGIC;
pBlob->dwVersion = BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_VERSION1;
pBlob->cbKeyData = (uint)keySize;
- }
- key.CopyTo(blob.AsSpan(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)));
- SafeKeyHandle hKey;
- NTSTATUS ntStatus = BCryptImportKey(hAlg, IntPtr.Zero, BCRYPT_KEY_DATA_BLOB, out hKey, IntPtr.Zero, 0, blob, blobSize, 0);
- if (ntStatus != NTSTATUS.STATUS_SUCCESS)
- {
- throw CreateCryptographicException(ntStatus);
- }
- return hKey;
+ key.CopyTo(blob.Slice(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)));
+ SafeKeyHandle hKey;
+ NTSTATUS ntStatus = BCryptImportKey(hAlg, IntPtr.Zero, BCRYPT_KEY_DATA_BLOB, out hKey, IntPtr.Zero, 0, pbBlob, blobSize, 0);
+ if (ntStatus != NTSTATUS.STATUS_SUCCESS)
+ {
+ throw CreateCryptographicException(ntStatus);
+ }
+
+ return hKey;
+ }
}
[StructLayout(LayoutKind.Sequential)]
- private struct BCRYPT_KEY_DATA_BLOB_HEADER
+ internal struct BCRYPT_KEY_DATA_BLOB_HEADER
{
public uint dwMagic;
public uint dwVersion;
@@ -48,6 +62,6 @@ private struct BCRYPT_KEY_DATA_BLOB_HEADER
}
[GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)]
- private static partial NTSTATUS BCryptImportKey(SafeAlgorithmHandle hAlgorithm, IntPtr hImportKey, string pszBlobType, out SafeKeyHandle hKey, IntPtr pbKeyObject, int cbKeyObject, byte[] pbInput, int cbInput, int dwFlags);
+ private static unsafe partial NTSTATUS BCryptImportKey(SafeAlgorithmHandle hAlgorithm, IntPtr hImportKey, string pszBlobType, out SafeKeyHandle hKey, IntPtr pbKeyObject, int cbKeyObject, byte* pbInput, int cbInput, int dwFlags);
}
}
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/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/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 hash,
+ ReadOnlySpan signature,
+ DSASignatureFormat signatureFormat)
+ {
+ SafeDsaHandle key = GetKey();
+
+ if (signatureFormat == DSASignatureFormat.IeeeP1363FixedFieldConcatenation)
{
- if (_key == null)
+ int expectedSignatureBytes = Interop.Crypto.DsaSignatureFieldSize(key) * 2;
+ if (signature.Length != expectedSignatureBytes)
{
- throw new ObjectDisposedException(
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- nameof(DSA)
-#else
- nameof(DSAOpenSsl)
-#endif
- );
+ // The input isn't of the right length (assuming no DER), so we can't sensibly re-encode it with DER.
+ return false;
}
- }
- private SafeDsaHandle GetKey()
+ signature = AsymmetricAlgorithmHelpers.ConvertIeee1363ToDer(signature);
+ }
+ else if (signatureFormat != DSASignatureFormat.Rfc3279DerSequence)
{
- ThrowIfDisposed();
+ Debug.Fail($"Missing internal implementation handler for signature format {signatureFormat}");
+ throw new CryptographicException(
+ SR.Cryptography_UnknownSignatureFormat,
+ signatureFormat.ToString());
+ }
- SafeDsaHandle key = _key.Value;
- CheckInvalidKey(key);
+ return Interop.Crypto.DsaVerify(key, hash, signature);
+ }
- return key;
+ private void ThrowIfDisposed()
+ {
+ if (_key == null)
+ {
+ throw new ObjectDisposedException(nameof(DSAOpenSsl));
}
+ }
- private void SetKey(SafeDsaHandle newKey)
- {
- // Do not call ThrowIfDisposed here, as it breaks the SafeEvpPKey ctor
+ private SafeDsaHandle GetKey()
+ {
+ ThrowIfDisposed();
- // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere
- // with the already loaded key.
- ForceSetKeySize(BitsPerByte * Interop.Crypto.DsaKeySize(newKey));
+ SafeDsaHandle key = _key.Value;
+ CheckInvalidKey(key);
- _key = new Lazy(newKey);
- }
+ return key;
+ }
- static partial void ThrowIfNotSupported();
+ private void SetKey(SafeDsaHandle newKey)
+ {
+ // Do not call ThrowIfDisposed here, as it breaks the SafeEvpPKey ctor
- private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) };
+ // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere
+ // with the already loaded key.
+ ForceSetKeySize(BitsPerByte * Interop.Crypto.DsaKeySize(newKey));
+
+ _key = new Lazy(newKey);
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
+
+ static partial void ThrowIfNotSupported();
+
+ private static readonly KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(minSize: 512, maxSize: 3072, skipSize: 64) };
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs
index 8b7e0dbb4ec710..a804b198d51401 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/DSASecurityTransforms.cs
@@ -1,26 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Buffers;
-using System.Diagnostics;
-using System.Formats.Asn1;
using System.IO;
-using System.Runtime.InteropServices;
using System.Security.Cryptography.Apple;
using Internal.Cryptography;
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- public partial class DSA : AsymmetricAlgorithm
- {
- private static DSA CreateCore()
- {
- return new DSAImplementation.DSASecurityTransforms();
- }
- }
-#endif
-
internal static partial class DSAImplementation
{
public sealed partial class DSASecurityTransforms : DSA
@@ -102,7 +88,7 @@ public override byte[] CreateSignature(byte[] rgbHash)
// are always 160 bits / 20 bytes (the size of SHA-1, and the only legal length for Q).
byte[] ieeeFormatSignature = AsymmetricAlgorithmHelpers.ConvertDerToIeee1363(
derFormatSignature.AsSpan(0, derFormatSignature.Length),
- fieldSizeBits: 160);
+ fieldSizeBits: SHA1.HashSizeInBits);
return ieeeFormatSignature;
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs
index a18e08635b9346..ebe5922994637d 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.ImportExport.cs
@@ -5,260 +5,253 @@
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class ECDiffieHellmanImplementation
+ public sealed partial class ECDiffieHellmanCng : ECDiffieHellman
{
-#endif
- public sealed partial class ECDiffieHellmanCng : ECDiffieHellman
+ public override void ImportParameters(ECParameters parameters)
{
- public override void ImportParameters(ECParameters parameters)
- {
- parameters.Validate();
- ThrowIfDisposed();
+ parameters.Validate();
+ ThrowIfDisposed();
- ECCurve curve = parameters.Curve;
- bool includePrivateParameters = parameters.D != null;
- bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null;
+ ECCurve curve = parameters.Curve;
+ bool includePrivateParameters = parameters.D != null;
+ bool hasPublicParameters = parameters.Q.X != null && parameters.Q.Y != null;
- if (curve.IsPrime)
- {
- if (!hasPublicParameters && includePrivateParameters)
- {
- byte[] zero = new byte[parameters.D!.Length];
- ECParameters ecParamsCopy = parameters;
- ecParamsCopy.Q.X = zero;
- ecParamsCopy.Q.Y = zero;
- byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: true);
- ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true);
- }
- else
- {
- byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: true);
- ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters);
- }
- }
- else if (curve.IsNamed)
+ if (curve.IsPrime)
+ {
+ if (!hasPublicParameters && includePrivateParameters)
{
- // FriendlyName is required; an attempt was already made to default it in ECCurve
- if (string.IsNullOrEmpty(curve.Oid.FriendlyName))
- {
- throw new PlatformNotSupportedException(
- SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value));
- }
-
- if (!hasPublicParameters && includePrivateParameters)
- {
- byte[] zero = new byte[parameters.D!.Length];
- ECParameters ecParamsCopy = parameters;
- ecParamsCopy.Q.X = zero;
- ecParamsCopy.Q.Y = zero;
- byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: true);
- ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true);
- }
- else
- {
- byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: true);
- ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters);
- }
+ byte[] zero = new byte[parameters.D!.Length];
+ ECParameters ecParamsCopy = parameters;
+ ecParamsCopy.Q.X = zero;
+ ecParamsCopy.Q.Y = zero;
+ byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref ecParamsCopy, ecdh: true);
+ ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters: true);
}
else
{
- throw new PlatformNotSupportedException(
- SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
+ byte[] ecExplicitBlob = ECCng.GetPrimeCurveBlob(ref parameters, ecdh: true);
+ ImportFullKeyBlob(ecExplicitBlob, includePrivateParameters);
}
}
-
- public override ECParameters ExportExplicitParameters(bool includePrivateParameters)
+ else if (curve.IsNamed)
{
- byte[] blob = ExportFullKeyBlob(includePrivateParameters);
+ // FriendlyName is required; an attempt was already made to default it in ECCurve
+ if (string.IsNullOrEmpty(curve.Oid.FriendlyName))
+ {
+ throw new PlatformNotSupportedException(
+ SR.Format(SR.Cryptography_InvalidCurveOid, curve.Oid.Value));
+ }
- try
+ if (!hasPublicParameters && includePrivateParameters)
{
- ECParameters ecparams = default;
- ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters);
- return ecparams;
+ byte[] zero = new byte[parameters.D!.Length];
+ ECParameters ecParamsCopy = parameters;
+ ecParamsCopy.Q.X = zero;
+ ecParamsCopy.Q.Y = zero;
+ byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref ecParamsCopy, ecdh: true);
+ ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters: true);
}
- finally
+ else
{
- Array.Clear(blob);
+ byte[] ecNamedCurveBlob = ECCng.GetNamedCurveBlob(ref parameters, ecdh: true);
+ ImportKeyBlob(ecNamedCurveBlob, curve.Oid.FriendlyName, includePrivateParameters);
}
}
+ else
+ {
+ throw new PlatformNotSupportedException(
+ SR.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
+ }
+ }
- public override ECParameters ExportParameters(bool includePrivateParameters)
+ public override ECParameters ExportExplicitParameters(bool includePrivateParameters)
+ {
+ byte[] blob = ExportFullKeyBlob(includePrivateParameters);
+
+ try
{
ECParameters ecparams = default;
+ ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters);
+ return ecparams;
+ }
+ finally
+ {
+ Array.Clear(blob);
+ }
+ }
- string? curveName = GetCurveName(out string? oidValue);
- byte[]? blob = null;
+ public override ECParameters ExportParameters(bool includePrivateParameters)
+ {
+ ECParameters ecparams = default;
- try
+ string? curveName = GetCurveName(out string? oidValue);
+ byte[]? blob = null;
+
+ try
+ {
+ if (string.IsNullOrEmpty(curveName))
{
- if (string.IsNullOrEmpty(curveName))
- {
- blob = ExportFullKeyBlob(includePrivateParameters);
- ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters);
- }
- else
- {
- blob = ExportKeyBlob(includePrivateParameters);
- ECCng.ExportNamedCurveParameters(ref ecparams, blob, includePrivateParameters);
- ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName));
- }
-
- return ecparams;
+ blob = ExportFullKeyBlob(includePrivateParameters);
+ ECCng.ExportPrimeCurveParameters(ref ecparams, blob, includePrivateParameters);
}
- finally
+ else
{
- if (blob != null)
- {
- Array.Clear(blob);
- }
+ blob = ExportKeyBlob(includePrivateParameters);
+ ECCng.ExportNamedCurveParameters(ref ecparams, blob, includePrivateParameters);
+ ecparams.Curve = ECCurve.CreateFromOid(new Oid(oidValue, curveName));
}
- }
-
- public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead)
- {
- ThrowIfDisposed();
- CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead);
- ProcessPkcs8Response(response);
- bytesRead = localRead;
+ return ecparams;
}
-
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- ReadOnlySpan source,
- out int bytesRead)
+ finally
{
- ThrowIfDisposed();
- CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey(
- passwordBytes,
- source,
- out int localRead);
-
- ProcessPkcs8Response(response);
- bytesRead = localRead;
+ if (blob != null)
+ {
+ Array.Clear(blob);
+ }
}
+ }
- public override void ImportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- ReadOnlySpan source,
- out int bytesRead)
- {
- ThrowIfDisposed();
- CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey(
- password,
- source,
- out int localRead);
+ public override void ImportPkcs8PrivateKey(ReadOnlySpan source, out int bytesRead)
+ {
+ ThrowIfDisposed();
+ CngPkcs8.Pkcs8Response response = CngPkcs8.ImportPkcs8PrivateKey(source, out int localRead);
- ProcessPkcs8Response(response);
- bytesRead = localRead;
- }
+ ProcessPkcs8Response(response);
+ bytesRead = localRead;
+ }
- private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response)
- {
- // Wrong algorithm?
- if (response.GetAlgorithmGroup() != BCryptNative.AlgorithmName.ECDH)
- {
- response.FreeKey();
- throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey);
- }
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey(
+ passwordBytes,
+ source,
+ out int localRead);
+
+ ProcessPkcs8Response(response);
+ bytesRead = localRead;
+ }
- AcceptImport(response);
- }
+ public override void ImportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ ReadOnlySpan source,
+ out int bytesRead)
+ {
+ ThrowIfDisposed();
+ CngPkcs8.Pkcs8Response response = CngPkcs8.ImportEncryptedPkcs8PrivateKey(
+ password,
+ source,
+ out int localRead);
+
+ ProcessPkcs8Response(response);
+ bytesRead = localRead;
+ }
- public override byte[] ExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- PbeParameters pbeParameters)
+ private void ProcessPkcs8Response(CngPkcs8.Pkcs8Response response)
+ {
+ // Wrong algorithm?
+ if (response.GetAlgorithmGroup() != BCryptNative.AlgorithmName.ECDH)
{
- if (pbeParameters == null)
- throw new ArgumentNullException(nameof(pbeParameters));
-
- return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
- this,
- passwordBytes,
- pbeParameters);
+ response.FreeKey();
+ throw new CryptographicException(SR.Cryptography_NotValidPublicOrPrivateKey);
}
- public override byte[] ExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan password,
- PbeParameters pbeParameters)
- {
- if (pbeParameters == null)
- {
- throw new ArgumentNullException(nameof(pbeParameters));
- }
+ AcceptImport(response);
+ }
- PasswordBasedEncryption.ValidatePbeParameters(
- pbeParameters,
- password,
- ReadOnlySpan.Empty);
+ public override byte[] ExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan passwordBytes,
+ PbeParameters pbeParameters)
+ {
+ if (pbeParameters == null)
+ throw new ArgumentNullException(nameof(pbeParameters));
- if (CngPkcs8.IsPlatformScheme(pbeParameters))
- {
- return ExportEncryptedPkcs8(password, pbeParameters.IterationCount);
- }
+ return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
+ this,
+ passwordBytes,
+ pbeParameters);
+ }
- return CngPkcs8.ExportEncryptedPkcs8PrivateKey(
- this,
- password,
- pbeParameters);
+ public override byte[] ExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ PbeParameters pbeParameters)
+ {
+ if (pbeParameters == null)
+ {
+ throw new ArgumentNullException(nameof(pbeParameters));
}
- public override bool TryExportEncryptedPkcs8PrivateKey(
- ReadOnlySpan passwordBytes,
- PbeParameters pbeParameters,
- Span destination,
- out int bytesWritten)
+ PasswordBasedEncryption.ValidatePbeParameters(
+ pbeParameters,
+ password,
+ ReadOnlySpan.Empty);
+
+ if (CngPkcs8.IsPlatformScheme(pbeParameters))
{
- if (pbeParameters == null)
- throw new ArgumentNullException(nameof(pbeParameters));
-
- PasswordBasedEncryption.ValidatePbeParameters(
- pbeParameters,
- ReadOnlySpan.Empty,
- passwordBytes);
-
- return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
- this,
- passwordBytes,
- pbeParameters,
- destination,
- out bytesWritten);
+ 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 (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 TryExportEncryptedPkcs8(
- password,
- pbeParameters.IterationCount,
- destination,
- out bytesWritten);
- }
+ public override bool TryExportEncryptedPkcs8PrivateKey(
+ ReadOnlySpan password,
+ PbeParameters pbeParameters,
+ Span destination,
+ out int bytesWritten)
+ {
+ if (pbeParameters == null)
+ throw new ArgumentNullException(nameof(pbeParameters));
+
+ PasswordBasedEncryption.ValidatePbeParameters(
+ pbeParameters,
+ password,
+ ReadOnlySpan.Empty);
- return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
- this,
+ if (CngPkcs8.IsPlatformScheme(pbeParameters))
+ {
+ return TryExportEncryptedPkcs8(
password,
- pbeParameters,
+ pbeParameters.IterationCount,
destination,
out bytesWritten);
}
+
+ return CngPkcs8.TryExportEncryptedPkcs8PrivateKey(
+ this,
+ password,
+ pbeParameters,
+ destination,
+ out bytesWritten);
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs
index ad955d55ce8eed..f1db21ff401e77 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanCng.cs
@@ -1,141 +1,138 @@
// 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.Versioning;
using Microsoft.Win32.SafeHandles;
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class ECDiffieHellmanImplementation
+ public sealed partial class ECDiffieHellmanCng : ECDiffieHellman
{
-#endif
- public sealed partial class ECDiffieHellmanCng : ECDiffieHellman
+ [SupportedOSPlatform("windows")]
+ public ECDiffieHellmanCng() : this(521) { }
+
+ [SupportedOSPlatform("windows")]
+ public ECDiffieHellmanCng(int keySize)
{
- public ECDiffieHellmanCng() : this(521) { }
+ KeySize = keySize;
+ }
- public ECDiffieHellmanCng(int keySize)
- {
- KeySize = keySize;
- }
+ [SupportedOSPlatform("windows")]
+ public ECDiffieHellmanCng(ECCurve curve)
+ {
+ // GenerateKey will already do all of the validation we need.
+ GenerateKey(curve);
+ }
- public ECDiffieHellmanCng(ECCurve curve)
+ public override int KeySize
+ {
+ get
{
- // GenerateKey will already do all of the validation we need.
- GenerateKey(curve);
+ return base.KeySize;
}
-
- public override int KeySize
+ set
{
- get
+ if (KeySize == value)
{
- return base.KeySize;
+ return;
}
- set
- {
- if (KeySize == value)
- {
- return;
- }
- // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key
- base.KeySize = value;
+ // Set the KeySize before DisposeKey so that an invalid value doesn't throw away the key
+ base.KeySize = value;
- DisposeKey();
- // Key will be lazily re-created
- }
+ DisposeKey();
+ // Key will be lazily re-created
}
+ }
- ///
- /// Set the KeySize without validating against LegalKeySizes.
- ///
- /// The value to set the KeySize to.
- private void ForceSetKeySize(int newKeySize)
- {
- // In the event that a key was loaded via ImportParameters, curve name, 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;
- }
+ ///
+ /// Set the KeySize without validating against LegalKeySizes.
+ ///
+ /// The value to set the KeySize to.
+ private void ForceSetKeySize(int newKeySize)
+ {
+ // In the event that a key was loaded via ImportParameters, curve name, 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 the three sizes that can be explicitly set (for backwards compatibility)
- return new[] {
- new KeySizes(minSize: 256, maxSize: 384, skipSize: 128),
- new KeySizes(minSize: 521, maxSize: 521, skipSize: 0),
- };
- }
+ // Return the three sizes that can be explicitly set (for backwards compatibility)
+ return new[] {
+ new KeySizes(minSize: 256, maxSize: 384, skipSize: 128),
+ new KeySizes(minSize: 521, maxSize: 521, skipSize: 0),
+ };
}
+ }
- public override byte[] DeriveKeyFromHash(
- ECDiffieHellmanPublicKey otherPartyPublicKey,
- HashAlgorithmName hashAlgorithm,
- byte[]? secretPrepend,
- byte[]? secretAppend)
- {
- ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
- ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
+ public override byte[] DeriveKeyFromHash(
+ ECDiffieHellmanPublicKey otherPartyPublicKey,
+ HashAlgorithmName hashAlgorithm,
+ byte[]? secretPrepend,
+ byte[]? secretAppend)
+ {
+ ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
+ ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
- using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
- {
- return Interop.NCrypt.DeriveKeyMaterialHash(
- secretAgreement,
- hashAlgorithm.Name,
- secretPrepend,
- secretAppend,
- Interop.NCrypt.SecretAgreementFlags.None);
- }
+ using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
+ {
+ return Interop.NCrypt.DeriveKeyMaterialHash(
+ secretAgreement,
+ hashAlgorithm.Name,
+ secretPrepend,
+ secretAppend,
+ Interop.NCrypt.SecretAgreementFlags.None);
}
+ }
- public override byte[] DeriveKeyFromHmac(
- ECDiffieHellmanPublicKey otherPartyPublicKey,
- HashAlgorithmName hashAlgorithm,
- byte[]? hmacKey,
- byte[]? secretPrepend,
- byte[]? secretAppend)
- {
- ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
- ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
+ public override byte[] DeriveKeyFromHmac(
+ ECDiffieHellmanPublicKey otherPartyPublicKey,
+ HashAlgorithmName hashAlgorithm,
+ byte[]? hmacKey,
+ byte[]? secretPrepend,
+ byte[]? secretAppend)
+ {
+ ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
+ ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
- using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
- {
- Interop.NCrypt.SecretAgreementFlags flags = hmacKey == null ?
- Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey :
- Interop.NCrypt.SecretAgreementFlags.None;
-
- return Interop.NCrypt.DeriveKeyMaterialHmac(
- secretAgreement,
- hashAlgorithm.Name,
- hmacKey,
- secretPrepend,
- secretAppend,
- flags);
- }
+ using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
+ {
+ Interop.NCrypt.SecretAgreementFlags flags = hmacKey == null ?
+ Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey :
+ Interop.NCrypt.SecretAgreementFlags.None;
+
+ return Interop.NCrypt.DeriveKeyMaterialHmac(
+ secretAgreement,
+ hashAlgorithm.Name,
+ hmacKey,
+ secretPrepend,
+ secretAppend,
+ flags);
}
+ }
- public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
+ public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
+ {
+ if (otherPartyPublicKey == null)
+ throw new ArgumentNullException(nameof(otherPartyPublicKey));
+ if (prfLabel == null)
+ throw new ArgumentNullException(nameof(prfLabel));
+ if (prfSeed == null)
+ throw new ArgumentNullException(nameof(prfSeed));
+
+ using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
{
- if (otherPartyPublicKey == null)
- throw new ArgumentNullException(nameof(otherPartyPublicKey));
- if (prfLabel == null)
- throw new ArgumentNullException(nameof(prfLabel));
- if (prfSeed == null)
- throw new ArgumentNullException(nameof(prfSeed));
-
- using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
- {
- return Interop.NCrypt.DeriveKeyMaterialTls(
- secretAgreement,
- prfLabel,
- prfSeed,
- Interop.NCrypt.SecretAgreementFlags.None);
- }
+ return Interop.NCrypt.DeriveKeyMaterialTls(
+ secretAgreement,
+ prfLabel,
+ prfSeed,
+ Interop.NCrypt.SecretAgreementFlags.None);
}
}
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
}
-#endif
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs
index 9d32a702bf07fa..bee07782afc3d9 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/ECDiffieHellmanOpenSsl.Derive.cs
@@ -6,196 +6,189 @@
namespace System.Security.Cryptography
{
-#if INTERNAL_ASYMMETRIC_IMPLEMENTATIONS
- internal static partial class ECDiffieHellmanImplementation
+ public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman
{
-#endif
- public sealed partial class ECDiffieHellmanOpenSsl : ECDiffieHellman
+ ///
+ /// Given a second party's public key, derive shared key material
+ ///
+ public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) =>
+ DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256, null, null);
+
+ public override byte[] DeriveKeyFromHash(
+ ECDiffieHellmanPublicKey otherPartyPublicKey,
+ HashAlgorithmName hashAlgorithm,
+ byte[]? secretPrepend,
+ byte[]? secretAppend)
{
- ///
- /// Given a second party's public key, derive shared key material
- ///
- public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) =>
- DeriveKeyFromHash(otherPartyPublicKey, HashAlgorithmName.SHA256, null, null);
-
- public override byte[] DeriveKeyFromHash(
- ECDiffieHellmanPublicKey otherPartyPublicKey,
- HashAlgorithmName hashAlgorithm,
- byte[]? secretPrepend,
- byte[]? secretAppend)
- {
- ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
- ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
+ ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
+ ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
- ThrowIfDisposed();
+ ThrowIfDisposed();
- return ECDiffieHellmanDerivation.DeriveKeyFromHash(
- otherPartyPublicKey,
- hashAlgorithm,
- secretPrepend,
- secretAppend,
- (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
- }
+ return ECDiffieHellmanDerivation.DeriveKeyFromHash(
+ otherPartyPublicKey,
+ hashAlgorithm,
+ secretPrepend,
+ secretAppend,
+ (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
+ }
- public override byte[] DeriveKeyFromHmac(
- ECDiffieHellmanPublicKey otherPartyPublicKey,
- HashAlgorithmName hashAlgorithm,
- byte[]? hmacKey,
- byte[]? secretPrepend,
- byte[]? secretAppend)
- {
- ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
- ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
-
- ThrowIfDisposed();
-
- return ECDiffieHellmanDerivation.DeriveKeyFromHmac(
- otherPartyPublicKey,
- hashAlgorithm,
- hmacKey,
- secretPrepend,
- secretAppend,
- (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
- }
+ public override byte[] DeriveKeyFromHmac(
+ ECDiffieHellmanPublicKey otherPartyPublicKey,
+ HashAlgorithmName hashAlgorithm,
+ byte[]? hmacKey,
+ byte[]? secretPrepend,
+ byte[]? secretAppend)
+ {
+ ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
+ ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
+
+ ThrowIfDisposed();
+
+ return ECDiffieHellmanDerivation.DeriveKeyFromHmac(
+ otherPartyPublicKey,
+ hashAlgorithm,
+ hmacKey,
+ secretPrepend,
+ secretAppend,
+ (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
+ }
- public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
- {
- if (otherPartyPublicKey == null)
- throw new ArgumentNullException(nameof(otherPartyPublicKey));
- if (prfLabel == null)
- throw new ArgumentNullException(nameof(prfLabel));
- if (prfSeed == null)
- throw new ArgumentNullException(nameof(prfSeed));
-
- ThrowIfDisposed();
-
- return ECDiffieHellmanDerivation.DeriveKeyTls(
- otherPartyPublicKey,
- prfLabel,
- prfSeed,
- (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
- }
+ public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
+ {
+ if (otherPartyPublicKey == null)
+ throw new ArgumentNullException(nameof(otherPartyPublicKey));
+ if (prfLabel == null)
+ throw new ArgumentNullException(nameof(prfLabel));
+ if (prfSeed == null)
+ throw new ArgumentNullException(nameof(prfSeed));
+
+ ThrowIfDisposed();
+
+ return ECDiffieHellmanDerivation.DeriveKeyTls(
+ otherPartyPublicKey,
+ prfLabel,
+ prfSeed,
+ (pubKey, hasher) => DeriveSecretAgreement(pubKey, hasher));
+ }
+
+ ///
+ /// Get the secret agreement generated between two parties
+ ///
+ private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash? hasher)
+ {
+ Debug.Assert(otherPartyPublicKey != null);
- ///
- /// Get the secret agreement generated between two parties
- ///
- private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash? hasher)
+ // Ensure that this ECDH object contains a private key by attempting a parameter export
+ // which will throw an OpenSslCryptoException if no private key is available
+ ECParameters thisKeyExplicit = ExportExplicitParameters(true);
+ bool thisIsNamed = Interop.Crypto.EcKeyHasCurveName(_key.Value);
+ ECDiffieHellmanOpenSslPublicKey? otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey;
+ bool disposeOtherKey = false;
+
+ if (otherKey == null)
{
- Debug.Assert(otherPartyPublicKey != null);
+ disposeOtherKey = true;
- // Ensure that this ECDH object contains a private key by attempting a parameter export
- // which will throw an OpenSslCryptoException if no private key is available
- ECParameters thisKeyExplicit = ExportExplicitParameters(true);
- bool thisIsNamed = Interop.Crypto.EcKeyHasCurveName(_key.Value);
- ECDiffieHellmanOpenSslPublicKey? otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey;
- bool disposeOtherKey = false;
+ ECParameters otherParameters =
+ thisIsNamed
+ ? otherPartyPublicKey.ExportParameters()
+ : otherPartyPublicKey.ExportExplicitParameters();
- if (otherKey == null)
- {
- disposeOtherKey = true;
+ otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters);
+ }
- ECParameters otherParameters =
- thisIsNamed
- ? otherPartyPublicKey.ExportParameters()
- : otherPartyPublicKey.ExportExplicitParameters();
+ bool otherIsNamed = otherKey.HasCurveName;
- otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters);
- }
+ SafeEvpPKeyHandle? ourKey = null;
+ SafeEvpPKeyHandle? theirKey = null;
+ byte[]? rented = null;
+ int secretLength = 0;
- bool otherIsNamed = otherKey.HasCurveName;
+ try
+ {
+ if (otherKey.KeySize != KeySize)
+ {
+ throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
+ }
- SafeEvpPKeyHandle? ourKey = null;
- SafeEvpPKeyHandle? theirKey = null;
- byte[]? rented = null;
- int secretLength = 0;
+ if (otherIsNamed == thisIsNamed)
+ {
+ ourKey = _key.UpRefKeyHandle();
+ theirKey = otherKey.DuplicateKeyHandle();
+ }
+ else if (otherIsNamed)
+ {
+ ourKey = _key.UpRefKeyHandle();
- try
+ using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters()))
+ {
+ theirKey = tmp.UpRefKeyHandle();
+ }
+ }
+ else
{
- if (otherKey.KeySize != KeySize)
+ using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit))
{
- throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
+ ourKey = tmp.UpRefKeyHandle();
}
- if (otherIsNamed == thisIsNamed)
+ theirKey = otherKey.DuplicateKeyHandle();
+ }
+
+ using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU))
+ {
+ if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue)
{
- ourKey = _key.UpRefKeyHandle();
- theirKey = otherKey.DuplicateKeyHandle();
+ throw Interop.Crypto.CreateOpenSslCryptographicException();
}
- else if (otherIsNamed)
- {
- ourKey = _key.UpRefKeyHandle();
- using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters()))
- {
- theirKey = tmp.UpRefKeyHandle();
- }
+ secretLength = (int)secretLengthU;
+
+ // Indicate that secret can hold stackallocs from nested scopes
+ Span secret = stackalloc byte[0];
+
+ // Arbitrary limit. But it covers secp521r1, which is the biggest common case.
+ const int StackAllocMax = 66;
+
+ if (secretLength > StackAllocMax)
+ {
+ rented = CryptoPool.Rent(secretLength);
+ secret = new Span(rented, 0, secretLength);
}
else
{
- using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit))
- {
- ourKey = tmp.UpRefKeyHandle();
- }
-
- theirKey = otherKey.DuplicateKeyHandle();
+ secret = stackalloc byte[secretLength];
}
- using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU))
- {
- if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue)
- {
- throw Interop.Crypto.CreateOpenSslCryptographicException();
- }
-
- secretLength = (int)secretLengthU;
-
- // Indicate that secret can hold stackallocs from nested scopes
- Span secret = stackalloc byte[0];
-
- // Arbitrary limit. But it covers secp521r1, which is the biggest common case.
- const int StackAllocMax = 66;
-
- if (secretLength > StackAllocMax)
- {
- rented = CryptoPool.Rent(secretLength);
- secret = new Span