Commit 3d517670 authored by fpizlo@apple.com's avatar fpizlo@apple.com

DFG should be able to print disassembly interleaved with the IR

https://bugs.webkit.org/show_bug.cgi?id=89551

Reviewed by Geoffrey Garen.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::labelIgnoringWatchpoints):
(ARMv7Assembler):
* assembler/AbstractMacroAssembler.h:
(AbstractMacroAssembler):
(JSC::AbstractMacroAssembler::labelIgnoringWatchpoints):
* assembler/X86Assembler.h:
(X86Assembler):
(JSC::X86Assembler::labelIgnoringWatchpoints):
* dfg/DFGCommon.h:
(JSC::DFG::shouldShowDisassembly):
(DFG):
* dfg/DFGDisassembler.cpp: Added.
(DFG):
(JSC::DFG::Disassembler::Disassembler):
(JSC::DFG::Disassembler::dump):
(JSC::DFG::Disassembler::dumpDisassembly):
* dfg/DFGDisassembler.h: Added.
(DFG):
(Disassembler):
(JSC::DFG::Disassembler::setStartOfCode):
(JSC::DFG::Disassembler::setForBlock):
(JSC::DFG::Disassembler::setForNode):
(JSC::DFG::Disassembler::setEndOfMainPath):
(JSC::DFG::Disassembler::setEndOfCode):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dumpCodeOrigin):
(JSC::DFG::Graph::amountOfNodeWhiteSpace):
(DFG):
(JSC::DFG::Graph::printNodeWhiteSpace):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::dumpBlockHeader):
* dfg/DFGGraph.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(DFG):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
(JSC::DFG::JITCompiler::setStartOfCode):
(JSC::DFG::JITCompiler::setForBlock):
(JSC::DFG::JITCompiler::setForNode):
(JSC::DFG::JITCompiler::setEndOfMainPath):
(JSC::DFG::JITCompiler::setEndOfCode):
* dfg/DFGNode.h:
(Node):
(JSC::DFG::Node::willHaveCodeGen):
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::nodeFlagsAsString):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* runtime/Options.cpp:
(Options):
(JSC::Options::initializeOptions):
* runtime/Options.h:
(Options):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@120834 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 009af9d8
......@@ -71,6 +71,7 @@ SET(JavaScriptCore_SOURCES
dfg/DFGConstantFoldingPhase.cpp
dfg/DFGCorrectableJumpPoint.cpp
dfg/DFGCSEPhase.cpp
dfg/DFGDisassembler.cpp
dfg/DFGDominators.cpp
dfg/DFGDriver.cpp
dfg/DFGFixupPhase.cpp
......
2012-06-20 Filip Pizlo <fpizlo@apple.com>
DFG should be able to print disassembly interleaved with the IR
https://bugs.webkit.org/show_bug.cgi?id=89551
Reviewed by Geoffrey Garen.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::labelIgnoringWatchpoints):
(ARMv7Assembler):
* assembler/AbstractMacroAssembler.h:
(AbstractMacroAssembler):
(JSC::AbstractMacroAssembler::labelIgnoringWatchpoints):
* assembler/X86Assembler.h:
(X86Assembler):
(JSC::X86Assembler::labelIgnoringWatchpoints):
* dfg/DFGCommon.h:
(JSC::DFG::shouldShowDisassembly):
(DFG):
* dfg/DFGDisassembler.cpp: Added.
(DFG):
(JSC::DFG::Disassembler::Disassembler):
(JSC::DFG::Disassembler::dump):
(JSC::DFG::Disassembler::dumpDisassembly):
* dfg/DFGDisassembler.h: Added.
(DFG):
(Disassembler):
(JSC::DFG::Disassembler::setStartOfCode):
(JSC::DFG::Disassembler::setForBlock):
(JSC::DFG::Disassembler::setForNode):
(JSC::DFG::Disassembler::setEndOfMainPath):
(JSC::DFG::Disassembler::setEndOfCode):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dumpCodeOrigin):
(JSC::DFG::Graph::amountOfNodeWhiteSpace):
(DFG):
(JSC::DFG::Graph::printNodeWhiteSpace):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::dumpBlockHeader):
* dfg/DFGGraph.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::JITCompiler):
(DFG):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
* dfg/DFGJITCompiler.h:
(JITCompiler):
(JSC::DFG::JITCompiler::setStartOfCode):
(JSC::DFG::JITCompiler::setForBlock):
(JSC::DFG::JITCompiler::setForNode):
(JSC::DFG::JITCompiler::setEndOfMainPath):
(JSC::DFG::JITCompiler::setEndOfCode):
* dfg/DFGNode.h:
(Node):
(JSC::DFG::Node::willHaveCodeGen):
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::nodeFlagsAsString):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* runtime/Options.cpp:
(Options):
(JSC::Options::initializeOptions):
* runtime/Options.h:
(Options):
2012-06-19 Filip Pizlo <fpizlo@apple.com>
JSC should be able to show disassembly for all generated JIT code
......
......@@ -168,6 +168,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.h \
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp \
Source/JavaScriptCore/dfg/DFGCSEPhase.h \
Source/JavaScriptCore/dfg/DFGDisassembler.cpp \
Source/JavaScriptCore/dfg/DFGDisassembler.h \
Source/JavaScriptCore/dfg/DFGDominators.cpp \
Source/JavaScriptCore/dfg/DFGDominators.h \
Source/JavaScriptCore/dfg/DFGDoubleFormatState.h \
......
......@@ -209,6 +209,8 @@
0FF4274B158EBE91004CB9FF /* udis86.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4273F158EBD94004CB9FF /* udis86.h */; };
0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */; };
0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */; };
0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; };
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -929,6 +931,8 @@
0FF4273F158EBD94004CB9FF /* udis86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = udis86.h; path = disassembler/udis86/udis86.h; sourceTree = "<group>"; };
0FF4274C158EBFE1004CB9FF /* udis86_itab_holder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = udis86_itab_holder.c; path = disassembler/udis86/udis86_itab_holder.c; sourceTree = "<group>"; };
0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; };
0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDisassembler.cpp; path = dfg/DFGDisassembler.cpp; sourceTree = "<group>"; };
0FF427621591A1C9004CB9FF /* DFGDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDisassembler.h; path = dfg/DFGDisassembler.h; sourceTree = "<group>"; };
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
......@@ -2201,6 +2205,8 @@
0F3B3A18153E68EF003ED0FF /* DFGConstantFoldingPhase.h */,
0FC0979D146B271E00CF2442 /* DFGCorrectableJumpPoint.cpp */,
0FC0979A146A772000CF2442 /* DFGCorrectableJumpPoint.h */,
0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */,
0FF427621591A1C9004CB9FF /* DFGDisassembler.h */,
0FD81ACF154FB4EB00983E72 /* DFGDominators.cpp */,
0FD81AD0154FB4EB00983E72 /* DFGDominators.h */,
0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */,
......@@ -2759,6 +2765,7 @@
0FF42748158EBE91004CB9FF /* udis86_syn.h in Headers */,
0FF42749158EBE91004CB9FF /* udis86_types.h in Headers */,
0FF4274B158EBE91004CB9FF /* udis86.h in Headers */,
0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -3345,6 +3352,7 @@
C2E526BD1590EF000054E48D /* HeapTimer.cpp in Sources */,
0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */,
C2D58C3415912FEE0021A844 /* GCActivityCallback.cpp in Sources */,
0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -102,6 +102,7 @@ SOURCES += \
dfg/DFGConstantFoldingPhase.cpp \
dfg/DFGCorrectableJumpPoint.cpp \
dfg/DFGCSEPhase.cpp \
dfg/DFGDisassembler.cpp \
dfg/DFGDominators.cpp \
dfg/DFGDriver.cpp \
dfg/DFGFixupPhase.cpp \
......
......@@ -1827,6 +1827,11 @@ public:
m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
}
AssemblerLabel labelIgnoringWatchpoints()
{
return m_formatter.label();
}
AssemblerLabel labelForWatchpoint()
{
AssemblerLabel result = m_formatter.label();
......
......@@ -555,6 +555,15 @@ public:
// Section 3: Misc admin methods
#if ENABLE(DFG_JIT)
Label labelIgnoringWatchpoints()
{
Label result;
result.m_label = m_assembler.labelIgnoringWatchpoints();
return result;
}
#endif
Label label()
{
return Label(this);
......
......@@ -1730,6 +1730,11 @@ public:
m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
return result;
}
AssemblerLabel labelIgnoringWatchpoints()
{
return m_formatter.label();
}
AssemblerLabel label()
{
......
......@@ -134,6 +134,11 @@ enum NoResultTag { NoResult };
enum OptimizationFixpointState { FixpointConverged, FixpointNotConverged };
inline bool shouldShowDisassembly()
{
return Options::showDisassembly || Options::showDFGDisassembly;
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DFGDisassembler.h"
#if ENABLE(DFG_JIT)
#include "DFGGraph.h"
namespace JSC { namespace DFG {
Disassembler::Disassembler(Graph& graph)
: m_graph(graph)
{
m_labelForBlockIndex.resize(graph.m_blocks.size());
m_labelForNodeIndex.resize(graph.size());
}
void Disassembler::dump(LinkBuffer& linkBuffer)
{
m_graph.m_dominators.computeIfNecessary(m_graph);
dataLog("Generated JIT code for DFG CodeBlock %p:\n", m_graph.m_codeBlock);
dataLog(" Code at [%p, %p):\n", linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize());
const char* prefix = " ";
const char* disassemblyPrefix = " ";
NodeIndex lastNodeIndex = NoNode;
MacroAssembler::Label previousLabel = m_startOfCode;
for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
BasicBlock* block = m_graph.m_blocks[blockIndex].get();
if (!block)
continue;
dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNodeIndex);
m_graph.dumpBlockHeader(prefix, blockIndex, Graph::DumpLivePhisOnly);
NodeIndex lastNodeIndexForDisassembly = block->at(0);
for (size_t i = 0; i < block->size(); ++i) {
if (!m_graph[block->at(i)].willHaveCodeGen())
continue;
MacroAssembler::Label currentLabel;
if (m_labelForNodeIndex[block->at(i)].isSet())
currentLabel = m_labelForNodeIndex[block->at(i)];
else {
// Dump the last instruction by using the first label of the next block
// as the end point. This case is hit either during peephole compare
// optimizations (the Branch won't have its own label) or if we have a
// forced OSR exit.
if (blockIndex + 1 < m_graph.m_blocks.size())
currentLabel = m_labelForBlockIndex[blockIndex + 1];
else
currentLabel = m_endOfMainPath;
}
dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeIndexForDisassembly);
m_graph.dumpCodeOrigin(prefix, lastNodeIndex, block->at(i));
m_graph.dump(prefix, block->at(i));
lastNodeIndex = block->at(i);
lastNodeIndexForDisassembly = block->at(i);
}
}
dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNodeIndex);
dataLog("%s(End Of Main Path)\n", prefix);
dumpDisassembly(disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, NoNode);
}
void Disassembler::dumpDisassembly(const char* prefix, LinkBuffer& linkBuffer, MacroAssembler::Label& previousLabel, MacroAssembler::Label currentLabel, NodeIndex context)
{
size_t prefixLength = strlen(prefix);
int amountOfNodeWhiteSpace;
if (context == NoNode)
amountOfNodeWhiteSpace = 0;
else
amountOfNodeWhiteSpace = Graph::amountOfNodeWhiteSpace(m_graph[context]);
OwnArrayPtr<char> prefixBuffer = adoptArrayPtr(new char[prefixLength + amountOfNodeWhiteSpace + 1]);
strcpy(prefixBuffer.get(), prefix);
for (int i = 0; i < amountOfNodeWhiteSpace; ++i)
prefixBuffer[i + prefixLength] = ' ';
prefixBuffer[prefixLength + amountOfNodeWhiteSpace] = 0;
CodeLocationLabel start = linkBuffer.locationOf(previousLabel);
CodeLocationLabel end = linkBuffer.locationOf(currentLabel);
previousLabel = currentLabel;
ASSERT(bitwise_cast<uintptr_t>(end.executableAddress()) >= bitwise_cast<uintptr_t>(start.executableAddress()));
if (tryToDisassemble(start, bitwise_cast<uintptr_t>(end.executableAddress()) - bitwise_cast<uintptr_t>(start.executableAddress()), prefixBuffer.get(), WTF::dataFile()))
return;
dataLog("%s disassembly not available for range %p...%p\n", prefixBuffer.get(), start.executableAddress(), end.executableAddress());
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DFGDisassembler_h
#define DFGDisassembler_h
#include <wtf/Platform.h>
#if ENABLE(DFG_JIT)
#include "DFGCommon.h"
#include "LinkBuffer.h"
#include "MacroAssembler.h"
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
class Graph;
class Disassembler {
WTF_MAKE_FAST_ALLOCATED;
public:
Disassembler(Graph&);
void setStartOfCode(MacroAssembler::Label label) { m_startOfCode = label; }
void setForBlock(BlockIndex blockIndex, MacroAssembler::Label label)
{
m_labelForBlockIndex[blockIndex] = label;
}
void setForNode(NodeIndex nodeIndex, MacroAssembler::Label label)
{
m_labelForNodeIndex[nodeIndex] = label;
}
void setEndOfMainPath(MacroAssembler::Label label)
{
m_endOfMainPath = label;
}
void setEndOfCode(MacroAssembler::Label label)
{
m_endOfCode = label;
}
void dump(LinkBuffer&);
private:
void dumpDisassembly(const char* prefix, LinkBuffer&, MacroAssembler::Label& previousLabel, MacroAssembler::Label currentLabel, NodeIndex context);
Graph& m_graph;
MacroAssembler::Label m_startOfCode;
Vector<MacroAssembler::Label> m_labelForBlockIndex;
Vector<MacroAssembler::Label> m_labelForNodeIndex;
MacroAssembler::Label m_endOfMainPath;
MacroAssembler::Label m_endOfCode;
};
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGDisassembler_h
......@@ -92,7 +92,6 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt);
#endif
dfg.m_dominators.compute(dfg);
performVirtualRegisterAllocation(dfg);
GraphDumpMode modeForFinalValidate = DumpGraph;
......
......@@ -89,7 +89,7 @@ static void printWhiteSpace(unsigned amount)
dataLog(" ");
}
void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex)
void Graph::dumpCodeOrigin(const char* prefix, NodeIndex prevNodeIndex, NodeIndex nodeIndex)
{
if (prevNodeIndex == NoNode)
return;
......@@ -112,18 +112,30 @@ void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex)
// Print the pops.
for (unsigned i = previousInlineStack.size(); i-- > indexOfDivergence;) {
dataLog("%s", prefix);
printWhiteSpace(i * 2);
dataLog("<-- %p\n", previousInlineStack[i].inlineCallFrame->executable.get());
}
// Print the pushes.
for (unsigned i = indexOfDivergence; i < currentInlineStack.size(); ++i) {
dataLog("%s", prefix);
printWhiteSpace(i * 2);
dataLog("--> %p\n", currentInlineStack[i].inlineCallFrame->executable.get());
}
}
void Graph::dump(NodeIndex nodeIndex)
int Graph::amountOfNodeWhiteSpace(Node& node)
{
return (node.codeOrigin.inlineDepth() - 1) * 2;
}
void Graph::printNodeWhiteSpace(Node& node)
{
printWhiteSpace(amountOfNodeWhiteSpace(node));
}
void Graph::dump(const char* prefix, NodeIndex nodeIndex)
{
Node& node = at(nodeIndex);
NodeType op = node.op();
......@@ -134,7 +146,8 @@ void Graph::dump(NodeIndex nodeIndex)
if (mustGenerate)
--refCount;
printWhiteSpace((node.codeOrigin.inlineDepth() - 1) * 2);
dataLog("%s", prefix);
printNodeWhiteSpace(node);
// Example/explanation of dataflow dump output
//
......@@ -288,6 +301,54 @@ void Graph::dump(NodeIndex nodeIndex)
dataLog("\n");
}
void Graph::dumpBlockHeader(const char* prefix, BlockIndex blockIndex, PhiNodeDumpMode phiNodeDumpMode)
{
BasicBlock* block = m_blocks[blockIndex].get();
dataLog("%sBlock #%u (bc#%u): %s%s\n", prefix, (int)blockIndex, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "");
dataLog("%s Predecessors:", prefix);
for (size_t i = 0; i < block->m_predecessors.size(); ++i)
dataLog(" #%u", block->m_predecessors[i]);
dataLog("\n");
if (m_dominators.isValid()) {
dataLog("%s Dominated by:", prefix);
for (size_t i = 0; i < m_blocks.size(); ++i) {
if (!m_dominators.dominates(i, blockIndex))
continue;
dataLog(" #%lu", static_cast<unsigned long>(i));
}
dataLog("\n");
dataLog("%s Dominates:", prefix);
for (size_t i = 0; i < m_blocks.size(); ++i) {
if (!m_dominators.dominates(blockIndex, i))
continue;
dataLog(" #%lu", static_cast<unsigned long>(i));
}
dataLog("\n");
}
dataLog("%s Phi Nodes:", prefix);
unsigned count = 0;
for (size_t i = 0; i < block->phis.size(); ++i) {
NodeIndex phiNodeIndex = block->phis[i];
Node& phiNode = at(phiNodeIndex);
if (!phiNode.shouldGenerate() && phiNodeDumpMode == DumpLivePhisOnly)
continue;
if (!((++count) % 4))
dataLog("\n%s ", prefix);
dataLog(" @%u->(", phiNodeIndex);
if (phiNode.child1()) {
dataLog("@%u", phiNode.child1().index());
if (phiNode.child2()) {
dataLog(", @%u", phiNode.child2().index());
if (phiNode.child3())
dataLog(", @%u", phiNode.child3().index());
}
}
dataLog(")%s", i + 1 < block->phis.size() ? "," : "");
}
dataLog("\n");
}
void Graph::dump()
{
NodeIndex lastNodeIndex = NoNode;
......@@ -295,33 +356,7 @@ void Graph::dump()
BasicBlock* block = m_blocks[b].get();
if (!block)
continue;
dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : "");
dataLog(" Predecessors:");
for (size_t i = 0; i < block->m_predecessors.size(); ++i)
dataLog(" #%u", block->m_predecessors[i]);
dataLog("\n");
if (m_dominators.isValid()) {
dataLog(" Dominated by:");
for (size_t i = 0; i < m_blocks.size(); ++i) {
if (!m_dominators.dominates(i, b))
continue;
dataLog(" #%lu", static_cast<unsigned long>(i));
}
dataLog("\n");
dataLog(" Dominates:");
for (size_t i = 0; i < m_blocks.size(); ++i) {
if (!m_dominators.dominates(b, i))
continue;
dataLog(" #%lu", static_cast<unsigned long>(i));
}
dataLog("\n");
}
dataLog(" Phi Nodes:\n");
for (size_t i = 0; i < block->phis.size(); ++i) {
dumpCodeOrigin(lastNodeIndex, block->phis[i]);
dump(block->phis[i]);
lastNodeIndex = block->phis[i];
}
dumpBlockHeader("", b, DumpAllPhis);
dataLog(" vars before: ");
if (block->cfaHasVisited)
dumpOperands(block->valuesAtHead, WTF::dataFile());
......@@ -332,8 +367,8 @@ void Graph::dump()
dumpOperands(block->variablesAtHead, WTF::dataFile());
dataLog("\n");
for (size_t i = 0; i < block->size(); ++i) {
dumpCodeOrigin(lastNodeIndex, block->at(i));
dump(block->at(i));
dumpCodeOrigin("", lastNodeIndex, block->at(i));
dump("", block->at(i));
lastNodeIndex = block->at(i);
}
dataLog(" vars after: ");
......
......@@ -179,11 +179,15 @@ public:
// CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
void dump();
void dump(NodeIndex);
enum PhiNodeDumpMode { DumpLivePhisOnly, DumpAllPhis };
void dumpBlockHeader(const char* prefix, BlockIndex, PhiNodeDumpMode);
void dump(const char* prefix, NodeIndex);
static int amountOfNodeWhiteSpace(Node&);
static void printNodeWhiteSpace(Node&);
// Dump the code origin of the given node as a diff from the code origin of the
// preceding node.
void dumpCodeOrigin(NodeIndex, NodeIndex);
void dumpCodeOrigin(const char* prefix, NodeIndex, NodeIndex);
BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin);
......
......@@ -40,6 +40,15 @@
namespace JSC { namespace DFG {
JITCompiler::JITCompiler(Graph& dfg)
: CCallHelpers(&dfg.m_globalData, dfg.m_codeBlock)
, m_graph(dfg)
, m_currentCodeOriginIndex(0)
{
if (shouldShowDisassembly())
m_disassembler = adoptPtr(new Disassembler(dfg));
}
void JITCompiler::linkOSRExits()
{
for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) {
......@@ -201,9 +210,11 @@ void JITCompiler::link(LinkBuffer& linkBuffer)
bool JITCompiler::compile(JITCode& entry)
{
setStartOfCode();
compileEntry();
SpeculativeJIT speculative(*this);
compileBody(speculative);
setEndOfMainPath();
// Generate slow path code.
speculative.runSlowPathGenerators();
......@@ -213,6 +224,7 @@ bool JITCompiler::compile(JITCode& entry)
// Create OSR entry trampolines if necessary.
speculative.createOSREntries();
setEndOfCode();
LinkBuffer linkBuffer(*m_globalData, this, m_codeBlock, JITCompilationCanFail);
if (linkBuffer.didFailToAllocate())
......@@ -220,14 +232,18 @@ bool JITCompiler::compile(JITCode& entry)