Skip to content

Commit f8034ce

Browse files
authored
Merge branch 'main' into remove-stack-probe
2 parents 9de229b + 4008de1 commit f8034ce

File tree

563 files changed

+11473
-6319
lines changed

Some content is hidden

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

563 files changed

+11473
-6319
lines changed

Directory.Build.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
Minimum target OS versions, keep in sync with:
5757
- eng/native/configurecompiler.cmake
5858
- eng/native/build-commons.sh
59+
- eng/native/gen-buildsys.cmd
5960
- src/native/libs/build-native.sh
6061
- src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ObjectWriter/MachObjectWriter.cs
6162
- src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
@@ -328,7 +329,7 @@
328329
<!-- Runtime doesn't support Arcade-driven target framework filtering. -->
329330
<NoTargetFrameworkFiltering>true</NoTargetFrameworkFiltering>
330331

331-
<NativeBuildPartitionPropertiesToRemove>ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs;CxxStandardLibrary;CxxStandardLibraryStatic;CxxAbiLibrary</NativeBuildPartitionPropertiesToRemove>
332+
<NativeBuildPartitionPropertiesToRemove>ClrFullNativeBuild;ClrRuntimeSubset;ClrJitSubset;ClrPalTestsSubset;ClrAllJitsSubset;ClrAllJitsCommunitySubset;ClrILToolsSubset;ClrNativeAotSubset;ClrSpmiSubset;ClrCrossComponentsSubset;ClrDebugSubset;HostArchitecture;PgoInstrument;NativeOptimizationDataSupported;CMakeArgs;CxxStandardLibrary;CxxStandardLibraryStatic;CxxAbiLibrary</NativeBuildPartitionPropertiesToRemove>
332333
<UseSystemZlib Condition="'$(TargetsAppleMobile)' == 'true' or '$(TargetOS)' == 'android' or '$(TargetArchitecture)' == 'armv6'">true</UseSystemZlib>
333334
</PropertyGroup>
334335

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,7 @@ Passing/returning structs according to hardware floating-point calling conventio
108108

109109
## Return buffers
110110

111-
The same applies to some return buffers. See `MethodTable::IsStructRequiringStackAllocRetBuf()`. When that returns `false`, the return buffer might be on the heap, either due to reflection/remoting code paths mentioned previously or due to a JIT optimization where a call with a return buffer that then assigns to a field (on the GC heap) are changed into passing the field reference as the return buffer. Conversely, when it returns true, the JIT does not need to use a write barrier when storing to the return buffer, but it is still not guaranteed to be a compiler temp, and as such the JIT should not introduce spurious writes to the return buffer.
112-
113-
NOTE: This optimization is now disabled for all platforms (`IsStructRequiringStackAllocRetBuf()` always returns `false`).
111+
Since .NET 10, return buffers must always be allocated on the stack by the caller. After the call, the caller is responsible for copying the return buffer to the final destination using write barriers if necessary. The JIT can assume that the return buffer is always on the stack and may optimize accordingly, such as by omitting write barriers when writing GC pointers to the return buffer. In addition, the buffer is allowed to be used for temporary storage within the method since its content must not be aliased or cross-thread visible.
114112

115113
ARM64-only: When a method returns a structure that is larger than 16 bytes the caller reserves a return buffer of sufficient size and alignment to hold the result. The address of the buffer is passed as an argument to the method in `R8` (defined in the JIT as `REG_ARG_RET_BUFF`). The callee isn't required to preserve the value stored in `R8`.
116114

@@ -778,9 +776,7 @@ The return value is handled as follows:
778776
1. Floating-point values are returned on the top of the hardware FP stack.
779777
2. Integers up to 32 bits long are returned in EAX.
780778
3. 64-bit integers are passed with EAX holding the least significant 32 bits and EDX holding the most significant 32 bits.
781-
4. All other cases require the use of a return buffer, through which the value is returned.
782-
783-
In addition, there is a guarantee that if a return buffer is used a value is stored there only upon ordinary exit from the method. The buffer is not allowed to be used for temporary storage within the method and its contents will be unaltered if an exception occurs while executing the method.
779+
4. All other cases require the use of a return buffer, through which the value is returned. See [Return buffers](#return-buffers).
784780

785781
# Control Flow Guard (CFG) support on Windows
786782

docs/design/features/tailcalls-with-helpers.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,9 @@ stack, even on ARM architectures, due to its return address hijacking mechanism.
259259

260260
When the result is returned by value the JIT will introduce a local and pass a
261261
pointer to it in the second argument. For ret bufs the JIT will typically
262-
directly pass along its own return buffer parameter to DispatchTailCalls. It is
263-
possible that this return buffer is pointing into GC heap, so the result is
264-
always tracked as a byref in the mechanism.
262+
directly pass along its own return buffer parameter to DispatchTailCalls. The
263+
return buffer is always located on the stack, so the result does not need to be
264+
tracked as a byref.
265265

266266
In certain cases the target function pointer is also stored. For some targets
267267
this might require the JIT to perform the equivalent of `ldvirtftn` or `ldftn`

docs/design/mono/mono-library-mode.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public class MainActivity extends AppCompatActivity {
109109

110110
After building the mono library with `dotnet publish -r ios-arm64`, it can be found as `lib<Managed Project Name>.dylib` in the binaries folder (i.e. `library-mode-sample/ManagedProject/bin/Release/net8.0/ios-arm64/Bundle/libManagedProject.dylib`). The mono library when built as a shared library with bundling (on by default) can be loaded and used with the following steps:
111111

112-
1. Open/Create the iOS native project in XCode.
112+
1. Open/Create the iOS native project in Xcode.
113113

114114
2. Copy the mono library into the project's root directory (not creating a reference).
115115

docs/project/os-onboarding.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Onboarding Guide for New Operating System Versions
2+
3+
Adding support for new operating systems versions is a frequent need. This guide describes how we do that, including the policies we use.
4+
5+
> Being _active_ in `main` enables being _lazy_ in `release/`.
6+
7+
This witticism is the underlying philosophy of our approach. By actively maintaining OS versions in our active coding branch, we get the double benefit of bleeding-edge coverage and (in many cases) can avoid EOL remediation cost in `release/` branches. Spending time on avoidable work is a failure of planning.
8+
9+
> Users are best served when we act _quickly_ not _exhaustively_.
10+
11+
12+
This double meaning is instructing us to be boldly pragmatic. Each new OS release brings a certain risk of breakage. The risk is far from uniform across the various repos and components that we maintain. Users are best served when we've developed 80% confidence and to leave the remaining (potential) 20% to bug reports. Exhaustive testing serves no one. We've also found that our users do a great job finding corner cases and enthusiastically participate in the process by opening issues in the appropriate repo.
13+
14+
15+
Continuing with the idea of pragmatism, if you only read this far, you've got the basic idea. The rest of the doc describes more context and mechanics.
16+
17+
References:
18+
19+
- [.NET OS Support Tracking](https://github.com/dotnet/core/issues/9638)
20+
- [.NET Support](https://github.com/dotnet/core/blob/main/support.md)
21+
- [Prereq container image lifecycle](https://github.com/dotnet/dotnet-buildtools-prereqs-docker/blob/main/lifecycle.md)
22+
- [Support for Linux Distros](https://dev.azure.com/dnceng/internal/_wiki/wikis/DNCEng%20Services%20Wiki/940/Support-for-Linux-Distros) (MS internal)
23+
- [Support for Apple Operating Systems](https://dev.azure.com/dnceng/internal/_wiki/wikis/DNCEng%20Services%20Wiki/933/Support-for-Apple-Operating-Systems-(macOS-iOS-and-tvOS)) (MS internal)
24+
- [Support for Windows Operating Systems](https://dev.azure.com/dnceng/internal/_wiki/wikis/DNCEng%20Services%20Wiki/939/Support-for-Windows-Operating-Systems) (MS internal)
25+
26+
## Context
27+
28+
In most cases, we find that new OS versions _may_ uncover problems in dotnet/runtime, but don't affect up-stack components or apps once resolved. A key design point of our runtime is to be a quite complete cross-platform and -architecture abstraction, so resolving OS compatibility breaks for higher-level code is an enduring intent.
29+
30+
Nearly all the APIs that touch native code (networking, cryptography) and deal with standard formats (time zones, ASN.1) are in dotnet/runtime. In many cases, we only see test breaks when we onboard a new OS, often from code that tests edge cases.
31+
32+
## Approach
33+
34+
Our rule is that we declare support (for all [supported .NET releases](https://github.com/dotnet/core/blob/main/releases.md)) for a new OS version after it is validated in dotnet/runtime `main`. We will only hold support on additional testing in special cases (which are uncommon).
35+
36+
We aim to have "day of" support for about half the OSes we support, including Azure Linux, Ubuntu LTS, and Windows. This means we need to perform ahead-of-time signoff on non-final builds.
37+
38+
Our testing philosophy is based on perceived risk and past experience. The effective test matrix is huge, the product of OSes \* supported versions \* architectures. We try to make smart choices to **skip testing most of the matrix** while retaining much of the **practical coverage**. We also know where we tend to get bitten most when we don't pay sufficient attention. For example, our bug risk across Linux, macOS, and Windows is not uniform.
39+
40+
We use pragmatism and efficiency to drive our decision making. All things being equal, we'll choose the lowest cost approach.
41+
42+
## Testing
43+
44+
Testing is the bread and butter of OS onboarding, particularly for a mature runtime like ours. New OS support always needs some form of test enablement.
45+
46+
Linux, Wasm, and some Windows testing is done in container images. This approach enables us to test many and regularly changing OS versions in a fixed/limited VM environment. The container image creation/update process is self-service (discussed later).
47+
48+
We use VMs (Linux and Windows) and raw metal hardware (Android and Apple) in cases where containers are not practical or where direct testing is desired. This is the primary model for Apple and Windows OSes. The VMs and mobile/Apple hardware are relatively slow to change and require support from dnceng (discussed later).
49+
50+
### Adding coverage
51+
52+
New OS coverage should be added/tested first in `main`. If changes are required, we should prove them out first in `main` before committing to shipping them in a servicing release, if necessary.
53+
54+
There are multiple reasons to add a new OS reference in a release branch:
55+
56+
- Known product (as opposed to test) breaks that require validation and regression testing.
57+
- Past experience suggests that coverage is required to protect against risk.
58+
- OS version is or [will soon go EOL](https://github.com/dotnet/runtime/issues/111818#issuecomment-2613642202) and should be replaced by a newer version.
59+
60+
For example, we frequently need to backport Alpine updates to release branches to avoid EOL references but less commonly for Ubuntu, given the vast difference in support length.
61+
62+
A good strategy is to keep `main` at the bleeding edge of new OS versions. That way those references have a decent chance of never needing remediation once they end up in release branches.
63+
64+
### Updating or removing coverage
65+
66+
We will often replace an older OS version with a new one, when it comes available. This approach is an effective strategy of maintaining the same level of coverage and of remediating EOL OSes ahead of time. For the most part, we don't need to care about a specific version. We just want coverage for the OS, like Alpine.
67+
68+
We should remediate any EOL OS references in our codebase. They don't serve any benefit and come with some risk. They are also likely to result in compliance tickets (that come with a deadline) that we want to avoid.
69+
70+
In the case that a .NET version will be EOL in <6 (and certainly <3) months, new coverage can typically be skipped. We may even be able to skip remediating EOL OS references. We often opt to stop updating [supported OSes](https://github.com/dotnet/core/blob/main/os-lifecycle-policy.md) late in support period for related reasons. A lazy approach is often the best approach late in the game. Don't upset what's working.
71+
72+
## Building
73+
74+
Our [build methodology](https://github.com/dotnet/runtime/blob/main/docs/project/linux-build-methodology.md) is oriented around cross-compiling, enabling us to target an old OS version and run on newer ones. It is uncommon for us to need to make changes to the build to address new OS versions, however, there are [rare cases where we need to make adjustments](https://github.com/dotnet/runtime/issues/101944).
75+
76+
We use both containers and VMs for building, depending on the OS. If we test in a container, we likely build in a container. Same for VMs.
77+
78+
Our primary concern is ensuring that we are using [supported operating systems and tools for our build](https://github.com/dotnet/runtime/tree/main/docs/workflow/requirements).
79+
80+
Our Linux build containers are based on Azure Linux. We [typically need to update them](https://github.com/dotnet/runtime/issues/112191) with a new version of Azure Linux once per release. We do not update the toolset, however. That's fixed, per release.
81+
82+
For Apple, we likely need to make an adjustment at each macOS or iOS release to account for an Xcode version no longer being supported.
83+
84+
## Environments
85+
86+
We rely on a set of standard environments for building and testing. These environments are managed with a "config as code" paradigm in our source code. This approach delivers CI reliability -- which we greatly value -- but also comes with the tedious cost of needing to regularly update various reference strings in several files. Updating version strings almost always requires sorting through build breaks, which is a reminder of why we value our approach.
87+
88+
We may use multiple environments for building and testing a given OS.
89+
90+
### Containers
91+
92+
New container images need to be created for each new OS version in the [dotnet/dotnet-buildtools-prereqs-docker](https://github.com/dotnet/dotnet-buildtools-prereqs-docker) repo. These are used for building and testing Android, Linux, Wasm, and Windows OSes/targets.
93+
94+
The repo is self-service and largely self-explanatory. One typically creates a new image using the pattern demonstrated by the previous version. Look at commits and [blame](https://github.com/dotnet/dotnet-buildtools-prereqs-docker/blame/776324ff16d38e22fd9f06c9842ec338a4b98489/src/alpine/3.20/helix/Dockerfile) to find people who are best suited to help.
95+
96+
Installing/building the Helix client can be quite involved, particularly for Arm platforms. Don't struggle with that. Just ask for help.
97+
98+
Container images are referenced in our pipeline files:
99+
100+
- [eng/pipelines/coreclr/templates/helix-queues-setup.yml](https://github.com/dotnet/runtime/blob/main/eng/pipelines/coreclr/templates/helix-queues-setup.yml)
101+
- [eng/pipelines/libraries/helix.yml](https://github.com/dotnet/runtime/blob/main/eng/pipelines/libraries/helix.yml)
102+
- [eng/pipelines/common/templates/pipeline-with-resources.yml](https://github.com/dotnet/runtime/blob/main/eng/pipelines/common/templates/pipeline-with-resources.yml)
103+
104+
Notes:
105+
106+
- The first two links are for testing and the last for building.
107+
- The links are for the `main` branch. Release branches should have the same layout.
108+
109+
Example PRs:
110+
111+
- [dotnet/runtime #111768](https://github.com/dotnet/runtime/pull/111768)
112+
- [dotnet/runtime #111504](https://github.com/dotnet/runtime/pull/111504)
113+
- [dotnet/runtime #110492](https://github.com/dotnet/runtime/pull/110492)
114+
- [dotnet/dotnet-buildtools-prereqs-docker #1282](https://github.com/dotnet/dotnet-buildtools-prereqs-docker/pull/1282)
115+
- [dotnet/dotnet-buildtools-prereqs-docker #1314](https://github.com/dotnet/dotnet-buildtools-prereqs-docker/pull/1314)
116+
117+
### VMs
118+
119+
VMs and raw metal environments are used for Android, Apple, Linux, and Windows OSes. They need to be [requested from dnceng](https://github.com/dotnet/dnceng/issues/4307). The turnaround can be long so put in your request before you need it.
120+
121+
- Android: Raw metal hosts for some forms of Android testing.
122+
- Apple: Raw metal hosts for all forms of Apple testing.
123+
- Linux: All Linux VMs are moving to Azure Linux as a container host.
124+
- Windows: Windows Client and Server VMs
125+
126+
### Other
127+
128+
Other environments are typically use a custom process.
129+
130+
- [Browser Wasm](https://github.com/dotnet/runtime/pull/112066)
131+
132+
## Porting
133+
134+
[Porting .NET to a new operating system or architecture](../design/coreclr/botr/guide-for-porting.md) is a related task. The same patterns likely apply, but the overall task is much larger in scope.

docs/workflow/building/coreclr/ios.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Build and run the sample app with
2020
./dotnet.sh publish src/mono/sample/iOS/Program.csproj -c Release /p:TargetOS=iossimulator /p:TargetArchitecture=arm64 /p:DeployAndRun=true /p:UseMonoRuntime=false /p:RunAOTCompilation=false /p:MonoForceInterpreter=false
2121
```
2222

23-
The command also produces an XCode project that can be opened with `open ./src/mono/sample/iOS/bin/iossimulator-arm64/Bundle/HelloiOS/HelloiOS.xcodeproj` and debugged in Xcode.
23+
The command also produces an Xcode project that can be opened with `open ./src/mono/sample/iOS/bin/iossimulator-arm64/Bundle/HelloiOS/HelloiOS.xcodeproj` and debugged in Xcode.
2424

2525
## Running the runtime tests
2626

docs/workflow/testing/libraries/testing-apple.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
## Prerequisites
44

5-
- XCode 11.3 or higher
5+
- Xcode 11.3 or higher
66
- a certificate and provisioning profile if using a device
77
- a simulator with a proper device type and OS version.
8-
Go `XCode > Window > Devices and Simulators` to revise the list of the available simulators and then `"+" button on bottom left > OS Version dropdown selection > Download more simulator runtimes` in case you need to download more simulators.
8+
Go `Xcode > Window > Devices and Simulators` to revise the list of the available simulators and then `"+" button on bottom left > OS Version dropdown selection > Download more simulator runtimes` in case you need to download more simulators.
99

1010
## Building Libs and Tests
1111

0 commit comments

Comments
 (0)