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;