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 "JITDisassembler.h"
31 #include "CodeBlock.h"
32 #include "CodeBlockWithJITType.h"
34 #include "JSCInlines.h"
35 #include "LinkBuffer.h"
36 #include <wtf/StringPrintStream.h>
40 JITDisassembler::JITDisassembler(CodeBlock
*codeBlock
)
41 : m_codeBlock(codeBlock
)
42 , m_labelForBytecodeIndexInMainPath(codeBlock
->instructionCount())
43 , m_labelForBytecodeIndexInSlowPath(codeBlock
->instructionCount())
47 JITDisassembler::~JITDisassembler()
51 void JITDisassembler::dump(PrintStream
& out
, LinkBuffer
& linkBuffer
)
53 dumpHeader(out
, linkBuffer
);
54 dumpDisassembly(out
, linkBuffer
, m_startOfCode
, m_labelForBytecodeIndexInMainPath
[0]);
56 dumpForInstructions(out
, linkBuffer
, " ", m_labelForBytecodeIndexInMainPath
, firstSlowLabel());
57 out
.print(" (End Of Main Path)\n");
58 dumpForInstructions(out
, linkBuffer
, " (S) ", m_labelForBytecodeIndexInSlowPath
, m_endOfSlowPath
);
59 out
.print(" (End Of Slow Path)\n");
61 dumpDisassembly(out
, linkBuffer
, m_endOfSlowPath
, m_endOfCode
);
64 void JITDisassembler::dump(LinkBuffer
& linkBuffer
)
66 dump(WTF::dataFile(), linkBuffer
);
69 void JITDisassembler::reportToProfiler(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
)
71 StringPrintStream out
;
73 dumpHeader(out
, linkBuffer
);
74 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
76 dumpDisassembly(out
, linkBuffer
, m_startOfCode
, m_labelForBytecodeIndexInMainPath
[0]);
77 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
79 reportInstructions(compilation
, linkBuffer
, " ", m_labelForBytecodeIndexInMainPath
, firstSlowLabel());
80 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Main Path)\n"));
81 reportInstructions(compilation
, linkBuffer
, " (S) ", m_labelForBytecodeIndexInSlowPath
, m_endOfSlowPath
);
82 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Slow Path)\n"));
84 dumpDisassembly(out
, linkBuffer
, m_endOfSlowPath
, m_endOfCode
);
85 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
88 void JITDisassembler::dumpHeader(PrintStream
& out
, LinkBuffer
& linkBuffer
)
90 out
.print("Generated Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock
, JITCode::BaselineJIT
), ", instruction count = ", m_codeBlock
->instructionCount(), "\n");
91 out
.print(" Source: ", m_codeBlock
->sourceCodeOnOneLine(), "\n");
92 out
.print(" Code at [", RawPointer(linkBuffer
.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer
.debugAddress()) + linkBuffer
.size()), "):\n");
95 MacroAssembler::Label
JITDisassembler::firstSlowLabel()
97 MacroAssembler::Label firstSlowLabel
;
98 for (unsigned i
= 0; i
< m_labelForBytecodeIndexInSlowPath
.size(); ++i
) {
99 if (m_labelForBytecodeIndexInSlowPath
[i
].isSet()) {
100 firstSlowLabel
= m_labelForBytecodeIndexInSlowPath
[i
];
104 return firstSlowLabel
.isSet() ? firstSlowLabel
: m_endOfSlowPath
;
107 Vector
<JITDisassembler::DumpedOp
> JITDisassembler::dumpVectorForInstructions(LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
109 StringPrintStream out
;
110 Vector
<DumpedOp
> result
;
112 for (unsigned i
= 0; i
< labels
.size();) {
113 if (!labels
[i
].isSet()) {
118 result
.append(DumpedOp());
119 result
.last().index
= i
;
121 m_codeBlock
->dumpBytecode(out
, i
);
122 for (unsigned nextIndex
= i
+ 1; ; nextIndex
++) {
123 if (nextIndex
>= labels
.size()) {
124 dumpDisassembly(out
, linkBuffer
, labels
[i
], endLabel
);
125 result
.last().disassembly
= out
.toCString();
128 if (labels
[nextIndex
].isSet()) {
129 dumpDisassembly(out
, linkBuffer
, labels
[i
], labels
[nextIndex
]);
130 result
.last().disassembly
= out
.toCString();
140 void JITDisassembler::dumpForInstructions(PrintStream
& out
, LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
142 Vector
<DumpedOp
> dumpedOps
= dumpVectorForInstructions(linkBuffer
, prefix
, labels
, endLabel
);
144 for (unsigned i
= 0; i
< dumpedOps
.size(); ++i
)
145 out
.print(dumpedOps
[i
].disassembly
);
148 void JITDisassembler::reportInstructions(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
150 Vector
<DumpedOp
> dumpedOps
= dumpVectorForInstructions(linkBuffer
, prefix
, labels
, endLabel
);
152 for (unsigned i
= 0; i
< dumpedOps
.size(); ++i
) {
153 compilation
->addDescription(
154 Profiler::CompiledBytecode(
155 Profiler::OriginStack(Profiler::Origin(compilation
->bytecodes(), dumpedOps
[i
].index
)),
156 dumpedOps
[i
].disassembly
));
160 void JITDisassembler::dumpDisassembly(PrintStream
& out
, LinkBuffer
& linkBuffer
, MacroAssembler::Label from
, MacroAssembler::Label to
)
162 CodeLocationLabel fromLocation
= linkBuffer
.locationOf(from
);
163 CodeLocationLabel toLocation
= linkBuffer
.locationOf(to
);
164 disassemble(fromLocation
, bitwise_cast
<uintptr_t>(toLocation
.executableAddress()) - bitwise_cast
<uintptr_t>(fromLocation
.executableAddress()), " ", out
);
169 #endif // ENABLE(JIT)