From b4a3ebef427b00e6115c63ebb6acba7337cce65f Mon Sep 17 00:00:00 2001 From: jashook Date: Thu, 20 May 2021 09:45:14 -0700 Subject: [PATCH 1/2] Restrict console output for methods and types with QUIET passed In addition, if JitDisasm is set skip methods which do not have the method name. This avoids compiling all methods when there is only one that is intended to be dumped. --- src/pmi/PMIDriver.cs | 15 ++-- src/pmi/pmi.cs | 171 +++++++++++++++++++++++++------------------ 2 files changed, 107 insertions(+), 79 deletions(-) diff --git a/src/pmi/PMIDriver.cs b/src/pmi/PMIDriver.cs index facc3a9b..fd5fb40e 100644 --- a/src/pmi/PMIDriver.cs +++ b/src/pmi/PMIDriver.cs @@ -51,7 +51,7 @@ public static int Drive(string assemblyName, bool verbose, Dictionary methodName = null; + + if (useEnv) { - Console.WriteLine(); - Console.WriteLine($"InvalidOperationException {type.FullName}::{method.Name}"); + int methodNameStart = methodToDisasm.IndexOf(':') + 1; + ReadOnlySpan splitStr = methodToDisasm.AsSpan(methodNameStart); + + int endofMethodNameStart = splitStr.IndexOf('('); + + methodName = splitStr.Slice(0, endofMethodNameStart); } - catch (Exception e) + + if (!useEnv || (methodName.CompareTo(method.Name.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0 && methodToDisasm.IndexOf(method.DeclaringType.Name) != -1)) { - Console.WriteLine(); - Console.WriteLine($"Unknown exception {type.FullName}::{method.Name}"); - Console.WriteLine(e); + try + { + DateTime startFunc = DateTime.Now; + GC.WaitForPendingFinalizers(); + System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle); + elapsedFunc = DateTime.Now - startFunc; + success = true; + } + catch (System.EntryPointNotFoundException) + { + Console.WriteLine(); + Console.WriteLine($"EntryPointNotFoundException {type.FullName}::{method.Name}"); + } + catch (System.BadImageFormatException) + { + Console.WriteLine(); + Console.WriteLine($"BadImageFormatException {type.FullName}::{method.Name}"); + } + catch (System.MissingMethodException) + { + Console.WriteLine(); + Console.WriteLine($"MissingMethodException {type.FullName}::{method.Name}"); + } + catch (System.ArgumentException e) + { + Console.WriteLine(); + string msg = e.Message.Split(new char[] { '\r', '\n' })[0]; + Console.WriteLine($"ArgumentException {type.FullName}::{method.Name} {msg}"); + } + catch (System.IO.FileNotFoundException eFileNotFound) + { + Console.WriteLine(); + Console.WriteLine($"FileNotFoundException {type.FullName}::{method.Name}" + + $" - {eFileNotFound.FileName} ({eFileNotFound.Message})"); + } + catch (System.DllNotFoundException eDllNotFound) + { + Console.WriteLine(); + Console.WriteLine($"DllNotFoundException {type.FullName}::{method.Name} ({eDllNotFound.Message})"); + } + catch (System.TypeInitializationException eTypeInitialization) + { + Console.WriteLine(); + Console.WriteLine("TypeInitializationException {type.FullName}::{method.Name}" + + $"{eTypeInitialization.TypeName} ({eTypeInitialization.Message})"); + } + catch (System.Runtime.InteropServices.MarshalDirectiveException) + { + Console.WriteLine(); + Console.WriteLine($"MarshalDirectiveException {type.FullName}::{method.Name}"); + } + catch (System.TypeLoadException) + { + Console.WriteLine(); + Console.WriteLine($"TypeLoadException {type.FullName}::{method.Name}"); + } + catch (System.OverflowException) + { + Console.WriteLine(); + Console.WriteLine($"OverflowException {type.FullName}::{method.Name}"); + } + catch (System.InvalidProgramException) + { + Console.WriteLine(); + Console.WriteLine($"InvalidProgramException {type.FullName}::{method.Name}"); + } + catch (System.InvalidOperationException) + { + Console.WriteLine(); + Console.WriteLine($"InvalidOperationException {type.FullName}::{method.Name}"); + } + catch (Exception e) + { + Console.WriteLine(); + Console.WriteLine($"Unknown exception {type.FullName}::{method.Name}"); + Console.WriteLine(e); + } } return success; @@ -997,10 +1015,17 @@ bool Work(Type type) } } + string methodToDisasm = Environment.GetEnvironmentVariable("COMPlus_JitDisasm"); + if (keepGoing) { foreach (MethodBase methodBase in methods) { + if (methodToDisasm != null && methodToDisasm.IndexOf(methodBase.DeclaringType.Name) == -1) + { + continue; + } + if (methodBase == cctor) { continue; From b78ab4cd3820802218222b8c85aca5923dc99ee3 Mon Sep 17 00:00:00 2001 From: jashook Date: Fri, 11 Jun 2021 23:04:01 -0700 Subject: [PATCH 2/2] Update to allow * --- src/pmi/pmi.cs | 60 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/src/pmi/pmi.cs b/src/pmi/pmi.cs index 7f444d06..d10b9cb5 100644 --- a/src/pmi/pmi.cs +++ b/src/pmi/pmi.cs @@ -440,18 +440,70 @@ protected bool TryPrepareMethod(Type type, MethodBase method, out TimeSpan elaps bool useEnv = methodToDisasm != null; ReadOnlySpan methodName = null; + ReadOnlySpan className = null; + + bool namesMatch = false; if (useEnv) { - int methodNameStart = methodToDisasm.IndexOf(':') + 1; + bool hasClassName = methodToDisasm.IndexOf(':') != -1; + bool containsArgs = methodToDisasm.IndexOf('(') != -1; + bool endsWithWildcard = methodToDisasm.IndexOf('*') != -1; + + // COMPlus_JitDisasm=* passed, this is the same as not having + // the environment set. + if (endsWithWildcard && methodToDisasm.Length == 1) + { + useEnv = false; + } + + int methodNameStart = 0; ReadOnlySpan splitStr = methodToDisasm.AsSpan(methodNameStart); - int endofMethodNameStart = splitStr.IndexOf('('); + if (hasClassName) + { + methodNameStart = methodToDisasm.IndexOf(':') + 1; + className = splitStr.Slice(0, methodNameStart - 1); + } + + int methodNameEnd = splitStr.Length - methodNameStart; + if (containsArgs) + { + methodNameEnd = splitStr.IndexOf('(') - methodNameStart; + } + + if (endsWithWildcard) + { + --methodNameEnd; + } + + methodName = splitStr.Slice(methodNameStart, methodNameEnd); - methodName = splitStr.Slice(0, endofMethodNameStart); + bool classNamesMatch = className.CompareTo(method.DeclaringType.Name.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0; + + if (!endsWithWildcard) + { + namesMatch = methodName.CompareTo(method.Name.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0; + } + else + { + ReadOnlySpan compareName = method.Name.AsSpan(); + + bool same = true; + for (int index = 0; index < methodName.Length; ++index) + { + if (methodName[index] != compareName[index]) + { + same = false; + break; + } + } + + namesMatch = same; + } } - if (!useEnv || (methodName.CompareTo(method.Name.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0 && methodToDisasm.IndexOf(method.DeclaringType.Name) != -1)) + if (!useEnv || namesMatch) { try {