2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "DFGDisassembler.h"
31 #include "CodeBlockWithJITType.h"
34 namespace JSC
{ namespace DFG
{
36 Disassembler::Disassembler(Graph
& graph
)
39 m_labelForBlockIndex
.resize(graph
.m_blocks
.size());
42 void Disassembler::dump(PrintStream
& out
, LinkBuffer
& linkBuffer
)
44 Vector
<DumpedOp
> ops
= createDumpList(linkBuffer
);
45 for (unsigned i
= 0; i
< ops
.size(); ++i
)
46 out
.print(ops
[i
].text
);
49 void Disassembler::dump(LinkBuffer
& linkBuffer
)
51 dump(WTF::dataFile(), linkBuffer
);
54 void Disassembler::reportToProfiler(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
)
56 Vector
<DumpedOp
> ops
= createDumpList(linkBuffer
);
58 for (unsigned i
= 0; i
< ops
.size(); ++i
) {
59 Profiler::OriginStack stack
;
61 if (ops
[i
].codeOrigin
.isSet())
62 stack
= Profiler::OriginStack(*m_graph
.m_vm
.m_perBytecodeProfiler
, m_graph
.m_codeBlock
, ops
[i
].codeOrigin
);
64 compilation
->addDescription(Profiler::CompiledBytecode(stack
, ops
[i
].text
));
68 void Disassembler::dumpHeader(PrintStream
& out
, LinkBuffer
& linkBuffer
)
70 out
.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph
.m_codeBlock
, JITCode::DFGJIT
), ", instruction count = ", m_graph
.m_codeBlock
->instructionCount(), ":\n");
71 out
.print(" Optimized with execution counter = ", m_graph
.m_profiledBlock
->jitExecuteCounter(), "\n");
72 out
.print(" Source: ", m_graph
.m_codeBlock
->sourceCodeOnOneLine(), "\n");
73 out
.print(" Code at [", RawPointer(linkBuffer
.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer
.debugAddress()) + linkBuffer
.debugSize()), "):\n");
76 void Disassembler::append(Vector
<Disassembler::DumpedOp
>& result
, StringPrintStream
& out
, CodeOrigin
& previousOrigin
)
78 result
.append(DumpedOp(previousOrigin
, out
.toCString()));
79 previousOrigin
= CodeOrigin();
83 Vector
<Disassembler::DumpedOp
> Disassembler::createDumpList(LinkBuffer
& linkBuffer
)
85 StringPrintStream out
;
86 Vector
<DumpedOp
> result
;
88 CodeOrigin previousOrigin
= CodeOrigin();
89 dumpHeader(out
, linkBuffer
);
90 append(result
, out
, previousOrigin
);
92 m_graph
.m_dominators
.computeIfNecessary(m_graph
);
94 const char* prefix
= " ";
95 const char* disassemblyPrefix
= " ";
98 MacroAssembler::Label previousLabel
= m_startOfCode
;
99 for (size_t blockIndex
= 0; blockIndex
< m_graph
.m_blocks
.size(); ++blockIndex
) {
100 BasicBlock
* block
= m_graph
.m_blocks
[blockIndex
].get();
103 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_labelForBlockIndex
[blockIndex
], lastNode
);
104 append(result
, out
, previousOrigin
);
105 m_graph
.dumpBlockHeader(out
, prefix
, blockIndex
, Graph::DumpLivePhisOnly
);
106 append(result
, out
, previousOrigin
);
107 Node
* lastNodeForDisassembly
= block
->at(0);
108 for (size_t i
= 0; i
< block
->size(); ++i
) {
109 if (!block
->at(i
)->willHaveCodeGenOrOSR() && !Options::showAllDFGNodes())
111 MacroAssembler::Label currentLabel
;
112 HashMap
<Node
*, MacroAssembler::Label
>::iterator iter
= m_labelForNode
.find(block
->at(i
));
113 if (iter
!= m_labelForNode
.end())
114 currentLabel
= iter
->value
;
116 // Dump the last instruction by using the first label of the next block
117 // as the end point. This case is hit either during peephole compare
118 // optimizations (the Branch won't have its own label) or if we have a
120 if (blockIndex
+ 1 < m_graph
.m_blocks
.size())
121 currentLabel
= m_labelForBlockIndex
[blockIndex
+ 1];
123 currentLabel
= m_endOfMainPath
;
125 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, currentLabel
, lastNodeForDisassembly
);
126 append(result
, out
, previousOrigin
);
127 previousOrigin
= block
->at(i
)->codeOrigin
;
128 if (m_graph
.dumpCodeOrigin(out
, prefix
, lastNode
, block
->at(i
))) {
129 append(result
, out
, previousOrigin
);
130 previousOrigin
= block
->at(i
)->codeOrigin
;
132 m_graph
.dump(out
, prefix
, block
->at(i
));
133 lastNode
= block
->at(i
);
134 lastNodeForDisassembly
= block
->at(i
);
137 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_endOfMainPath
, lastNode
);
138 append(result
, out
, previousOrigin
);
139 out
.print(prefix
, "(End Of Main Path)\n");
140 append(result
, out
, previousOrigin
);
141 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_endOfCode
, 0);
142 append(result
, out
, previousOrigin
);
147 void Disassembler::dumpDisassembly(PrintStream
& out
, const char* prefix
, LinkBuffer
& linkBuffer
, MacroAssembler::Label
& previousLabel
, MacroAssembler::Label currentLabel
, Node
* context
)
149 size_t prefixLength
= strlen(prefix
);
150 int amountOfNodeWhiteSpace
;
152 amountOfNodeWhiteSpace
= 0;
154 amountOfNodeWhiteSpace
= Graph::amountOfNodeWhiteSpace(context
);
155 OwnArrayPtr
<char> prefixBuffer
= adoptArrayPtr(new char[prefixLength
+ amountOfNodeWhiteSpace
+ 1]);
156 strcpy(prefixBuffer
.get(), prefix
);
157 for (int i
= 0; i
< amountOfNodeWhiteSpace
; ++i
)
158 prefixBuffer
[i
+ prefixLength
] = ' ';
159 prefixBuffer
[prefixLength
+ amountOfNodeWhiteSpace
] = 0;
161 CodeLocationLabel start
= linkBuffer
.locationOf(previousLabel
);
162 CodeLocationLabel end
= linkBuffer
.locationOf(currentLabel
);
163 previousLabel
= currentLabel
;
164 ASSERT(bitwise_cast
<uintptr_t>(end
.executableAddress()) >= bitwise_cast
<uintptr_t>(start
.executableAddress()));
165 disassemble(start
, bitwise_cast
<uintptr_t>(end
.executableAddress()) - bitwise_cast
<uintptr_t>(start
.executableAddress()), prefixBuffer
.get(), out
);
168 } } // namespace JSC::DFG
170 #endif // ENABLE(DFG_JIT)