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/globals.h" | 9 #include "vm/globals.h" |
9 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
10 #include "vm/instructions.h" | 11 #include "vm/instructions.h" |
11 #include "vm/json_stream.h" | 12 #include "vm/json_stream.h" |
12 #include "vm/log.h" | 13 #include "vm/log.h" |
13 #include "vm/os.h" | 14 #include "vm/os.h" |
14 #include "vm/code_patcher.h" | 15 #include "vm/code_patcher.h" |
15 | 16 |
16 | 17 |
17 namespace dart { | 18 namespace dart { |
18 | 19 |
| 20 DECLARE_FLAG(bool, trace_inlining_intervals); |
| 21 |
19 void DisassembleToStdout::ConsumeInstruction(const Code& code, | 22 void DisassembleToStdout::ConsumeInstruction(const Code& code, |
20 char* hex_buffer, | 23 char* hex_buffer, |
21 intptr_t hex_size, | 24 intptr_t hex_size, |
22 char* human_buffer, | 25 char* human_buffer, |
23 intptr_t human_size, | 26 intptr_t human_size, |
24 uword pc) { | 27 uword pc) { |
25 static const int kHexColumnWidth = 23; | 28 static const int kHexColumnWidth = 23; |
26 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); | 29 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); |
27 THR_Print("%p %s", pc_ptr, hex_buffer); | 30 THR_Print("%p %s", pc_ptr, hex_buffer); |
28 int hex_length = strlen(hex_buffer); | 31 int hex_length = strlen(hex_buffer); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 formatter->ConsumeInstruction(code, | 178 formatter->ConsumeInstruction(code, |
176 hex_buffer, | 179 hex_buffer, |
177 sizeof(hex_buffer), | 180 sizeof(hex_buffer), |
178 human_buffer, | 181 human_buffer, |
179 sizeof(human_buffer), | 182 sizeof(human_buffer), |
180 pc); | 183 pc); |
181 pc += instruction_length; | 184 pc += instruction_length; |
182 } | 185 } |
183 } | 186 } |
184 | 187 |
| 188 |
| 189 void Disassembler::DisassembleCode(const Function& function, bool optimized) { |
| 190 const char* function_fullname = function.ToFullyQualifiedCString(); |
| 191 THR_Print("Code for %sfunction '%s' {\n", |
| 192 optimized ? "optimized " : "", |
| 193 function_fullname); |
| 194 const Code& code = Code::Handle(function.CurrentCode()); |
| 195 code.Disassemble(); |
| 196 THR_Print("}\n"); |
| 197 |
| 198 THR_Print("Pointer offsets for function: {\n"); |
| 199 // Pointer offsets are stored in descending order. |
| 200 Object& obj = Object::Handle(); |
| 201 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { |
| 202 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
| 203 obj = *reinterpret_cast<RawObject**>(addr); |
| 204 THR_Print(" %d : %#" Px " '%s'\n", |
| 205 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
| 206 } |
| 207 THR_Print("}\n"); |
| 208 |
| 209 THR_Print("PC Descriptors for function '%s' {\n", function_fullname); |
| 210 PcDescriptors::PrintHeaderString(); |
| 211 const PcDescriptors& descriptors = |
| 212 PcDescriptors::Handle(code.pc_descriptors()); |
| 213 THR_Print("%s}\n", descriptors.ToCString()); |
| 214 |
| 215 uword start = Instructions::Handle(code.instructions()).EntryPoint(); |
| 216 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 217 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); |
| 218 if (deopt_table_length > 0) { |
| 219 THR_Print("DeoptInfo: {\n"); |
| 220 Smi& offset = Smi::Handle(); |
| 221 TypedData& info = TypedData::Handle(); |
| 222 Smi& reason_and_flags = Smi::Handle(); |
| 223 for (intptr_t i = 0; i < deopt_table_length; ++i) { |
| 224 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); |
| 225 const intptr_t reason = |
| 226 DeoptTable::ReasonField::decode(reason_and_flags.Value()); |
| 227 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); |
| 228 THR_Print("%4" Pd ": 0x%" Px " %s (%s)\n", |
| 229 i, |
| 230 start + offset.Value(), |
| 231 DeoptInfo::ToCString(deopt_table, info), |
| 232 DeoptReasonToCString( |
| 233 static_cast<ICData::DeoptReasonId>(reason))); |
| 234 } |
| 235 THR_Print("}\n"); |
| 236 } |
| 237 |
| 238 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); |
| 239 object_pool.DebugPrint(); |
| 240 |
| 241 THR_Print("Stackmaps for function '%s' {\n", function_fullname); |
| 242 if (code.stackmaps() != Array::null()) { |
| 243 const Array& stackmap_table = Array::Handle(code.stackmaps()); |
| 244 Stackmap& map = Stackmap::Handle(); |
| 245 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { |
| 246 map ^= stackmap_table.At(i); |
| 247 THR_Print("%s\n", map.ToCString()); |
| 248 } |
| 249 } |
| 250 THR_Print("}\n"); |
| 251 |
| 252 THR_Print("Variable Descriptors for function '%s' {\n", |
| 253 function_fullname); |
| 254 const LocalVarDescriptors& var_descriptors = |
| 255 LocalVarDescriptors::Handle(code.GetLocalVarDescriptors()); |
| 256 intptr_t var_desc_length = |
| 257 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); |
| 258 String& var_name = String::Handle(); |
| 259 for (intptr_t i = 0; i < var_desc_length; i++) { |
| 260 var_name = var_descriptors.GetName(i); |
| 261 RawLocalVarDescriptors::VarInfo var_info; |
| 262 var_descriptors.GetInfo(i, &var_info); |
| 263 const int8_t kind = var_info.kind(); |
| 264 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { |
| 265 THR_Print(" saved current CTX reg offset %d\n", var_info.index()); |
| 266 } else { |
| 267 if (kind == RawLocalVarDescriptors::kContextLevel) { |
| 268 THR_Print(" context level %d scope %d", var_info.index(), |
| 269 var_info.scope_id); |
| 270 } else if (kind == RawLocalVarDescriptors::kStackVar) { |
| 271 THR_Print(" stack var '%s' offset %d", |
| 272 var_name.ToCString(), var_info.index()); |
| 273 } else { |
| 274 ASSERT(kind == RawLocalVarDescriptors::kContextVar); |
| 275 THR_Print(" context var '%s' level %d offset %d", |
| 276 var_name.ToCString(), var_info.scope_id, var_info.index()); |
| 277 } |
| 278 THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(), |
| 279 var_info.end_pos.ToCString()); |
| 280 } |
| 281 } |
| 282 THR_Print("}\n"); |
| 283 |
| 284 THR_Print("Exception Handlers for function '%s' {\n", function_fullname); |
| 285 const ExceptionHandlers& handlers = |
| 286 ExceptionHandlers::Handle(code.exception_handlers()); |
| 287 THR_Print("%s}\n", handlers.ToCString()); |
| 288 |
| 289 { |
| 290 THR_Print("Static call target functions {\n"); |
| 291 const Array& table = Array::Handle(code.static_calls_target_table()); |
| 292 Smi& offset = Smi::Handle(); |
| 293 Function& function = Function::Handle(); |
| 294 Code& code = Code::Handle(); |
| 295 for (intptr_t i = 0; i < table.Length(); |
| 296 i += Code::kSCallTableEntryLength) { |
| 297 offset ^= table.At(i + Code::kSCallTableOffsetEntry); |
| 298 function ^= table.At(i + Code::kSCallTableFunctionEntry); |
| 299 code ^= table.At(i + Code::kSCallTableCodeEntry); |
| 300 if (function.IsNull()) { |
| 301 Class& cls = Class::Handle(); |
| 302 cls ^= code.owner(); |
| 303 if (cls.IsNull()) { |
| 304 const String& code_name = String::Handle(code.Name()); |
| 305 THR_Print(" 0x%" Px ": %s, %p\n", |
| 306 start + offset.Value(), |
| 307 code_name.ToCString(), |
| 308 code.raw()); |
| 309 } else { |
| 310 THR_Print(" 0x%" Px ": allocation stub for %s, %p\n", |
| 311 start + offset.Value(), |
| 312 cls.ToCString(), |
| 313 code.raw()); |
| 314 } |
| 315 } else { |
| 316 THR_Print(" 0x%" Px ": %s, %p\n", |
| 317 start + offset.Value(), |
| 318 function.ToFullyQualifiedCString(), |
| 319 code.raw()); |
| 320 } |
| 321 } |
| 322 THR_Print("}\n"); |
| 323 } |
| 324 if (optimized && FLAG_trace_inlining_intervals) { |
| 325 code.DumpInlinedIntervals(); |
| 326 } |
| 327 } |
| 328 |
| 329 |
185 } // namespace dart | 330 } // namespace dart |
OLD | NEW |