Title: [279740] trunk/Source/_javascript_Core
Revision
279740
Author
keith_mil...@apple.com
Date
2021-07-08 11:54:16 -0700 (Thu, 08 Jul 2021)

Log Message

display-profiler-output should be able to print disassembly for the FTL
https://bugs.webkit.org/show_bug.cgi?id=227798

Reviewed by Saam Barati.

Right now running JSC with the bytecode profiler will not print
disassembly for FTL code. This patch adds this support. In order to get
execution counts there is a callback at the transition between each
DFG node in the Air disassembler. Since B3 code move parts of
DFG nodes to different basic blocks we don't include execution
counts in the dump. However, the DFG-only graph printed before
the disassembly will still have the counts.

* ftl/FTLCompile.cpp:
(JSC::FTL::compile):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLState.cpp:
(JSC::FTL::State::dumpDisassembly):
* ftl/FTLState.h:
(JSC::FTL::State::dumpDisassembly):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (279739 => 279740)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-08 18:48:12 UTC (rev 279739)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-08 18:54:16 UTC (rev 279740)
@@ -1,3 +1,27 @@
+2021-07-08  Keith Miller  <keith_mil...@apple.com>
+
+        display-profiler-output should be able to print disassembly for the FTL
+        https://bugs.webkit.org/show_bug.cgi?id=227798
+
+        Reviewed by Saam Barati.
+
+        Right now running JSC with the bytecode profiler will not print
+        disassembly for FTL code. This patch adds this support. In order to get
+        execution counts there is a callback at the transition between each
+        DFG node in the Air disassembler. Since B3 code move parts of
+        DFG nodes to different basic blocks we don't include execution
+        counts in the dump. However, the DFG-only graph printed before
+        the disassembly will still have the counts.
+
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLLink.cpp:
+        (JSC::FTL::link):
+        * ftl/FTLState.cpp:
+        (JSC::FTL::State::dumpDisassembly):
+        * ftl/FTLState.h:
+        (JSC::FTL::State::dumpDisassembly):
+
 2021-07-08  Yusuke Suzuki  <ysuz...@apple.com>
 
         Use JSC::Yarr::flagsString to get string representation of RegExp flags

Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (279739 => 279740)


--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2021-07-08 18:48:12 UTC (rev 279739)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2021-07-08 18:54:16 UTC (rev 279740)
@@ -55,7 +55,7 @@
     CodeBlock* codeBlock = graph.m_codeBlock;
     VM& vm = graph.m_vm;
 
-    if (shouldDumpDisassembly())
+    if (shouldDumpDisassembly() || vm.m_perBytecodeProfiler)
         state.proc->code().setDisassembler(makeUnique<B3::Air::Disassembler>());
 
     if (!shouldDumpDisassembly() && !Options::asyncDisassembly() && !graph.compilation() && !state.proc->needsPCToOriginMap())
@@ -171,79 +171,74 @@
     }
     state.jitCode->common.finalizeCatchEntrypoints(WTFMove(state.graph.m_catchEntrypoints));
 
-    if (B3::Air::Disassembler* disassembler = state.proc->code().disassembler()) {
-        PrintStream& out = WTF::dataFile();
+    if (shouldDumpDisassembly())
+        state.dumpDisassembly(WTF::dataFile());
 
-        out.print("Generated ", state.graph.m_plan.mode(), " code for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITType::FTLJIT), ", instructions size = ", state.graph.m_codeBlock->instructionsSize(), ":\n");
+    Profiler::Compilation* compilation = graph.compilation();
+    if (UNLIKELY(compilation)) {
+        compilation->addDescription(
+            Profiler::OriginStack(),
+            toCString("Generated FTL DFG IR for ", CodeBlockWithJITType(codeBlock, JITType::FTLJIT), ", instructions size = ", graph.m_codeBlock->instructionsSize(), ":\n"));
 
-        LinkBuffer& linkBuffer = *state.finalizer->b3CodeLinkBuffer;
-        B3::Value* currentB3Value = nullptr;
-        Node* currentDFGNode = nullptr;
+        graph.ensureSSADominators();
+        graph.ensureSSANaturalLoops();
 
-        HashSet<B3::Value*> printedValues;
-        HashSet<Node*> printedNodes;
-        const char* dfgPrefix = "DFG " "    ";
-        const char* b3Prefix  = "b3  " "          ";
-        const char* airPrefix = "Air " "              ";
-        const char* asmPrefix = "asm " "                ";
+        const char* prefix = "    ";
 
-        auto printDFGNode = [&] (Node* node) {
-            if (currentDFGNode == node)
-                return;
+        DumpContext dumpContext;
+        StringPrintStream out;
+        Node* lastNode = nullptr;
+        for (size_t blockIndex = 0; blockIndex < graph.numBlocks(); ++blockIndex) {
+            DFG::BasicBlock* block = graph.block(blockIndex);
+            if (!block)
+                continue;
 
-            currentDFGNode = node;
-            if (!currentDFGNode)
-                return;
+            graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &dumpContext);
+            compilation->addDescription(Profiler::OriginStack(), out.toCString());
+            out.reset();
 
-            HashSet<Node*> localPrintedNodes;
-            WTF::Function<void(Node*)> printNodeRecursive = [&] (Node* node) {
-                if (printedNodes.contains(node) || localPrintedNodes.contains(node))
-                    return;
+            for (size_t nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+                Node* node = block->at(nodeIndex);
 
-                localPrintedNodes.add(node);
-                graph.doToChildren(node, [&] (Edge child) {
-                    printNodeRecursive(child.node());
-                });
-                graph.dump(out, dfgPrefix, node);
-            };
-            printNodeRecursive(node);
-            printedNodes.add(node);
-        };
+                Profiler::OriginStack stack;
 
-        auto printB3Value = [&] (B3::Value* value) {
-            if (currentB3Value == value)
-                return;
+                if (node->origin.semantic.isSet()) {
+                    stack = Profiler::OriginStack(
+                        *vm.m_perBytecodeProfiler, codeBlock, node->origin.semantic);
+                }
 
-            currentB3Value = value;
-            if (!currentB3Value)
-                return;
+                if (graph.dumpCodeOrigin(out, prefix, lastNode, node, &dumpContext)) {
+                    compilation->addDescription(stack, out.toCString());
+                    out.reset();
+                }
 
-            printDFGNode(bitwise_cast<Node*>(value->origin().data()));
+                graph.dump(out, prefix, node, &dumpContext);
+                compilation->addDescription(stack, out.toCString());
+                out.reset();
 
-            HashSet<B3::Value*> localPrintedValues;
-            auto printValueRecursive = recursableLambda([&] (auto self, B3::Value* value) -> void {
-                if (printedValues.contains(value) || localPrintedValues.contains(value))
-                    return;
+                if (node->origin.semantic.isSet())
+                    lastNode = node;
+            }
+        }
 
-                localPrintedValues.add(value);
-                for (unsigned i = 0; i < value->numChildren(); i++)
-                    self(value->child(i));
-                out.print(b3Prefix);
-                value->deepDump(state.proc.get(), out);
-                out.print("\n");
-            });
+        dumpContext.dump(out, prefix);
+        compilation->addDescription(Profiler::OriginStack(), out.toCString());
+        out.reset();
 
-            printValueRecursive(currentB3Value);
-            printedValues.add(value);
-        };
+        out.print("\n\n\n    FTL B3/Air Disassembly:\n");
+        compilation->addDescription(Profiler::OriginStack(), out.toCString());
+        out.reset();
 
-        auto forEachInst = scopedLambda<void(B3::Air::Inst&)>([&] (B3::Air::Inst& inst) {
-            printB3Value(inst.origin);
-        });
+        state.dumpDisassembly(out, scopedLambda<void(Node*)>([&] (Node*) {
+            compilation->addDescription({ }, out.toCString());
+            out.reset();
+        }));
+        compilation->addDescription({ }, out.toCString());
+        out.reset();
 
-        disassembler->dump(state.proc->code(), out, linkBuffer, airPrefix, asmPrefix, forEachInst);
-        linkBuffer.didAlreadyDisassemble();
+        state.jitCode->common.compilation = compilation;
     }
+
 }
 
 } } // namespace JSC::FTL

Modified: trunk/Source/_javascript_Core/ftl/FTLLink.cpp (279739 => 279740)


--- trunk/Source/_javascript_Core/ftl/FTLLink.cpp	2021-07-08 18:48:12 UTC (rev 279739)
+++ trunk/Source/_javascript_Core/ftl/FTLLink.cpp	2021-07-08 18:54:16 UTC (rev 279740)
@@ -69,65 +69,6 @@
     CCallHelpers::Address frame = CCallHelpers::Address(
         CCallHelpers::stackPointerRegister, -static_cast<int32_t>(AssemblyHelpers::prologueStackPointerDelta()));
     
-    Profiler::Compilation* compilation = graph.compilation();
-    if (UNLIKELY(compilation)) {
-        compilation->addDescription(
-            Profiler::OriginStack(),
-            toCString("Generated FTL JIT code for ", CodeBlockWithJITType(codeBlock, JITType::FTLJIT), ", instructions size = ", graph.m_codeBlock->instructionsSize(), ":\n"));
-        
-        graph.ensureSSADominators();
-        graph.ensureSSANaturalLoops();
-        
-        const char* prefix = "    ";
-        
-        DumpContext dumpContext;
-        StringPrintStream out;
-        Node* lastNode = nullptr;
-        for (size_t blockIndex = 0; blockIndex < graph.numBlocks(); ++blockIndex) {
-            BasicBlock* block = graph.block(blockIndex);
-            if (!block)
-                continue;
-            
-            graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &dumpContext);
-            compilation->addDescription(Profiler::OriginStack(), out.toCString());
-            out.reset();
-            
-            for (size_t nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
-                Node* node = block->at(nodeIndex);
-                
-                Profiler::OriginStack stack;
-                
-                if (node->origin.semantic.isSet()) {
-                    stack = Profiler::OriginStack(
-                        *vm.m_perBytecodeProfiler, codeBlock, node->origin.semantic);
-                }
-                
-                if (graph.dumpCodeOrigin(out, prefix, lastNode, node, &dumpContext)) {
-                    compilation->addDescription(stack, out.toCString());
-                    out.reset();
-                }
-                
-                graph.dump(out, prefix, node, &dumpContext);
-                compilation->addDescription(stack, out.toCString());
-                out.reset();
-                
-                if (node->origin.semantic.isSet())
-                    lastNode = node;
-            }
-        }
-        
-        dumpContext.dump(out, prefix);
-        compilation->addDescription(Profiler::OriginStack(), out.toCString());
-        out.reset();
-
-        out.print("    Disassembly:\n");
-        out.print("        <not implemented yet>\n");
-        compilation->addDescription(Profiler::OriginStack(), out.toCString());
-        out.reset();
-        
-        state.jitCode->common.compilation = compilation;
-    }
-
     switch (graph.m_plan.mode()) {
     case JITCompilationMode::FTL: {
         bool requiresArityFixup = codeBlock->numParameters() != 1;
@@ -233,7 +174,6 @@
         state.jitCode->initializeArityCheckEntrypoint(arityCheckCodeRef);
     }
 
-    
     state.finalizer->entrypointLinkBuffer = WTFMove(linkBuffer);
     state.finalizer->function = state.generatedFunction;
     state.finalizer->jitCode = state.jitCode;

Modified: trunk/Source/_javascript_Core/ftl/FTLState.cpp (279739 => 279740)


--- trunk/Source/_javascript_Core/ftl/FTLState.cpp	2021-07-08 18:48:12 UTC (rev 279739)
+++ trunk/Source/_javascript_Core/ftl/FTLState.cpp	2021-07-08 18:54:16 UTC (rev 279740)
@@ -28,11 +28,16 @@
 
 #if ENABLE(FTL_JIT)
 
+#include "AirCode.h"
+#include "AirDisassembler.h"
+#include "CodeBlockWithJITType.h"
 #include "FTLForOSREntryJITCode.h"
 #include "FTLJITCode.h"
 #include "FTLJITFinalizer.h"
 #include "FTLPatchpointExceptionHandle.h"
 
+#include <wtf/RecursableLambda.h>
+
 namespace JSC { namespace FTL {
 
 using namespace B3;
@@ -74,6 +79,83 @@
     proc->setFrontendData(&graph);
 }
 
+void State::dumpDisassembly(PrintStream& out, const ScopedLambda<void(DFG::Node*)>& perDFGNodeCallback)
+{
+    B3::Air::Disassembler* disassembler = proc->code().disassembler();
+
+    out.print("Generated ", graph.m_plan.mode(), " code for ", CodeBlockWithJITType(graph.m_codeBlock, JITType::FTLJIT), ", instructions size = ", graph.m_codeBlock->instructionsSize(), ":\n");
+
+    LinkBuffer& linkBuffer = *finalizer->b3CodeLinkBuffer;
+    B3::Value* currentB3Value = nullptr;
+    Node* currentDFGNode = nullptr;
+
+    HashSet<B3::Value*> printedValues;
+    HashSet<Node*> printedNodes;
+    const char* dfgPrefix = "DFG " "    ";
+    const char* b3Prefix  = "b3  " "          ";
+    const char* airPrefix = "Air " "              ";
+    const char* asmPrefix = "asm " "                ";
+
+    auto printDFGNode = [&] (Node* node) {
+        if (currentDFGNode == node)
+            return;
+
+        currentDFGNode = node;
+        if (!currentDFGNode)
+            return;
+
+        perDFGNodeCallback(node);
+
+        HashSet<Node*> localPrintedNodes;
+        WTF::Function<void(Node*)> printNodeRecursive = [&] (Node* node) {
+            if (printedNodes.contains(node) || localPrintedNodes.contains(node))
+                return;
+
+            localPrintedNodes.add(node);
+            graph.doToChildren(node, [&] (Edge child) {
+                printNodeRecursive(child.node());
+            });
+            graph.dump(out, dfgPrefix, node);
+        };
+        printNodeRecursive(node);
+        printedNodes.add(node);
+    };
+
+    auto printB3Value = [&] (B3::Value* value) {
+        if (currentB3Value == value)
+            return;
+
+        currentB3Value = value;
+        if (!currentB3Value)
+            return;
+
+        printDFGNode(bitwise_cast<Node*>(value->origin().data()));
+
+        HashSet<B3::Value*> localPrintedValues;
+        auto printValueRecursive = recursableLambda([&] (auto self, B3::Value* value) -> void {
+            if (printedValues.contains(value) || localPrintedValues.contains(value))
+                return;
+
+            localPrintedValues.add(value);
+            for (unsigned i = 0; i < value->numChildren(); i++)
+                self(value->child(i));
+            out.print(b3Prefix);
+            value->deepDump(proc.get(), out);
+            out.print("\n");
+        });
+
+        printValueRecursive(currentB3Value);
+        printedValues.add(value);
+    };
+
+    auto forEachInst = scopedLambda<void(B3::Air::Inst&)>([&] (B3::Air::Inst& inst) {
+        printB3Value(inst.origin);
+    });
+
+    disassembler->dump(proc->code(), out, linkBuffer, airPrefix, asmPrefix, forEachInst);
+    linkBuffer.didAlreadyDisassemble();
+}
+
 State::~State()
 {
 }

Modified: trunk/Source/_javascript_Core/ftl/FTLState.h (279739 => 279740)


--- trunk/Source/_javascript_Core/ftl/FTLState.h	2021-07-08 18:48:12 UTC (rev 279739)
+++ trunk/Source/_javascript_Core/ftl/FTLState.h	2021-07-08 18:54:16 UTC (rev 279740)
@@ -69,6 +69,8 @@
 
     VM& vm() { return graph.m_vm; }
 
+    void dumpDisassembly(PrintStream&, const ScopedLambda<void(DFG::Node*)>& perDFGNodeCallback = scopedLambda<void(DFG::Node*)>([] (DFG::Node*) { }));
+
     // None of these things is owned by State. It is the responsibility of
     // FTL phases to properly manage the lifecycle of the module and function.
     DFG::Graph& graph;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to