diff --git a/NuGet.Config b/NuGet.Config index 01c661c5..c187b39a 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -3,9 +3,7 @@ - - - + diff --git a/doc/diffs.md b/doc/diffs.md index 65985405..d14d3c2b 100644 --- a/doc/diffs.md +++ b/doc/diffs.md @@ -47,8 +47,8 @@ To build jitutils not using the bootstrap script: * Run `build.{cmd,sh}`. By default the script just builds the tools and does not publish them in a separate directory. -To publish the utilities add the '-p' flag which publishes each utility to the ./bin directory -in the root of the repo. Additionally, to download the default set of framework assemblies +To publish the utilities add the '-p' flag which publishes each utility to the ./bin directory +in the root of the repo. Additionally, to download the default set of framework assemblies that can be used for generating asm diffs, add '-f'. ``` @@ -66,23 +66,23 @@ build.sh [-b ] [-f] [-h] [-p] [-t ] By default, assembly code output (aka, "dasm") is generated by running crossgen with a specified JIT to compile a specified set of assemblies, by setting the following JIT environment variables to generate the output: -* `COMPlus_NgenDisasm` -* `COMPlus_NgenUnwindDump` -* `COMPlus_NgenEHDump` -* `COMPlus_JitDiffableDasm` -* optionally, `COMPlus_NgenGCDump` +* `DOTNET_NgenDisasm` +* `DOTNET_NgenUnwindDump` +* `DOTNET_NgenEHDump` +* `DOTNET_JitDiffableDasm` +* optionally, `DOTNET_NgenGCDump` Generating "diffs" involves generating assembly code output for both a baseline and a "diff" JIT, and comparing the results. Passing the `--pmi` option to `jit-diffs` will instead use reflection to jit each method in the assembly, setting these options: -* `COMPlus_JitDisasm` -* `COMPlus_JitUnwindDump` -* `COMPlus_JitEHDump` -* `COMPlus_JitDiffableDasm` -* `COMPlus_JitDisasmAssemblies` -* optionally, `COMPlus_JitGCDump` +* `DOTNET_JitDisasm` +* `DOTNET_JitUnwindDump` +* `DOTNET_JitEHDump` +* `DOTNET_JitDiffableDasm` +* `DOTNET_JitDisasmAssemblies` +* optionally, `DOTNET_JitGCDump` ## What can jit-diff produce asm diffs for? @@ -168,7 +168,7 @@ The "jit-diff diff" command has this help message: [-t ] [-c] [-f] [--benchmarks] [--tests] [--gcinfo] [-v] [--core_root ] [--test_root ] [--base_root ] [--diff_root ] [--arch ] [--build ] [--altjit ] - + -b, --base [arg] The base compiler directory or tag. Will use crossgen or clrjit from this directory. -d, --diff [arg] The diff compiler directory or tag. Will use crossgen or clrjit from this @@ -195,35 +195,35 @@ The "jit-diff diff" command has this help message: --altjit If set, the name of the altjit to use (e.g., clrjit_win_arm64_x64.dll). --pmi Generate diffs via jitting instead of running crossgen --assembly Look at diffs for methods in the specified assembly - + Examples: - + jit-diff diff --output c:\diffs --corelib --core_root c:\coreclr\bin\tests\windows.x64.Release\Tests\Core_Root --base c:\coreclr_base\bin\Product \windows.x64.Checked --diff c:\coreclr\bin\Product\windows.x86.Checked Generate diffs of System.Private.CoreLib.dll by specifying baseline and diff compiler directories explicitly. - + jit-diff diff --output c:\diffs --base c:\coreclr_base\bin\Product\windows.x64.Checked --diff If run within the c:\coreclr git clone of dotnet/coreclr, does the same as the prevous example, using defaults. - + jit-diff diff --output c:\diffs --base --base_root c:\coreclr_base --diff Does the same as the prevous example, using -base_root to find the base directory (if run from c:\coreclr tree). - + jit-diff diff --base --diff Does the same as the prevous example (if run from c:\coreclr tree), but uses default c:\coreclr\bin\diffs output directory, and `base_root` must be specified in the config.json file in the directory pointed to by the JIT_UTILS_ROOT environment variable. - + jit-diff diff --diff Only generates asm using the diff JIT -- does not generate asm from a baseline compiler -- using all computed defaults. - + jit-diff diff --diff --arch x86 Generate diffs, but for x86, even if there is an x64 compiler available. - + jit-diff diff --diff --build Debug Generate diffs, but using a Debug build, even if there is a Checked build available. ``` @@ -380,7 +380,7 @@ Or, disassemble the jitted code for all the methods in `mytest.exe`: ``` Note this latter run should produce similar disassembly as running `mytest.exe` via -corerun (with appropriate COMPlus flags set) for the methods that are executed +corerun (with appropriate DOTNET_ flags set) for the methods that are executed during the run. But `jit-diff diff -pmi` will attempt to show code generated for all methods, executed or not. And it also works on libraries which are not directly executable on their own. So PMI offers a potentially faster and more diff --git a/src/AnalyzeAsm/AnalyzeAsm.csproj b/src/AnalyzeAsm/AnalyzeAsm.csproj index f730ef52..74954604 100644 --- a/src/AnalyzeAsm/AnalyzeAsm.csproj +++ b/src/AnalyzeAsm/AnalyzeAsm.csproj @@ -2,11 +2,7 @@ Exe - netcoreapp3.1 + net6.0 - - - - diff --git a/src/AnalyzeAsm/OccurenceInfo.cs b/src/AnalyzeAsm/OccurenceInfo.cs index 4106b03f..a41e0424 100644 --- a/src/AnalyzeAsm/OccurenceInfo.cs +++ b/src/AnalyzeAsm/OccurenceInfo.cs @@ -2,12 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Text.Json; using MethodDB = System.Collections.Generic.Dictionary>>; namespace AnalyzeAsm @@ -135,7 +135,7 @@ private static MethodIndex CreateIndex(string folderPath) index.AddFile(dasmFile); } - string contents = JsonConvert.SerializeObject(index); + string contents = JsonSerializer.Serialize(index); File.WriteAllText(Path.Combine(folderPath, indexFileName), contents); stopWatch.Stop(); @@ -158,7 +158,7 @@ private static bool TryGetIndex(string folderPath, out MethodIndex index, bool d return false; } - index = JsonConvert.DeserializeObject(File.ReadAllText(indexFilePath)); + index = JsonSerializer.Deserialize(File.ReadAllText(indexFilePath)); var expectedExeTimeStamp = index.LastModifiedTimeOfExe; var actualExeTimeStamp = File.GetLastWriteTimeUtc(Assembly.GetExecutingAssembly().Location); diff --git a/src/AnalyzeAsm/README.md b/src/AnalyzeAsm/README.md index faa76417..04dd5b71 100644 --- a/src/AnalyzeAsm/README.md +++ b/src/AnalyzeAsm/README.md @@ -1,10 +1,10 @@ Notes: -* The code in `Program.cs` has **lot of redundant code**. Most of the methods are copied from previous methods with little tweak. +* The code in `Program.cs` has **lot of redundant code**. Most of the methods are copied from previous methods with little tweak. * All the methods rely on `ngen_arm64.txt` / `ngen_amd64.txt` file that are produced by doing the following: - * `set COMPlus_NGenDisasm=1` - * Running `build-test.cmd crossgen > ngen_arm64.txt` -* The path locations of these files are hardcoded too. + * `set DOTNET_NGenDisasm=1` + * Running `build-test.cmd crossgen > ngen_arm64.txt` +* The path locations of these files are hardcoded too. `FindLdrGroups_1()` finds patterns: diff --git a/src/cijobs/cijobs.cs b/src/cijobs/cijobs.cs index d7362109..81918adf 100755 --- a/src/cijobs/cijobs.cs +++ b/src/cijobs/cijobs.cs @@ -23,17 +23,17 @@ using System; -using System.IO; using System.Collections.Generic; +using System.CommandLine; +using System.IO; +using System.IO.Compression; +using System.Linq; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.Json; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using System.CommandLine; -using System.Linq; -using System.Text.RegularExpressions; -using System.IO.Compression; -using Newtonsoft.Json; namespace ManagedCodeGen { @@ -386,7 +386,7 @@ string productString if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); - var productJobs = JsonConvert.DeserializeObject(json); + var productJobs = JsonSerializer.Deserialize(json); return productJobs.jobs; } else @@ -414,7 +414,7 @@ var messageString if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync(); - var jobBuilds = JsonConvert.DeserializeObject(json); + var jobBuilds = JsonSerializer.Deserialize(json); if (lastSuccessfulBuild) { @@ -492,7 +492,7 @@ public async Task GetJobBuildInfo(string repoName, string branchName, if (response.IsSuccessStatusCode) { var buildInfoJson = await response.Content.ReadAsStringAsync(); - var info = JsonConvert.DeserializeObject(buildInfoJson); + var info = JsonSerializer.Deserialize(buildInfoJson); return info; } else diff --git a/src/jit-analyze/jit-analyze.cs b/src/jit-analyze/jit-analyze.cs index c50ed591..66f008a7 100644 --- a/src/jit-analyze/jit-analyze.cs +++ b/src/jit-analyze/jit-analyze.cs @@ -3,17 +3,20 @@ // See the LICENSE file in the project root for more information. using System; -using System.Diagnostics; +using System.Collections.Generic; using System.CommandLine; +using System.Diagnostics; +using System.Globalization; using System.IO; -using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; -using Newtonsoft.Json; -using System.Text; -using System.Runtime.CompilerServices; -using System.Globalization; using System.Reflection; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; namespace ManagedCodeGen { @@ -397,7 +400,7 @@ static MetricCollection() } } - [JsonProperty()] + [JsonInclude] private Metric[] metrics; public MetricCollection() @@ -1185,7 +1188,7 @@ public static StringBuilder GenerateJson(IEnumerable compareList) { StringBuilder fileContents = new StringBuilder(); - fileContents.AppendLine(JsonConvert.SerializeObject(compareList.Where(file => !file.deltaMetrics.IsZero()), Formatting.Indented)); + fileContents.AppendLine(JsonSerializer.Serialize(compareList.Where(file => !file.deltaMetrics.IsZero()), new JsonSerializerOptions { WriteIndented = true })); return fileContents; } diff --git a/src/jit-dasm-pmi/jit-dasm-pmi.cs b/src/jit-dasm-pmi/jit-dasm-pmi.cs index aa40ad70..00d6e9c5 100644 --- a/src/jit-dasm-pmi/jit-dasm-pmi.cs +++ b/src/jit-dasm-pmi/jit-dasm-pmi.cs @@ -24,7 +24,7 @@ namespace ManagedCodeGen { - // Define options to be parsed + // Define options to be parsed public class Config { private ArgumentSyntax _syntaxResult; @@ -481,10 +481,10 @@ void AppendEnvironmentVariableToPmiEnv(string varName, string varValue) } } - // Pick up ambient COMPlus settings. + // Pick up ambient DOTNET settings. foreach (string envVar in Environment.GetEnvironmentVariables().Keys) { - if (envVar.IndexOf("COMPlus_") == 0) + if (envVar.IndexOf("DOTNET_") == 0) { string value = Environment.GetEnvironmentVariable(envVar); AppendEnvironmentVariableToPmiEnv(envVar, value); @@ -492,45 +492,45 @@ void AppendEnvironmentVariableToPmiEnv(string varName, string varValue) } // Set up environment do PMI based disasm. - AppendEnvironmentVariableToPmiEnv("COMPlus_JitDisasm", "*"); - AppendEnvironmentVariableToPmiEnv("COMPlus_JitDisasmAssemblies", Path.GetFileNameWithoutExtension(assembly.Name)); - AppendEnvironmentVariableToPmiEnv("COMPlus_JitUnwindDump", "*"); - AppendEnvironmentVariableToPmiEnv("COMPlus_JitEHDump", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitDisasm", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitDisasmAssemblies", Path.GetFileNameWithoutExtension(assembly.Name)); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitUnwindDump", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitEHDump", "*"); if (!this._config.NoDiffable) { - AppendEnvironmentVariableToPmiEnv("COMPlus_JitDiffableDasm", "1"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitDiffableDasm", "1"); } - AppendEnvironmentVariableToPmiEnv("COMPlus_ReadyToRun", "0"); - AppendEnvironmentVariableToPmiEnv("COMPlus_ZapDisable", "1"); - AppendEnvironmentVariableToPmiEnv("COMPlus_JitEnableNoWayAssert", "1"); // Force noway_assert to generate assert (not fall back to MinOpts). - AppendEnvironmentVariableToPmiEnv("COMPlus_JitNoForceFallback", "1"); // Don't stress noway fallback path. - AppendEnvironmentVariableToPmiEnv("COMPlus_JitRequired", "1"); // Force NO_WAY to generate assert. Also generates assert for BADCODE/BADCODE3. - + AppendEnvironmentVariableToPmiEnv("DOTNET_ReadyToRun", "0"); + AppendEnvironmentVariableToPmiEnv("DOTNET_ZapDisable", "1"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitEnableNoWayAssert", "1"); // Force noway_assert to generate assert (not fall back to MinOpts). + AppendEnvironmentVariableToPmiEnv("DOTNET_JitNoForceFallback", "1"); // Don't stress noway fallback path. + AppendEnvironmentVariableToPmiEnv("DOTNET_JitRequired", "1"); // Force NO_WAY to generate assert. Also generates assert for BADCODE/BADCODE3. + // We likely don't want tiering enabled, but allow it, if user wants tier0 codegen - AppendEnvironmentVariableToPmiEnv("COMPlus_TieredCompilation", _config.Tier0 ? "1" : "0"); + AppendEnvironmentVariableToPmiEnv("DOTNET_TieredCompilation", _config.Tier0 ? "1" : "0"); if (_config.Tier0) { // jit all methods at tier0 - AppendEnvironmentVariableToPmiEnv("COMPlus_TC_QuickJitForLoops", "1"); + AppendEnvironmentVariableToPmiEnv("DOTNET_TC_QuickJitForLoops", "1"); // don't promote any method to tier1 - AppendEnvironmentVariableToPmiEnv("COMPlus_TC_CallCounting", "0"); + AppendEnvironmentVariableToPmiEnv("DOTNET_TC_CallCounting", "0"); } if (this.doGCDump) { - AppendEnvironmentVariableToPmiEnv("COMPlus_JitGCDump", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitGCDump", "*"); } if (this.doDebugDump) { - AppendEnvironmentVariableToPmiEnv("COMPlus_JitDebugDump", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitDebugDump", "*"); } if (this._altjit != null) { - AppendEnvironmentVariableToPmiEnv("COMPlus_AltJit", "*"); - AppendEnvironmentVariableToPmiEnv("COMPlus_AltJitName", _altjit); + AppendEnvironmentVariableToPmiEnv("DOTNET_AltJit", "*"); + AppendEnvironmentVariableToPmiEnv("DOTNET_AltJitName", _altjit); const string arm64AsTarget = "_arm64_"; int targetArm64 = _altjit.IndexOf(arm64AsTarget); @@ -541,7 +541,7 @@ void AppendEnvironmentVariableToPmiEnv(string varName, string varValue) { // If this looks like a cross-targeting altjit with a arm64 target and a different host // then fix the SIMD size. - AppendEnvironmentVariableToPmiEnv("COMPlus_SIMD16ByteOnly", "1"); + AppendEnvironmentVariableToPmiEnv("DOTNET_SIMD16ByteOnly", "1"); } } } @@ -565,7 +565,7 @@ void AppendEnvironmentVariableToPmiEnv(string varName, string varValue) Utility.EnsureParentDirectoryExists(dasmPath); - AppendEnvironmentVariableToPmiEnv("COMPlus_JitStdOutFile", dasmPath); + AppendEnvironmentVariableToPmiEnv("DOTNET_JitStdOutFile", dasmPath); AddEnvironmentVariable("PMIENV", pmiEnv.ToString()); @@ -610,7 +610,7 @@ void AppendEnvironmentVariableToPmiEnv(string varName, string varValue) if (hasOutput && File.Exists(logPath) && !File.Exists(dasmPath)) { - // Looks like the JIT does not support COMPlus_JitStdOutFile so + // Looks like the JIT does not support DOTNET_JitStdOutFile so // the assembly output must be in the log file. File.Move(logPath, dasmPath); } diff --git a/src/jit-dasm/jit-dasm.cs b/src/jit-dasm/jit-dasm.cs index 7b865fdc..dd258be5 100644 --- a/src/jit-dasm/jit-dasm.cs +++ b/src/jit-dasm/jit-dasm.cs @@ -10,7 +10,7 @@ // tools to validate ongoing development. // // Scenario 1: Pass A and B compilers to jitdasm. Using the --base and --diff -// arguments pass two seperate compilers and a passed set of assemblies. This +// arguments pass two seperate compilers and a passed set of assemblies. This // is the most common scenario. // // Scenario 2: Iterativly call jitdasm with a series of compilers tagging @@ -37,7 +37,7 @@ public enum CodeGenerator Crossgen2 } - // Define options to be parsed + // Define options to be parsed public class Config { private ArgumentSyntax _syntaxResult; @@ -207,7 +207,7 @@ public static int Main(string[] args) // Builds assemblyInfoList on jitdasm List assemblyWorkList = GenerateAssemblyWorklist(config); - + // The disasm engine encapsulates a particular set of diffs. An engine is // produced with a given code generator and assembly list, which then produces // a set of disasm outputs. @@ -224,7 +224,7 @@ public static int Main(string[] args) crossgenDisasm = new Crossgen2DisasmEngine(config.CrossgenExecutable, config, config.RootPath, assemblyWorkList); } crossgenDisasm.GenerateAsm(); - + if (crossgenDisasm.ErrorCount > 0) { Console.Error.WriteLine("{0} errors compiling set.", crossgenDisasm.ErrorCount); @@ -466,10 +466,10 @@ public void GenerateAsm() commandArgs.Add(fullPathAssembly); - // Pick up ambient COMPlus settings. + // Pick up ambient DOTNET_ settings. foreach (string envVar in Environment.GetEnvironmentVariables().Keys) { - if (envVar.IndexOf("COMPlus_") == 0) + if (envVar.IndexOf("DOTNET_") == 0) { string value = Environment.GetEnvironmentVariable(envVar); AddEnvironmentVariable(envVar, value); @@ -477,32 +477,32 @@ public void GenerateAsm() } // Set up environment do disasm. - AddEnvironmentVariable("COMPlus_NgenDisasm", "*"); - AddEnvironmentVariable("COMPlus_NgenUnwindDump", "*"); - AddEnvironmentVariable("COMPlus_NgenEHDump", "*"); + AddEnvironmentVariable("DOTNET_NgenDisasm", "*"); + AddEnvironmentVariable("DOTNET_NgenUnwindDump", "*"); + AddEnvironmentVariable("DOTNET_NgenEHDump", "*"); if (!this._config.NoDiffable) { - AddEnvironmentVariable("COMPlus_JitDiffableDasm", "1"); + AddEnvironmentVariable("DOTNET_JitDiffableDasm", "1"); } - AddEnvironmentVariable("COMPlus_JitEnableNoWayAssert", "1"); // Force noway_assert to generate assert (not fall back to MinOpts). - AddEnvironmentVariable("COMPlus_JitNoForceFallback", "1"); // Don't stress noway fallback path. - AddEnvironmentVariable("COMPlus_JitRequired", "1"); // Force NO_WAY to generate assert. Also generates assert for BADCODE/BADCODE3. + AddEnvironmentVariable("DOTNET_JitEnableNoWayAssert", "1"); // Force noway_assert to generate assert (not fall back to MinOpts). + AddEnvironmentVariable("DOTNET_JitNoForceFallback", "1"); // Don't stress noway fallback path. + AddEnvironmentVariable("DOTNET_JitRequired", "1"); // Force NO_WAY to generate assert. Also generates assert for BADCODE/BADCODE3. if (this.doGCDump) { - AddEnvironmentVariable("COMPlus_NgenGCDump", "*"); + AddEnvironmentVariable("DOTNET_NgenGCDump", "*"); } if (this.doDebugDump) { - AddEnvironmentVariable("COMPlus_NgenDebugDump", "*"); + AddEnvironmentVariable("DOTNET_NgenDebugDump", "*"); } if (this._altjit != null) { - AddEnvironmentVariable("COMPlus_AltJit", "*"); - AddEnvironmentVariable("COMPlus_AltJitNgen", "*"); - AddEnvironmentVariable("COMPlus_AltJitName", _altjit); + AddEnvironmentVariable("DOTNET_AltJit", "*"); + AddEnvironmentVariable("DOTNET_AltJitNgen", "*"); + AddEnvironmentVariable("DOTNET_AltJitName", _altjit); } string dasmPath = null; @@ -514,7 +514,7 @@ public void GenerateAsm() Utility.EnsureParentDirectoryExists(dasmPath); - AddEnvironmentVariable("COMPlus_JitStdOutFile", dasmPath); + AddEnvironmentVariable("DOTNET_JitStdOutFile", dasmPath); } if (this.verbose) @@ -568,7 +568,7 @@ public void GenerateAsm() if (hasOutput && File.Exists(logPath) && !File.Exists(dasmPath)) { - // Looks like the JIT does not support COMPlus_JitStdOutFile so + // Looks like the JIT does not support DOTNET_JitStdOutFile so // the assembly output must be in the log file. File.Move(logPath, dasmPath); } @@ -714,8 +714,8 @@ override protected ProcessResult ExecuteProcess(List commandArgs, bool c foreach (var envVar in _environmentVariables) { commandArgs.Add("--codegenopt"); - string complusPrefix = "COMPlus_"; - commandArgs.Add(String.Format("{0}={1}", envVar.Key.Substring(complusPrefix.Length), envVar.Value)); + string dotnetPrefix = "DOTNET_"; + commandArgs.Add(String.Format("{0}={1}", envVar.Key.Substring(dotnetPrefix.Length), envVar.Value)); } return Utility.ExecuteProcess(_executablePath, commandArgs, capture); } diff --git a/src/jit-diff/install.cs b/src/jit-diff/install.cs index b550f215..fc154ff5 100644 --- a/src/jit-diff/install.cs +++ b/src/jit-diff/install.cs @@ -3,13 +3,18 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.CommandLine; +using System.Diagnostics; using System.IO; -using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; namespace ManagedCodeGen { @@ -19,7 +24,7 @@ public static int InstallCommand(Config config) { var configFilePath = Path.Combine(config.JitUtilsRoot, s_configFileName); string configJson = File.ReadAllText(configFilePath); - var jObj = JObject.Parse(configJson); + var jObj = JsonObject.Parse(configJson); if ((jObj[s_configFileRootKey] == null) || (jObj[s_configFileRootKey]["tools"] == null)) { @@ -32,7 +37,7 @@ public static int InstallCommand(Config config) return -1; } - var tools = (JArray)jObj[s_configFileRootKey]["tools"]; + var tools = (JsonArray)jObj[s_configFileRootKey]["tools"]; // Early out if the tool is already installed. We can only do this if we're not doing // "--last_successful", in which case we don't know what the build number (and hence @@ -134,8 +139,6 @@ public static int InstallCommand(Config config) toolPath = Path.Combine(toolPath, tag); - JObject newTool = new JObject(); - newTool.Add("tag", tag); string platformPath = Path.Combine(toolPath, "Product"); if (!Directory.Exists(platformPath)) { @@ -148,27 +151,20 @@ public static int InstallCommand(Config config) { if (Path.GetFileName(dir).ToUpper().Contains(buildOS)) { - newTool.Add("path", Path.GetFullPath(dir)); - if (tools.HasValues) + tools.Add(new JsonObject { - tools.Last.AddAfterSelf(newTool); - } - else - { - tools.Add(newTool); - } + ["tag"] = tag, + ["path"] = Path.GetFullPath(dir) + }); break; } } // Overwrite current config.json with new data. - using (var file = File.CreateText(configFilePath)) + using (var sw = File.CreateText(configFilePath)) { - using (JsonTextWriter writer = new JsonTextWriter(file)) - { - writer.Formatting = Formatting.Indented; - jObj.WriteTo(writer); - } + var json = JsonSerializer.Serialize (jObj, new JsonSerializerOptions { WriteIndented = true }); + sw.Write(json); } return 0; diff --git a/src/jit-diff/jit-diff.cs b/src/jit-diff/jit-diff.cs index dd6bd10f..eb9a6d20 100755 --- a/src/jit-diff/jit-diff.cs +++ b/src/jit-diff/jit-diff.cs @@ -3,12 +3,13 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.CommandLine; using System.IO; -using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Linq; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Runtime.InteropServices; @@ -152,7 +153,7 @@ public class Config private bool _cctors; private int _count = 20; private string _metric = "CodeSize"; - private JObject _jObj; + private JsonObject _jObj; private bool _configFileLoaded = false; private bool _noJitUtilsRoot = false; private bool _validationError = false; @@ -701,7 +702,7 @@ private void ExpandToolTags() return; } - var tools = _jObj[s_configFileRootKey]["tools"]; + var tools = (JsonArray)_jObj[s_configFileRootKey]["tools"]; if (tools == null) { return; @@ -948,13 +949,13 @@ public string GetToolPath(string tool, out bool found) { found = true; - string tag = token.Value(); + string tag = token.ToString(); // Extract set value for tool and see if we can find it // in the installed tools. - var path = _jObj[s_configFileRootKey]["tools"].Children() - .Where(x => (string)x["tag"] == tag) - .Select(x => (string)x["path"]); + var tools = (JsonArray)_jObj[s_configFileRootKey]["tools"]; + var path = tools.Where(x => (string)x["tag"] == tag) + .Select(x => (string)x["path"]); // If the tag resolves to a tool return it, otherwise just return it // as a posible path. return path.Any() ? path.First() : tag; @@ -981,7 +982,7 @@ public T ExtractDefault(string name, out bool found) try { - return token.Value(); + return token.GetValue(); } catch (System.FormatException e) { @@ -1013,9 +1014,9 @@ private void LoadFileConfig() try { - _jObj = JObject.Parse(configJson); + _jObj = (JsonObject)JsonObject.Parse(configJson); } - catch (Newtonsoft.Json.JsonReaderException ex) + catch (JsonException ex) { Console.Error.WriteLine("Error reading config file: {0}", ex.Message); Console.Error.WriteLine("Continuing; ignoring config file."); @@ -1227,12 +1228,12 @@ public int ListCommand() // Print list of the installed tools. - var tools = asmdiffNode["tools"]; + var tools = (JsonArray)asmdiffNode["tools"]; if (tools != null) { Console.WriteLine("Installed tools:"); - foreach (var tool in tools.Children()) + foreach (JsonObject tool in tools) { string tag = (string)tool["tag"]; string path = (string)tool["path"]; diff --git a/src/jit-diff/uninstall.cs b/src/jit-diff/uninstall.cs index d1a59c2b..0ad793c8 100644 --- a/src/jit-diff/uninstall.cs +++ b/src/jit-diff/uninstall.cs @@ -6,8 +6,8 @@ using System.CommandLine; using System.IO; using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; namespace ManagedCodeGen { @@ -17,7 +17,7 @@ public static int UninstallCommand(Config config) { var configFilePath = Path.Combine(config.JitUtilsRoot, s_configFileName); string configJson = File.ReadAllText(configFilePath); - var jObj = JObject.Parse(configJson); + var jObj = JsonObject.Parse(configJson); if ((jObj[s_configFileRootKey] == null) || (jObj[s_configFileRootKey]["tools"] == null)) { @@ -25,9 +25,8 @@ public static int UninstallCommand(Config config) return -1; } - var tools = (JArray)jObj[s_configFileRootKey]["tools"]; - var elem = tools.Children() - .Where(x => (string)x["tag"] == config.Tag); + var tools = (JsonArray)jObj[s_configFileRootKey]["tools"]; + var elem = tools.Where(x => (string)x["tag"] == config.Tag); if (!elem.Any()) { Console.WriteLine("{0} is not installed in {1}.", config.Tag, s_configFileName); @@ -47,16 +46,13 @@ public static int UninstallCommand(Config config) } Console.WriteLine("Removing tag {0} from config file.", config.Tag); - jobj.Remove(); + tools.Remove(jobj); // Overwrite current config.json with new data. - using (var file = File.CreateText(configFilePath)) + using (var sw = File.CreateText(configFilePath)) { - using (JsonTextWriter writer = new JsonTextWriter(file)) - { - writer.Formatting = Formatting.Indented; - jObj.WriteTo(writer); - } + var json = JsonSerializer.Serialize (jObj, new JsonSerializerOptions { WriteIndented = true }); + sw.Write(json); } return 0; diff --git a/src/jit-format/jit-format.cs b/src/jit-format/jit-format.cs index f7e736d5..3dd41e71 100644 --- a/src/jit-format/jit-format.cs +++ b/src/jit-format/jit-format.cs @@ -8,17 +8,17 @@ // using System; -using System.Diagnostics; +using System.Collections.Generic; using System.CommandLine; +using System.Diagnostics; using System.IO; -using System.Xml; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Xml; namespace ManagedCodeGen { @@ -46,7 +46,7 @@ public class Config private string _compileCommands = null; private bool _rewriteCompileCommands = false; - private JObject _jObj; + private JsonObject _jObj; private string _jitUtilsRoot = null; public Config(string[] args) @@ -332,7 +332,7 @@ private void LoadFileConfig() { string configJson = File.ReadAllText(path); - _jObj = JObject.Parse(configJson); + _jObj = (JsonObject)JsonObject.Parse(configJson); // Check if there is any default config specified. if (_jObj[s_configFileRootKey]["default"] != null) @@ -395,7 +395,7 @@ public T ExtractDefault(string name, out bool found) try { - return token.Value(); + return token.GetValue(); } catch (System.FormatException e) { @@ -580,17 +580,17 @@ public static int Main(string[] args) public static string rewriteCompileCommands (string compileCommandFile, string project) { string allCommands = File.ReadAllText(compileCommandFile); - JArray commands = (JArray)JArray.Parse(allCommands); + JsonArray commands = (JsonArray)JsonArray.Parse(allCommands); List newCommands = new List(); - foreach (JObject command in commands.Children()) + foreach (JsonObject command in commands) { // Search for directory entries containing jit/ - if (command["directory"].Value().Contains("jit/" + project)) + if (command["directory"].ToString().Contains("jit/" + project)) { // Add the command to our list of new commands - string directory = command["directory"].Value(); - string compileCommand = command["command"].Value().Replace("-I", "-isystem").Replace("\\","/"); + string directory = command["directory"].ToString(); + string compileCommand = command["command"].ToString().Replace("-I", "-isystem").Replace("\\","/"); if (compileCommand.Contains("cl.exe")) { // First extract cl.exe path: it may contain spaces. @@ -622,7 +622,7 @@ public static string rewriteCompileCommands (string compileCommandFile, string p } } } - string file = command["file"].Value(); + string file = command["file"].ToString(); newCommands.Add(new CompileCommand(directory, compileCommand, file)); } @@ -630,7 +630,7 @@ public static string rewriteCompileCommands (string compileCommandFile, string p // write commands back to a file. string newCompileCommandsFileName = Path.Combine(Path.GetDirectoryName(compileCommandFile), "compile_commands.json"); - string json = JsonConvert.SerializeObject(newCommands.ToArray(), Newtonsoft.Json.Formatting.Indented); + string json = JsonSerializer.Serialize(newCommands.ToArray(), new JsonSerializerOptions { WriteIndented = true }); System.IO.File.WriteAllText(newCompileCommandsFileName, json); return newCompileCommandsFileName; diff --git a/src/jit-include.props b/src/jit-include.props index 6be307a9..ed35d9fd 100644 --- a/src/jit-include.props +++ b/src/jit-include.props @@ -1,7 +1,6 @@ - diff --git a/src/mutate-test/MutateTestRootCommand.cs b/src/mutate-test/MutateTestRootCommand.cs new file mode 100644 index 00000000..48bd1e3c --- /dev/null +++ b/src/mutate-test/MutateTestRootCommand.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.CommandLine; + +namespace MutateTest +{ + internal sealed class MutateTestRootCommand : RootCommand + { + public Argument InputFilePath { get; } = + new("input-test-case", "Input test case file or directory (for --recursive)") { Arity = ArgumentArity.OneOrMore }; + public Option EHStress { get; } = + new(new[] { "--ehStress" }, "Add EH to methods"); + public Option StructStress { get; } = + new(new[] { "--structStress" }, "Replace locals with structs"); + public Option ShowResults { get; } = + new(new[] { "--showResults" }, "Add EH to methods"); + public Option Verbose { get; } = + new(new[] { "--verbose" }, "Describe each transformation"); + public Option Quiet { get; } = + new(new[] { "--quiet" }, "Produce minimal output"); + public Option Recursive { get; } = + new(new[] { "--recursive" }, "Process each file recursively"); + public Option Seed { get; } = + new(new[] { "--seed" }, () => 42, "Random seed"); + public Option StopAtFirstFailure { get; } = + new(new[] { "--stopAtFirstFailure" }, "Stop each test at first failure"); + public Option EmptyBlocks { get; } = + new(new[] { "--emptyBlocks" }, "Transform empty blocks"); + public Option SizeLimit { get; } = + new(new[] { "--sizeLimit" }, () => 10000, "Don't process programs larger than this size"); + public Option TimeLimit { get; } = + new(new[] { "--timeLimit" }, () => 10000, "Don't stress programs where compile + run takes more than this many milliseconds"); + public Option Projects { get; } = + new(new[] { "--projects" }, "Look for .csproj files instead of .cs files when doing recursive exploration"); + public Option OnlyFailures { get; } = + new(new[] { "--onlyFailures" }, "Only emit output for cases that fail at runtime"); + + public ParseResult Result { get; private set; } + + public MutateTestRootCommand(string[] args) : base(".NET JIT mutate test utility") + { + AddArgument(InputFilePath); + AddOption(EHStress); + AddOption(StructStress); + AddOption(ShowResults); + AddOption(Verbose); + AddOption(Quiet); + AddOption(Recursive); + AddOption(Seed); + AddOption(StopAtFirstFailure); + AddOption(EmptyBlocks); + AddOption(SizeLimit); + AddOption(TimeLimit); + AddOption(Projects); + AddOption(OnlyFailures); + + this.SetHandler(context => + { + Result = context.ParseResult; + + try + { + context.ExitCode = new Program(this).Run(); + } + catch (Exception e) + { + Console.ResetColor(); + Console.ForegroundColor = ConsoleColor.Red; + + Console.Error.WriteLine("Error: " + e.Message); + Console.Error.WriteLine(e.ToString()); + + Console.ResetColor(); + + context.ExitCode = 1; + } + }); + } + } +} diff --git a/src/mutate-test/Program.cs b/src/mutate-test/Program.cs index 26e89aba..94197bee 100644 --- a/src/mutate-test/Program.cs +++ b/src/mutate-test/Program.cs @@ -2,24 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Build.Locator; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Emit; -using Microsoft.CodeAnalysis.MSBuild; using System; -using System.Collections.Generic; using System.CommandLine; -using System.CommandLine.Invocation; -using System.Data; +using System.CommandLine.Parsing; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; -// TODO: +using Microsoft.Build.Locator; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.MSBuild; + +// TODO: // * Fix dependent project limitation // * Find better way of piping in references needed for compilation, and resolving what's needed to run // * Try random stuff from https://github.com/dotnet/roslyn-sdk/tree/master/samples/CSharp/TreeTransforms @@ -29,33 +29,10 @@ // Useful if you can express what you want in C# and need to see how to get a transform to create it for you. using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static MutateTest.OptionHolder; namespace MutateTest { - class OptionHolder - { - public string InputFile { get; set; } - public bool EhStress { get; set; } - public bool StructStress { get; set; } - public bool ShowResults { get; set; } - public bool Recursive { get; set; } - public bool Verbose { get; set; } - public bool Quiet { get; set; } - public bool StopAtFirstFailure { get; set; } - public int Seed { get; set; } - public int SizeLimit { get; set; } - public int TimeLimit { get; set; } - public bool Projects { get; set; } - public bool OnlyFailures { get; set; } - - public static OptionHolder Options { get; set; } - } - - public class MutateTestException : Exception - { - - } + public class MutateTestException : Exception { } enum ExecutionResultKind { @@ -83,7 +60,7 @@ struct ExecutionResult public int value; public bool Success => kind == ExecutionResultKind.RanNormally; - public bool OriginalCompileFailed => kind == ExecutionResultKind.CompilationFailed || kind == ExecutionResultKind.CompilationException + public bool OriginalCompileFailed => kind == ExecutionResultKind.CompilationFailed || kind == ExecutionResultKind.CompilationException || kind == ExecutionResultKind.HasDependentProjects || kind == ExecutionResultKind.SkipSpecialCase; public bool CompileFailed => kind == ExecutionResultKind.CompilationFailed || kind == ExecutionResultKind.CompilationException @@ -104,8 +81,8 @@ public override string ToString() case ExecutionResultKind.CompilationFailed: return "base compilation failed"; case ExecutionResultKind.MutantCompilationException: return "mutant compilation caused exception"; case ExecutionResultKind.MutantCompilationFailed: return "mutant compilation failed"; - case ExecutionResultKind.SizeTooLarge: return $"test case size {value} bytes exceeds current size limit {Options.SizeLimit} bytes"; - case ExecutionResultKind.RanTooLong: return $"base compile or excution time {value} ms exceeds current time limit {Options.TimeLimit} ms"; + case ExecutionResultKind.SizeTooLarge: return $"test case size {value} bytes exceeds current size limit {Program.SizeLimit} bytes"; + case ExecutionResultKind.RanTooLong: return $"base compile or excution time {value} ms exceeds current time limit {Program.TimeLimit} ms"; case ExecutionResultKind.LoadFailed: return "base assembly load failed"; case ExecutionResultKind.ThrewException: return "base execution threw an exception"; case ExecutionResultKind.BadExitCode: return $"base execution returned bad exit code {value}"; @@ -121,8 +98,12 @@ public override string ToString() } } - public class Program + internal sealed class Program { + public static int SizeLimit; + public static int TimeLimit; + public static bool Verbose; + private static readonly CSharpCompilationOptions DebugOptions = new CSharpCompilationOptions(OutputKind.ConsoleApplication, concurrentBuild: false, optimizationLevel: OptimizationLevel.Debug).WithAllowUnsafe(true); @@ -150,21 +131,30 @@ public class Program MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Threading.Tasks")).Location), }; - public static Random Random; + public readonly Random _random; + private readonly List _mutators; + private readonly MutateTestRootCommand _command; + private readonly bool _quiet; - static IEnumerable Mutators; - - static IEnumerable GetMutators() + public Program(MutateTestRootCommand command) { - var mutators = new List(); + _command = command; + _random = new Random(Get(command.Seed)); + _quiet = Get(_command.Quiet); + + SizeLimit = Get(_command.SizeLimit); + TimeLimit = Get(_command.TimeLimit); + Verbose = Get(_command.Verbose); + + _mutators = new List(); - SplitBlocksInTwo splitBlocks = new SplitBlocksInTwo(Random); - mutators.Add(splitBlocks); + SplitBlocksInTwo splitBlocks = new SplitBlocksInTwo(_random); + _mutators.Add(splitBlocks); AddBlocks addBlocks = new AddBlocks(); - mutators.Add(addBlocks); + _mutators.Add(addBlocks); - if (Options.EhStress) + if (Get(_command.EHStress)) { // Singletons Mutator tryCatch = new WrapBlocksInTryCatch(); @@ -191,16 +181,16 @@ static IEnumerable GetMutators() Mutator randomMoveToCatchx2 = new RepeatMutator(randomMoveToCatch, 2); // Random @ mutation time - Mutator tryCatchRandom = new RandomMutator(tryCatch, Random, 0.25); - Mutator tryEmtpyFinallyRandom = new RandomMutator(tryEmptyFinally, Random, 0.25); - Mutator emptyTryFinallyRandom = new RandomMutator(emptyTryFinally, Random, 0.25); - Mutator moveToCatchRandom = new RandomMutator(randomMoveToCatch, Random, 0.25); + Mutator tryCatchRandom = new RandomMutator(tryCatch, _random, 0.25); + Mutator tryEmtpyFinallyRandom = new RandomMutator(tryEmptyFinally, _random, 0.25); + Mutator emptyTryFinallyRandom = new RandomMutator(emptyTryFinally, _random, 0.25); + Mutator moveToCatchRandom = new RandomMutator(randomMoveToCatch, _random, 0.25); // Alternative - Mutator either12 = new RandomChoiceMutator(tryCatch, tryEmptyFinally, Random, 0.5); - Mutator either34 = new RandomChoiceMutator(randomMoveToCatch, tryEmptyFinally, Random, 0.5); - Mutator either1s = new RandomChoiceMutator(tryCatch, splitBlocks, Random, 0.5); - Mutator either2s = new RandomChoiceMutator(randomMoveToCatch, splitBlocks, Random, 0.5); + Mutator either12 = new RandomChoiceMutator(tryCatch, tryEmptyFinally, _random, 0.5); + Mutator either34 = new RandomChoiceMutator(randomMoveToCatch, tryEmptyFinally, _random, 0.5); + Mutator either1s = new RandomChoiceMutator(tryCatch, splitBlocks, _random, 0.5); + Mutator either2s = new RandomChoiceMutator(randomMoveToCatch, splitBlocks, _random, 0.5); // Combination Mutator addSplit = new ComboMutator(addBlocks, splitBlocks); @@ -220,94 +210,40 @@ static IEnumerable GetMutators() Mutator combo1s2 = new ComboMutator(combo1s, combo2); Mutator combo4s3 = new ComboMutator(combo4s, combo3); - mutators.AddRange(new Mutator[] { - addSplit, - tryCatch, tryCatchx2, - tryEmptyFinally, tryEmtpyFinallyx2, - emptyTryFinally, emptyTryFinallyx2, - randomTryCatch, randomTryEmptyFinally, randomEmptyTryFinally, - randomMoveToCatch, randomMoveToCatchx2, - tryCatchRandom, tryEmtpyFinallyRandom, - emptyTryFinallyRandom, moveToCatchRandom, - either12, either34, either1s, either2s, - combo1, combo2, combo3, combo4, - combo1s, combo2s, combo3s, combo4s, - combo2s1, combo3s4, combo1s2, combo4s3, - }); + _mutators.AddRange(new Mutator[] + { + addSplit, + tryCatch, tryCatchx2, + tryEmptyFinally, tryEmtpyFinallyx2, + emptyTryFinally, emptyTryFinallyx2, + randomTryCatch, randomTryEmptyFinally, randomEmptyTryFinally, + randomMoveToCatch, randomMoveToCatchx2, + tryCatchRandom, tryEmtpyFinallyRandom, + emptyTryFinallyRandom, moveToCatchRandom, + either12, either34, either1s, either2s, + combo1, combo2, combo3, combo4, + combo1s, combo2s, combo3s, combo4s, + combo2s1, combo3s4, combo1s2, combo4s3, + }); } - - return mutators; } public static bool EnsureStack() => RuntimeHelpers.TryEnsureSufficientExecutionStack(); private static bool isFirstRun = true; - static int Main(string[] args) - { - RootCommand rootCommand = new RootCommand(); - rootCommand.Description = "Take an existing test case and produce new test cases via mutation"; - - Argument inputFile = new Argument(); - inputFile.Name = "InputFile"; - inputFile.Description = "Input test case file or directory (for --recursive)"; - rootCommand.AddArgument(inputFile); - - Option ehStressOption = new Option("--ehStress", "add EH to methods", new Argument()); - rootCommand.AddOption(ehStressOption); - - Option structStressOption = new Option("--structStress", "replace locals with structs", new Argument()); - rootCommand.AddOption(structStressOption); - - Option showResultsOption = new Option("--showResults", "print modified programs to stdout", new Argument()); - rootCommand.AddOption(showResultsOption); - - Option verboseOption = new Option("--verbose", "describe each transformation", new Argument()); - rootCommand.AddOption(verboseOption); - - Option quietOption = new Option("--quiet", "produce minimal output", new Argument()); - rootCommand.AddOption(quietOption); - - Option recursiveOption = new Option("--recursive", "process each file recursively", new Argument()); - rootCommand.AddOption(recursiveOption); - - Option seedOption = new Option("--seed", "random seed", new Argument(42)); - rootCommand.AddOption(seedOption); - - Option stopAtFirstFailureOption = new Option("--stopAtFirstFailure", "stop each test at first failure", new Argument()); - rootCommand.AddOption(stopAtFirstFailureOption); + private T Get(Option option) => _command.Result.GetValueForOption(option); - Option emptyBlocks = new Option("--emptyBlocks", "transform empty blocks", new Argument()); - rootCommand.AddOption(emptyBlocks); + private static int Main(string[] args) => + new CommandLineBuilder(new MutateTestRootCommand(args)) + .UseVersionOption("-v") + .UseHelp() + .UseParseErrorReporting() + .Build() + .Invoke(args); - Option sizeLimit = new Option("--sizeLimit", "don't process programs larger than this size", new Argument(10000)); - rootCommand.AddOption(sizeLimit); - - Option timeLimit = new Option("--timeLimit", "don't stress programs where compile + run takes more than this many milliseconds", new Argument(1000)); - rootCommand.AddOption(timeLimit); - - Option projectsOption = new Option("--projects", "look for .csproj files instead of .cs files when doing recursive exploration", new Argument()); - rootCommand.AddOption(projectsOption); - - Option onlyFailuresOption = new Option("--onlyFailures", "only emit output for cases that fail at runtime", new Argument()); - rootCommand.AddOption(onlyFailuresOption); - - rootCommand.Handler = CommandHandler.Create((options) => - { - Options = options; - return InnerMain(); - }); - - return rootCommand.InvokeAsync(args).Result; - } - - static int InnerMain() + public int Run() { - // Setup option-dependent statics - - Random = new Random(Options.Seed); - Mutators = GetMutators(); - int total = 0; int skipped = 0; int failed = 0; @@ -316,22 +252,23 @@ static int InnerMain() int variantFailedToCompile = 0; int variantFailedToRun = 0; - if (Options.Projects) + if (Get(_command.Projects)) { MSBuildLocator.RegisterDefaults(); } - if (Options.Recursive) + string inputFilePath = _command.Result.GetValueForArgument(_command.InputFilePath); + if (Get(_command.Recursive)) { - if (!Directory.Exists(Options.InputFile)) + if (!Directory.Exists(inputFilePath)) { - Console.WriteLine($"Unable to access directory '{Options.InputFile}'"); + Console.WriteLine($"Unable to access directory '{inputFilePath}'"); return -1; } - string suffix = Options.Projects ? ".csproj" : ".cs"; - string kind = Options.Projects ? "projects" : "test files"; - var inputFiles = Directory.EnumerateFiles(Options.InputFile, "*", SearchOption.AllDirectories) + string suffix = Get(_command.Projects) ? ".csproj" : ".cs"; + string kind = Get(_command.Projects) ? "projects" : "test files"; + var inputFiles = Directory.EnumerateFiles(inputFilePath, "*", SearchOption.AllDirectories) .Where(s => (s.EndsWith(suffix))); Console.WriteLine($"Processing {inputFiles.Count()} {kind}\n"); @@ -346,7 +283,7 @@ static int InnerMain() ExecutionResult result; - if (Options.Projects) + if (Get(_command.Projects)) { result = MutateOneProject(subInputFile, ref subVariantTotal, ref subVariantFailedToCompile, ref subVariantFailedToRun); } @@ -357,7 +294,7 @@ static int InnerMain() if (result.Success) { - if (!Options.OnlyFailures) + if (!Get(_command.OnlyFailures)) { Console.WriteLine($"// {subInputFile}: {subVariantTotal} variants, all passed"); } @@ -367,7 +304,7 @@ static int InnerMain() { if (result.OriginalCompileFailed || result.OriginalRunFailed || result.NoMutationsAttempted) { - if (!Options.OnlyFailures) + if (!Get(_command.OnlyFailures)) { Console.WriteLine($"// {subInputFile}: {result}"); } @@ -380,7 +317,7 @@ static int InnerMain() failed++; } - if ((subVariantFailedToRun > 0) || !Options.OnlyFailures) + if ((subVariantFailedToRun > 0) || !Get(_command.OnlyFailures)) { int successes = subVariantTotal - subVariantFailedToCompile - subVariantFailedToRun; Console.WriteLine($"// {subInputFile}: {subVariantTotal} variants, {successes} passed" + @@ -410,18 +347,18 @@ static int InnerMain() { ExecutionResult result; - if (Options.Projects) + if (Get(_command.Projects)) { - result = MutateOneProject(Options.InputFile, ref variantTotal, ref variantFailedToCompile, ref variantFailedToRun); + result = MutateOneProject(inputFilePath, ref variantTotal, ref variantFailedToCompile, ref variantFailedToRun); } else { - result = MutateOneTestFile(Options.InputFile, ref variantTotal, ref variantFailedToCompile, ref variantFailedToRun); + result = MutateOneTestFile(inputFilePath, ref variantTotal, ref variantFailedToCompile, ref variantFailedToRun); } if (result.Success) { - Console.WriteLine($"// {Options.InputFile}: {variantTotal} variants, all passed"); + Console.WriteLine($"// {inputFilePath}: {variantTotal} variants, all passed"); succeeded++; return 100; } @@ -429,22 +366,22 @@ static int InnerMain() if (result.OriginalCompileFailed || result.OriginalRunFailed || result.NoMutationsAttempted) { // base case did not compile - Console.WriteLine($"// {Options.InputFile}: {result}"); + Console.WriteLine($"// {inputFilePath}: {result}"); } else { int successes = variantTotal - variantFailedToCompile - variantFailedToRun; - Console.WriteLine($"// {Options.InputFile}: {variantTotal} variants, {successes} passed" + + Console.WriteLine($"// {inputFilePath}: {variantTotal} variants, {successes} passed" + $" [{variantFailedToCompile} did not compile, {variantFailedToRun} did not run correctly]"); } - + return -1; } } - static ExecutionResult MutateOneTestFile(string testFile, ref int attempted, ref int failedToCompile, ref int failedToRun) + private ExecutionResult MutateOneTestFile(string testFile, ref int attempted, ref int failedToCompile, ref int failedToRun) { - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine("---------------------------------------"); Console.WriteLine("// Original Program"); @@ -467,9 +404,9 @@ static ExecutionResult MutateOneTestFile(string testFile, ref int attempted, ref return MutateOneCompilation(compilation, Path.GetFileName(testFile), ref attempted, ref failedToCompile, ref failedToRun); } - static ExecutionResult MutateOneProject(string projectFile, ref int attempted, ref int failedToCompile, ref int failedToRun) + private ExecutionResult MutateOneProject(string projectFile, ref int attempted, ref int failedToCompile, ref int failedToRun) { - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine("---------------------------------------"); Console.WriteLine("// Original Program"); @@ -493,11 +430,11 @@ static ExecutionResult MutateOneProject(string projectFile, ref int attempted, r // Seems like we need to spoon feed in the assembly references here? // Probably missing some important step. - var compilation = project.GetCompilationAsync().Result.AddReferences(References); + var compilation = project.GetCompilationAsync().Result.AddReferences(References); - if (!Options.Quiet) + if (!_quiet) { - if (Options.ShowResults) + if (Get(_command.ShowResults)) { // Would be nice to show breakdown by file.... foreach (SyntaxTree s in compilation.SyntaxTrees) @@ -511,7 +448,7 @@ static ExecutionResult MutateOneProject(string projectFile, ref int attempted, r } } - static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, string name, ref int attempted, ref int failedToCompile, ref int failedToRun) + private ExecutionResult MutateOneCompilation(CSharpCompilation compilation, string name, ref int attempted, ref int failedToCompile, ref int failedToRun) { // Bail on some specific tests // We use substring match as there are often variants @@ -533,7 +470,7 @@ static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, strin if (exclusions.Any(x => name.Contains(x))) { - return new ExecutionResult() { kind = ExecutionResultKind.SkipSpecialCase }; + return new ExecutionResult { kind = ExecutionResultKind.SkipSpecialCase }; } Stopwatch s = new Stopwatch(); @@ -550,13 +487,13 @@ static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, strin int inputSize = compilation.SyntaxTrees.Sum(x => x.Length); - if (inputSize > Options.SizeLimit) + if (inputSize > Get(_command.SizeLimit)) { - return new ExecutionResult() { kind = ExecutionResultKind.SizeTooLarge, value = inputSize }; + return new ExecutionResult { kind = ExecutionResultKind.SizeTooLarge, value = inputSize }; } // First run will be slower because of jitting (sigh) - int timeLimit = Options.TimeLimit; + int timeLimit = Program.TimeLimit; if (isFirstRun) { timeLimit *= 3; @@ -565,15 +502,15 @@ static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, strin if (s.ElapsedMilliseconds > timeLimit) { - return new ExecutionResult() { kind = ExecutionResultKind.RanTooLong, value = (int) s.ElapsedMilliseconds }; + return new ExecutionResult { kind = ExecutionResultKind.RanTooLong, value = (int) s.ElapsedMilliseconds }; } // Ok, we have a compile and runnable test case. Now, mess with it.... int variantNumber = 0; - ExecutionResult result = new ExecutionResult() { kind = ExecutionResultKind.RanNormally }; + ExecutionResult result = new ExecutionResult { kind = ExecutionResultKind.RanNormally }; - foreach (var mutator in Mutators) + foreach (var mutator in _mutators) { attempted++; ExecutionResult mutationResult = ApplyMutations(variantNumber++, mutator, compilation); @@ -581,7 +518,7 @@ static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, strin if (!mutationResult.Success) { // count assembly load failures as compile failures for now. - if (mutationResult.CompileFailed || mutationResult.AssemblyLoadFailed) + if (mutationResult.CompileFailed || mutationResult.AssemblyLoadFailed) { failedToCompile++; } @@ -601,12 +538,12 @@ static ExecutionResult MutateOneCompilation(CSharpCompilation compilation, strin return result; } - static ExecutionResult ApplyMutations(int variantNumber, Mutator m, CSharpCompilation compilation) + private ExecutionResult ApplyMutations(int variantNumber, Mutator m, CSharpCompilation compilation) { string shortTitle = $"Mutation [{variantNumber}]"; string title = $"// {shortTitle}: {m.Name}"; - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine(); Console.WriteLine("---------------------------------------"); @@ -624,11 +561,11 @@ static ExecutionResult ApplyMutations(int variantNumber, Mutator m, CSharpCompil transformedTrees.Add(SyntaxTree(transformedRoot)); } - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine($"// {shortTitle}: made {totalTransformCount} mutations"); - if (Options.ShowResults) + if (Get(_command.ShowResults)) { foreach (SyntaxTree s in transformedTrees) { @@ -642,7 +579,7 @@ static ExecutionResult ApplyMutations(int variantNumber, Mutator m, CSharpCompil return CompileAndExecute(newCompilation, shortTitle, isMutant: true); } - static ExecutionResult CompileAndExecute(CSharpCompilation compilation, string name, bool isMutant = false) + private ExecutionResult CompileAndExecute(CSharpCompilation compilation, string name, bool isMutant = false) { using (var ms = new MemoryStream()) { @@ -653,7 +590,7 @@ static ExecutionResult CompileAndExecute(CSharpCompilation compilation, string n } catch (Exception ex) { - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine($"// Compilation of '{name}' failed: {ex.Message}"); } @@ -662,7 +599,7 @@ static ExecutionResult CompileAndExecute(CSharpCompilation compilation, string n if (!emitResult.Success) { - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine($"// Compilation of '{name}' failed: {emitResult.Diagnostics.Length} errors"); foreach (var d in emitResult.Diagnostics) @@ -673,7 +610,7 @@ static ExecutionResult CompileAndExecute(CSharpCompilation compilation, string n return new ExecutionResult() { kind = isMutant ? ExecutionResultKind.MutantCompilationFailed : ExecutionResultKind.CompilationFailed }; } - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine($"// Compiled '{name}' successfully"); } @@ -742,7 +679,7 @@ static ExecutionResult CompileAndExecute(CSharpCompilation compilation, string n return new ExecutionResult() { kind = isMutant? ExecutionResultKind.MutantBadExitCode : ExecutionResultKind.BadExitCode, value = (int)inputResult }; } - if (!Options.Quiet) + if (!_quiet) { Console.WriteLine($"// Execution of '{name}' succeeded (exitCode {inputResult})"); } @@ -781,7 +718,7 @@ protected int GetTransformCount() protected virtual void Announce(SyntaxNode node, string message = "") { - if (Options.Verbose) + if (Program.Verbose) { var lineSpan = node.GetLocation().GetMappedLineSpan(); Console.WriteLine($"// {Name} [{TransformCount}] @ lines {lineSpan.StartLinePosition.Line}-{lineSpan.EndLinePosition.Line} {message}"); @@ -791,7 +728,7 @@ protected virtual void Announce(SyntaxNode node, string message = "") protected void AnnounceSkip(SyntaxNode node, string message = "") { - if (Options.Verbose) + if (Program.Verbose) { var lineSpan = node.GetLocation().GetMappedLineSpan(); Console.WriteLine($"// SKIP {Name} [{TransformCount}] @ lines {lineSpan.StartLinePosition.Line}-{lineSpan.EndLinePosition.Line} {message}"); @@ -850,12 +787,12 @@ protected static bool InvalidInFinally(SyntaxNode node) // before we see a block. Bail for now. return node.DescendantNodes(descendIntoTrivia: false).Any( x => - x.Kind() == SyntaxKind.ReturnStatement - || x.Kind() == SyntaxKind.ThrowStatement - || x.Kind() == SyntaxKind.ImplicitStackAllocArrayCreationExpression - || x.Kind() == SyntaxKind.StackAllocArrayCreationExpression - || x.Kind() == SyntaxKind.GotoStatement - || x.Kind() == SyntaxKind.BreakStatement + x.IsKind(SyntaxKind.ReturnStatement) + || x.IsKind(SyntaxKind.ThrowStatement) + || x.IsKind(SyntaxKind.ImplicitStackAllocArrayCreationExpression) + || x.IsKind(SyntaxKind.StackAllocArrayCreationExpression) + || x.IsKind(SyntaxKind.GotoStatement) + || x.IsKind(SyntaxKind.BreakStatement) ); ; } @@ -864,32 +801,32 @@ protected static bool IsInvalidInCatchOrFinally(SyntaxNode node) { // Throw is legally ok, but we disallow to try and avoid causing stack overflow return node.DescendantNodes(descendIntoTrivia: false).Any( - x => x.Kind() == SyntaxKind.ImplicitStackAllocArrayCreationExpression - || x.Kind() == SyntaxKind.StackAllocArrayCreationExpression - || x.Kind() == SyntaxKind.ThrowStatement + x => x.IsKind(SyntaxKind.ImplicitStackAllocArrayCreationExpression) + || x.IsKind(SyntaxKind.StackAllocArrayCreationExpression) + || x.IsKind(SyntaxKind.ThrowStatement) ); } protected static bool IsEnclosedInLoop(SyntaxNode node) { return node.Ancestors().Any( - x => x.Kind() == SyntaxKind.ForStatement - || x.Kind() == SyntaxKind.DoStatement - || x.Kind() == SyntaxKind.WhileStatement - || x.Kind() == SyntaxKind.ForEachStatement + x => x.IsKind(SyntaxKind.ForStatement) + || x.IsKind(SyntaxKind.DoStatement) + || x.IsKind(SyntaxKind.WhileStatement) + || x.IsKind(SyntaxKind.ForEachStatement) ); } protected static bool IsEnclosedInCatch(SyntaxNode node) { return node.Ancestors().Any( - x => x.Kind() == SyntaxKind.CatchClause + x => x.IsKind(SyntaxKind.CatchClause) ); } protected static bool DefinesLabel(SyntaxNode node) { - return node.DescendantNodes().Any(x => x.Kind() == SyntaxKind.LabeledStatement); + return node.DescendantNodes().Any(x => x.IsKind(SyntaxKind.LabeledStatement)); } public SyntaxNode Mutate(SyntaxNode node, out int transformCount) @@ -901,7 +838,7 @@ public SyntaxNode Mutate(SyntaxNode node, out int transformCount) } } - // Rewrite as + // Rewrite as // try { } catch (MutateTest.MutateTestException) { throw; } public class WrapBlocksInTryCatch : Mutator { @@ -1331,7 +1268,7 @@ public override SyntaxNode VisitExpressionStatement(ExpressionStatementSyntax no { node = (ExpressionStatementSyntax)base.VisitExpressionStatement(node); - if (node.Parent.Kind() == SyntaxKind.Block) + if (node.Parent.IsKind(SyntaxKind.Block)) { AnnounceSkip(node); return node; @@ -1346,7 +1283,7 @@ public override SyntaxNode VisitReturnStatement(ReturnStatementSyntax node) { node = (ReturnStatementSyntax)base.VisitReturnStatement(node); - if (node.Parent.Kind() == SyntaxKind.Block) + if (node.Parent.IsKind(SyntaxKind.Block)) { AnnounceSkip(node); return node; diff --git a/src/mutate-test/mutate-test.csproj b/src/mutate-test/mutate-test.csproj index eb470254..5533bbaa 100644 --- a/src/mutate-test/mutate-test.csproj +++ b/src/mutate-test/mutate-test.csproj @@ -2,17 +2,16 @@ Exe - netcoreapp3.1 + net6.0 Mutate Mutate - 7.3 - - - - + + + + diff --git a/src/superpmi/superpmicollect.cs b/src/superpmi/superpmicollect.cs index c88a9886..63e8dc39 100644 --- a/src/superpmi/superpmicollect.cs +++ b/src/superpmi/superpmicollect.cs @@ -314,18 +314,18 @@ private static void CollectMCFiles(string runProgramPath, string runProgramArgum Console.WriteLine("Setting environment variables:"); Console.WriteLine(" SuperPMIShimLogPath=" + s_tempDir); Console.WriteLine(" SuperPMIShimPath=" + Global.JitPath); - Console.WriteLine(" COMPlus_JitName=" + Global.CollectorShimName); + Console.WriteLine(" DOTNET_JitName=" + Global.CollectorShimName); Environment.SetEnvironmentVariable("SuperPMIShimLogPath", s_tempDir); Environment.SetEnvironmentVariable("SuperPMIShimPath", Global.JitPath); - Environment.SetEnvironmentVariable("COMPlus_JitName", Global.CollectorShimName); + Environment.SetEnvironmentVariable("DOTNET_JitName", Global.CollectorShimName); RunProgramsWhileCollecting(runProgramPath, runProgramArguments); // Un-set environment variables Environment.SetEnvironmentVariable("SuperPMIShimLogPath", ""); Environment.SetEnvironmentVariable("SuperPMIShimPath", ""); - Environment.SetEnvironmentVariable("COMPlus_JitName", ""); + Environment.SetEnvironmentVariable("DOTNET_JitName", ""); // Did any .mc files get generated? string[] mcFiles = Directory.GetFiles(s_tempDir, "*.mc"); @@ -604,7 +604,7 @@ private static void Usage() Console.WriteLine("If -mch is not given, all generated files are deleted, and the result is simply the exit code"); Console.WriteLine("indicating whether the collection succeeded. This is useful as a test."); Console.WriteLine(""); - Console.WriteLine("If the COMPlus_JitName variable is already set, it is assumed SuperPMI collection is already happening,"); + Console.WriteLine("If the DOTNET_JitName variable is already set, it is assumed SuperPMI collection is already happening,"); Console.WriteLine("and the program exits with success."); Console.WriteLine(""); Console.WriteLine("On success, the return code is 100."); @@ -701,14 +701,14 @@ private static int Main(string[] args) // Done with argument parsing. - string jitnamevar = System.Environment.GetEnvironmentVariable("COMPlus_JitName"); + string jitnamevar = System.Environment.GetEnvironmentVariable("DOTNET_JitName"); if (!String.IsNullOrEmpty(jitnamevar)) { - // Someone already has the COMPlus_JitName variable set. We don't want to override + // Someone already has the DOTNET_JitName variable set. We don't want to override // that. Perhaps someone is already doing a SuperPMI collection and invokes this // program as part of a full test path in which this program exists. - Console.WriteLine("COMPlus_JitName already exists: skipping SuperPMI collection and returning success"); + Console.WriteLine("DOTNET_JitName already exists: skipping SuperPMI collection and returning success"); return 100; } diff --git a/src/target-framework.props b/src/target-framework.props index 7e777ca8..f7f9a41f 100644 --- a/src/target-framework.props +++ b/src/target-framework.props @@ -3,7 +3,7 @@ - netcoreapp3.1 + net6.0