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"
33 #include "DFGJITCode.h"
34 #include "JSCInlines.h"
35 #include "LinkBuffer.h"
36 #include "ProfilerDatabase.h"
37 #include <wtf/StdLibExtras.h>
39 namespace JSC
{ namespace DFG
{
41 Disassembler::Disassembler(Graph
& graph
)
44 m_dumpContext
.graph
= &m_graph
;
45 m_labelForBlockIndex
.resize(graph
.numBlocks());
48 void Disassembler::dump(PrintStream
& out
, LinkBuffer
& linkBuffer
)
50 Vector
<DumpedOp
> ops
= createDumpList(linkBuffer
);
51 for (unsigned i
= 0; i
< ops
.size(); ++i
)
52 out
.print(ops
[i
].text
);
55 void Disassembler::dump(LinkBuffer
& linkBuffer
)
57 dump(WTF::dataFile(), linkBuffer
);
60 void Disassembler::reportToProfiler(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
)
62 Vector
<DumpedOp
> ops
= createDumpList(linkBuffer
);
64 for (unsigned i
= 0; i
< ops
.size(); ++i
) {
65 Profiler::OriginStack stack
;
67 if (ops
[i
].codeOrigin
.isSet())
68 stack
= Profiler::OriginStack(*m_graph
.m_vm
.m_perBytecodeProfiler
, m_graph
.m_codeBlock
, ops
[i
].codeOrigin
);
70 compilation
->addDescription(Profiler::CompiledBytecode(stack
, ops
[i
].text
));
74 void Disassembler::dumpHeader(PrintStream
& out
, LinkBuffer
& linkBuffer
)
76 out
.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph
.m_codeBlock
, JITCode::DFGJIT
), ", instruction count = ", m_graph
.m_codeBlock
->instructionCount(), ":\n");
77 out
.print(" Optimized with execution counter = ", m_graph
.m_profiledBlock
->jitExecuteCounter(), "\n");
78 out
.print(" Code at [", RawPointer(linkBuffer
.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer
.debugAddress()) + linkBuffer
.size()), "):\n");
81 void Disassembler::append(Vector
<Disassembler::DumpedOp
>& result
, StringPrintStream
& out
, CodeOrigin
& previousOrigin
)
83 result
.append(DumpedOp(previousOrigin
, out
.toCString()));
84 previousOrigin
= CodeOrigin();
88 Vector
<Disassembler::DumpedOp
> Disassembler::createDumpList(LinkBuffer
& linkBuffer
)
90 StringPrintStream out
;
91 Vector
<DumpedOp
> result
;
93 CodeOrigin previousOrigin
= CodeOrigin();
94 dumpHeader(out
, linkBuffer
);
95 append(result
, out
, previousOrigin
);
97 m_graph
.m_dominators
.computeIfNecessary(m_graph
);
98 m_graph
.m_naturalLoops
.computeIfNecessary(m_graph
);
100 const char* prefix
= " ";
101 const char* disassemblyPrefix
= " ";
104 MacroAssembler::Label previousLabel
= m_startOfCode
;
105 for (size_t blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
106 BasicBlock
* block
= m_graph
.block(blockIndex
);
109 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_labelForBlockIndex
[blockIndex
], lastNode
);
110 append(result
, out
, previousOrigin
);
111 m_graph
.dumpBlockHeader(out
, prefix
, block
, Graph::DumpLivePhisOnly
, &m_dumpContext
);
112 append(result
, out
, previousOrigin
);
113 Node
* lastNodeForDisassembly
= block
->at(0);
114 for (size_t i
= 0; i
< block
->size(); ++i
) {
115 if (!block
->at(i
)->willHaveCodeGenOrOSR() && !Options::showAllDFGNodes())
117 MacroAssembler::Label currentLabel
;
118 HashMap
<Node
*, MacroAssembler::Label
>::iterator iter
= m_labelForNode
.find(block
->at(i
));
119 if (iter
!= m_labelForNode
.end())
120 currentLabel
= iter
->value
;
122 // Dump the last instruction by using the first label of the next block
123 // as the end point. This case is hit either during peephole compare
124 // optimizations (the Branch won't have its own label) or if we have a
126 if (blockIndex
+ 1 < m_graph
.numBlocks())
127 currentLabel
= m_labelForBlockIndex
[blockIndex
+ 1];
129 currentLabel
= m_endOfMainPath
;
131 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, currentLabel
, lastNodeForDisassembly
);
132 append(result
, out
, previousOrigin
);
133 previousOrigin
= block
->at(i
)->origin
.semantic
;
134 if (m_graph
.dumpCodeOrigin(out
, prefix
, lastNode
, block
->at(i
), &m_dumpContext
)) {
135 append(result
, out
, previousOrigin
);
136 previousOrigin
= block
->at(i
)->origin
.semantic
;
138 m_graph
.dump(out
, prefix
, block
->at(i
), &m_dumpContext
);
139 lastNode
= block
->at(i
);
140 lastNodeForDisassembly
= block
->at(i
);
143 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_endOfMainPath
, lastNode
);
144 append(result
, out
, previousOrigin
);
145 out
.print(prefix
, "(End Of Main Path)\n");
146 append(result
, out
, previousOrigin
);
147 dumpDisassembly(out
, disassemblyPrefix
, linkBuffer
, previousLabel
, m_endOfCode
, 0);
148 append(result
, out
, previousOrigin
);
149 m_dumpContext
.dump(out
, prefix
);
150 append(result
, out
, previousOrigin
);
155 void Disassembler::dumpDisassembly(PrintStream
& out
, const char* prefix
, LinkBuffer
& linkBuffer
, MacroAssembler::Label
& previousLabel
, MacroAssembler::Label currentLabel
, Node
* context
)
157 size_t prefixLength
= strlen(prefix
);
158 int amountOfNodeWhiteSpace
;
160 amountOfNodeWhiteSpace
= 0;
162 amountOfNodeWhiteSpace
= Graph::amountOfNodeWhiteSpace(context
);
163 auto prefixBuffer
= std::make_unique
<char[]>(prefixLength
+ amountOfNodeWhiteSpace
+ 1);
164 strcpy(prefixBuffer
.get(), prefix
);
165 for (int i
= 0; i
< amountOfNodeWhiteSpace
; ++i
)
166 prefixBuffer
[i
+ prefixLength
] = ' ';
167 prefixBuffer
[prefixLength
+ amountOfNodeWhiteSpace
] = 0;
169 CodeLocationLabel start
= linkBuffer
.locationOf(previousLabel
);
170 CodeLocationLabel end
= linkBuffer
.locationOf(currentLabel
);
171 previousLabel
= currentLabel
;
172 ASSERT(bitwise_cast
<uintptr_t>(end
.executableAddress()) >= bitwise_cast
<uintptr_t>(start
.executableAddress()));
173 disassemble(start
, bitwise_cast
<uintptr_t>(end
.executableAddress()) - bitwise_cast
<uintptr_t>(start
.executableAddress()), prefixBuffer
.get(), out
);
176 } } // namespace JSC::DFG
178 #endif // ENABLE(DFG_JIT)