| 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/disassembler.h" | 5 #include "src/disassembler.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/assembler-inl.h" | 9 #include "src/assembler-inl.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 | 67 |
| 68 static void DumpBuffer(std::ostream* os, StringBuilder* out) { | 68 static void DumpBuffer(std::ostream* os, StringBuilder* out) { |
| 69 (*os) << out->Finalize() << std::endl; | 69 (*os) << out->Finalize() << std::endl; |
| 70 out->Reset(); | 70 out->Reset(); |
| 71 } | 71 } |
| 72 | 72 |
| 73 | 73 |
| 74 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; | 74 static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength; |
| 75 static const int kRelocInfoPosition = 57; | 75 static const int kRelocInfoPosition = 57; |
| 76 | 76 |
| 77 static void PrintRelocInfo(StringBuilder* out, Isolate* isolate, | |
| 78 const ExternalReferenceEncoder& ref_encoder, | |
| 79 std::ostream* os, RelocInfo* relocinfo, | |
| 80 bool first_reloc_info = true) { | |
| 81 // Indent the printing of the reloc info. | |
| 82 if (first_reloc_info) { | |
| 83 // The first reloc info is printed after the disassembled instruction. | |
| 84 out->AddPadding(' ', kRelocInfoPosition - out->position()); | |
| 85 } else { | |
| 86 // Additional reloc infos are printed on separate lines. | |
| 87 DumpBuffer(os, out); | |
| 88 out->AddPadding(' ', kRelocInfoPosition); | |
| 89 } | |
| 90 | |
| 91 RelocInfo::Mode rmode = relocinfo->rmode(); | |
| 92 if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) { | |
| 93 out->AddFormatted(" ;; debug: deopt position, script offset '%d'", | |
| 94 static_cast<int>(relocinfo->data())); | |
| 95 } else if (rmode == RelocInfo::DEOPT_INLINING_ID) { | |
| 96 out->AddFormatted(" ;; debug: deopt position, inlining id '%d'", | |
| 97 static_cast<int>(relocinfo->data())); | |
| 98 } else if (rmode == RelocInfo::DEOPT_REASON) { | |
| 99 DeoptimizeReason reason = static_cast<DeoptimizeReason>(relocinfo->data()); | |
| 100 out->AddFormatted(" ;; debug: deopt reason '%s'", | |
| 101 DeoptimizeReasonToString(reason)); | |
| 102 } else if (rmode == RelocInfo::DEOPT_ID) { | |
| 103 out->AddFormatted(" ;; debug: deopt index %d", | |
| 104 static_cast<int>(relocinfo->data())); | |
| 105 } else if (rmode == RelocInfo::EMBEDDED_OBJECT) { | |
| 106 HeapStringAllocator allocator; | |
| 107 StringStream accumulator(&allocator); | |
| 108 relocinfo->target_object()->ShortPrint(&accumulator); | |
| 109 std::unique_ptr<char[]> obj_name = accumulator.ToCString(); | |
| 110 out->AddFormatted(" ;; object: %s", obj_name.get()); | |
| 111 } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { | |
| 112 const char* reference_name = ref_encoder.NameOfAddress( | |
| 113 isolate, relocinfo->target_external_reference()); | |
| 114 out->AddFormatted(" ;; external reference (%s)", reference_name); | |
| 115 } else if (RelocInfo::IsCodeTarget(rmode)) { | |
| 116 out->AddFormatted(" ;; code:"); | |
| 117 Code* code = Code::GetCodeFromTargetAddress(relocinfo->target_address()); | |
| 118 Code::Kind kind = code->kind(); | |
| 119 if (code->is_inline_cache_stub()) { | |
| 120 out->AddFormatted(" %s", Code::Kind2String(kind)); | |
| 121 if (kind == Code::BINARY_OP_IC || kind == Code::TO_BOOLEAN_IC || | |
| 122 kind == Code::COMPARE_IC) { | |
| 123 InlineCacheState ic_state = IC::StateFromCode(code); | |
| 124 out->AddFormatted(" %s", Code::ICState2String(ic_state)); | |
| 125 } | |
| 126 } else if (kind == Code::STUB || kind == Code::HANDLER) { | |
| 127 // Get the STUB key and extract major and minor key. | |
| 128 uint32_t key = code->stub_key(); | |
| 129 uint32_t minor_key = CodeStub::MinorKeyFromKey(key); | |
| 130 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | |
| 131 DCHECK(major_key == CodeStub::MajorKeyFromKey(key)); | |
| 132 out->AddFormatted(" %s, %s, ", Code::Kind2String(kind), | |
| 133 CodeStub::MajorName(major_key)); | |
| 134 out->AddFormatted("minor: %d", minor_key); | |
| 135 } else { | |
| 136 out->AddFormatted(" %s", Code::Kind2String(kind)); | |
| 137 } | |
| 138 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { | |
| 139 out->AddFormatted(" (id = %d)", static_cast<int>(relocinfo->data())); | |
| 140 } | |
| 141 } else if (RelocInfo::IsRuntimeEntry(rmode) && | |
| 142 isolate->deoptimizer_data() != nullptr) { | |
| 143 // A runtime entry reloinfo might be a deoptimization bailout-> | |
| 144 Address addr = relocinfo->target_address(); | |
| 145 int id = | |
| 146 Deoptimizer::GetDeoptimizationId(isolate, addr, Deoptimizer::EAGER); | |
| 147 if (id == Deoptimizer::kNotDeoptimizationEntry) { | |
| 148 id = Deoptimizer::GetDeoptimizationId(isolate, addr, Deoptimizer::LAZY); | |
| 149 if (id == Deoptimizer::kNotDeoptimizationEntry) { | |
| 150 id = Deoptimizer::GetDeoptimizationId(isolate, addr, Deoptimizer::SOFT); | |
| 151 if (id == Deoptimizer::kNotDeoptimizationEntry) { | |
| 152 out->AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); | |
| 153 } else { | |
| 154 out->AddFormatted(" ;; soft deoptimization bailout %d", id); | |
| 155 } | |
| 156 } else { | |
| 157 out->AddFormatted(" ;; lazy deoptimization bailout %d", id); | |
| 158 } | |
| 159 } else { | |
| 160 out->AddFormatted(" ;; deoptimization bailout %d", id); | |
| 161 } | |
| 162 } else { | |
| 163 out->AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 static int DecodeIt(Isolate* isolate, std::ostream* os, | 77 static int DecodeIt(Isolate* isolate, std::ostream* os, |
| 168 const V8NameConverter& converter, byte* begin, byte* end) { | 78 const V8NameConverter& converter, byte* begin, byte* end) { |
| 169 SealHandleScope shs(isolate); | 79 SealHandleScope shs(isolate); |
| 170 DisallowHeapAllocation no_alloc; | 80 DisallowHeapAllocation no_alloc; |
| 171 ExternalReferenceEncoder ref_encoder(isolate); | 81 ExternalReferenceEncoder ref_encoder(isolate); |
| 172 | 82 |
| 173 v8::internal::EmbeddedVector<char, 128> decode_buffer; | 83 v8::internal::EmbeddedVector<char, 128> decode_buffer; |
| 174 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; | 84 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; |
| 175 StringBuilder out(out_buffer.start(), out_buffer.length()); | 85 StringBuilder out(out_buffer.start(), out_buffer.length()); |
| 176 byte* pc = begin; | 86 byte* pc = begin; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 prev_pc - begin); | 155 prev_pc - begin); |
| 246 | 156 |
| 247 // Instruction. | 157 // Instruction. |
| 248 out.AddFormatted("%s", decode_buffer.start()); | 158 out.AddFormatted("%s", decode_buffer.start()); |
| 249 | 159 |
| 250 // Print all the reloc info for this instruction which are not comments. | 160 // Print all the reloc info for this instruction which are not comments. |
| 251 for (int i = 0; i < pcs.length(); i++) { | 161 for (int i = 0; i < pcs.length(); i++) { |
| 252 // Put together the reloc info | 162 // Put together the reloc info |
| 253 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); | 163 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); |
| 254 | 164 |
| 255 bool first_reloc_info = (i == 0); | 165 // Indent the printing of the reloc info. |
| 256 PrintRelocInfo(&out, isolate, ref_encoder, os, &relocinfo, | 166 if (i == 0) { |
| 257 first_reloc_info); | 167 // The first reloc info is printed after the disassembled instruction. |
| 258 } | 168 out.AddPadding(' ', kRelocInfoPosition - out.position()); |
| 169 } else { |
| 170 // Additional reloc infos are printed on separate lines. |
| 171 DumpBuffer(os, &out); |
| 172 out.AddPadding(' ', kRelocInfoPosition); |
| 173 } |
| 259 | 174 |
| 260 // If this is a constant pool load and we haven't found any RelocInfo | 175 RelocInfo::Mode rmode = relocinfo.rmode(); |
| 261 // already, check if we can find some RelocInfo for the target address in | 176 if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) { |
| 262 // the constant pool. | 177 out.AddFormatted(" ;; debug: deopt position, script offset '%d'", |
| 263 if (pcs.is_empty() && converter.code() != nullptr) { | 178 static_cast<int>(relocinfo.data())); |
| 264 RelocInfo dummy_rinfo(prev_pc, RelocInfo::NONE32, 0, nullptr); | 179 } else if (rmode == RelocInfo::DEOPT_INLINING_ID) { |
| 265 if (dummy_rinfo.IsInConstantPool()) { | 180 out.AddFormatted(" ;; debug: deopt position, inlining id '%d'", |
| 266 byte* constant_pool_entry_address = | 181 static_cast<int>(relocinfo.data())); |
| 267 dummy_rinfo.constant_pool_entry_address(); | 182 } else if (rmode == RelocInfo::DEOPT_REASON) { |
| 268 RelocIterator* it = new RelocIterator(converter.code()); | 183 DeoptimizeReason reason = |
| 269 while (!it->done()) { | 184 static_cast<DeoptimizeReason>(relocinfo.data()); |
| 270 if (it->rinfo()->IsInConstantPool() && | 185 out.AddFormatted(" ;; debug: deopt reason '%s'", |
| 271 (it->rinfo()->constant_pool_entry_address() == | 186 DeoptimizeReasonToString(reason)); |
| 272 constant_pool_entry_address)) { | 187 } else if (rmode == RelocInfo::DEOPT_ID) { |
| 273 PrintRelocInfo(&out, isolate, ref_encoder, os, it->rinfo()); | 188 out.AddFormatted(" ;; debug: deopt index %d", |
| 274 break; | 189 static_cast<int>(relocinfo.data())); |
| 190 } else if (rmode == RelocInfo::EMBEDDED_OBJECT) { |
| 191 HeapStringAllocator allocator; |
| 192 StringStream accumulator(&allocator); |
| 193 relocinfo.target_object()->ShortPrint(&accumulator); |
| 194 std::unique_ptr<char[]> obj_name = accumulator.ToCString(); |
| 195 out.AddFormatted(" ;; object: %s", obj_name.get()); |
| 196 } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { |
| 197 const char* reference_name = ref_encoder.NameOfAddress( |
| 198 isolate, relocinfo.target_external_reference()); |
| 199 out.AddFormatted(" ;; external reference (%s)", reference_name); |
| 200 } else if (RelocInfo::IsCodeTarget(rmode)) { |
| 201 out.AddFormatted(" ;; code:"); |
| 202 Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address()); |
| 203 Code::Kind kind = code->kind(); |
| 204 if (code->is_inline_cache_stub()) { |
| 205 out.AddFormatted(" %s", Code::Kind2String(kind)); |
| 206 if (kind == Code::BINARY_OP_IC || kind == Code::TO_BOOLEAN_IC || |
| 207 kind == Code::COMPARE_IC) { |
| 208 InlineCacheState ic_state = IC::StateFromCode(code); |
| 209 out.AddFormatted(" %s", Code::ICState2String(ic_state)); |
| 275 } | 210 } |
| 276 it->next(); | 211 } else if (kind == Code::STUB || kind == Code::HANDLER) { |
| 212 // Get the STUB key and extract major and minor key. |
| 213 uint32_t key = code->stub_key(); |
| 214 uint32_t minor_key = CodeStub::MinorKeyFromKey(key); |
| 215 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 216 DCHECK(major_key == CodeStub::MajorKeyFromKey(key)); |
| 217 out.AddFormatted(" %s, %s, ", Code::Kind2String(kind), |
| 218 CodeStub::MajorName(major_key)); |
| 219 out.AddFormatted("minor: %d", minor_key); |
| 220 } else { |
| 221 out.AddFormatted(" %s", Code::Kind2String(kind)); |
| 277 } | 222 } |
| 223 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { |
| 224 out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data())); |
| 225 } |
| 226 } else if (RelocInfo::IsRuntimeEntry(rmode) && |
| 227 isolate->deoptimizer_data() != NULL) { |
| 228 // A runtime entry reloinfo might be a deoptimization bailout. |
| 229 Address addr = relocinfo.target_address(); |
| 230 int id = Deoptimizer::GetDeoptimizationId(isolate, |
| 231 addr, |
| 232 Deoptimizer::EAGER); |
| 233 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 234 id = Deoptimizer::GetDeoptimizationId(isolate, |
| 235 addr, |
| 236 Deoptimizer::LAZY); |
| 237 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 238 id = Deoptimizer::GetDeoptimizationId(isolate, |
| 239 addr, |
| 240 Deoptimizer::SOFT); |
| 241 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 242 out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); |
| 243 } else { |
| 244 out.AddFormatted(" ;; soft deoptimization bailout %d", id); |
| 245 } |
| 246 } else { |
| 247 out.AddFormatted(" ;; lazy deoptimization bailout %d", id); |
| 248 } |
| 249 } else { |
| 250 out.AddFormatted(" ;; deoptimization bailout %d", id); |
| 251 } |
| 252 } else { |
| 253 out.AddFormatted(" ;; %s", RelocInfo::RelocModeName(rmode)); |
| 278 } | 254 } |
| 279 } | 255 } |
| 280 | |
| 281 DumpBuffer(os, &out); | 256 DumpBuffer(os, &out); |
| 282 } | 257 } |
| 283 | 258 |
| 284 // Emit comments following the last instruction (if any). | 259 // Emit comments following the last instruction (if any). |
| 285 if (it != NULL) { | 260 if (it != NULL) { |
| 286 for ( ; !it->done(); it->next()) { | 261 for ( ; !it->done(); it->next()) { |
| 287 if (RelocInfo::IsComment(it->rinfo()->rmode())) { | 262 if (RelocInfo::IsComment(it->rinfo()->rmode())) { |
| 288 out.AddFormatted(" %s", | 263 out.AddFormatted(" %s", |
| 289 reinterpret_cast<const char*>(it->rinfo()->data())); | 264 reinterpret_cast<const char*>(it->rinfo()->data())); |
| 290 DumpBuffer(os, &out); | 265 DumpBuffer(os, &out); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 307 | 282 |
| 308 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, | 283 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, |
| 309 byte* end, Code* code) { | 284 byte* end, Code* code) { |
| 310 return 0; | 285 return 0; |
| 311 } | 286 } |
| 312 | 287 |
| 313 #endif // ENABLE_DISASSEMBLER | 288 #endif // ENABLE_DISASSEMBLER |
| 314 | 289 |
| 315 } // namespace internal | 290 } // namespace internal |
| 316 } // namespace v8 | 291 } // namespace v8 |
| OLD | NEW |