| 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 |