Skip to content

Commit 0cca6c5

Browse files
authored
Merge branch 'main' into copilot/refactor-string-comparison-logic
2 parents 46e8115 + a550606 commit 0cca6c5

2,103 files changed

Lines changed: 53118 additions & 19730 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/devcontainer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
},
1515

1616
"features": {
17-
"ghcr.io/devcontainers/features/github-cli:1": {}
17+
"ghcr.io/devcontainers/features/github-cli:1": {},
18+
"ghcr.io/devcontainers/features/sshd:1": {},
19+
"ghcr.io/devcontainers/features/copilot-cli:1": {}
1820
},
1921

2022
// Configure tool-specific properties.

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,4 @@ src/tests/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-
8181
src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input.txt text eol=lf
8282
src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input-big.txt text eol=lf
8383
src/mono/browser/runtime/dotnet.d.ts text eol=lf
84-
src/native/corehost/browserhost/loader/dotnet.d.ts text eol=lf
84+
src/native/libs/Common/JavaScript/loader/dotnet.d.ts text eol=lf

.github/skills/jit-regression-test/SKILL.md

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
---
22
name: jit-regression-test
3-
description: Extract a standalone JIT regression test case from a given GitHub issue and save it under the JitBlue folder. Use this when asked to create or extract a JIT regression test from an issue.
3+
description: >
4+
Extract a standalone JIT regression test case from a given GitHub issue and
5+
save it under the JitBlue folder. USE FOR: creating JIT regression tests,
6+
extracting repro code from dotnet/runtime issues, "write a test for this JIT
7+
bug", "create a regression test for issue #NNNNN", converting issue repro to
8+
xunit test. DO NOT USE FOR: non-JIT tests (use standard test patterns),
9+
debugging JIT issues without a known repro, performance benchmarks (use
10+
performance-benchmark skill).
411
---
512

613
# JIT Regression Test Extraction
714

8-
When you need to extract a JIT regression test case from a GitHub issue, follow this process to create a properly structured test under `src/tests/JIT/Regression/JitBlue/`.
15+
> 🚨 **Do NOT create a test when**: the issue has no reproducible code and you cannot compose a minimal repro, the issue is a duplicate of an existing test under `JitBlue/`, or the bug is in libraries/runtime rather than the JIT compiler itself.
16+
17+
Extract a JIT regression test case from a GitHub issue into a properly structured test under `src/tests/JIT/Regression/JitBlue/`.
918

1019
## Step 1: Gather Information from the GitHub Issue
1120

1221
From the GitHub issue, extract:
13-
1. **Issue number** - Used to name the test folder and files (e.g., issue #99391`Runtime_99391`)
14-
2. **Reproduction code** - The C# code that demonstrates the bug. If no code provided, try to compose it yourself.
15-
3. **Environment variables** - Any DOTNET_* environment variables required to reproduce the bug
16-
4. **Expected behavior** - What the correct output/behavior should be
22+
1. **Issue number** → folder/file name (e.g., #99391`Runtime_99391`)
23+
2. **Reproduction code** — if none provided, compose a minimal repro yourself
24+
3. **Environment variables** — any `DOTNET_*` vars needed to reproduce
25+
4. **Expected behavior** correct output/behavior
1726

1827
## Step 2: Create the Test Directory
1928

@@ -52,8 +61,9 @@ public class Runtime_<issue_number>
5261

5362
- **License header**: Always include the standard .NET Foundation license header
5463
- **Class name**: Match the file name exactly (`Runtime_<issue_number>`)
55-
- **Test method**: Use `[Fact]` attribute and name the method `TestEntryPoint()` or `Test()`
56-
- **Assertions**: Use Xunit's helpers or just throw plain exceptions.
64+
- **Test method**: `[Fact]` attribute, named `TestEntryPoint()`
65+
- **Minimize the reproduction**: Strip to the minimal case that triggers the bug
66+
- **Use `[MethodImpl(MethodImplOptions.NoInlining)]`** when preventing inlining is needed to reproduce
5767

5868
### Example: Simple Test (from Runtime_99391)
5969

@@ -86,13 +96,15 @@ public class Runtime_99391
8696
}
8797
```
8898

89-
## [Optional] Step 4: Create a .csproj File (Only When Needed)
99+
## Step 4: Create a .csproj File or add to the existing Regression_*.csproj
90100

91101
A custom `.csproj` file is **only required** when:
92102
- Environment variables are needed to reproduce the bug (such as `DOTNET_JitStressModeNames`)
93103
- Special compilation settings are required
94104

95-
It should be located next to the test source file with the following name: `Runtime_<issue_number>.csproj`. Example:
105+
Otherwise, register the test file in the existing `src/tests/JIT/Regression/Regression_*.csproj` (`Regression_ro_2.csproj` is a good default) file and skip creating a new .csproj.
106+
107+
If a custom .csproj file is needed, it should be located next to the test source file with the following name: `Runtime_<issue_number>.csproj`. Example:
96108

97109
```xml
98110
<Project Sdk="Microsoft.NET.Sdk">
@@ -110,9 +122,7 @@ It should be located next to the test source file with the following name: `Runt
110122
</Project>
111123
```
112124

113-
## Important Notes
125+
## Tips
114126

115-
- **No .csproj needed for simple tests**: Most tests only need the `.cs` file. The test infrastructure uses default settings that work for most cases.
116-
- **Look at recent tests**: When in doubt, examine recent tests under `src/tests/JIT/Regression/JitBlue/Runtime_*` for the latest conventions.
117-
- **Use `[MethodImpl(MethodImplOptions.NoInlining)]`**: When you need to prevent inlining to reproduce a JIT bug.
118-
- **Minimize the reproduction**: Strip down the test code to the minimal case that reproduces the issue.
127+
- **No .csproj needed for simple tests** — register the `.cs` file in `Regression_ro_2.csproj` instead.
128+
- **Look at recent tests** under `src/tests/JIT/Regression/JitBlue/Runtime_*` when in doubt about current conventions.

.github/skills/performance-benchmark/SKILL.md

Lines changed: 18 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ name: performance-benchmark
33
description: Generate and run ad hoc performance benchmarks to validate code changes. Use this when asked to benchmark, profile, or validate the performance impact of a code change in dotnet/runtime.
44
---
55

6-
# Ad Hoc Performance Benchmarking
6+
# Ad Hoc Performance Benchmarking with @EgorBot
77

8-
When you need to validate the performance impact of a code change, follow this process to write a BenchmarkDotNet benchmark and trigger EgorBot to run it.
8+
When you need to validate the performance impact of a code change, follow this process to write a BenchmarkDotNet benchmark and trigger @EgorBot to run it.
9+
The bot will notify you when results are ready, so don't wait for them.
910

1011
## Step 1: Write the Benchmark
1112

@@ -120,50 +121,37 @@ public class Bench
120121
}
121122
```
122123

123-
## Step 2: Post the EgorBot Comment
124+
## Step 2: Mention @EgorBot in a comment/PR description
124125

125126
Post a comment on the PR to trigger EgorBot with your benchmark. The general format is:
126127

127-
```
128-
@EgorBot [target flags] [options] [BenchmarkDotNet args]
128+
@EgorBot [targets] [options] [BenchmarkDotNet args]
129129

130130
```cs
131131
// Your benchmark code here
132132
```
133-
```
134-
135-
### Target Flags (Required - Choose at Least One)
133+
> **Note:** The @EgorBot command must not be inside the code block. Only the benchmark code should be inside the code block.
136134
137-
| Flag | Architecture | Description |
138-
|------|--------------|-------------|
139-
| `-x64` or `-amd` | x64 | Linux Azure Genoa (AMD EPYC) - default x64 target |
140-
| `-arm` | ARM64 | Linux Azure Cobalt100 (Neoverse-N2) |
141-
| `-intel` | x64 | Azure Cascade Lake (more flaky due to JCC Erratum and loop alignment sensitivity) |
142-
| `-windows_x64` | x64 | Windows x64 (when Windows-specific testing is needed) |
135+
### Target Flags
143136

144-
**Choosing targets:**
137+
- `-linux_amd`
138+
- `-linux_intel`
139+
- `-windows_amd`
140+
- `-windows_intel`
141+
- `-linux_arm64`
142+
- `-osx_arm64` (baremetal, feel free to always include it)
145143

146-
- **Default for most changes**: Use `-x64` for quick verification of non-architecture/non-OS specific changes
147-
- **Default when ARM might differ**: Use `-x64 -arm` if there's any suspicion the change might behave differently on ARM
148-
- **Windows-specific changes**: Use `-windows_x64` when Windows behavior needs testing
149-
- **Noisy results suspected**: Use `-arm -intel -amd` to get results from multiple x64 CPUs (note: `-intel` targets are more flaky)
144+
The most common combination is `-linux_amd -osx_arm64`. Do not include more than 4 targets.
150145

151146
### Common Options
152147

153-
| Option | Description |
154-
|--------|-------------|
155-
| `-profiler` | Collect flamegraph/hot assembly using perf record |
156-
| `--envvars KEY:VALUE` | Set environment variables (e.g., `DOTNET_JitDisasm:MethodName`) |
157-
| `-commit <hash>` | Run against a specific commit |
158-
| `-commit <hash1> vs <hash2>` | Compare two commits |
159-
| `-commit <hash> vs previous` | Compare commit with its parent |
148+
Use `-profiler` when absolutely necessary along with `-linux_arm64` and/or `-linux_amd` to include `perf` profiling and disassembly in the results.
160149

161150
### Example: Basic PR Benchmark
162151

163152
To benchmark the current PR changes against the base branch:
164153

165-
```
166-
@EgorBot -x64 -arm
154+
@EgorBot -linux_amd -osx_arm64
167155

168156
```cs
169157
using BenchmarkDotNet.Attributes;
@@ -182,73 +170,17 @@ public class Bench
182170
}
183171
}
184172
```
185-
```
186-
187-
### Example: Benchmark with Profiling and Disassembly
188-
189-
```
190-
@EgorBot -x64 -profiler --envvars DOTNET_JitDisasm:SumArray
191-
192-
```cs
193-
using System.Linq;
194-
using BenchmarkDotNet.Attributes;
195-
using BenchmarkDotNet.Running;
196-
197-
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
198-
199-
public class Bench
200-
{
201-
private int[] _data = Enumerable.Range(0, 1000).ToArray();
202-
203-
[Benchmark]
204-
public int SumArray() => _data.Sum();
205-
}
206-
```
207-
```
208-
209-
### Example: Compare Two Commits
210-
211-
```
212-
@EgorBot -amd -commit abc1234 vs def5678
213-
214-
```cs
215-
using BenchmarkDotNet.Attributes;
216-
using BenchmarkDotNet.Running;
217-
218-
BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);
219-
220-
public class Bench
221-
{
222-
[Benchmark]
223-
public void TestMethod()
224-
{
225-
// Benchmark code
226-
}
227-
}
228-
```
229-
```
230-
231-
### Example: Run Existing dotnet/performance Benchmarks
232-
233-
To run benchmarks from the dotnet/performance repository (no code snippet needed):
234-
235-
```
236-
@EgorBot -arm -intel --filter `*TryGetValueFalse<String, String>*`
237-
```
238-
239-
**Note**: Surround filter expressions with backticks to avoid issues with special characters.
240173

241174
## Important Notes
242175

243176
- **Bot response time**: EgorBot uses polling and may take up to 30 seconds to respond
244177
- **Supported repositories**: EgorBot monitors `dotnet/runtime` and `EgorBot/runtime-utils`
245178
- **PR mode (default)**: When posting in a PR, EgorBot automatically compares the PR changes against the base branch
246179
- **Results variability**: Results may vary between runs due to VM differences. Do not compare results across different architectures or cloud providers
247-
- **Check the manual**: EgorBot replies include a link to the [manual](https://github.com/EgorBot/runtime-utils) for advanced options
180+
- **Check the manual**: EgorBot replies include a link to the [manual](https://github.com/EgorBo/EgorBot?tab=readme-ov-file#github-usage) for advanced options
248181

249182
## Additional Resources
250183

251184
- [Microbenchmark Design Guidelines](https://github.com/dotnet/performance/blob/main/docs/microbenchmark-design-guidelines.md) - Essential reading for writing effective benchmarks
252185
- [BenchmarkDotNet CLI Arguments](https://github.com/dotnet/BenchmarkDotNet/blob/master/docs/articles/guides/console-args.md)
253-
- [EgorBot Manual](https://github.com/EgorBot/runtime-utils)
254-
- [BenchmarkDotNet Filter Simulator](http://egorbot.westus2.cloudapp.azure.com:5042/microbenchmarks)
186+
- [EgorBot Manual](https://github.com/EgorBo/EgorBot?tab=readme-ov-file#github-usage)

.github/workflows/aspnetcore-sync.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
mkdir ..\artifacts
4343
git status > ..\artifacts\status.txt
4444
git diff > ..\artifacts\diff.txt
45-
- uses: actions/upload-artifact@v6
45+
- uses: actions/upload-artifact@v7
4646
with:
4747
name: results
4848
path: artifacts

.github/workflows/breaking-change-doc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
GITHUB_MODELS_API_KEY: ${{ secrets.MODELS_TOKEN }}
6767

6868
- name: Upload artifacts
69-
uses: actions/upload-artifact@v6
69+
uses: actions/upload-artifact@v7
7070
with:
7171
name: breaking-change-doc-artifacts-${{ inputs.pr_number || github.event.pull_request.number }}
7272
path: artifacts/docs/breakingChanges/

.github/workflows/jit-format.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
ROOTFS_DIR: ${{ matrix.os.rootfs }}
4747

4848
- name: Publish format.patch
49-
uses: actions/upload-artifact@v6
49+
uses: actions/upload-artifact@v7
5050
with:
5151
path: runtime/format.patch
5252
name: format.${{matrix.os.name}}.patch

.markdownlint.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"default": false,
33
"MD009": {
4-
"br_spaces": 0
4+
"br_spaces": 2
55
}
66
}

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
<WasmProjectRoot>$([MSBuild]::NormalizeDirectory($(MonoProjectRoot), 'wasm'))</WasmProjectRoot>
139139
<WasiProjectRoot>$([MSBuild]::NormalizeDirectory($(MonoProjectRoot), 'wasi'))</WasiProjectRoot>
140140

141+
<CoreclrRuntimeBinDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'coreclr', '$(TargetOS).$(TargetArchitecture).$(Configuration)'))</CoreclrRuntimeBinDir>
141142
<AppleAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', '$(TasksConfiguration)', '$(NetCoreAppToolCurrent)'))</AppleAppBuilderDir>
142143
<AndroidAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidAppBuilder', '$(TasksConfiguration)', '$(NetCoreAppToolCurrent)', 'publish'))</AndroidAppBuilderDir>
143144
<MobileBuildTasksDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MobileBuildTasks', '$(TasksConfiguration)', '$(NetCoreAppToolCurrent)'))</MobileBuildTasksDir>

docs/design/coreclr/botr/clr-abi.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,17 @@ Structs are generally returned via hidden buffers, whose address is supplied by
721721

722722
### Prolog
723723

724-
The prolog will increment the stack pointer, home any arguments that are stored on the linear stack, and zero initialize slots on the linear stack as appropriate. It will establish a frame pointer if one is needed.
724+
The prolog will decrement the stack pointer by the fixed frame size, home any arguments that are stored on the linear stack, and zero initialize slots on the linear stack as appropriate. It will establish a frame pointer if one is needed.
725725

726-
It will also save a frame descriptor onto the stack, for use during GC and EH. For methods with EH or with GC safe points, a slot on the linear stack will be reserved for a "virtual IP" that will index into the EH and GC info to provide within-method information and allow external code to walk the managed stack frames.
726+
So on exit from the prolog the stack pointer (`$sp`) will point to the bottom of the fixed part of the stack frame. The frame pointer (`$fp`) if used, will also point to the bottom of fixed part of the stack frame. `$sp` and `$fp` will only differ in methods that can allocate extra storage on the stack at runtime (typically from `localloc`). The stack is kept 16 byte aligned.
727+
728+
For methods that can be interrupted by GC or EH (generally speaking: methods with gc safe calls) the prolog also saves a frame descriptor onto the stack, for use during GC and EH. By convention this value is stored at `fp[0]`. Since only `sp` will be available for unwinding (by virtue of being saved to `$__stack_pointer`) we adopt the convention that when `$sp` moves in the middle of the method, `$sp[0]` is set to `$fp`.
729+
730+
Thus to access information for EH/GC/unwinding, the frame descriptor `fd` can be found from the managed frame `$sp` as follows:
731+
* `fd = $sp[0]`
732+
* if `fd` is a stack address, it is the saved `$fp`. So then `fd = fd[0]`.
733+
734+
We will save the "virtual IP" in a similar fashion (TBD: exact details on this).
727735

728736
### Epilog
729737

0 commit comments

Comments
 (0)