Enhancements to MCS dumpMap (#52412)
authorAndy Ayers <andya@microsoft.com>
Fri, 7 May 2021 01:36:53 +0000 (18:36 -0700)
committerGitHub <noreply@github.com>
Fri, 7 May 2021 01:36:53 +0000 (18:36 -0700)
I've been trying to correlate methods in SPMI collections with methods
seen in profile data (say perfview). But for generic classes or generic
methods this is not easy.

To make it more feasible, in the "extra query" mode, get the names of
all the generic parameters, and then add these to the class name in MCS's
dumpMap output.

Also dump out the jit flags, so it's easier to find a particular instance
if the method was jitted more than once.

src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp
src/coreclr/jit/compiler.cpp

index 9e2faf5..4880d1b 100644 (file)
@@ -8,6 +8,7 @@
 #include "verbdumpmap.h"
 #include "verbildump.h"
 #include "spmiutil.h"
+#include "spmidumphelper.h"
 
 // Dump the CSV format header for all the columns we're going to dump.
 void DumpMapHeader()
@@ -15,7 +16,8 @@ void DumpMapHeader()
     printf("index,");
     // printf("process name,");
     printf("method name,");
-    printf("full signature\n");
+    printf("full signature,");
+    printf("jit flags\n");
 }
 
 void DumpMap(int index, MethodContext* mc)
@@ -37,9 +39,78 @@ void DumpMap(int index, MethodContext* mc)
     printf("\"");
     DumpAttributeToConsoleBare(mc->repGetMethodAttribs(cmi.ftn));
     DumpPrimToConsoleBare(mc, cmi.args.retType, CastHandle(cmi.args.retTypeClass));
-    printf(" %s(", methodName);
+    printf(" %s", methodName);
+
+    // Show class and method generic params, if there are any
+    CORINFO_SIG_INFO sig;
+    mc->repGetMethodSig(cmi.ftn, &sig, nullptr);
+
+    const unsigned classInst = sig.sigInst.classInstCount;
+    if (classInst > 0)
+    {
+        for (unsigned i = 0; i < classInst; i++)
+        {
+            CORINFO_CLASS_HANDLE ci = sig.sigInst.classInst[i];
+            className = mc->repGetClassName(ci);
+
+            printf("%s%s%s%s",
+                i == 0 ? "[" : "",
+                i > 0 ? ", " : "",
+                className,
+                i == classInst - 1 ? "]" : "");
+        }
+    }
+
+    const unsigned methodInst = sig.sigInst.methInstCount;
+    if (methodInst > 0)
+    {
+        for (unsigned i = 0; i < methodInst; i++)
+        {
+            CORINFO_CLASS_HANDLE ci = sig.sigInst.methInst[i];
+            className = mc->repGetClassName(ci);
+
+            printf("%s%s%s%s",
+                i == 0 ? "[" : "",
+                i > 0 ? ", " : "",
+                className,
+                i == methodInst - 1 ? "]" : "");
+        }
+    }
+
+    printf("(");
     DumpSigToConsoleBare(mc, &cmi.args);
-    printf(")\"\n");
+    printf(")\"");
+
+    // Dump the jit flags
+    CORJIT_FLAGS corJitFlags;
+    mc->repGetJitFlags(&corJitFlags, sizeof(corJitFlags));
+    unsigned long long rawFlags = corJitFlags.GetFlagsRaw();
+
+    // Add in the "fake" pgo flags
+    bool hasEdgeProfile = false;
+    bool hasClassProfile = false;
+    bool hasLikelyClass = false;
+    if (mc->hasPgoData(hasEdgeProfile, hasClassProfile, hasLikelyClass))
+    {
+        rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_PGO);
+
+        if (hasEdgeProfile)
+        {
+            rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_EDGE_PROFILE);
+        }
+
+        if (hasClassProfile)
+        {
+            rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_CLASS_PROFILE);
+        }
+
+        if (hasLikelyClass)
+        {
+            rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS);
+        }
+    }
+
+    printf(", %s\n", SpmiDumpHelper::DumpJitFlags(rawFlags).c_str());
 }
 
 int verbDumpMap::DoWork(const char* nameOfInput)
index 6377f0f..953672d 100644 (file)
@@ -5652,11 +5652,37 @@ int Compiler::compCompile(CORINFO_MODULE_HANDLE classPtr,
         // This call to getClassModule/getModuleAssembly/getAssemblyName fails in crossgen2 due to these
         // APIs being unimplemented. So disable this extra info for pre-jit mode. See
         // https://github.com/dotnet/runtime/issues/48888.
+        //
+        // Ditto for some of the class name queries for generic params.
+        //
         if (!compileFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
         {
             // Get the assembly name, to aid finding any particular SuperPMI method context function
             (void)info.compCompHnd->getAssemblyName(
                 info.compCompHnd->getModuleAssembly(info.compCompHnd->getClassModule(info.compClassHnd)));
+
+            // Fetch class names for the method's generic parameters.
+            //
+            CORINFO_SIG_INFO sig;
+            info.compCompHnd->getMethodSig(info.compMethodHnd, &sig, nullptr);
+
+            const unsigned classInst = sig.sigInst.classInstCount;
+            if (classInst > 0)
+            {
+                for (unsigned i = 0; i < classInst; i++)
+                {
+                    eeGetClassName(sig.sigInst.classInst[i]);
+                }
+            }
+
+            const unsigned methodInst = sig.sigInst.methInstCount;
+            if (methodInst > 0)
+            {
+                for (unsigned i = 0; i < methodInst; i++)
+                {
+                    eeGetClassName(sig.sigInst.methInst[i]);
+                }
+            }
         }
     }
 #endif // DEBUG