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 |