OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/deopt_instructions.h" | 8 #include "vm/deopt_instructions.h" |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 jsarr_.AddValueNull(); // Not a reference to null. | 74 jsarr_.AddValueNull(); // Not a reference to null. |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 void DisassembleToJSONStream::Print(const char* format, ...) { | 79 void DisassembleToJSONStream::Print(const char* format, ...) { |
80 va_list args; | 80 va_list args; |
81 va_start(args, format); | 81 va_start(args, format); |
82 intptr_t len = OS::VSNPrint(NULL, 0, format, args); | 82 intptr_t len = OS::VSNPrint(NULL, 0, format, args); |
83 va_end(args); | 83 va_end(args); |
84 char* p = reinterpret_cast<char*>(malloc(len+1)); | 84 char* p = reinterpret_cast<char*>(malloc(len + 1)); |
85 va_start(args, format); | 85 va_start(args, format); |
86 intptr_t len2 = OS::VSNPrint(p, len, format, args); | 86 intptr_t len2 = OS::VSNPrint(p, len, format, args); |
87 va_end(args); | 87 va_end(args); |
88 ASSERT(len == len2); | 88 ASSERT(len == len2); |
89 for (intptr_t i = 0; i < len; i++) { | 89 for (intptr_t i = 0; i < len; i++) { |
90 if (p[i] == '\n' || p[i] == '\r') { | 90 if (p[i] == '\n' || p[i] == '\r') { |
91 p[i] = ' '; | 91 p[i] = ' '; |
92 } | 92 } |
93 } | 93 } |
94 // Instructions are represented as four consecutive values in a JSON array. | 94 // Instructions are represented as four consecutive values in a JSON array. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 f.Print(" -> %s", name); | 139 f.Print(" -> %s", name); |
140 } | 140 } |
141 } | 141 } |
142 if (!first) { | 142 if (!first) { |
143 f.Print("]\n"); | 143 f.Print("]\n"); |
144 formatter->Print(str); | 144 formatter->Print(str); |
145 } | 145 } |
146 } | 146 } |
147 int instruction_length; | 147 int instruction_length; |
148 Object* object; | 148 Object* object; |
149 DecodeInstruction(hex_buffer, | 149 DecodeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer, |
150 sizeof(hex_buffer), | 150 sizeof(human_buffer), &instruction_length, code, &object, |
151 human_buffer, | 151 pc); |
152 sizeof(human_buffer), | 152 formatter->ConsumeInstruction(code, hex_buffer, sizeof(hex_buffer), |
153 &instruction_length, code, &object, pc); | 153 human_buffer, sizeof(human_buffer), object, |
154 formatter->ConsumeInstruction(code, | |
155 hex_buffer, | |
156 sizeof(hex_buffer), | |
157 human_buffer, | |
158 sizeof(human_buffer), | |
159 object, | |
160 pc); | 154 pc); |
161 pc += instruction_length; | 155 pc += instruction_length; |
162 } | 156 } |
163 } | 157 } |
164 | 158 |
165 | 159 |
166 void Disassembler::DisassembleCodeHelper( | 160 void Disassembler::DisassembleCodeHelper(const char* function_fullname, |
167 const char* function_fullname, const Code& code, bool optimized) { | 161 const Code& code, |
| 162 bool optimized) { |
168 LocalVarDescriptors& var_descriptors = LocalVarDescriptors::Handle(); | 163 LocalVarDescriptors& var_descriptors = LocalVarDescriptors::Handle(); |
169 if (FLAG_print_variable_descriptors) { | 164 if (FLAG_print_variable_descriptors) { |
170 var_descriptors = code.GetLocalVarDescriptors(); | 165 var_descriptors = code.GetLocalVarDescriptors(); |
171 } | 166 } |
172 THR_Print("Code for %sfunction '%s' {\n", | 167 THR_Print("Code for %sfunction '%s' {\n", optimized ? "optimized " : "", |
173 optimized ? "optimized " : "", | |
174 function_fullname); | 168 function_fullname); |
175 code.Disassemble(); | 169 code.Disassemble(); |
176 THR_Print("}\n"); | 170 THR_Print("}\n"); |
177 | 171 |
178 #if defined(TARGET_ARCH_IA32) | 172 #if defined(TARGET_ARCH_IA32) |
179 THR_Print("Pointer offsets for function: {\n"); | 173 THR_Print("Pointer offsets for function: {\n"); |
180 // Pointer offsets are stored in descending order. | 174 // Pointer offsets are stored in descending order. |
181 Object& obj = Object::Handle(); | 175 Object& obj = Object::Handle(); |
182 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { | 176 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { |
183 const uword addr = code.GetPointerOffsetAt(i) + code.PayloadStart(); | 177 const uword addr = code.GetPointerOffsetAt(i) + code.PayloadStart(); |
184 obj = *reinterpret_cast<RawObject**>(addr); | 178 obj = *reinterpret_cast<RawObject**>(addr); |
185 THR_Print(" %d : %#" Px " '%s'\n", | 179 THR_Print(" %d : %#" Px " '%s'\n", code.GetPointerOffsetAt(i), addr, |
186 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 180 obj.ToCString()); |
187 } | 181 } |
188 THR_Print("}\n"); | 182 THR_Print("}\n"); |
189 #else | 183 #else |
190 ASSERT(code.pointer_offsets_length() == 0); | 184 ASSERT(code.pointer_offsets_length() == 0); |
191 #endif | 185 #endif |
192 | 186 |
193 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); | 187 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); |
194 object_pool.DebugPrint(); | 188 object_pool.DebugPrint(); |
195 | 189 |
196 THR_Print("PC Descriptors for function '%s' {\n", function_fullname); | 190 THR_Print("PC Descriptors for function '%s' {\n", function_fullname); |
197 PcDescriptors::PrintHeaderString(); | 191 PcDescriptors::PrintHeaderString(); |
198 const PcDescriptors& descriptors = | 192 const PcDescriptors& descriptors = |
199 PcDescriptors::Handle(code.pc_descriptors()); | 193 PcDescriptors::Handle(code.pc_descriptors()); |
200 THR_Print("%s}\n", descriptors.ToCString()); | 194 THR_Print("%s}\n", descriptors.ToCString()); |
201 | 195 |
202 uword start = Instructions::Handle(code.instructions()).PayloadStart(); | 196 uword start = Instructions::Handle(code.instructions()).PayloadStart(); |
203 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 197 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
204 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); | 198 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); |
205 if (deopt_table_length > 0) { | 199 if (deopt_table_length > 0) { |
206 THR_Print("DeoptInfo: {\n"); | 200 THR_Print("DeoptInfo: {\n"); |
207 Smi& offset = Smi::Handle(); | 201 Smi& offset = Smi::Handle(); |
208 TypedData& info = TypedData::Handle(); | 202 TypedData& info = TypedData::Handle(); |
209 Smi& reason_and_flags = Smi::Handle(); | 203 Smi& reason_and_flags = Smi::Handle(); |
210 for (intptr_t i = 0; i < deopt_table_length; ++i) { | 204 for (intptr_t i = 0; i < deopt_table_length; ++i) { |
211 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); | 205 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); |
212 const intptr_t reason = | 206 const intptr_t reason = |
213 DeoptTable::ReasonField::decode(reason_and_flags.Value()); | 207 DeoptTable::ReasonField::decode(reason_and_flags.Value()); |
214 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); | 208 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); |
215 THR_Print("%4" Pd ": 0x%" Px " %s (%s)\n", | 209 THR_Print( |
216 i, | 210 "%4" Pd ": 0x%" Px " %s (%s)\n", i, start + offset.Value(), |
217 start + offset.Value(), | 211 DeoptInfo::ToCString(deopt_table, info), |
218 DeoptInfo::ToCString(deopt_table, info), | 212 DeoptReasonToCString(static_cast<ICData::DeoptReasonId>(reason))); |
219 DeoptReasonToCString( | |
220 static_cast<ICData::DeoptReasonId>(reason))); | |
221 } | 213 } |
222 THR_Print("}\n"); | 214 THR_Print("}\n"); |
223 } | 215 } |
224 | 216 |
225 THR_Print("Stackmaps for function '%s' {\n", function_fullname); | 217 THR_Print("Stackmaps for function '%s' {\n", function_fullname); |
226 if (code.stackmaps() != Array::null()) { | 218 if (code.stackmaps() != Array::null()) { |
227 const Array& stackmap_table = Array::Handle(code.stackmaps()); | 219 const Array& stackmap_table = Array::Handle(code.stackmaps()); |
228 Stackmap& map = Stackmap::Handle(); | 220 Stackmap& map = Stackmap::Handle(); |
229 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { | 221 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { |
230 map ^= stackmap_table.At(i); | 222 map ^= stackmap_table.At(i); |
231 THR_Print("%s\n", map.ToCString()); | 223 THR_Print("%s\n", map.ToCString()); |
232 } | 224 } |
233 } | 225 } |
234 THR_Print("}\n"); | 226 THR_Print("}\n"); |
235 | 227 |
236 if (FLAG_print_variable_descriptors) { | 228 if (FLAG_print_variable_descriptors) { |
237 THR_Print("Variable Descriptors for function '%s' {\n", | 229 THR_Print("Variable Descriptors for function '%s' {\n", function_fullname); |
238 function_fullname); | |
239 intptr_t var_desc_length = | 230 intptr_t var_desc_length = |
240 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); | 231 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); |
241 String& var_name = String::Handle(); | 232 String& var_name = String::Handle(); |
242 for (intptr_t i = 0; i < var_desc_length; i++) { | 233 for (intptr_t i = 0; i < var_desc_length; i++) { |
243 var_name = var_descriptors.GetName(i); | 234 var_name = var_descriptors.GetName(i); |
244 RawLocalVarDescriptors::VarInfo var_info; | 235 RawLocalVarDescriptors::VarInfo var_info; |
245 var_descriptors.GetInfo(i, &var_info); | 236 var_descriptors.GetInfo(i, &var_info); |
246 const int8_t kind = var_info.kind(); | 237 const int8_t kind = var_info.kind(); |
247 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { | 238 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { |
248 THR_Print(" saved current CTX reg offset %d\n", var_info.index()); | 239 THR_Print(" saved current CTX reg offset %d\n", var_info.index()); |
249 } else { | 240 } else { |
250 if (kind == RawLocalVarDescriptors::kContextLevel) { | 241 if (kind == RawLocalVarDescriptors::kContextLevel) { |
251 THR_Print(" context level %d scope %d", var_info.index(), | 242 THR_Print(" context level %d scope %d", var_info.index(), |
252 var_info.scope_id); | 243 var_info.scope_id); |
253 } else if (kind == RawLocalVarDescriptors::kStackVar) { | 244 } else if (kind == RawLocalVarDescriptors::kStackVar) { |
254 THR_Print(" stack var '%s' offset %d", | 245 THR_Print(" stack var '%s' offset %d", var_name.ToCString(), |
255 var_name.ToCString(), var_info.index()); | 246 var_info.index()); |
256 } else { | 247 } else { |
257 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | 248 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
258 THR_Print(" context var '%s' level %d offset %d", | 249 THR_Print(" context var '%s' level %d offset %d", |
259 var_name.ToCString(), var_info.scope_id, var_info.index()); | 250 var_name.ToCString(), var_info.scope_id, var_info.index()); |
260 } | 251 } |
261 THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(), | 252 THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(), |
262 var_info.end_pos.ToCString()); | 253 var_info.end_pos.ToCString()); |
263 } | 254 } |
264 } | 255 } |
265 THR_Print("}\n"); | 256 THR_Print("}\n"); |
266 } | 257 } |
267 | 258 |
268 THR_Print("Exception Handlers for function '%s' {\n", function_fullname); | 259 THR_Print("Exception Handlers for function '%s' {\n", function_fullname); |
269 const ExceptionHandlers& handlers = | 260 const ExceptionHandlers& handlers = |
270 ExceptionHandlers::Handle(code.exception_handlers()); | 261 ExceptionHandlers::Handle(code.exception_handlers()); |
271 THR_Print("%s}\n", handlers.ToCString()); | 262 THR_Print("%s}\n", handlers.ToCString()); |
272 | 263 |
273 { | 264 { |
274 THR_Print("Static call target functions {\n"); | 265 THR_Print("Static call target functions {\n"); |
275 const Array& table = Array::Handle(code.static_calls_target_table()); | 266 const Array& table = Array::Handle(code.static_calls_target_table()); |
276 Smi& offset = Smi::Handle(); | 267 Smi& offset = Smi::Handle(); |
277 Function& function = Function::Handle(); | 268 Function& function = Function::Handle(); |
278 Code& code = Code::Handle(); | 269 Code& code = Code::Handle(); |
279 for (intptr_t i = 0; i < table.Length(); | 270 for (intptr_t i = 0; i < table.Length(); |
280 i += Code::kSCallTableEntryLength) { | 271 i += Code::kSCallTableEntryLength) { |
281 offset ^= table.At(i + Code::kSCallTableOffsetEntry); | 272 offset ^= table.At(i + Code::kSCallTableOffsetEntry); |
282 function ^= table.At(i + Code::kSCallTableFunctionEntry); | 273 function ^= table.At(i + Code::kSCallTableFunctionEntry); |
283 code ^= table.At(i + Code::kSCallTableCodeEntry); | 274 code ^= table.At(i + Code::kSCallTableCodeEntry); |
284 if (function.IsNull()) { | 275 if (function.IsNull()) { |
285 Class& cls = Class::Handle(); | 276 Class& cls = Class::Handle(); |
286 cls ^= code.owner(); | 277 cls ^= code.owner(); |
287 if (cls.IsNull()) { | 278 if (cls.IsNull()) { |
288 THR_Print(" 0x%" Px ": %s, %p\n", | 279 THR_Print(" 0x%" Px ": %s, %p\n", start + offset.Value(), |
289 start + offset.Value(), | 280 code.Name(), code.raw()); |
290 code.Name(), | |
291 code.raw()); | |
292 } else { | 281 } else { |
293 THR_Print(" 0x%" Px ": allocation stub for %s, %p\n", | 282 THR_Print(" 0x%" Px ": allocation stub for %s, %p\n", |
294 start + offset.Value(), | 283 start + offset.Value(), cls.ToCString(), code.raw()); |
295 cls.ToCString(), | |
296 code.raw()); | |
297 } | 284 } |
298 } else { | 285 } else { |
299 THR_Print(" 0x%" Px ": %s, %p\n", | 286 THR_Print(" 0x%" Px ": %s, %p\n", start + offset.Value(), |
300 start + offset.Value(), | 287 function.ToFullyQualifiedCString(), code.raw()); |
301 function.ToFullyQualifiedCString(), | |
302 code.raw()); | |
303 } | 288 } |
304 } | 289 } |
305 THR_Print("}\n"); | 290 THR_Print("}\n"); |
306 } | 291 } |
307 if (optimized && FLAG_trace_inlining_intervals) { | 292 if (optimized && FLAG_trace_inlining_intervals) { |
308 code.DumpInlinedIntervals(); | 293 code.DumpInlinedIntervals(); |
309 } | 294 } |
310 } | 295 } |
311 | 296 |
312 | 297 |
313 void Disassembler::DisassembleCode(const Function& function, bool optimized) { | 298 void Disassembler::DisassembleCode(const Function& function, bool optimized) { |
314 const char* function_fullname = function.ToFullyQualifiedCString(); | 299 const char* function_fullname = function.ToFullyQualifiedCString(); |
315 const Code& code = Code::Handle(function.CurrentCode()); | 300 const Code& code = Code::Handle(function.CurrentCode()); |
316 DisassembleCodeHelper(function_fullname, code, optimized); | 301 DisassembleCodeHelper(function_fullname, code, optimized); |
317 } | 302 } |
318 | 303 |
319 | 304 |
320 void Disassembler::DisassembleCodeUnoptimized( | 305 void Disassembler::DisassembleCodeUnoptimized(const Function& function, |
321 const Function& function, bool optimized) { | 306 bool optimized) { |
322 const char* function_fullname = function.ToFullyQualifiedCString(); | 307 const char* function_fullname = function.ToFullyQualifiedCString(); |
323 const Code& code = Code::Handle(function.unoptimized_code()); | 308 const Code& code = Code::Handle(function.unoptimized_code()); |
324 DisassembleCodeHelper(function_fullname, code, optimized); | 309 DisassembleCodeHelper(function_fullname, code, optimized); |
325 } | 310 } |
326 | 311 |
327 | 312 |
328 #endif // !PRODUCT | 313 #endif // !PRODUCT |
329 | 314 |
330 } // namespace dart | 315 } // namespace dart |
OLD | NEW |