2 * Copyright (C) 2012 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 <wtf/StringPrintStream.h>
38 JITDisassembler::JITDisassembler(CodeBlock
*codeBlock
)
39 : m_codeBlock(codeBlock
)
40 , m_labelForBytecodeIndexInMainPath(codeBlock
->instructionCount())
41 , m_labelForBytecodeIndexInSlowPath(codeBlock
->instructionCount())
45 JITDisassembler::~JITDisassembler()
49 void JITDisassembler::dump(PrintStream
& out
, LinkBuffer
& linkBuffer
)
51 dumpHeader(out
, linkBuffer
);
52 dumpDisassembly(out
, linkBuffer
, m_startOfCode
, m_labelForBytecodeIndexInMainPath
[0]);
54 dumpForInstructions(out
, linkBuffer
, " ", m_labelForBytecodeIndexInMainPath
, firstSlowLabel());
55 out
.print(" (End Of Main Path)\n");
56 dumpForInstructions(out
, linkBuffer
, " (S) ", m_labelForBytecodeIndexInSlowPath
, m_endOfSlowPath
);
57 out
.print(" (End Of Slow Path)\n");
59 dumpDisassembly(out
, linkBuffer
, m_endOfSlowPath
, m_endOfCode
);
62 void JITDisassembler::dump(LinkBuffer
& linkBuffer
)
64 dump(WTF::dataFile(), linkBuffer
);
67 void JITDisassembler::reportToProfiler(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
)
69 StringPrintStream out
;
71 dumpHeader(out
, linkBuffer
);
72 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
74 dumpDisassembly(out
, linkBuffer
, m_startOfCode
, m_labelForBytecodeIndexInMainPath
[0]);
75 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
77 reportInstructions(compilation
, linkBuffer
, " ", m_labelForBytecodeIndexInMainPath
, firstSlowLabel());
78 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Main Path)\n"));
79 reportInstructions(compilation
, linkBuffer
, " (S) ", m_labelForBytecodeIndexInSlowPath
, m_endOfSlowPath
);
80 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Slow Path)\n"));
82 dumpDisassembly(out
, linkBuffer
, m_endOfSlowPath
, m_endOfCode
);
83 compilation
->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out
.toCString()));
86 void JITDisassembler::dumpHeader(PrintStream
& out
, LinkBuffer
& linkBuffer
)
88 out
.print("Generated Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock
, JITCode::BaselineJIT
), ", instruction count = ", m_codeBlock
->instructionCount(), "\n");
89 out
.print(" Source: ", m_codeBlock
->sourceCodeOnOneLine(), "\n");
90 out
.print(" Code at [", RawPointer(linkBuffer
.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer
.debugAddress()) + linkBuffer
.debugSize()), "):\n");
93 MacroAssembler::Label
JITDisassembler::firstSlowLabel()
95 MacroAssembler::Label firstSlowLabel
;
96 for (unsigned i
= 0; i
< m_labelForBytecodeIndexInSlowPath
.size(); ++i
) {
97 if (m_labelForBytecodeIndexInSlowPath
[i
].isSet()) {
98 firstSlowLabel
= m_labelForBytecodeIndexInSlowPath
[i
];
102 return firstSlowLabel
.isSet() ? firstSlowLabel
: m_endOfSlowPath
;
105 Vector
<JITDisassembler::DumpedOp
> JITDisassembler::dumpVectorForInstructions(LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
107 StringPrintStream out
;
108 Vector
<DumpedOp
> result
;
110 for (unsigned i
= 0; i
< labels
.size();) {
111 if (!labels
[i
].isSet()) {
116 result
.append(DumpedOp());
117 result
.last().index
= i
;
119 m_codeBlock
->dumpBytecode(out
, i
);
120 for (unsigned nextIndex
= i
+ 1; ; nextIndex
++) {
121 if (nextIndex
>= labels
.size()) {
122 dumpDisassembly(out
, linkBuffer
, labels
[i
], endLabel
);
123 result
.last().disassembly
= out
.toCString();
126 if (labels
[nextIndex
].isSet()) {
127 dumpDisassembly(out
, linkBuffer
, labels
[i
], labels
[nextIndex
]);
128 result
.last().disassembly
= out
.toCString();
138 void JITDisassembler::dumpForInstructions(PrintStream
& out
, LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
140 Vector
<DumpedOp
> dumpedOps
= dumpVectorForInstructions(linkBuffer
, prefix
, labels
, endLabel
);
142 for (unsigned i
= 0; i
< dumpedOps
.size(); ++i
)
143 out
.print(dumpedOps
[i
].disassembly
);
146 void JITDisassembler::reportInstructions(Profiler::Compilation
* compilation
, LinkBuffer
& linkBuffer
, const char* prefix
, Vector
<MacroAssembler::Label
>& labels
, MacroAssembler::Label endLabel
)
148 Vector
<DumpedOp
> dumpedOps
= dumpVectorForInstructions(linkBuffer
, prefix
, labels
, endLabel
);
150 for (unsigned i
= 0; i
< dumpedOps
.size(); ++i
) {
151 compilation
->addDescription(
152 Profiler::CompiledBytecode(
153 Profiler::OriginStack(Profiler::Origin(compilation
->bytecodes(), dumpedOps
[i
].index
)),
154 dumpedOps
[i
].disassembly
));
158 void JITDisassembler::dumpDisassembly(PrintStream
& out
, LinkBuffer
& linkBuffer
, MacroAssembler::Label from
, MacroAssembler::Label to
)
160 CodeLocationLabel fromLocation
= linkBuffer
.locationOf(from
);
161 CodeLocationLabel toLocation
= linkBuffer
.locationOf(to
);
162 disassemble(fromLocation
, bitwise_cast
<uintptr_t>(toLocation
.executableAddress()) - bitwise_cast
<uintptr_t>(fromLocation
.executableAddress()), " ", out
);
167 #endif // ENABLE(JIT)