OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/debug.h" | 9 #include "src/debug.h" |
10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
11 #include "src/disasm.h" | 11 #include "src/disasm.h" |
12 #include "src/disassembler.h" | 12 #include "src/disassembler.h" |
13 #include "src/macro-assembler.h" | 13 #include "src/macro-assembler.h" |
14 #include "src/serialize.h" | 14 #include "src/serialize.h" |
15 #include "src/string-stream.h" | 15 #include "src/string-stream.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
20 #ifdef ENABLE_DISASSEMBLER | 20 #ifdef ENABLE_DISASSEMBLER |
21 | 21 |
22 void Disassembler::Dump(FILE* f, byte* begin, byte* end) { | |
23 for (byte* pc = begin; pc < end; pc++) { | |
24 if (f == NULL) { | |
25 PrintF("%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", | |
26 reinterpret_cast<intptr_t>(pc), | |
27 pc - begin, | |
28 *pc); | |
29 } else { | |
30 PrintF(f, "%" V8PRIxPTR " %4" V8PRIdPTR " %02x\n", | |
31 reinterpret_cast<uintptr_t>(pc), pc - begin, *pc); | |
32 } | |
33 } | |
34 } | |
35 | |
36 | |
37 class V8NameConverter: public disasm::NameConverter { | 22 class V8NameConverter: public disasm::NameConverter { |
38 public: | 23 public: |
39 explicit V8NameConverter(Code* code) : code_(code) {} | 24 explicit V8NameConverter(Code* code) : code_(code) {} |
40 virtual const char* NameOfAddress(byte* pc) const; | 25 virtual const char* NameOfAddress(byte* pc) const; |
41 virtual const char* NameInCode(byte* addr) const; | 26 virtual const char* NameInCode(byte* addr) const; |
42 Code* code() const { return code_; } | 27 Code* code() const { return code_; } |
43 private: | 28 private: |
44 Code* code_; | 29 Code* code_; |
45 | 30 |
46 EmbeddedVector<char, 128> v8_buffer_; | 31 EmbeddedVector<char, 128> v8_buffer_; |
(...skipping 20 matching lines...) Expand all Loading... |
67 } | 52 } |
68 | 53 |
69 | 54 |
70 const char* V8NameConverter::NameInCode(byte* addr) const { | 55 const char* V8NameConverter::NameInCode(byte* addr) const { |
71 // The V8NameConverter is used for well known code, so we can "safely" | 56 // The V8NameConverter is used for well known code, so we can "safely" |
72 // dereference pointers in generated code. | 57 // dereference pointers in generated code. |
73 return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : ""; | 58 return (code_ != NULL) ? reinterpret_cast<const char*>(addr) : ""; |
74 } | 59 } |
75 | 60 |
76 | 61 |
77 static void DumpBuffer(FILE* f, StringBuilder* out) { | 62 static void DumpBuffer(OStream* os, StringBuilder* out) { |
78 if (f == NULL) { | 63 (*os) << out->Finalize() << endl; |
79 PrintF("%s\n", out->Finalize()); | |
80 } else { | |
81 PrintF(f, "%s\n", out->Finalize()); | |
82 } | |
83 out->Reset(); | 64 out->Reset(); |
84 } | 65 } |
85 | 66 |
86 | 67 |
87 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; | 68 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; |
88 static const int kRelocInfoPosition = 57; | 69 static const int kRelocInfoPosition = 57; |
89 | 70 |
90 static int DecodeIt(Isolate* isolate, | 71 static int DecodeIt(Isolate* isolate, OStream* os, |
91 FILE* f, | 72 const V8NameConverter& converter, byte* begin, byte* end) { |
92 const V8NameConverter& converter, | |
93 byte* begin, | |
94 byte* end) { | |
95 SealHandleScope shs(isolate); | 73 SealHandleScope shs(isolate); |
96 DisallowHeapAllocation no_alloc; | 74 DisallowHeapAllocation no_alloc; |
97 ExternalReferenceEncoder ref_encoder(isolate); | 75 ExternalReferenceEncoder ref_encoder(isolate); |
98 | 76 |
99 v8::internal::EmbeddedVector<char, 128> decode_buffer; | 77 v8::internal::EmbeddedVector<char, 128> decode_buffer; |
100 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; | 78 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; |
101 StringBuilder out(out_buffer.start(), out_buffer.length()); | 79 StringBuilder out(out_buffer.start(), out_buffer.length()); |
102 byte* pc = begin; | 80 byte* pc = begin; |
103 disasm::Disassembler d(converter); | 81 disasm::Disassembler d(converter); |
104 RelocIterator* it = NULL; | 82 RelocIterator* it = NULL; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 rmodes.Add(it->rinfo()->rmode()); | 135 rmodes.Add(it->rinfo()->rmode()); |
158 datas.Add(it->rinfo()->data()); | 136 datas.Add(it->rinfo()->data()); |
159 } | 137 } |
160 it->next(); | 138 it->next(); |
161 } | 139 } |
162 } | 140 } |
163 | 141 |
164 // Comments. | 142 // Comments. |
165 for (int i = 0; i < comments.length(); i++) { | 143 for (int i = 0; i < comments.length(); i++) { |
166 out.AddFormatted(" %s", comments[i]); | 144 out.AddFormatted(" %s", comments[i]); |
167 DumpBuffer(f, &out); | 145 DumpBuffer(os, &out); |
168 } | 146 } |
169 | 147 |
170 // Instruction address and instruction offset. | 148 // Instruction address and instruction offset. |
171 out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin); | 149 out.AddFormatted("%p %4d ", prev_pc, prev_pc - begin); |
172 | 150 |
173 // Instruction. | 151 // Instruction. |
174 out.AddFormatted("%s", decode_buffer.start()); | 152 out.AddFormatted("%s", decode_buffer.start()); |
175 | 153 |
176 // Print all the reloc info for this instruction which are not comments. | 154 // Print all the reloc info for this instruction which are not comments. |
177 for (int i = 0; i < pcs.length(); i++) { | 155 for (int i = 0; i < pcs.length(); i++) { |
178 // Put together the reloc info | 156 // Put together the reloc info |
179 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); | 157 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); |
180 | 158 |
181 // Indent the printing of the reloc info. | 159 // Indent the printing of the reloc info. |
182 if (i == 0) { | 160 if (i == 0) { |
183 // The first reloc info is printed after the disassembled instruction. | 161 // The first reloc info is printed after the disassembled instruction. |
184 out.AddPadding(' ', kRelocInfoPosition - out.position()); | 162 out.AddPadding(' ', kRelocInfoPosition - out.position()); |
185 } else { | 163 } else { |
186 // Additional reloc infos are printed on separate lines. | 164 // Additional reloc infos are printed on separate lines. |
187 DumpBuffer(f, &out); | 165 DumpBuffer(os, &out); |
188 out.AddPadding(' ', kRelocInfoPosition); | 166 out.AddPadding(' ', kRelocInfoPosition); |
189 } | 167 } |
190 | 168 |
191 RelocInfo::Mode rmode = relocinfo.rmode(); | 169 RelocInfo::Mode rmode = relocinfo.rmode(); |
192 if (RelocInfo::IsPosition(rmode)) { | 170 if (RelocInfo::IsPosition(rmode)) { |
193 if (RelocInfo::IsStatementPosition(rmode)) { | 171 if (RelocInfo::IsStatementPosition(rmode)) { |
194 out.AddFormatted(" ;; debug: statement %d", relocinfo.data()); | 172 out.AddFormatted(" ;; debug: statement %d", relocinfo.data()); |
195 } else { | 173 } else { |
196 out.AddFormatted(" ;; debug: position %d", relocinfo.data()); | 174 out.AddFormatted(" ;; debug: position %d", relocinfo.data()); |
197 } | 175 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 } else { | 249 } else { |
272 out.AddFormatted(" ;; lazy deoptimization bailout %d", id); | 250 out.AddFormatted(" ;; lazy deoptimization bailout %d", id); |
273 } | 251 } |
274 } else { | 252 } else { |
275 out.AddFormatted(" ;; deoptimization bailout %d", id); | 253 out.AddFormatted(" ;; deoptimization bailout %d", id); |
276 } | 254 } |
277 } else { | 255 } else { |
278 out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); | 256 out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); |
279 } | 257 } |
280 } | 258 } |
281 DumpBuffer(f, &out); | 259 DumpBuffer(os, &out); |
282 } | 260 } |
283 | 261 |
284 // Emit comments following the last instruction (if any). | 262 // Emit comments following the last instruction (if any). |
285 if (it != NULL) { | 263 if (it != NULL) { |
286 for ( ; !it->done(); it->next()) { | 264 for ( ; !it->done(); it->next()) { |
287 if (RelocInfo::IsComment(it->rinfo()->rmode())) { | 265 if (RelocInfo::IsComment(it->rinfo()->rmode())) { |
288 out.AddFormatted(" %s", | 266 out.AddFormatted(" %s", |
289 reinterpret_cast<const char*>(it->rinfo()->data())); | 267 reinterpret_cast<const char*>(it->rinfo()->data())); |
290 DumpBuffer(f, &out); | 268 DumpBuffer(os, &out); |
291 } | 269 } |
292 } | 270 } |
293 } | 271 } |
294 | 272 |
295 delete it; | 273 delete it; |
296 return static_cast<int>(pc - begin); | 274 return static_cast<int>(pc - begin); |
297 } | 275 } |
298 | 276 |
299 | 277 |
300 int Disassembler::Decode(Isolate* isolate, FILE* f, byte* begin, byte* end) { | 278 int Disassembler::Decode(Isolate* isolate, OStream* os, byte* begin, byte* end, |
301 V8NameConverter defaultConverter(NULL); | 279 Code* code) { |
302 return DecodeIt(isolate, f, defaultConverter, begin, end); | |
303 } | |
304 | |
305 | |
306 // Called by Code::CodePrint. | |
307 void Disassembler::Decode(FILE* f, Code* code) { | |
308 Isolate* isolate = code->GetIsolate(); | |
309 int decode_size = code->is_crankshafted() | |
310 ? static_cast<int>(code->safepoint_table_offset()) | |
311 : code->instruction_size(); | |
312 // If there might be a back edge table, stop before reaching it. | |
313 if (code->kind() == Code::FUNCTION) { | |
314 decode_size = | |
315 Min(decode_size, static_cast<int>(code->back_edge_table_offset())); | |
316 } | |
317 | |
318 byte* begin = code->instruction_start(); | |
319 byte* end = begin + decode_size; | |
320 V8NameConverter v8NameConverter(code); | 280 V8NameConverter v8NameConverter(code); |
321 DecodeIt(isolate, f, v8NameConverter, begin, end); | 281 return DecodeIt(isolate, os, v8NameConverter, begin, end); |
322 } | 282 } |
323 | 283 |
324 #else // ENABLE_DISASSEMBLER | 284 #else // ENABLE_DISASSEMBLER |
325 | 285 |
326 void Disassembler::Dump(FILE* f, byte* begin, byte* end) {} | 286 int Disassembler::Decode(Isolate* isolate, OStream* os, byte* begin, byte* end, |
327 int Disassembler::Decode(Isolate* isolate, FILE* f, byte* begin, byte* end) { | 287 Code* code) { |
328 return 0; | 288 return 0; |
329 } | 289 } |
330 | 290 |
331 | |
332 void Disassembler::Decode(FILE* f, Code* code) {} | |
333 | |
334 #endif // ENABLE_DISASSEMBLER | 291 #endif // ENABLE_DISASSEMBLER |
335 | 292 |
336 } } // namespace v8::internal | 293 } } // namespace v8::internal |
OLD | NEW |