EE_THREAD_REQUIRED simply asserts that GetThread() != NULL.
-EE_THREAD_NOT_REQUIRED is a noop by default. You must "set COMPlus_EnforceEEThreadNotRequiredContracts=1" for this to be enforced. Setting the envvar forces a C version of GetThread() to be used, instead of the optimized assembly versions. This C GetThread() always asserts in an EE_THREAD_NOT_REQUIRED scope regardless of whether there actually is an EE Thread available or not. The reason is that if you claim you don't require an EE Thread, then you have no business asking for it (even if you get lucky and there happens to be an EE Thread available).
+EE_THREAD_NOT_REQUIRED is a noop by default. You must "set DOTNET_EnforceEEThreadNotRequiredContracts=1" for this to be enforced. Setting the envvar forces a C version of GetThread() to be used, instead of the optimized assembly versions. This C GetThread() always asserts in an EE_THREAD_NOT_REQUIRED scope regardless of whether there actually is an EE Thread available or not. The reason is that if you claim you don't require an EE Thread, then you have no business asking for it (even if you get lucky and there happens to be an EE Thread available).
Of course, there are exceptions to this. In particular, if there is a clear code path for GetThread() == NULL, then it's ok to call GetThread() in an EE_THREAD_NOT_REQUIRED scope. You declare your intention by using GetThreadNULLOk():
It is generally discouraged to permanently disable code by commenting it out or by putting `#if 0` around it, in an attempt to keep it around for reference. This reduces the hygiene of the code base over time and such disabled code is rarely actually useful. Instead, such disabled code should be entirely deleted. If you do disable code without deleting it, then you must add a comment as to why the code is disabled, and why it is better to leave the code disabled than it is to delete it.
-One exception is that it is often useful to `#if 0` code that is useful for debugging an area, but is not otherwise useful. Even in this case, however, it is probably better to introduce a COMPlus_* variable to enable the special debugging mode.
+One exception is that it is often useful to `#if 0` code that is useful for debugging an area, but is not otherwise useful. Even in this case, however, it is probably better to introduce a DOTNET_* variable to enable the special debugging mode.
### <a name="14.1.3"></a>14.1.3 Debug code
Use the `INDEBUG(x)` macro (and related macros) judiciously, for code that only runs in DEBUG, to avoid `#ifdef`s.
-Use the `JITDUMP(x)` macro for printing things to the JIT dump output. Note that these things will only get printed when the `verbose` variable is set, which is when `COMPlus_JitDump=*` or when `COMPlus_JitDump=XXX` and we are JITting function XXX. Do not use `JITDUMP` for all output in a debug-only function that might be useful to call from the debugger. In that case, define a function that uses `printf` (which is a JIT-specific implementation of this function), which can be called from the debugger, and invoke that function like this:
+Use the `JITDUMP(x)` macro for printing things to the JIT dump output. Note that these things will only get printed when the `verbose` variable is set, which is when `DOTNET_JitDump=*` or when `DOTNET_JitDump=XXX` and we are JITting function XXX. Do not use `JITDUMP` for all output in a debug-only function that might be useful to call from the debugger. In that case, define a function that uses `printf` (which is a JIT-specific implementation of this function), which can be called from the debugger, and invoke that function like this:
```c++
DBEXEC(verbose, MyDumpFunction());
JITDUMP("*************** In genGenerateCode()\n");
```
-However, the former is preferred because it is trivial to set an unconditional breakpoint on the "printf" that triggers when we are compiling the function that matches what COMPlus_JitDump is set to – a very common debugging technique. Note that conditional breakpoints could be used, but they are more cumbersome, and are very difficult to get right in windbg.
+However, the former is preferred because it is trivial to set an unconditional breakpoint on the "printf" that triggers when we are compiling the function that matches what DOTNET_JitDump is set to – a very common debugging technique. Note that conditional breakpoints could be used, but they are more cumbersome, and are very difficult to get right in windbg.
If many back-to-back JITDUMP statements are going to be used it is preferred that they be written using printf().
getting some code to work is a prerequisite for handling more complex
scenarios. When doing initial bringup, configuring the Gen0 budget of the GC
to be a large number so that the GC does not attempt to run during most
- tests is very useful. (Set `COMPlus_GCgen0size=99999999`)
+ tests is very useful. (Set `DOTNET_GCgen0size=99999999`)
- Once basic code is executing, the focus shifts to enabling the GC to work.
In this initial phase, the correct choice is to enable conservative GC
really works.
- See the various test passes done in CI, but most critically GCStress testing
- is needed. See documentation around use of the ComPlus_GCStress environment
+ is needed. See documentation around use of the DOTNET_GCStress environment
variable.
Stage 5 productization
Any configuration or policy is set with environment variables which are passed as options to the _createdump_ utility.
-Starting with .NET 7.0 or greater the below environment variables can be prefixed with DOTNET_ or COMPlus_.
-
Environment variables supported:
-- `COMPlus_DbgEnableMiniDump`: if set to "1", enables this core dump generation. The default is NOT to generate a dump.
-- `COMPlus_DbgMiniDumpType`: See below. Default is "2" MiniDumpWithPrivateReadWriteMemory.
-- `COMPlus_DbgMiniDumpName`: if set, use as the template to create the dump path and file name. See "Dump name formatting" for how the dump name can be formatted. The default is _/tmp/coredump.%p_.
-- `COMPlus_CreateDumpDiagnostics`: if set to "1", enables the _createdump_ utilities diagnostic messages (TRACE macro).
-- `COMPlus_CreateDumpVerboseDiagnostics`: if set to "1", enables the _createdump_ utilities verbose diagnostic messages (TRACE_VERBOSE macro).
-- `COMPlus_CreateDumpLogToFile`: if set, it is the path of the file to write the _createdump_ diagnostic messages.
-- `COMPlus_EnableCrashReport`: In .NET 6.0 or greater, if set to "1", createdump also generates a json formatted crash report which includes information about the threads and stack frames of the crashing application. The crash report name is the dump path/name with _.crashreport.json_ appended.
-- `COMPlus_EnableCrashReportOnly`: In .NET 7.0 or greater, same as COMPlus_EnableCrashReport except the core dump is not generated.
+- `DOTNET_DbgEnableMiniDump`: if set to "1", enables this core dump generation. The default is NOT to generate a dump.
+- `DOTNET_DbgMiniDumpType`: See below. Default is "2" MiniDumpWithPrivateReadWriteMemory.
+- `DOTNET_DbgMiniDumpName`: if set, use as the template to create the dump path and file name. See "Dump name formatting" for how the dump name can be formatted. The default is _/tmp/coredump.%p_.
+- `DOTNET_CreateDumpDiagnostics`: if set to "1", enables the _createdump_ utilities diagnostic messages (TRACE macro).
+- `DOTNET_CreateDumpVerboseDiagnostics`: if set to "1", enables the _createdump_ utilities verbose diagnostic messages (TRACE_VERBOSE macro).
+- `DOTNET_CreateDumpLogToFile`: if set, it is the path of the file to write the _createdump_ diagnostic messages.
+- `DOTNET_EnableCrashReport`: In .NET 6.0 or greater, if set to "1", createdump also generates a json formatted crash report which includes information about the threads and stack frames of the crashing application. The crash report name is the dump path/name with _.crashreport.json_ appended.
+- `DOTNET_EnableCrashReportOnly`: In .NET 7.0 or greater, same as DOTNET_EnableCrashReport except the core dump is not generated.
-COMPlus_DbgMiniDumpType values:
+DOTNET_DbgMiniDumpType values:
|Value|Minidump Enum|Description|
collect profiles and correlate them with that machine code. This could
benefit any developers doing performance analysis of their own code.
The JIT team has discussed this, options include building something on top of
- the profiler APIs, enabling COMPlus_JitDisasm in release builds, and shipping
+ the profiler APIs, enabling DOTNET_JitDisasm in release builds, and shipping
with or making easily available an alt jit that supports JitDisasm.
- Hardware companies maintain optimization/performance guides for their ISAs.
Should we maintain one for MSIL and/or C# (and/or F#)? If we hosted such a
Without runtime support for hot/cold splitting in .NET as of summer 2022, testing the JIT's existing hot/cold splitting
support is not as simple as turning the feature on. A new "fake" splitting mode, enabled by the
-`COMPlus_JitFakeProcedureSplitting` environment variable, removes this dependency on runtime support. This mode allows
+`DOTNET_JitFakeProcedureSplitting` environment variable, removes this dependency on runtime support. This mode allows
the JIT to execute its hot/cold splitting workflow without changing the runtime's behavior. This workflow proceeds as
follows:
While enabling fake-splitting also enables `opts.compProcedureSplitting`, there is no guarantee the JIT will fake-split
a function unless `Compiler::fgDetermineFirstColdBlock` finds a splitting point; without PGO data, the JIT's heuristics
may be too conservative for extensive testing. To aid regression testing, the JIT also has a stress-splitting mode now,
-under `COMPlus_JitStressProcedureSplitting`. When `opts.compProcedureSplitting` and stress-splitting are both enabled,
+under `DOTNET_JitStressProcedureSplitting`. When `opts.compProcedureSplitting` and stress-splitting are both enabled,
the JIT splits every function after its first basic block; in other words, `fgFirstColdBlock` is always
`fgFirstBB->bbNext`. The rest of the hot/cold splitting workflow is the same: The JIT emits instructions to handle the
split code sections and, if fake-splitting, utilizes only one memory buffer.
- This is generally not required, as the block will
normally have a predecessor block that has already
been allocated. This facility is exercised by the 0x100
- (`LSRA_BLOCK_BOUNDARY_LAYOUT`) or 0x200 (`LSRA_BLOCK_BOUNDARY_ROTATE`) settings of `COMPlus_JitStressRegs`.
+ (`LSRA_BLOCK_BOUNDARY_LAYOUT`) or 0x200 (`LSRA_BLOCK_BOUNDARY_ROTATE`) settings of `DOTNET_JitStressRegs`.
- At the end of a block, for any exposed uses that do not have downstream
`RefPosition`s (e.g. variables that are live across the backedge, so there is no
- Resolution of exception edges
- - When `COMPlus_EnableEHWriteThru == 0`, any variable that's
+ - When `DOTNET_EnableEHWriteThru == 0`, any variable that's
live in to an exception region is always referenced on the stack.
- See [Enable EHWriteThru by default](#enable-ehwritethru-by-default).
LSRA Stress Modes
-----------------
-The implementation uses the `COMPlus_JitStressRegs` environment variable.
+The implementation uses the `DOTNET_JitStressRegs` environment variable.
The following are the stress modes associated with this variable. For
the most part they can be combined, though in some cases the values are
exclusive:
### Enable EHWriteThru by default
-When `COMPlus_EnableEHWriteThru` is set, some performance regressions are observed. When an EH write-thru variable (i.e. one that is live into an exception region) is defined, its value is
+When `DOTNET_EnableEHWriteThru` is set, some performance regressions are observed. When an EH write-thru variable (i.e. one that is live into an exception region) is defined, its value is
always stored, in addition to potentially remaining live in a register. This increases register
pressure which may result in worse code.
## Test and Cleanup Issues
Issue [\#9767](https://github.com/dotnet/runtime/issues/9767) captures the issue that the
-"spill always" stress mode, `LSRA_SPILL_ALWAYS`, `COMPlus_JitStressRegs=0x800` doesn't work properly.
+"spill always" stress mode, `LSRA_SPILL_ALWAYS`, `DOTNET_JitStressRegs=0x800` doesn't work properly.
Issue [\#6261](https://github.com/dotnet/runtime/issues/6261) has to do with `RegOptional`
`RefPositions` that are marked as `copyReg` or `moveReg`. See the notes on this issue;
```
-If we wanted to change the order of heuristics, we would have to update above code to rearrange the portion of heuristics we apply. To experiment with different heuristics ordering, it is not feasible to do such refactoring for every combination. After doing some research on which design pattern to pick for such problems, we went the old school way and moved the individual heuristics code in its own method (marked with `__forceinline`, to eliminate the throughput impact of refactoring changes). We could use function pointer to invoke one of these methods in any order we wanted. The last bit was an ability to add a way for user to specify heuristic order they want to try. We assigned a single letter to each heuristic (`Shorthand` column in above table) and we exposed `COMPlus_JitLsraOrdering` environment variable to specify the ordering. The default ordering is `"ABCDEFGHIJKLMNOPQ"` (the current order), but if given something else like `"PEHDCGAIJNLKOBFMQ"`, it would apply heuristic in that order. In this example, heuristic corresponding to `P` is `PREV_REG_OPT` and thus would apply busy register heuristics first, followed by `OWN_PREFERENCE`, `CALLER_CALLEE` and so forth. As you notice, now we will be able to apply the busy register heuristics before applying the ones for free registers.
+If we wanted to change the order of heuristics, we would have to update above code to rearrange the portion of heuristics we apply. To experiment with different heuristics ordering, it is not feasible to do such refactoring for every combination. After doing some research on which design pattern to pick for such problems, we went the old school way and moved the individual heuristics code in its own method (marked with `__forceinline`, to eliminate the throughput impact of refactoring changes). We could use function pointer to invoke one of these methods in any order we wanted. The last bit was an ability to add a way for user to specify heuristic order they want to try. We assigned a single letter to each heuristic (`Shorthand` column in above table) and we exposed `DOTNET_JitLsraOrdering` environment variable to specify the ordering. The default ordering is `"ABCDEFGHIJKLMNOPQ"` (the current order), but if given something else like `"PEHDCGAIJNLKOBFMQ"`, it would apply heuristic in that order. In this example, heuristic corresponding to `P` is `PREV_REG_OPT` and thus would apply busy register heuristics first, followed by `OWN_PREFERENCE`, `CALLER_CALLEE` and so forth. As you notice, now we will be able to apply the busy register heuristics before applying the ones for free registers.
After stitching all this together, the refactored code looked like this:
LinearScan::allocateReg(RefPosition refPosition, Interval* interval)
{
- char *ordering = Read_COMPlus_LsraOrdering();
+ char *ordering = Read_DOTNET_JitLsraOrdering();
HeuristicFn fn;
for (char order in ordering) {
if (ScoreMappingTable->Lookup(order, &fn)) {
## Impact measurement
-Now that rearranging the heuristic ordering is possible with `COMPlus_JitLsraOrdering`, we decided to measure the impact of the reordering by running [superpmi](https://github.com/dotnet/runtime/blob/e063533eb79eace045f43b41980cbed21c8d7365/src/coreclr/ToolBox/superpmi/readme.md) tool. `superpmi` tool JITs all the methods of a given assembly file (`*.dll` or `*.exe`) without executing the generated machine code. Given two versions of `clrjit.dll` (RyuJIT binary), it also has an ability to perform the comparison of generated code and reporting back the number of methods that got improved/regressed in terms of `CodeSize` (machine code size), `PerfScore` (instruction latency/throughput measurements), `InstructionCount` (number of instructions present), etc. We picked `PerfScore` metrics because that accurately includes the cost of register spilling. If LSRA doesn't come up with optimal register choice, we would see several `mov` instructions that load/store into memory and that would decrease the throughput, increase the latency, and hence lower the `PerfScore`. If the spilling happens inside a loop, `PerfScore` metrics accounts for that by considering the product of loop block weights and `PerfScore`. Thus, our goal would be to reduce the `PerfScore` as much possible, lower the `PerfScore`, better is the code we generated. The baseline for the comparison was the default ordering, and we wanted to compare it with an ordering specified in `COMPlus_JitLsraOrdering`. We could specify any combination of sequence `A` thru `Q` and tweak the LSRA algorithm to apply a different heuristics order. But since there are 17 heuristics, there would be **355,687,428,096,000** (17!) possibilities to try out and it will not be practical to do so. We ought to find a better way!
+Now that rearranging the heuristic ordering is possible with `DOTNET_JitLsraOrdering`, we decided to measure the impact of the reordering by running [superpmi](https://github.com/dotnet/runtime/blob/e063533eb79eace045f43b41980cbed21c8d7365/src/coreclr/ToolBox/superpmi/readme.md) tool. `superpmi` tool JITs all the methods of a given assembly file (`*.dll` or `*.exe`) without executing the generated machine code. Given two versions of `clrjit.dll` (RyuJIT binary), it also has an ability to perform the comparison of generated code and reporting back the number of methods that got improved/regressed in terms of `CodeSize` (machine code size), `PerfScore` (instruction latency/throughput measurements), `InstructionCount` (number of instructions present), etc. We picked `PerfScore` metrics because that accurately includes the cost of register spilling. If LSRA doesn't come up with optimal register choice, we would see several `mov` instructions that load/store into memory and that would decrease the throughput, increase the latency, and hence lower the `PerfScore`. If the spilling happens inside a loop, `PerfScore` metrics accounts for that by considering the product of loop block weights and `PerfScore`. Thus, our goal would be to reduce the `PerfScore` as much possible, lower the `PerfScore`, better is the code we generated. The baseline for the comparison was the default ordering, and we wanted to compare it with an ordering specified in `DOTNET_JitLsraOrdering`. We could specify any combination of sequence `A` thru `Q` and tweak the LSRA algorithm to apply a different heuristics order. But since there are 17 heuristics, there would be **355,687,428,096,000** (17!) possibilities to try out and it will not be practical to do so. We ought to find a better way!
## Genetic Algorithm
[Genetic algorithm](https://en.wikipedia.org/wiki/Genetic_algorithm) is the perfect solution to solve these kind of problems. For those who are not familiar, here is a quick summary - The algorithm starts with a community that has few candidates whose fitness score is predetermined. Each candidate is made up of sequence of genes and all candidates have same number of genes in them. The algorithm picks a pair of fit candidates (parents) and mutate their genes to produce offsprings. The algorithm calculates the fitness of the new offsprings and add them (along with the fitness score) back to the community pool. As the community evolves, more and more candidates who has fitness score equivalent or better than the initial population are added to the community. Of course, the community cannot grow infinitely, so the least fit candidates die. When there are no more candidates that are fit than the fittest candidate, the algorithm stops, giving us a set of fit candidates.
-This can be perfectly mapped to the heuristic selection ordering problem. We want to start with `"ABCDEFGHIJKLMNOPQ"` (default selection order) and each letter in this combination can be represented as a gene. Genetic algorithm would mutate the gene to produce a different order say `"ABMCDEFGHIKLNJOPQ"` and we will set that value in `COMPlus_JitLsraOrdering` variable. We would then run `superpmi.py` to produce the generated code and compare the `PerfScore` with that of the one produced by the default order. `PerfScore` represents the fitness, lower the value of that metric, more fit is the corresponding candidate, in our case, better is the heuristic ordering.
+This can be perfectly mapped to the heuristic selection ordering problem. We want to start with `"ABCDEFGHIJKLMNOPQ"` (default selection order) and each letter in this combination can be represented as a gene. Genetic algorithm would mutate the gene to produce a different order say `"ABMCDEFGHIKLNJOPQ"` and we will set that value in `DOTNET_JitLsraOrdering` variable. We would then run `superpmi.py` to produce the generated code and compare the `PerfScore` with that of the one produced by the default order. `PerfScore` represents the fitness, lower the value of that metric, more fit is the corresponding candidate, in our case, better is the heuristic ordering.
Below is the pseudo code of genetic algorithm that we experimented with to find optimal heuristic ordering.
1. `superpmi.exe` was modified to aggregate **relative** `PerfScore` difference of code generated by default and modified LSRA ordering. When `superpmi.exe` is run in parallel (which is by default), this number was reported back on the console by each parallel process.
2. `superpmi.py` was modified to further aggregate the relative `PerfScore` differences of parallel `superpmi.exe` processes and report back the final relative `PerfScore` difference.
3. LSRA has many asserts throughout the codebase. They assume that during register selection, all the free registers are tried first before checking for busy registers. Since we wanted to understand the impact of preferring busy registers as well, we had to disable those asserts.
-4. `superpmi.exe asmdiffs` takes two versions of `clrjit.dll` that you want to compare. Both must be from different location. In our case, we only wanted to experiment with different heuristic ordering by passing different values for `COMPlus_JitLsraOrdering`, we made a copy of `clrjit.dll` -> `copy_clrjit.dll` and passed various ordering to the copied `copy_clrjit.dll`.
+4. `superpmi.exe asmdiffs` takes two versions of `clrjit.dll` that you want to compare. Both must be from different location. In our case, we only wanted to experiment with different heuristic ordering by passing different values for `DOTNET_JitLsraOrdering`, we made a copy of `clrjit.dll` -> `copy_clrjit.dll` and passed various ordering to the copied `copy_clrjit.dll`.
Here is the sample invocation of `superpmi.py` that genetic algorithm invoked to get the `PerfScore` (fitness score) of each experimented ordering:
* Create the new platform-specific files
* Create the platform-specific build instructions (in CMakeLists.txt). This probably will require
new platform-specific build instructions at the root level, as well as the JIT level of the source tree.
-* Focus on MinOpts; disable the optimization phases, or always test with `COMPlus_JITMinOpts=1`.
+* Focus on MinOpts; disable the optimization phases, or always test with `DOTNET_JITMinOpts=1`.
* Disable optional features, such as:
* `FEATURE_EH` -- if 0, all exception handling blocks are removed. Of course, tests with exception handling
that depend on exceptions being thrown and caught won't run correctly.
* `FEATURE_TAILCALL_OPT`
* `FEATURE_SIMD`
* Build the new JIT as an altjit. In this mode, a "base" JIT is invoked to compile all functions except
- the one(s) specified by the `COMPlus_AltJit` variable. For example, setting `COMPlus_AltJit=Add` and running
+ the one(s) specified by the `DOTNET_AltJit` variable. For example, setting `DOTNET_AltJit=Add` and running
a test will use the "base" JIT (say, the Windows x64 targeting JIT) to compile all functions *except*
`Add`, which will be first compiled by the new altjit, and if it fails, fall back to the "base" JIT. In this
way, only very limited JIT functionality need to work, as the "base" JIT takes care of most functions.
* Focus on the CodeGenBringUpTests (src\tests\JIT\CodeGenBringUpTests), starting with the simple ones.
These are designed such that for a test `XXX.cs`, there is a single interesting function named `XXX` to compile
(that is, the name of the source file is the same as the name of the interesting function. This was done to make
- the scripts to invoke these tests very simple.). Set `COMPlus_AltJit=XXX` so the new JIT only attempts to
+ the scripts to invoke these tests very simple.). Set `DOTNET_AltJit=XXX` so the new JIT only attempts to
compile that one function.
-* Use `COMPlus_JitDisasm` to see the generated code for functions, even if the code isn't run.
+* Use `DOTNET_JitDisasm` to see the generated code for functions, even if the code isn't run.
## Expand test coverage
## Bring the optimizer phases on-line
-* Run tests with and without `COMPlus_JITMinOpts=1`.
-* It probably makes sense to set `COMPlus_TieredCompilation=0` (or disable it for the platform entirely) until much later.
+* Run tests with and without `DOTNET_JITMinOpts=1`.
+* It probably makes sense to set `DOTNET_TieredCompilation=0` (or disable it for the platform entirely) until much later.
## Improve quality
* When the tests pass with the basic modes, start running with `JitStress` and `JitStressRegs` stress modes.
* Bring `GCStress` on-line. This also requires VM work.
-* Work on `COMPlus_GCStress=4` quality. When crossgen/ngen is brought on-line, test with `COMPlus_GCStress=8`
- and `COMPlus_GCStress=C` as well.
+* Work on `DOTNET_GCStress=4` quality. When crossgen/ngen is brought on-line, test with `DOTNET_GCStress=8`
+ and `DOTNET_GCStress=C` as well.
## Work on performance
### Example of Post-Import IR
For this snippet of code (extracted from
-[src/tests/JIT/CodeGenBringUpTests/DblRoots.cs](https://github.com/dotnet/runtime/blob/main/src/tests/JIT/CodeGenBringUpTests/DblRoots.cs)), with `COMPlus_TieredCompilation=0` and using the DblRoots_ro.csproj project to compile it:
+[src/tests/JIT/CodeGenBringUpTests/DblRoots.cs](https://github.com/dotnet/runtime/blob/main/src/tests/JIT/CodeGenBringUpTests/DblRoots.cs)), with `DOTNET_TieredCompilation=0` and using the DblRoots_ro.csproj project to compile it:
r1 = (-b + Math.Sqrt(b*b - 4*a*c))/(2*a);
## How to create a JitDump
-You can enable dumps by setting the `COMPlus_JitDump` environment variable to a space-separated list of the method(s)
+You can enable dumps by setting the `DOTNET_JitDump` environment variable to a space-separated list of the method(s)
you want to dump. For example:
```cmd
:: Print out lots of useful info when
:: compiling methods named Main/GetEnumerator
-set "COMPlus_JitDump=Main GetEnumerator"
+set "DOTNET_JitDump=Main GetEnumerator"
```
See [Setting configuration variables](viewing-jit-dumps.md#setting-configuration-variables) for more
`gtNewNode` to see when it is created, and then a data breakpoint on the field that you believe is corrupted.
The trees are connected by line characters (either in ASCII, by default, or in slightly more readable Unicode when
-`COMPlus_JitDumpASCII=0` is specified), to make it a bit easier to read.
+`DOTNET_JitDumpASCII=0` is specified), to make it a bit easier to read.
## Variable naming
### Getting Dumps
```
-set COMPlus_JitDump=Main
-set COMPlus_JitDumpAscii=0
-set COMPlus_JitDumpFg=Main
-set COMPlus_JitDumpFgDot=1
-set COMPlus_JitDumpFgFile=Main
-set COMPlus_JitDumpFgPhase=OPT-CHK
+set DOTNET_JitDump=Main
+set DOTNET_JitDumpAscii=0
+set DOTNET_JitDumpFg=Main
+set DOTNET_JitDumpFgDot=1
+set DOTNET_JitDumpFgFile=Main
+set DOTNET_JitDumpFgPhase=OPT-CHK
```
{BinaryDir}\CoreRun.exe PopCount.exe 1122334455667788 > jitdump.out.0
- unsigned optIsLclVarUpdateTree(GenTreePtr tree, GenTreePtr* otherTree, genTreeOps *updateOper);
Getting Ready
-- Set COMPlus_JitDump=Main
-- Set COMPlus_AltJit=*
+- Set DOTNET_JitDump=Main
+- Set DOTNET_AltJit=*
- Run and capture jitdump1.out
- Examine the IR for the loop just prior to optCloneLoops
- instrsxarch.h: encoding
- codegenxarch.cpp: generate instruction
- importer.cpp: name recognition
-- set COMPlus_JitDump
+- set DOTNET_JitDump
- Run & capture jitdump2.out, search for CountBits, then look at disassembly
Add Pattern Recognition (SampleStep2 shelveset):
## Backup
-### COMPlus Variables
-- COMPlus_JitDump={method-list} – lots of info about what the JIT is doing
-- COMPlus_JitDisasm={method-list} – disassembly listing of each method
-- COMPlus_JitDisasmDiffable – avoid printing pointer values that can change from one invocation to the next, so that the disassembly can be more easily diffed.
-- COMPlus_JITGCDump={method-list} – this dumps the GC information.
-- COMPlus_JitUnwindDump={method-list} – dumps the unwind tables.
-- COMPlus_JitEHDump={method-list} – dumps the exception handling tables.
-- COMPlus_JitTimeLogFile – a log file for timing information (dbg or chk builds)
-- COMPlus_JitTimeLogCsv – a log file for timing information in csv form (all builds)
+### Environment Variables
+- DOTNET_JitDump={method-list} – lots of info about what the JIT is doing
+- DOTNET_JitDisasm={method-list} – disassembly listing of each method
+- DOTNET_JitDisasmDiffable – avoid printing pointer values that can change from one invocation to the next, so that the disassembly can be more easily diffed.
+- DOTNET_JITGCDump={method-list} – this dumps the GC information.
+- DOTNET_JitUnwindDump={method-list} – dumps the unwind tables.
+- DOTNET_JitEHDump={method-list} – dumps the exception handling tables.
+- DOTNET_JitTimeLogFile – a log file for timing information (dbg or chk builds)
+- DOTNET_JitTimeLogCsv – a log file for timing information in csv form (all builds)
- {method-list} can be a space-separated list of method names or * for all methods
### IR Dump: Front-end
-Here is an example dump in tree order (shown with COMPlus_JitDumpAscii=0)
+Here is an example dump in tree order (shown with DOTNET_JitDumpAscii=0)
```
STMT00000 (IL ???... ???)
[000067] -AC-G------- ▌ call help void HELPER.CORINFO_HELP_ARRADDR_ST
## Setting configuration variables
-The behavior of the JIT can be controlled via a number of configuration variables. These are declared in [inc/clrconfigvalues.h](/src/coreclr/inc/clrconfigvalues.h) and [jit/jitconfigvalues.h](/src/coreclr/jit/jitconfigvalues.h). When used as an environment variable, the string name generally has `COMPlus_` prepended. When used as a registry value name, the configuration name is used directly.
+The behavior of the JIT can be controlled via a number of configuration variables. These are declared in [inc/clrconfigvalues.h](/src/coreclr/inc/clrconfigvalues.h) and [jit/jitconfigvalues.h](/src/coreclr/jit/jitconfigvalues.h). When used as an environment variable, the string name generally has `DOTNET_` prepended. When used as a registry value name, the configuration name is used directly.
These can be set in one of three ways:
-* Setting the environment variable `COMPlus_<flagname>`. For example, the following will set the `JitDump` flag so that the compilation of all methods named `Main` will be dumped:
+* Setting the environment variable `DOTNET_<flagname>`. For example, the following will set the `JitDump` flag so that the compilation of all methods named `Main` will be dumped:
```shell
# Windows
- set COMPlus_JitDump=Main
+ set DOTNET_JitDump=Main
# Powershell
- $env:COMPlus_JitDump="Main"
+ $env:DOTNET_JitDump="Main"
# Unix
- export COMPlus_JitDump=Main
+ export DOTNET_JitDump=Main
```
* *Windows-only:* Setting the registry key `HKCU\Software\Microsoft\.NETFramework`, Value `<flagName>`, type `REG_SZ` or `REG_DWORD` (depending on the flag).
## Specifying method names
-Some environment variables such as `COMPlus_JitDump` take a set of patterns specifying method names. The matching works in the following way:
+Some environment variables such as `DOTNET_JitDump` take a set of patterns specifying method names. The matching works in the following way:
* A method set string is a space-separated list of patterns. Patterns can arbitrarily contain both '*' (match any characters) and '?' (match any 1 character).
* The string matched against depends on characters in the pattern:
+ If the pattern contains a ':' character, the string matched against is prefixed by the class name and a colon
new C<int, int>().M<int, int>(default, default, default, default); // compilation 2
```
-The full names of these instantiations are the following, as printed by `COMPlus_JitDisasmSummary`:
+The full names of these instantiations are the following, as printed by `DOTNET_JitDisasmSummary`:
```
MyNamespace.C`2[byte,System.__Canon]:M[int,System.__Canon](byte,System.__Canon,int,System.__Canon)
Below are some of the most useful `COMPlus` variables. Where {method-list} is specified in the list below, you can supply a space-separated list of either fully-qualified or simple method names (the former is useful when running something that has many methods of the same name), or you can specify `*` to mean all methods.
-* `COMPlus_JitDump`={method-list} – dump lots of useful information about what the JIT is doing. See [Reading a JitDump](ryujit-overview.md#reading-a-jitdump) for more on how to analyze this data.
-* `COMPlus_JitDumpASCII`={1 or 0} - Specifies whether the JIT dump should be ASCII only (Defaults to 1). Disabling this generates more readable expression trees.
-* `COMPlus_JitDisasm`={method-list} – dump a disassembly listing of each method.
-* `COMPlus_JitDisasmDiffable` – set to 1 to tell the JIT to avoid printing things like pointer values that can change from one invocation to the next, so that the disassembly can be more easily compared.
-* `COMPlus_JitGCDump`={method-list} – dump the GC information.
-* `COMPlus_JitUnwindDump`={method-list} – dump the unwind tables.
-* `COMPlus_JitEHDump`={method-list} – dump the exception handling tables.
-* `COMPlus_JitTimeLogFile`={file name} – this specifies a log file to which timing information is written.
-* `COMPlus_JitTimeLogCsv`={file name} – this specifies a log file to which summary timing information can be written, in CSV form.
+* `DOTNET_JitDump`={method-list} – dump lots of useful information about what the JIT is doing. See [Reading a JitDump](ryujit-overview.md#reading-a-jitdump) for more on how to analyze this data.
+* `DOTNET_JitDumpASCII`={1 or 0} - Specifies whether the JIT dump should be ASCII only (Defaults to 1). Disabling this generates more readable expression trees.
+* `DOTNET_JitDisasm`={method-list} – dump a disassembly listing of each method.
+* `DOTNET_JitDisasmDiffable` – set to 1 to tell the JIT to avoid printing things like pointer values that can change from one invocation to the next, so that the disassembly can be more easily compared.
+* `DOTNET_JitGCDump`={method-list} – dump the GC information.
+* `DOTNET_JitUnwindDump`={method-list} – dump the unwind tables.
+* `DOTNET_JitEHDump`={method-list} – dump the exception handling tables.
+* `DOTNET_JitTimeLogFile`={file name} – this specifies a log file to which timing information is written.
+* `DOTNET_JitTimeLogCsv`={file name} – this specifies a log file to which summary timing information can be written, in CSV form.
## Dumping native images
- This will increase the size of the image by up to 5 * the specified alignment. Typical increases will be more similar to 3 * the specified alignment
2. The composite image must be copied into a hugetlbfs filesystem which is visible to the .NET process instead of the composite image being loaded from the normal path.
- IMPORTANT: The composite image must NOT be located in the normal path next to the application binary, or that file will be used instead of the huge page version.
- - The environment variable `COMPlus_NativeImageSearchPaths` must be set to point at the location of the hugetlbfs in use. For instance, `COMPlus_NativeImageSearchPaths` might be set to `/var/lib/hugetlbfs/user/USER/pagesize-2MB`
+ - The environment variable `DOTNET_NativeImageSearchPaths` must be set to point at the location of the hugetlbfs in use. For instance, `DOTNET_NativeImageSearchPaths` might be set to `/var/lib/hugetlbfs/user/USER/pagesize-2MB`
- As the cp command does not support copying into a hugetlbfs due to lack of support for the write syscall in that file system, a custom copy application must be used. A sample application that may be used to perform this task has a source listing in Appendix A.
3. The machine must be configured to have sufficient huge pages available in the appropriate huge page pool. The memory requirements of huge page PE loading are as follows.
- Sufficient pages to hold the unmodified copy of the composite image in the hugetlbfs. These pages will be used by the initial copy which emplaces the composite image into huge pages.
- Additional checks in heap verification
-Heap verification will now include checks to verify that no one changes the string content after it’s hash is computed. This can be turned on when a certain level of COMPlus_HeapVerify is specified.
+Heap verification will now include checks to verify that no one changes the string content after it’s hash is computed. This can be turned on when a certain level of DOTNET_HeapVerify is specified.
- Stress mode
```
dotnet build -p:Configuration=Release
-set COMPLUS_TieredPGO=1
-set COMPLUS_TC_QuickJitForLoops=1
-set COMPLUS_TC_CallCountThreshold=10000
-set COMPLUS_ReadyToRun=0
+set DOTNET_TieredPGO=1
+set DOTNET_TC_QuickJitForLoops=1
+set DOTNET_TC_CallCountThreshold=10000
+set DOTNET_ReadyToRun=0
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:0x1E000080018:4 -- bin\Release\net6.0\pgotest.exe
-set COMPLUS_TieredPGO=
-set COMPLUS_TC_QuickJitForLoops=
-set COMPLUS_TC_CallCountThreshold=
-set COMPLUS_ReadyToRun=
+set DOTNET_TieredPGO=
+set DOTNET_TC_QuickJitForLoops=
+set DOTNET_TC_CallCountThreshold=
+set DOTNET_ReadyToRun=
dotnet-pgo create-mibc --trace trace.nettrace --output trace.mibc
### Platform Target Information
-The JIT depends on the VM and configuration settings to determine what target platform to generate code for. The VM settings are communicated in the `JitFlags` on `Compiler::opts` and the JIT checks the various `COMPlus_EnableXXX` configuration settings as well. See `Compiler::compSetProcessor()` and `jitconfigvalues.h`.
+The JIT depends on the VM and configuration settings to determine what target platform to generate code for. The VM settings are communicated in the `JitFlags` on `Compiler::opts` and the JIT checks the various `DOTNET_EnableXXX` configuration settings as well. See `Compiler::compSetProcessor()` and `jitconfigvalues.h`.
### Importation
allocate a new block of memory in the acceptable range. If this function
can't find and allocate space in the required range, we have, on AMD64,
one more fallback: if an emergency jump stub reserve was created using
-the `COMPlus_NGenReserveForjumpStubs` configuration (see below), we
+the `DOTNET_NGenReserveForjumpStubs` configuration (see below), we
attempt to find an appropriate, in range, allocation from that emergency
pool. If all attempts fail to create an allocation in the appropriate
range, we encounter a fatal error (and tear down the process), with a
configuration variables are relevant (these can be set in the registry
as well as the environment, as usual):
-* `COMPlus_CodeHeapReserveForJumpStubs`. This value specifies a percentage
+* `DOTNET_CodeHeapReserveForJumpStubs`. This value specifies a percentage
of every code heap to reserve for jump stubs. When a non-jump stub
allocation in the code heap would eat into the reserved percentage, a
new code heap is allocated instead, leaving some buffer in the existing
code heap. The default value is 2.
-* `COMPlus_NGenReserveForjumpStubs`. This value, when non-zero, creates an
+* `DOTNET_NGenReserveForjumpStubs`. This value, when non-zero, creates an
"emergency jump stub reserve". For each NGEN image loaded, an emergency
jump stub reserve space is calculated by multiplying this number, as a
percentage, against the loaded native image size. This amount of space
stub space are followed, and only if they fail to find appropriate space
are the emergency jump stub reserve heaps tried. The default value is
zero.
-* `COMPlus_BreakOnOutOfMemoryWithinRange`. When set to 1, this breaks into
+* `DOTNET_BreakOnOutOfMemoryWithinRange`. When set to 1, this breaks into
the debugger when the specific jump stub allocation failure condition
occurs.
-The `COMPlus_NGenReserveForjumpStubs` mitigation is described publicly
+The `DOTNET_NGenReserveForjumpStubs` mitigation is described publicly
here:
https://support.microsoft.com/en-us/help/3152158/out-of-memory-exception-in-a-managed-application-that-s-running-on-the-64-bit-.net-framework.
-(It also mentions, in passing, `COMPlus_CodeHeapReserveForJumpStubs`, but
+(It also mentions, in passing, `DOTNET_CodeHeapReserveForJumpStubs`, but
only to say not to use it.)
## Jump stubs and the JIT
For non-LCG, we are reserving, but not allocating, a space at the end
of the code heap. This is similar and in addition to the reservation done by
-COMPlus_CodeHeapReserveForJumpStubs. (See https://github.com/dotnet/coreclr/pull/15296).
+DOTNET_CodeHeapReserveForJumpStubs. (See https://github.com/dotnet/coreclr/pull/15296).
## Ready2Run
## Stress modes
-Setting `COMPlus_ForceRelocs=1` forces jump stubs to be created in all
+Setting `DOTNET_ForceRelocs=1` forces jump stubs to be created in all
scenarios except for JIT generated code. As described previously, the
VM doesn't know when the JIT is reporting a rel32 data address or code
address, and in addition the JIT reports relocations for intra-function
can reliably force jump stub creation for every rel32 call or jump. In
addition, we should make sure to enable code to stress the creation of
jump stubs for every mitigation that is implemented whether that be
-using the existing `COMPlus_ForceRelocs` configuration, or the creation of
+using the existing `DOTNET_ForceRelocs` configuration, or the creation of
a new configuration option.
loading a standalone GC.
There is one environment variable that governs the behavior of the standalone GC loader:
-`COMPlus_GCName`. It should be set to be a path to a dynamic shared library containing
+`DOTNET_GCName`. It should be set to be a path to a dynamic shared library containing
the GC that the EE intends to load. Its presence informs the EE that, first, a standalone GC
is to be loaded and, second, precisely where the EE should load it from.
-The EE will call `LoadLibrary` using the path given by `COMPlus_GCName`.
+The EE will call `LoadLibrary` using the path given by `DOTNET_GCName`.
If this succeeds, the EE will move to the next step in the loading process.
### Verifying the version of a candidate GC
### Application running single file based EventPipe session
-If application supports controlled runtime shutdown, `mono_jit_cleanup` gets called before terminating process, it is possible to run a single file based EventPipe session using environment variables as described in https://docs.microsoft.com/en-us/dotnet/core/diagnostics/eventpipe#trace-using-environment-variables. In .net6 an additional variable has been added, `COMPlus_EventPipeOutputStreaming`, making sure data is periodically flushed into the output file.
+If application supports controlled runtime shutdown, `mono_jit_cleanup` gets called before terminating process, it is possible to run a single file based EventPipe session using environment variables as described in https://docs.microsoft.com/en-us/dotnet/core/diagnostics/eventpipe#trace-using-environment-variables. In .net6 an additional variable has been added, `DOTNET_EventPipeOutputStreaming`, making sure data is periodically flushed into the output file.
If application doesn't support controlled runtime shutdown, this mode won't work, since it requires rundown events, only emitted when closing session and flushing memory manager. If application doesn't call `mono_jit_cleanup` before terminating, generated nettrace file will lack rundown events needed to produce callstacks including symbols.
2. **[App]** Setup the application shell - this enables tracing configuration inside of CoreCLR.
> ```bash
- > export COMPlus_PerfMapEnabled=1
- > export COMPlus_EnableEventLog=1
+ > export DOTNET_PerfMapEnabled=1
+ > export DOTNET_EnableEventLog=1
> ```
Note:
- COMPlus_PerfMapEnabled will cause the .NET runtime to write a file containing symbolic information for managed code to the disk. Depending on the performance of your disk and the amount of managed code in the application this could have a significant performance overhead.
+ DOTNET_PerfMapEnabled will cause the .NET runtime to write a file containing symbolic information for managed code to the disk. Depending on the performance of your disk and the amount of managed code in the application this could have a significant performance overhead.
3. **[Trace]** Start collection.
can tolerate that (you probably can), then this is an alternative. You were already setting environment variables
in order to get symbols, you simply need to add one more.
> ```bash
- > export COMPlus_ZapDisable=1
+ > export DOTNET_ZapDisable=1
> ```
With this change you should get the symbols for all .NET code.
On Linux those mechanisms are not available yet. Instead, there are two environment variables that exist just on linux to do some basic filtering.
-* COMPlus_EventSourceFilter – filter event sources by name
-* COMPlus_EventNameFilter – filter events by name
+* DOTNET_EventSourceFilter – filter event sources by name
+* DOTNET_EventNameFilter – filter events by name
Setting one or both of these variables will only enable collecting events that contain the name you specify as a substring. Strings are treated as case insensitive.
// Setting this env var allows Diagnostic.Debug to write to stderr. In a browser environment this
// output will be sent to the console. Right now this is the only way to emit debug logging from
// corlib assemblies.
- monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0);
+ monoeg_g_setenv ("DOTNET_DebugWriteToStdErr", "1", 0);
```
## Updating Emscripten version in Docker image
Many test runs use a non-default product configuration, to allow re-using existing test assets to stress various aspects of the system.
Determine the precise test configuration under which the test has failed. This might be evident from the test job name. For example,
`net8.0-windows-Release-x86-CoreCLR_checked-jitstress1-Windows.10.Amd64.Open` is a libraries test run on Windows with a Release x86 libraries
-build, Checked coreclr build, and setting the `COMPlus_JitStress=1` configuration setting, in the `Windows.10.Amd64.Open` Helix queue.
+build, Checked coreclr build, and setting the `DOTNET_JitStress=1` configuration setting, in the `Windows.10.Amd64.Open` Helix queue.
You need to be careful when reproducing failures to set all the correct environment variables. In the above example, if you look at the
test failure console log, you find:
```
-C:\h\w\AE88094B\w\B1B409BF\e>set COMPlus
-COMPlus_JitStress=1
-COMPlus_TieredCompilation=0
+C:\h\w\AE88094B\w\B1B409BF\e>set DOTNET
+DOTNET_JitStress=1
+DOTNET_TieredCompilation=0
```
-Thus, you can see that you also need to set `COMPlus_TieredCompilation=0` when attempting to reproduce the failure.
+Thus, you can see that you also need to set `DOTNET_TieredCompilation=0` when attempting to reproduce the failure.
On non-Windows platforms, you'll see a similar output for the test configuration. E.g.,
```
+ printenv
-+ grep COMPlus
-COMPlus_TieredCompilation=1
-COMPlus_JitStress=1
-COMPlus_DbgMiniDumpName=/home/helixbot/dotnetbuild/dumps/coredump.%d.dmp
-COMPlus_DbgEnableMiniDump=1
++ grep DOTNET
+DOTNET_TieredCompilation=1
+DOTNET_JitStress=1
+DOTNET_DbgMiniDumpName=/home/helixbot/dotnetbuild/dumps/coredump.%d.dmp
+DOTNET_DbgEnableMiniDump=1
```
-You might need to set variables in addition to the `COMPlus_*` (equivalently, `DOTNET_*`) variables. For example, you might see:
+You might need to set variables in addition to the `DOTNET_*` variables. For example, you might see:
```
set RunCrossGen2=1
```
modes set.
Once the problem can be reproduced, attempt to reproduce the problem without setting any of the JIT stress variables, e.g., do not set:
-- `COMPlus_TieredCompilation`
-- `COMPlus_JitStress`
-- `COMPlus_JitStressRegs`
+- `DOTNET_TieredCompilation`
+- `DOTNET_JitStress`
+- `DOTNET_JitStressRegs`
If the test reliably fails with the JIT stress modes, but passes without, consider it a JIT issue.
## Example: GC stress failures
-Failures that occur only when the `COMPlus_GCStress` variable is set are called "GCStress failures". There are several general kinds
+Failures that occur only when the `DOTNET_GCStress` variable is set are called "GCStress failures". There are several general kinds
of failures:
- Timeouts: tests run under this stress mode run very slowly.
- A "GC hole": the JIT (or sometimes VM) doesn't properly report all GC object locations to the system.
- A bug in the GC stress infrastructure.
- A bug in the GC itself.
-Note the value `COMPlus_GCStress` is set to is a bitmask. Failures with 0x1 or 0x2 (and thus 0x3) are typically VM failures.
+Note the value `DOTNET_GCStress` is set to is a bitmask. Failures with 0x1 or 0x2 (and thus 0x3) are typically VM failures.
Failures with 0x4 or 0x8 (and thus 0xC) are typically JIT failures. Ideally, a failure can be reduced to fail with only a single
bit set (that is, either 0x4 or 0x8, which is more specific than just 0xC). That is especially true for 0xF, where we don't know if
it's likely a VM or a JIT failure without reducing it.
## Use:
Two environment variables dictate behavior:
-- `COMPlus_AutoTrace_N_Tracers`: The number of tracers to create. Should be a number in `[0,64]` where `0` will bypass the wait for attach.
-- `COMPlus_AutoTrace_Command`: The path to the executable to be invoked. Typically this will be a `run.sh|cmd` script.
+- `DOTNET_AutoTrace_N_Tracers`: The number of tracers to create. Should be a number in `[0,64]` where `0` will bypass the wait for attach.
+- `DOTNET_AutoTrace_Command`: The path to the executable to be invoked. Typically this will be a `run.sh|cmd` script.
-> (NB: you should `cd` into the directory you intend to execute `COMPlus_AutoTrace_Command` from as the first line of the script.)
+> (NB: you should `cd` into the directory you intend to execute `DOTNET_AutoTrace_Command` from as the first line of the script.)
-Once turned on, AutoTrace will run the specified command `COMPlus_AutoTrace_N_Tracers` times.
+Once turned on, AutoTrace will run the specified command `DOTNET_AutoTrace_N_Tracers` times.
- `<check-prefix>-FULL-LINE-NEXT:` - same as using FileCheck's `<check-prefix>-NEXT:`, but checks that the line matches exactly; leading and trailing whitespace is ignored.
# Test Run Limitations
1. Disasm checks will not run if these environment variables are set:
-- `COMPlus_JitStress`
-- `COMPlus_JitStressRegs`
-- `COMPlus_TailcallStress`
-- `COMPlus_TieredPGO`
+- `DOTNET_JitStress`
+- `DOTNET_JitStressRegs`
+- `DOTNET_TailcallStress`
+- `DOTNET_TieredPGO`
2. Disasm checks will not run under GCStress test modes.
3. Disasm checks will not run under heap-verify test modes.
4. Disasm checks will not run under cross-gen2 test modes.
; Total bytes of code 6, prolog size 0, PerfScore 2.10, instruction count 3, allocated bytes for code 6 (MethodHash=e2c7b489) for method Program:PerformMod_1(uint):uint <-- end anchor
```
- SuperFileCheck does not use a command line library today due to it being so minimal and most of the heavy lifting is done passing the arguments to FileCheck itself. As SuperFileCheck continues to grow, we will need to use a command line library, such as System.CommandLine.
-- Support various JIT test modes to allow testing codegen under specific scenarios. (Note: these can already be partially done by setting environment variables (like `COMPlus_JITMinOpts`) in the test itself.)
+- Support various JIT test modes to allow testing codegen under specific scenarios. (Note: these can already be partially done by setting environment variables (like `DOTNET_JITMinOpts`) in the test itself.)
- JIT IR Testing - we may want to allow testing against certain phases of a method by looking at the IR. There are a lot of unknowns surrounding this, but it would be useful to have a prototype.
**Disable using multiple attributes:**
This attribute can be used multiple times, in which case the test is disabled for any of the conditions. In this example,
-only Release builds where `COMPlus_JITMinOpts` is not set would run the test.
+only Release builds where `DOTNET_JITMinOpts` is not set would run the test.
```cs
[SkipOnCoreClr("https://github.com/dotnet/runtime/issues/67886", ~RuntimeConfiguration.Release)]
[SkipOnCoreClr("https://github.com/dotnet/runtime/issues/67886", RuntimeTestModes.JitMinOpts)]
// Verification asserts are disabled by default because some debuggers (cdb/windbg) probe likely locations
// for DAC and having this assert pop up all the time can be annoying. We let derived classes enable
- // this if they want. It can also be overridden at run-time with COMPlus_DbgDACAssertOnMismatch,
+ // this if they want. It can also be overridden at run-time with DOTNET_DbgDACAssertOnMismatch,
// see ClrDataAccess::VerifyDlls for details.
m_fEnableDllVerificationAsserts = false;
#endif
// Notes:
// The implementation of ASSERT accesses this via code:DacTargetConsistencyAssertsEnabled
//
-// By default, this is disabled, unless COMPlus_DbgDACEnableAssert is set (see code:ClrDataAccess::ClrDataAccess).
+// By default, this is disabled, unless DOTNET_DbgDACEnableAssert is set (see code:ClrDataAccess::ClrDataAccess).
// This is necessary for compatibility. For example, SOS expects to be able to scan for
// valid MethodTables etc. (which may cause ASSERTs), and also doesn't want ASSERTs when working
// with targets with corrupted memory.
// On Debug builds, we'll ASSERT by default whenever the target appears to be corrupt or
// otherwise inconsistent (both in DAC and DBI). But we also need the ability to
// explicitly test corrupt targets.
- // Tests should set COMPlus_DbgIgnoreInconsistentTarget=1 to suppress these asserts
+ // Tests should set DOTNET_DbgIgnoreInconsistentTarget=1 to suppress these asserts
// Note that this controls two things:
// 1) DAC behavior - see code:IDacDbiInterface::DacSetTargetConsistencyChecks
// 2) RS-only consistency asserts - see code:CordbProcess::TargetConsistencyCheck
//
// This is an encapsulation of the information necessary to connect to the debugger proxy on a remote machine.
// It includes the IP address and the port number. The IP address can be set via the env var
-// COMPlus_DbgTransportProxyAddress, and the port number is fixed when Mac debugging is configured.
+// DOTNET_DbgTransportProxyAddress, and the port number is fixed when Mac debugging is configured.
//
struct MachineInfo
// This lets us run a set of managed apps under a debugger.
if (!CORDebuggerAttached())
{
- #define DBG_ATTACH_ON_STARTUP_ENV_VAR W("COMPlus_DbgAttachOnStartup")
+ #define DBG_ATTACH_ON_STARTUP_ENV_VAR W("DOTNET_DbgAttachOnStartup")
PathString temp;
// We explicitly just check the env because we don't want a switch this invasive to be global.
DWORD fAttach = WszGetEnvironmentVariable(DBG_ATTACH_ON_STARTUP_ENV_VAR, temp) > 0;
// channel (and we've run out of bits for an additional channel) and is likely to be of limited use to anyone
// besides the transport developer (and even then only occasionally).
//
-// To enable use 'set|export COMPlus_DbgTransportLog=X' where X is 1 for RS logging, 2 for LS logging and 3
-// for both (default is disabled). Use 'set|export COMPlus_DbgTransportLogClass=X' where X is the hex
+// To enable use 'set|export DOTNET_DbgTransportLog=X' where X is 1 for RS logging, 2 for LS logging and 3
+// for both (default is disabled). Use 'set|export DOTNET_DbgTransportLogClass=X' where X is the hex
// representation of one or more DbgTransportLogClass flags defined below (default is all classes enabled).
-// For instance, 'set COMPlus_DbgTransportLogClass=f' will enable only message send and receive logging (for
+// For instance, 'set DOTNET_DbgTransportLogClass=f' will enable only message send and receive logging (for
// all message types).
enum DbgTransportLogEnable
{
#ifdef _DEBUG
//
// Debug-only network fault injection (in order to help test the robust session code). Control is via a single
-// DWORD read from the environment (COMPlus_DbgTransportFaultInject). This DWORD is treated as a set of bit
+// DWORD read from the environment (DOTNET_DbgTransportFaultInject). This DWORD is treated as a set of bit
// fields as follows:
//
// +-------+-------+-------+----------------+-----------+
//
// For example:
//
-// export COMPlus_DbgTransportFaultInject=1ff00001
+// export DOTNET_DbgTransportFaultInject=1ff00001
// --> Fail all network operations on the left side 1% of the time
//
-// export COMPlus_DbgTransportFaultInject=34200063
+// export DOTNET_DbgTransportFaultInject=34200063
// --> Fail Send() calls on both sides while the session is Open 99% of the time
//
#endif
/*
- This method is where COMPlus_LTTngConfig environment variable is parsed and is registered with the runtime provider
+ This method is where DOTNET_LTTngConfig environment variable is parsed and is registered with the runtime provider
context structs generated by src/scripts/genEventing.py.
It expects the environment variable to look like:
provider:keywords:level,provider:keywords:level
static BYTE* g_preferredRangeMin;
static BYTE* g_preferredRangeMax;
- // Caches the COMPlus_EnableWXORX setting
+ // Caches the DOTNET_EnableWXORX setting
static bool g_isWXorXEnabled;
// Head of the linked list of all RX blocks that were allocated by this allocator
#define JIT_IS_ALIGNED
#endif
-// ALLOW_SXS_JIT enables AltJit support for JIT-ing, via COMPlus_AltJit / COMPlus_AltJitName.
-// ALLOW_SXS_JIT_NGEN enables AltJit support for NGEN, via COMPlus_AltJitNgen / COMPlus_AltJitName.
+// ALLOW_SXS_JIT enables AltJit support for JIT-ing, via DOTNET_AltJit / DOTNET_AltJitName.
+// ALLOW_SXS_JIT_NGEN enables AltJit support for NGEN, via DOTNET_AltJitNgen / DOTNET_AltJitName.
// Note that if ALLOW_SXS_JIT_NGEN is defined, then ALLOW_SXS_JIT must be defined.
#define ALLOW_SXS_JIT
#define ALLOW_SXS_JIT_NGEN
#define FEATURE_JIT_TIMER
// This feature in RyuJIT supersedes the FEATURE_JIT_TIMER. In addition to supporting the time log file, this
-// feature also supports using COMPlus_JitTimeLogCsv=a.csv, which will dump method-level and phase-level timing
+// feature also supports using DOTNET_JitTimeLogCsv=a.csv, which will dump method-level and phase-level timing
// statistics. Also see comments on FEATURE_JIT_TIMER.
#define FEATURE_JIT_METHOD_PERF
#endif
// Enables a mode in which GC is completely conservative in stacks and registers: all stack slots and registers
-// are treated as potential pinned interior pointers. When enabled, the runtime flag COMPLUS_GCCONSERVATIVE
+// are treated as potential pinned interior pointers. When enabled, the runtime flag DOTNET_GCCONSERVATIVE
// determines dynamically whether GC is conservative. Note that appdomain unload, LCG and unloadable assemblies
// do not work reliably with conservative GC.
#define FEATURE_CONSERVATIVE_GC 1
/*****************************************************************************
* Unit testing of the ARM64 emitter: generate a bunch of instructions into the prolog
- * (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late
+ * (it's as good a place as any), then use DOTNET_JitLateDisasm=* to see if the late
* disassembler thinks the instructions as the same as we do.
*/
// ugliness of having the failure here.
if (!compiler->jitFallbackCompile)
{
- // Use COMPlus_JitNoForceFallback=1 to prevent NOWAY assert testing from happening,
+ // Use DOTNET_JitNoForceFallback=1 to prevent NOWAY assert testing from happening,
// especially that caused by enabling JIT stress.
if (!JitConfig.JitNoForceFallback())
{
{
// Unit testing of the emitter: generate a bunch of instructions into the last block
// (it's as good as any, but better than the prologue, which can only be a single instruction
-// group) then use COMPlus_JitLateDisasm=* to see if the late disassembler
+// group) then use DOTNET_JitLateDisasm=* to see if the late disassembler
// thinks the instructions are the same as we do.
#if defined(TARGET_AMD64) && defined(LATE_DISASM)
genAmd64EmitterUnitTests();
/*****************************************************************************
* Unit testing of the LOONGARCH64 emitter: generate a bunch of instructions into the prolog
- * (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late
+ * (it's as good a place as any), then use DOTNET_JitLateDisasm=* to see if the late
* disassembler thinks the instructions as the same as we do.
*/
/*****************************************************************************
* Unit testing of the XArch emitter: generate a bunch of instructions into the prolog
-* (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late
+* (it's as good a place as any), then use DOTNET_JitLateDisasm=* to see if the late
* disassembler thinks the instructions as the same as we do.
*/
extern ICorJitHost* g_jitHost;
#if defined(DEBUG)
-// Column settings for COMPlus_JitDumpIR. We could(should) make these programmable.
+// Column settings for DOTNET_JitDumpIR. We could(should) make these programmable.
#define COLUMN_OPCODE 30
#define COLUMN_OPERANDS (COLUMN_OPCODE + 25)
#define COLUMN_KINDS 110
//
// Return Value:
// An unsigned char value used to initizalize memory allocated by the JIT.
-// The default value is taken from COMPLUS_JitDefaultFill, if is not set
+// The default value is taken from DOTNET_JitDefaultFill, if is not set
// the value will be 0xdd. When JitStress is active a random value based
// on the method hash is used.
//
#ifdef PROFILING_SUPPORTED
// A Dummy routine to receive Enter/Leave/Tailcall profiler callbacks.
-// These are used when complus_JitEltHookEnabled=1
+// These are used when DOTNET_JitEltHookEnabled=1
#ifdef TARGET_AMD64
void DummyProfilerELTStub(UINT_PTR ProfilerHandle, UINT_PTR callerSP)
{
#endif // !DEBUG
- // Take care of COMPlus_AltJitExcludeAssemblies.
+ // Take care of DOTNET_AltJitExcludeAssemblies.
if (opts.altJit)
{
// First, initialize the AltJitExcludeAssemblies list, but only do it once.
bool altJitConfig = !pfAltJit->isEmpty();
// If we have a non-empty AltJit config then we change all of these other
- // config values to refer only to the AltJit. Otherwise, a lot of COMPlus_* variables
+ // config values to refer only to the AltJit. Otherwise, a lot of DOTNET_* variables
// would apply to both the altjit and the normal JIT, but we only care about
- // debugging the altjit if the COMPlus_AltJit configuration is set.
+ // debugging the altjit if the DOTNET_AltJit configuration is set.
//
if (compIsForImportOnly() && (!altJitConfig || opts.altJit))
{
opts.doLateDisasm = true;
#endif // LATE_DISASM
- // This one applies to both Ngen/Jit Disasm output: COMPlus_JitDasmWithAddress=1
+ // This one applies to both Ngen/Jit Disasm output: DOTNET_JitDasmWithAddress=1
if (JitConfig.JitDasmWithAddress() != 0)
{
opts.disAddr = true;
compProfilerMethHndIndirected = false;
}
- // Honour COMPlus_JitELTHookEnabled or STRESS_PROFILER_CALLBACKS stress mode
+ // Honour DOTNET_JitELTHookEnabled or STRESS_PROFILER_CALLBACKS stress mode
// only if VM has not asked us to generate profiler hooks in the first place.
// That is, override VM only if it hasn't asked for a profiler callback for this method.
// Don't run this stress mode when pre-JITing, as we would need to emit a relocation
// is nothing preventing that.
if (jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0))
{
- printf("OPTIONS: Tier-0 compilation (set COMPlus_TieredCompilation=0 to disable)\n");
+ printf("OPTIONS: Tier-0 compilation (set DOTNET_TieredCompilation=0 to disable)\n");
}
if (jitFlags->IsSet(JitFlags::JIT_FLAG_TIER1))
{
}
}
- // 0: No stress (Except when explicitly set in complus_JitStressModeNames)
+ // 0: No stress (Except when explicitly set in DOTNET_JitStressModeNames)
// !=2: Vary stress. Performance will be slightly/moderately degraded
// 2: Check-all stress. Performance will be REALLY horrible
const int stressLevel = getJitStressLevel();
}
#if !defined(TARGET_AMD64)
- // The VM sets JitFlags::JIT_FLAG_FRAMED for two reasons: (1) the COMPlus_JitFramed variable is set, or
+ // The VM sets JitFlags::JIT_FLAG_FRAMED for two reasons: (1) the DOTNET_JitFramed variable is set, or
// (2) the function is marked "noinline". The reason for #2 is that people mark functions
// noinline to ensure the show up on in a stack walk. But for AMD64, we don't need a frame
// pointer for the frame to show up in stack walk.
if (!compIsForInlining() && !opts.altJit && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ALT_JIT))
{
- // We're an altjit, but the COMPlus_AltJit configuration did not say to compile this method,
+ // We're an altjit, but the DOTNET_AltJit configuration did not say to compile this method,
// so skip it.
return CORJIT_SKIPPED;
}
#endif
- // Check for COMPlus_AggressiveInlining
+ // Check for DOTNET_AggressiveInlining
if (JitConfig.JitAggressiveInlining())
{
compDoAggressiveInlining = true;
#endif
bool disAsm; // Display native code as it is generated
- bool dspDiffable; // Makes the Jit Dump 'diff-able' (currently uses same COMPlus_* flag as disDiffable)
+ bool dspDiffable; // Makes the Jit Dump 'diff-able' (currently uses same DOTNET_* flag as disDiffable)
bool disDiffable; // Makes the Disassembly code 'diff-able'
bool disAlignment; // Display alignment boundaries in disassembly code
#ifdef DEBUG
#if defined(TARGET_ARM64)
// Decision about whether to save FP/LR registers with callee-saved registers (see
- // COMPlus_JitSaveFpLrWithCalleSavedRegisters).
+ // DOTNET_JitSaveFpLrWithCalleSavedRegisters).
int compJitSaveFpLrWithCalleeSavedRegisters;
#endif // defined(TARGET_ARM64)
#ifdef DEBUG
// Components used by the compiler may write unit test suites, and
// have them run within this method. They will be run only once per process, and only
- // in debug. (Perhaps should be under the control of a COMPlus_ flag.)
+ // in debug. (Perhaps should be under the control of a DOTNET_ flag.)
// These should fail by asserting.
void compDoComponentUnitTestsOnce();
#endif // DEBUG
static fgWalkPreFn gsReplaceShadowParams; // Shadow param replacement tree-walk
#define DEFAULT_MAX_INLINE_SIZE 100 // Methods with > DEFAULT_MAX_INLINE_SIZE IL bytes will never be inlined.
- // This can be overwritten by setting complus_JITInlineSize env variable.
+ // This can be overwritten by setting DOTNET_JITInlineSize env variable.
#define DEFAULT_MAX_INLINE_DEPTH 20 // Methods at more than this level deep will not be inlined
}
else
{
- // For non-adaptive, just take whatever is supplied using COMPlus_ variables
+ // For non-adaptive, just take whatever is supplied using DOTNET_ variables
maxLoopSize = emitComp->opts.compJitAlignLoopMaxCodeSize;
}
void DECLSPEC_NORETURN fatal(int errCode)
{
#ifdef DEBUG
- if (errCode != CORJIT_SKIPPED) // Don't stop on NYI: use COMPlus_AltJitAssertOnNYI for that.
+ if (errCode != CORJIT_SKIPPED) // Don't stop on NYI: use DOTNET_AltJitAssertOnNYI for that.
{
if (JitConfig.DebugBreakOnVerificationFailure())
{
logf(LL_ERROR, "COMPILATION FAILED: file: %s:%d compiling method %s reason %s\n", tail, line,
env->compiler->info.compFullName, msg);
- // We now only assert when user explicitly set ComPlus_JitRequired=1
- // If ComPlus_JitRequired is 0 or is not set, we will not assert.
+ // We now only assert when user explicitly set DOTNET_JitRequired=1
+ // If DOTNET_JitRequired is 0 or is not set, we will not assert.
if (JitConfig.JitRequired() == 1 || getBreakOnBadCode())
{
assertAbort(msg, file, line);
if (comp != nullptr && comp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ALT_JIT))
{
// If we hit an assert, and we got here, it's either because the user hit "ignore" on the
- // dialog pop-up, or they set COMPlus_ContinueOnAssert=1 to not emit a pop-up, but just continue.
+ // dialog pop-up, or they set DOTNET_ContinueOnAssert=1 to not emit a pop-up, but just continue.
// If we're an altjit, we have two options: (1) silently continue, as a normal JIT would, probably
// leading to additional asserts, or (2) tell the VM that the AltJit wants to skip this function,
- // thus falling back to the fallback JIT. Setting COMPlus_AltJitSkipOnAssert=1 chooses this "skip"
+ // thus falling back to the fallback JIT. Setting DOTNET_AltJitSkipOnAssert=1 chooses this "skip"
// to the fallback JIT behavior. This is useful when doing ASM diffs, where we only want to see
// the first assert for any function, but we don't want to kill the whole ngen process on the
- // first assert (which would happen if you used COMPlus_NoGuiOnAssert=1 for example).
+ // first assert (which would happen if you used DOTNET_NoGuiOnAssert=1 for example).
if (JitConfig.AltJitSkipOnAssert() != 0)
{
fatal(CORJIT_SKIPPED);
// type - A (wide) string indicating the type of dump, "dot" or "xml"
//
// Notes:
-// The filename to use to write the data comes from the COMPlus_JitDumpFgFile or COMPlus_NgenDumpFgFile
+// The filename to use to write the data comes from the DOTNET_JitDumpFgFile or DOTNET_NgenDumpFgFile
// configuration. If unset, use "default". The "type" argument is used as a filename extension,
// e.g., "default.dot".
//
// MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.
//
// Here are the config values that control it:
-// COMPlus_JitDumpFg A string (ala the COMPlus_JitDump string) indicating what methods to dump
+// DOTNET_JitDumpFg A string (ala the DOTNET_JitDump string) indicating what methods to dump
// flowgraphs for.
-// COMPlus_JitDumpFgDir A path to a directory into which the flowgraphs will be dumped.
-// COMPlus_JitDumpFgFile The filename to use. The default is "default.[xml|dot]".
+// DOTNET_JitDumpFgDir A path to a directory into which the flowgraphs will be dumped.
+// DOTNET_JitDumpFgFile The filename to use. The default is "default.[xml|dot]".
// Note that the new graphs will be appended to this file if it already exists.
-// COMPlus_JitDumpFgPhase Phase(s) after which to dump the flowgraph.
+// DOTNET_JitDumpFgPhase Phase(s) after which to dump the flowgraph.
// Set to the short name of a phase to see the flowgraph after that phase.
// Leave unset to dump after COLD-BLK (determine first cold block) or set to *
// for all phases.
-// COMPlus_JitDumpFgPrePhase Phase(s) before which to dump the flowgraph.
-// COMPlus_JitDumpFgDot 0 for xml format, non-zero for dot format. (Default is dot format.)
-// COMPlus_JitDumpFgEH (dot only) 0 for no exception-handling information; non-zero to include
+// DOTNET_JitDumpFgPrePhase Phase(s) before which to dump the flowgraph.
+// DOTNET_JitDumpFgDot 0 for xml format, non-zero for dot format. (Default is dot format.)
+// DOTNET_JitDumpFgEH (dot only) 0 for no exception-handling information; non-zero to include
// exception-handling regions.
-// COMPlus_JitDumpFgLoops (dot only) 0 for no loop information; non-zero to include loop regions.
-// COMPlus_JitDumpFgConstrained (dot only) 0 == don't constrain to mostly linear layout; non-zero == force
+// DOTNET_JitDumpFgLoops (dot only) 0 for no loop information; non-zero to include loop regions.
+// DOTNET_JitDumpFgConstrained (dot only) 0 == don't constrain to mostly linear layout; non-zero == force
// mostly lexical block linear layout.
-// COMPlus_JitDumpFgBlockId Display blocks with block ID, not just bbNum.
+// DOTNET_JitDumpFgBlockId Display blocks with block ID, not just bbNum.
//
// Example:
//
// If you want to dump just before and after a single phase, say loop cloning, use:
-// set COMPlus_JitDumpFgPhase=LP-CLONE
-// set COMPlus_JitDumpFgPrePhase=LP-CLONE
+// set DOTNET_JitDumpFgPhase=LP-CLONE
+// set DOTNET_JitDumpFgPrePhase=LP-CLONE
//
bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
{
if (!isTailCall && opts.compGcChecks && (info.compRetType == TYP_REF))
{
// DDB 3483 : JIT Stress: early termination of GC ref's life time in exception code path
- // VSW 440513: Incorrect gcinfo on the return value under COMPlus_JitGCChecks=1 for methods with
+ // VSW 440513: Incorrect gcinfo on the return value under DOTNET_JitGCChecks=1 for methods with
// one-return BB.
assert(op2->gtType == TYP_REF);
}
#endif
- // Check for COMPlus_AggressiveInlining
+ // Check for DOTNET_AggressiveInlining
if (compDoAggressiveInlining)
{
methAttr |= CORINFO_FLG_FORCEINLINE;
if (m_Compiler->compRandomInlineStress())
{
externalSeed = getJitStressLevel();
- // We can set COMPlus_JitStressModeNames without setting COMPlus_JitStress,
+ // We can set DOTNET_JitStressModeNames without setting DOTNET_JitStress,
// but we need external seed to be non-zero.
if (externalSeed == 0)
{
CONFIG_INTEGER(AltJitLimit, W("AltJitLimit"), 0) // Max number of functions to use altjit for (decimal)
CONFIG_INTEGER(AltJitSkipOnAssert, W("AltJitSkipOnAssert"), 0) // If AltJit hits an assert, fall back to the fallback
// JIT. Useful in conjunction with
- // COMPlus_ContinueOnAssert=1
+ // DOTNET_ContinueOnAssert=1
CONFIG_INTEGER(BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff) // Breaks when using internal logging on a
// particular token value.
CONFIG_INTEGER(DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0) // Halts the jit on
CONFIG_INTEGER(JitNoCSE, W("JitNoCSE"), 0)
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
+ // Overrides DOTNET_JitForceFallback and JIT stress
// flags.
CONFIG_INTEGER(JitNoForwardSub, W("JitNoForwardSub"), 0) // Disables forward sub
CONFIG_INTEGER(JitNoHoist, W("JitNoHoist"), 0)
// IsTelemetryEnabled: Can we perform JIT telemetry
//
// Return Value:
-// Returns "true" if COMPlus_JitTelemetry environment flag is
+// Returns "true" if DOTNET_JitTelemetry environment flag is
// non-zero. Else returns "false".
//
//
// Notification of noway_assert.
void NotifyNowayAssert(const char* filename, unsigned line);
- // Is telemetry enabled through COMPlus_JitTelemetry?
+ // Is telemetry enabled through DOTNET_JitTelemetry?
static bool IsTelemetryEnabled();
private:
//----------------------------------------------------------------------------
// optLoopCloningEnabled: Determine whether loop cloning is allowed. It is allowed
-// in release builds. For debug builds, use the value of the COMPlus_JitCloneLoops
+// in release builds. For debug builds, use the value of the DOTNET_JitCloneLoops
// flag (which defaults to 1, or allowed).
//
// Return Value:
// mask - The current mask of register candidates for a node
//
// Return Value:
-// A possibly-modified mask, based on the value of COMPlus_JitStressRegs.
+// A possibly-modified mask, based on the value of DOTNET_JitStressRegs.
//
// Notes:
// This is the method used to implement the stress options that limit
// same tree. However, now that last uses are computed as RefPositions are created,
// that is no longer necessary, and this method is simply retained as a check.
// The exception to the check-only behavior is when LSRA_EXTEND_LIFETIMES if set via
-// COMPlus_JitStressRegs. In that case, this method is required, because even though
+// DOTNET_JitStressRegs. In that case, this method is required, because even though
// the RefPositions will not be marked lastUse in that case, we still need to correctly
// mark the last uses on the tree nodes, which is done by this method.
//
{
// Spill "targetReg" to the stack and add its eventual target (otherTargetReg)
// to "targetRegsFromStack", which will be handled below.
- // NOTE: This condition is very rare. Setting COMPlus_JitStressRegs=0x203
+ // NOTE: This condition is very rare. Setting DOTNET_JitStressRegs=0x203
// has been known to trigger it in JIT SH.
// First, spill "otherInterval" from targetReg to the stack.
#ifdef DEBUG
private:
//------------------------------------------------------------------------
- // Should we stress lsra? This uses the COMPlus_JitStressRegs variable.
+ // Should we stress lsra? This uses the DOTNET_JitStressRegs variable.
//
// The mask bits are currently divided into fields in which each non-zero value
// is a distinct stress option (e.g. 0x3 is not a combination of 0x1 and 0x2).
//------------------------------------------------------------------------
// optConfigBiasedCSE:
// Stress mode to shuffle the decision to CSE or not using environment
- // variable COMPlus_JitStressBiasedCSE (= 0 to 100%). When the bias value
- // is not specified but COMPlus_JitStress is ON, generate a random bias.
+ // variable DOTNET_JitStressBiasedCSE (= 0 to 100%). When the bias value
+ // is not specified but DOTNET_JitStress is ON, generate a random bias.
//
// Return Value:
// 0 -- This method is indifferent about this CSE (no bias specified and no stress)
// A debug stress only method that returns "1" with probability (P)
// defined by:
//
- // P = (COMPlus_JitStressBiasedCSE / 100) (or)
- // P = (random(100) / 100) when COMPlus_JitStress is specified and
- // COMPlus_JitStressBiasedCSE is unspecified.
+ // P = (DOTNET_JitStressBiasedCSE / 100) (or)
+ // P = (random(100) / 100) when DOTNET_JitStress is specified and
+ // DOTNET_JitStressBiasedCSE is unspecified.
//
// When specified, the bias is reinterpreted as a decimal number between 0
// to 100.
- // When bias is not specified, a bias is randomly generated if COMPlus_JitStress
+ // When bias is not specified, a bias is randomly generated if DOTNET_JitStress
// is non-zero.
//
// Callers are supposed to call this method for each CSE promotion decision
//
bool Compiler::optConfigDisableCSE()
{
- // Next check if COMPlus_JitNoCSE is set and applies to this method
+ // Next check if DOTNET_JitNoCSE is set and applies to this method
//
unsigned jitNoCSE = JitConfig.JitNoCSE();
// UnwindFragmentInfo: represents all the unwind information for a single fragment of a function or funclet.
// A fragment is a section with a code size less than the maximum unwind code size: either 512K bytes, or
-// that specified by COMPlus_JitSplitFunctionSize. In most cases, there will be exactly one fragment.
+// that specified by DOTNET_JitSplitFunctionSize. In most cases, there will be exactly one fragment.
class UnwindFragmentInfo : public UnwindBase
{
// so the fragment size will fit in the unwind data "Function Length" field.
// The ARM Exception Data specification "Function Fragments" section describes this.
// We split the function so that it is no larger than 512K bytes, or the value of
-// the COMPlus_JitSplitFunctionSize value, if defined (and smaller). We must determine
+// the DOTNET_JitSplitFunctionSize value, if defined (and smaller). We must determine
// how to split the function/funclet before we issue the instructions, so we can
// reserve the unwind space with the VM. The instructions issued may shrink (but not
// expand!) during issuing (although this is extremely rare in any case, and may not
maxFragmentSize = UW_MAX_FRAGMENT_SIZE_BYTES;
#ifdef DEBUG
- // Consider COMPlus_JitSplitFunctionSize
+ // Consider DOTNET_JitSplitFunctionSize
unsigned splitFunctionSize = (unsigned)JitConfig.JitSplitFunctionSize();
if (splitFunctionSize != 0)
#ifdef DEBUG
// Did the emitter split the function/funclet into as many fragments as we asked for?
- // It might be fewer if the COMPlus_JitSplitFunctionSize was used, but it better not
+ // It might be fewer if the DOTNET_JitSplitFunctionSize was used, but it better not
// be fewer if we're splitting into 512K blocks!
unsigned fragCount = 0;
// If this fires, then we split into fewer fragments than we asked for, and we are using
// the default, unwind-data-defined 512K maximum fragment size. We won't be able to fit
- // this fragment into the unwind data! If you set COMPlus_JitSplitFunctionSize to something
+ // this fragment into the unwind data! If you set DOTNET_JitSplitFunctionSize to something
// small, we might not be able to split into as many fragments as asked for, because we
// can't split prologs or epilogs.
assert(maxFragmentSize != UW_MAX_FRAGMENT_SIZE_BYTES);
// so the fragment size will fit in the unwind data "Function Length" field.
// The LOONGARCH Exception Data specification "Function Fragments" section describes this.
// We split the function so that it is no larger than 512K bytes, or the value of
-// the COMPlus_JitSplitFunctionSize value, if defined (and smaller). We must determine
+// the DOTNET_JitSplitFunctionSize value, if defined (and smaller). We must determine
// how to split the function/funclet before we issue the instructions, so we can
// reserve the unwind space with the VM. The instructions issued may shrink (but not
// expand!) during issuing (although this is extremely rare in any case, and may not
maxFragmentSize = UW_MAX_FRAGMENT_SIZE_BYTES;
#ifdef DEBUG
- // Consider COMPlus_JitSplitFunctionSize
+ // Consider DOTNET_JitSplitFunctionSize
unsigned splitFunctionSize = (unsigned)JitConfig.JitSplitFunctionSize();
if (splitFunctionSize != 0)
#ifdef DEBUG
// Did the emitter split the function/funclet into as many fragments as we asked for?
- // It might be fewer if the COMPlus_JitSplitFunctionSize was used, but it better not
+ // It might be fewer if the DOTNET_JitSplitFunctionSize was used, but it better not
// be fewer if we're splitting into 512K blocks!
unsigned fragCount = 0;
// If this fires, then we split into fewer fragments than we asked for, and we are using
// the default, unwind-data-defined 512K maximum fragment size. We won't be able to fit
- // this fragment into the unwind data! If you set COMPlus_JitSplitFunctionSize to something
+ // this fragment into the unwind data! If you set DOTNET_JitSplitFunctionSize to something
// small, we might not be able to split into as many fragments as asked for, because we
// can't split prologs or epilogs.
assert(maxFragmentSize != UW_MAX_FRAGMENT_SIZE_BYTES);
#ifdef DEBUG
// This helps test some performance pathologies related to "evaluation" of VNF_MapSelect terms,
// especially relating to GcHeap/ByrefExposed. We count the number of applications of such terms we consider,
- // and if this exceeds a limit, indicated by a COMPlus_ variable, we assert.
+ // and if this exceeds a limit, indicated by a DOTNET_ variable, we assert.
unsigned m_numMapSels;
#endif
};
PAL_DisplayDialog
Display a simple modal dialog with an alert icon and a single OK button. Caller supplies the title of the
- dialog and the main text. The dialog is displayed only if the COMPlus_EnableAssertDialog environment
+ dialog and the main text. The dialog is displayed only if the DOTNET_EnableAssertDialog environment
variable is set to the value "1".
--*/
// table. This satisfies the vast majority of practical cases where the total amount of loaded native image memory
// does not exceed approximately 2 GB.
// - The code heap allocator for the JIT can allocate from this address space. Beyond this reservation, one can use
- // the COMPlus_CodeHeapReserveForJumpStubs environment variable to reserve space for jump stubs.
+ // the DOTNET_CodeHeapReserveForJumpStubs environment variable to reserve space for jump stubs.
sizeOfAllocation = MaxExecutableMemorySize;
m_startAddress = ReserveVirtualMemory(pthrCurrent, nullptr, sizeOfAllocation, MEM_RESERVE_EXECUTABLE);
if (m_startAddress == nullptr)
* EventPipe. The feature itself is enabled via the feature flag FEATURE_AUTO_TRACE.
*
* Two environment variables dictate behavior:
- * - COMPlus_AutoTrace_N_Tracers: a number in [0,64] where 0 will disable the feature
- * - COMPlus_AutoTrace_Command: The path to an executable to be invoked. Typically this will be a "run.sh|cmd".
- * > (NB: you should `cd` into the directory you intend to execute `COMPlus_AutoTrace_Command` from as the first line of the script.)
+ * - DOTNET_AutoTrace_N_Tracers: a number in [0,64] where 0 will disable the feature
+ * - DOTNET_AutoTrace_Command: The path to an executable to be invoked. Typically this will be a "run.sh|cmd".
+ * > (NB: you should `cd` into the directory you intend to execute `DOTNET_AutoTrace_Command` from as the first line of the script.)
*
- * Once turned on, AutoTrace will run the specified command `COMPlus_AutoTrace_N_Tracers` times. There is an event that will pause execution
+ * Once turned on, AutoTrace will run the specified command `DOTNET_AutoTrace_N_Tracers` times. There is an event that will pause execution
* of the runtime until all the tracers have attached. Once all the tracers are attached, execution will continue normally.
*
* This logic is easily modified to accommodate testing other mechanisms related to the Diagnostic Server.
"The 'LastThrownObject' should not be, but is, NULL.\n"
"The runtime may have lost track of the type of an exception in flight.\n"
"Please get a good stack trace, find the caller of Validate, and file a bug against the owner.\n\n"
- "To suppress this assert 'set COMPlus_SuppressLostExceptionTypeAssert=1'");
+ "To suppress this assert 'set DOTNET_SuppressLostExceptionTypeAssert=1'");
}
}
#ifdef ALLOW_SXS_JIT
- // Do not load altjit.dll unless COMPlus_AltJit is set.
+ // Do not load altjit.dll unless DOTNET_AltJit is set.
// Even if the main JIT fails to load, if the user asks for an altjit we try to load it.
// This allows us to display load error messages for loading altjit.
if (dwTestOnlyAllowedEventMask != 0)
{
// Remove from the immutable flag list those flags that a test-only profiler may
- // need to set post-startup (specified via COMPlus_TestOnlyAllowedEventMask)
+ // need to set post-startup (specified via DOTNET_TestOnlyAllowedEventMask)
dwImmutableEventFlags &= ~dwTestOnlyAllowedEventMask;
// And add to the "allowable after attach" list the same test-only flags.
// FC_RETURN_BOOL(ret); // return statements should be FC_RETURN_BOOL
// FCIMPLEND
-// This rules are verified in binder.cpp if COMPlus_ConsistencyCheck is set.
+// This rules are verified in binder.cpp if DOTNET_ConsistencyCheck is set.
#ifdef _PREFAST_
//
// Given all of this, skip the ReplaceInstrAfterCall call by default to avoid
// unexpected AVs. This implies leaving out the GC coverage breakpoints for direct calls
- // unless COMPlus_GcStressOnDirectCalls=1 is explicitly set in the environment.
+ // unless DOTNET_GcStressOnDirectCalls=1 is explicitly set in the environment.
//
static ConfigDWORD fGcStressOnDirectCalls;
#ifdef _DEBUG
if (g_pConfig->fAssertOnFailFast())
- _ASSERTE(!"About to FailFast. set ComPlus_AssertOnFailFast=0 if this is expected");
+ _ASSERTE(!"About to FailFast. set DOTNET_AssertOnFailFast=0 if this is expected");
#endif
#ifndef TARGET_UNIX
// *****************************************************************************
// JitHelperLogging usage:
// 1) Ngen using:
-// COMPlus_HardPrejitEnabled=0
+// DOTNET_HardPrejitEnabled=0
//
// This allows us to instrument even ngen'd image calls to JIT helpers.
// Remember to clear the key after ngen-ing and before actually running
// the app you want to log.
//
// 2) Then set:
-// COMPlus_JitHelperLogging=1
-// COMPlus_LogEnable=1
-// COMPlus_LogLevel=1
-// COMPlus_LogToFile=1
+// DOTNET_JitHelperLogging=1
+// DOTNET_LogEnable=1
+// DOTNET_LogLevel=1
+// DOTNET_LogToFile=1
//
// 3) Run the app that you want to log; Results will be in COMPLUS.LOG(.X)
//
_ASSERTE_MSG(m_theUnwindBlock == NULL,
"reserveUnwindInfo() can only be called before allocMem(), but allocMem() has already been called. "
"This may indicate the JIT has hit a NO_WAY assert after calling allocMem(), and is re-JITting. "
- "Set COMPlus_JitBreakOnBadCode=1 and rerun to get the real error.");
+ "Set DOTNET_JitBreakOnBadCode=1 and rerun to get the real error.");
uint32_t currentSize = unwindSize;
if (profilerCompatibilityFlag == kPreventLoad)
{
- LOG((LF_CORPROF, LL_INFO10, "**PROF: COMPlus_ProfAPI_ProfilerCompatibilitySetting is set to PreventLoad. "
+ LOG((LF_CORPROF, LL_INFO10, "**PROF: DOTNET_ProfAPI_ProfilerCompatibilitySetting is set to PreventLoad. "
"Profiler will not be loaded.\n"));
MAKE_UTF8PTR_FROMWIDE(szEnvVarName, CLRConfig::EXTERNAL_ProfAPI_ProfilerCompatibilitySetting.name);
{
if (profilerCompatibilityFlag == kDisableV2Profiler)
{
- LOG((LF_CORPROF, LL_INFO10, "**PROF: COMPlus_ProfAPI_ProfilerCompatibilitySetting is set to DisableV2Profiler (the default). "
+ LOG((LF_CORPROF, LL_INFO10, "**PROF: DOTNET_ProfAPI_ProfilerCompatibilitySetting is set to DisableV2Profiler (the default). "
"V2 profilers are not allowed, so that the configured V2 profiler is going to be unloaded.\n"));
LogProfInfo(IDS_PROF_V2PROFILER_DISABLED, szClsid);
_ASSERTE(profilerCompatibilityFlag == kEnableV2Profiler);
- LOG((LF_CORPROF, LL_INFO10, "**PROF: COMPlus_ProfAPI_ProfilerCompatibilitySetting is set to EnableV2Profiler. "
+ LOG((LF_CORPROF, LL_INFO10, "**PROF: DOTNET_ProfAPI_ProfilerCompatibilitySetting is set to EnableV2Profiler. "
"The configured V2 profiler is going to be initialized.\n"));
MAKE_UTF8PTR_FROMWIDE(szEnvVarName, CLRConfig::EXTERNAL_ProfAPI_ProfilerCompatibilitySetting.name);
#define COM_METHOD HRESULT STDMETHODCALLTYPE
#ifdef _DEBUG
-// On DEBUG builds, setting the COMPlus_ProfAPIFault to a bitmask of the flags
+// On DEBUG builds, setting the DOTNET_ProfAPIFault to a bitmask of the flags
// below forces the Profiling API to return failures at various points.
// Useful for event log testing. Also see code:ProfilingAPIUtility.ShouldInjectProfAPIFault
enum ProfAPIFaultFlags
// ProfilingAPIUtility::ShouldInjectProfAPIFault
//
// Description:
-// Determines whether COMPlus_ProfAPIFault is set to a bitmask value
+// Determines whether DOTNET_ProfAPIFault is set to a bitmask value
// with the specified flag set
//
// Return Value:
// The above restrictions are lifted for certain tests that run with these environment
// variables set. (These are only available on DEBUG builds--including chk--not retail
// builds.)
-// * COMPlus_TestOnlyEnableSlowELTHooks:
+// * DOTNET_TestOnlyEnableSlowELTHooks:
// * If nonzero, then on startup the runtime will act as if a profiler was loaded
// on startup and requested ELT slow-path (even if no profiler is loaded on
// startup). This will also allow the SetEnterLeaveFunctionHooks(2) info
// functions to be called outside of Initialize(). If a profiler later
// attaches and calls these functions, then the slow-path wrapper will call
// into the profiler's ELT hooks.
-// * COMPlus_TestOnlyEnableObjectAllocatedHook:
+// * DOTNET_TestOnlyEnableObjectAllocatedHook:
// * If nonzero, then on startup the runtime will act as if a profiler was loaded
// on startup and requested ObjectAllocated callback (even if no profiler is loaded
// on startup). If a profiler later attaches and calls these functions, then the
// ObjectAllocated notifications will call into the profiler's ObjectAllocated callback.
-// * COMPlus_TestOnlyEnableICorProfilerInfo:
+// * DOTNET_TestOnlyEnableICorProfilerInfo:
// * If nonzero, then attaching profilers allows to call ICorProfilerInfo interface,
// which would otherwise be disallowed for attaching profilers
-// * COMPlus_TestOnlyAllowedEventMask
+// * DOTNET_TestOnlyAllowedEventMask
// * If a profiler needs to work around the restrictions of either
// COR_PRF_ALLOWABLE_AFTER_ATTACH or COR_PRF_MONITOR_IMMUTABLE it may set
// this environment variable. Its value should be a bitmask containing all
// JITting happened. But if we fail to acquire (ngen'ed method) or enter (unloaded domain) the original domain,
// we then try to JIT it under the thread's app domain in which the method was last seen to be executing.
//
-// o The JIT to use is configurable with COMPlus_AltJitName when COMPlus_StackSampling is enabled.
+// o The JIT to use is configurable with DOTNET_AltJitName when DOTNET_StackSampling is enabled.
//
// o One use case is to collect traces as an .mc file from SuperPMI Shim JIT.
//
-p:MicrosoftNetCoreAppRuntimePackDir=/live-runtime-artifacts/microsoft.netcore.app.runtime.linux-x64/$CONFIGURATION/
# Enable dump collection
-ENV COMPlus_DbgEnableMiniDump=1
-ENV COMPlus_DbgMiniDumpType=MiniDumpWithFullMemory
-ENV COMPlus_DbgMiniDumpName="/dumps-share/coredump.%p"
+ENV DOTNET_DbgEnableMiniDump=1
+ENV DOTNET_DbgMiniDumpType=MiniDumpWithFullMemory
+ENV DOTNET_DbgMiniDumpName="/dumps-share/coredump.%p"
EXPOSE 5001
-p:MicrosoftNetCoreAppRuntimePackDir=C:/live-runtime-artifacts/microsoft.netcore.app.runtime.win-x64/$env:CONFIGURATION/
# Enable dump collection
-ENV COMPlus_DbgEnableMiniDump=1
-ENV COMPlus_DbgMiniDumpType=MiniDumpWithFullMemory
-ENV COMPlus_DbgMiniDumpName="C:/dumps-share/coredump.%p"
+ENV DOTNET_DbgEnableMiniDump=1
+ENV DOTNET_DbgMiniDumpType=MiniDumpWithFullMemory
+ENV DOTNET_DbgMiniDumpName="C:/dumps-share/coredump.%p"
EXPOSE 5001
{
public partial class DebugProvider
{
- private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1";
+ private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("DOTNET_DebugWriteToStdErr") == "1";
public static void FailCore(string stackTrace, string? message, string? detailMessage, string errorSource)
{
/// <summary>
/// Total available memory for the GC to use when this GC occurred.
///
- /// If the environment variable COMPlus_GCHeapHardLimit is set,
+ /// If the environment variable DOTNET_GCHeapHardLimit is set,
/// or "Server.GC.HeapHardLimit" is in runtimeconfig.json, this will come from that.
/// If the program is run in a container, this will be an implementation-defined fraction of the container's size.
/// Else, this is the physical memory on the machine that was available for the GC to use when this GC occurred.
In the simple case, no scenarios are specified and the default CoreCLR optimization configuration
is used to run the tests. If a set of comma-separated scenarios are specified in the `_Scenarios`
- property, then each test is run for each of the specified CoreCLR scenarios (e.g., COMPlus_JitStress=1;
- COMPlus_JitStressRegs=4; COMPlus_JitStress=2 + COMPlus_JitStressRegs=0x1000). The set of acceptable
+ property, then each test is run for each of the specified CoreCLR scenarios (e.g., DOTNET_JitStress=1;
+ DOTNET_JitStressRegs=4; DOTNET_JitStress=2 + DOTNET_JitStressRegs=0x1000). The set of acceptable
scenario names is defined and interpreted by src\tests\Common\testenvironment.proj.
"RunInParallelForEachScenario" is the "root" target for this Project. It first creates the
<HelixPreCommand Include="set __TestEnv=%HELIX_CORRELATION_PAYLOAD%\$(TestEnvFileName)" />
<HelixPreCommand Include="type %__TestEnv%" />
<HelixPreCommand Include="call %__TestEnv%" />
- <!-- Display the interesting COMPlus variables that are set in the environment -->
- <HelixPreCommand Include="set COMPlus" />
+ <!-- Display the interesting DOTNET variables that are set in the environment -->
+ <HelixPreCommand Include="set DOTNET" />
</ItemGroup>
<ItemGroup Condition=" '$(TestEnvFileName)' != '' and '$(TargetOS)' != 'windows' ">
<HelixPreCommand Include="export __TestEnv=$HELIX_CORRELATION_PAYLOAD/$(TestEnvFileName)" />
<HelixPreCommand Include="cat $__TestEnv" />
<HelixPreCommand Include=". $__TestEnv" /> <!-- Use "." not "source"; some clients appear to run scripts with "sh" not "bash" -->
- <!-- Display the interesting COMPlus variables that are set in the environment -->
- <HelixPreCommand Include="printenv | grep COMPlus" />
+ <!-- Display the interesting DOTNET variables that are set in the environment -->
+ <HelixPreCommand Include="printenv | grep DOTNET" />
</ItemGroup>
<ItemGroup Condition="'$(NeedsWorkload)' == 'true'">
'/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"'
run: publish
- COMPlus_DebugWriteToStdErr=1 \
+ DOTNET_DebugWriteToStdErr=1 \
MONO_ENV_OPTIONS="$(MONO_ENV_OPTIONS)" \
$(TOP)artifacts/bin/HelloWorld/$(MONO_ARCH)/$(MONO_CONFIG)/$(TARGET_OS)-$(MONO_ARCH)/publish/HelloWorld
$(DOTNET) publish -c $(CONFIG) -r $(TARGET_OS)-$(MONO_ARCH) -p:BuiltRuntimeConfiguration=$(BUILT_RUNTIME_CONFIG)
run: publish
- COMPlus_DebugWriteToStdErr=1 \
+ DOTNET_DebugWriteToStdErr=1 \
MONO_ENV_OPTIONS="$(MONO_ENV_OPTIONS)" \
DOTNET_MODIFIABLE_ASSEMBLIES=debug \
$(TOP)artifacts/bin/ConsoleDelta/$(MONO_ARCH)/$(CONFIG)/$(TARGET_OS)-$(MONO_ARCH)/publish/ConsoleDelta
// Setting this env var allows Diagnostic.Debug to write to stderr. In a browser environment this
// output will be sent to the console. Right now this is the only way to emit debug logging from
// corlib assemblies.
- // monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0);
+ // monoeg_g_setenv ("DOTNET_DebugWriteToStdErr", "1", 0);
#endif
char* debugger_fd = monoeg_g_getenv ("DEBUGGER_FD");
monoeg_g_setenv ("MONO_SLEEP_ABORT_LIMIT", "5000", 0);
#endif
- // monoeg_g_setenv ("COMPlus_DebugWriteToStdErr", "1", 0);
+ // monoeg_g_setenv ("DOTNET_DebugWriteToStdErr", "1", 0);
#ifdef DEBUG
// monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 0);