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 | |
77 static int DecodeIt(Isolate* isolate, std::ostream* os, | 167 static int DecodeIt(Isolate* isolate, std::ostream* os, |
78 const V8NameConverter& converter, byte* begin, byte* end) { | 168 const V8NameConverter& converter, byte* begin, byte* end) { |
79 SealHandleScope shs(isolate); | 169 SealHandleScope shs(isolate); |
80 DisallowHeapAllocation no_alloc; | 170 DisallowHeapAllocation no_alloc; |
81 ExternalReferenceEncoder ref_encoder(isolate); | 171 ExternalReferenceEncoder ref_encoder(isolate); |
82 | 172 |
83 v8::internal::EmbeddedVector<char, 128> decode_buffer; | 173 v8::internal::EmbeddedVector<char, 128> decode_buffer; |
84 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; | 174 v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer; |
85 StringBuilder out(out_buffer.start(), out_buffer.length()); | 175 StringBuilder out(out_buffer.start(), out_buffer.length()); |
86 byte* pc = begin; | 176 byte* pc = begin; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 prev_pc - begin); | 245 prev_pc - begin); |
156 | 246 |
157 // Instruction. | 247 // Instruction. |
158 out.AddFormatted("%s", decode_buffer.start()); | 248 out.AddFormatted("%s", decode_buffer.start()); |
159 | 249 |
160 // Print all the reloc info for this instruction which are not comments. | 250 // Print all the reloc info for this instruction which are not comments. |
161 for (int i = 0; i < pcs.length(); i++) { | 251 for (int i = 0; i < pcs.length(); i++) { |
162 // Put together the reloc info | 252 // Put together the reloc info |
163 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); | 253 RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); |
164 | 254 |
165 // Indent the printing of the reloc info. | 255 bool first_reloc_info = (i == 0); |
166 if (i == 0) { | 256 PrintRelocInfo(&out, isolate, ref_encoder, os, &relocinfo, |
167 // The first reloc info is printed after the disassembled instruction. | 257 first_reloc_info); |
168 out.AddPadding(' ', kRelocInfoPosition - out.position()); | 258 } |
169 } else { | |
170 // Additional reloc infos are printed on separate lines. | |
171 DumpBuffer(os, &out); | |
172 out.AddPadding(' ', kRelocInfoPosition); | |
173 } | |
174 | 259 |
175 RelocInfo::Mode rmode = relocinfo.rmode(); | 260 // If this is a constant pool load and we haven't found any RelocInfo |
176 if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) { | 261 // already, check if we can find some RelocInfo for the target address in |
177 out.AddFormatted(" ;; debug: deopt position, script offset '%d'", | 262 // the constant pool. |
178 static_cast<int>(relocinfo.data())); | 263 if (pcs.is_empty() && converter.code() != nullptr) { |
179 } else if (rmode == RelocInfo::DEOPT_INLINING_ID) { | 264 RelocInfo dummy_rinfo(prev_pc, RelocInfo::NONE32, 0, nullptr); |
180 out.AddFormatted(" ;; debug: deopt position, inlining id '%d'", | 265 if (dummy_rinfo.IsInConstantPool()) { |
181 static_cast<int>(relocinfo.data())); | 266 byte* constant_pool_entry_address = |
182 } else if (rmode == RelocInfo::DEOPT_REASON) { | 267 dummy_rinfo.constant_pool_entry_address(); |
183 DeoptimizeReason reason = | 268 RelocIterator* it = new RelocIterator(converter.code()); |
Clemens Hammacher
2017/05/24 10:47:36
This causes a memory leak: http://crbug.com/725714
| |
184 static_cast<DeoptimizeReason>(relocinfo.data()); | 269 while (!it->done()) { |
185 out.AddFormatted(" ;; debug: deopt reason '%s'", | 270 if (it->rinfo()->IsInConstantPool() && |
186 DeoptimizeReasonToString(reason)); | 271 (it->rinfo()->constant_pool_entry_address() == |
187 } else if (rmode == RelocInfo::DEOPT_ID) { | 272 constant_pool_entry_address)) { |
188 out.AddFormatted(" ;; debug: deopt index %d", | 273 PrintRelocInfo(&out, isolate, ref_encoder, os, it->rinfo()); |
189 static_cast<int>(relocinfo.data())); | 274 break; |
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)); | |
210 } | 275 } |
211 } else if (kind == Code::STUB || kind == Code::HANDLER) { | 276 it->next(); |
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)); | |
222 } | 277 } |
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)); | |
254 } | 278 } |
255 } | 279 } |
280 | |
256 DumpBuffer(os, &out); | 281 DumpBuffer(os, &out); |
257 } | 282 } |
258 | 283 |
259 // Emit comments following the last instruction (if any). | 284 // Emit comments following the last instruction (if any). |
260 if (it != NULL) { | 285 if (it != NULL) { |
261 for ( ; !it->done(); it->next()) { | 286 for ( ; !it->done(); it->next()) { |
262 if (RelocInfo::IsComment(it->rinfo()->rmode())) { | 287 if (RelocInfo::IsComment(it->rinfo()->rmode())) { |
263 out.AddFormatted(" %s", | 288 out.AddFormatted(" %s", |
264 reinterpret_cast<const char*>(it->rinfo()->data())); | 289 reinterpret_cast<const char*>(it->rinfo()->data())); |
265 DumpBuffer(os, &out); | 290 DumpBuffer(os, &out); |
(...skipping 16 matching lines...) Expand all Loading... | |
282 | 307 |
283 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, | 308 int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin, |
284 byte* end, Code* code) { | 309 byte* end, Code* code) { |
285 return 0; | 310 return 0; |
286 } | 311 } |
287 | 312 |
288 #endif // ENABLE_DISASSEMBLER | 313 #endif // ENABLE_DISASSEMBLER |
289 | 314 |
290 } // namespace internal | 315 } // namespace internal |
291 } // namespace v8 | 316 } // namespace v8 |
OLD | NEW |