| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 <setjmp.h> | 5 #include <setjmp.h> |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #if defined(TARGET_ARCH_ARM64) | 9 #if defined(TARGET_ARCH_ARM64) |
| 10 | 10 |
| 11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
| 12 #if !defined(HOST_ARCH_ARM64) | 12 #if !defined(HOST_ARCH_ARM64) |
| 13 | 13 |
| 14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
| 15 | 15 |
| 16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
| 17 #include "vm/constants_arm64.h" | 17 #include "vm/constants_arm64.h" |
| 18 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
| 19 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
| 20 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
| 21 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
| 22 #include "vm/thread.h" | 22 #include "vm/thread.h" |
| 23 | 23 |
| 24 namespace dart { | 24 namespace dart { |
| 25 | 25 |
| 26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 26 DEFINE_FLAG(int, trace_sim_after, -1, |
| 27 DEFINE_FLAG(int, stop_sim_at, 0, | 27 "Trace simulator execution after instruction count reached."); |
| 28 DEFINE_FLAG(int, stop_sim_at, -1, |
| 28 "Instruction address or instruction count to stop simulator at."); | 29 "Instruction address or instruction count to stop simulator at."); |
| 29 | 30 |
| 30 | 31 |
| 31 // This macro provides a platform independent use of sscanf. The reason for | 32 // This macro provides a platform independent use of sscanf. The reason for |
| 32 // SScanF not being implemented in a platform independent way through | 33 // SScanF not being implemented in a platform independent way through |
| 33 // OS in the same way as SNPrint is that the Windows C Run-Time | 34 // OS in the same way as SNPrint is that the Windows C Run-Time |
| 34 // Library does not provide vsscanf. | 35 // Library does not provide vsscanf. |
| 35 #define SScanF sscanf // NOLINT | 36 #define SScanF sscanf // NOLINT |
| 36 | 37 |
| 37 | 38 |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 OS::Print("V flag: %d\n", sim_->v_flag_); | 633 OS::Print("V flag: %d\n", sim_->v_flag_); |
| 633 } else if (strcmp(cmd, "unstop") == 0) { | 634 } else if (strcmp(cmd, "unstop") == 0) { |
| 634 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 635 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
| 635 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 636 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
| 636 if (stop_instr->IsExceptionGenOp()) { | 637 if (stop_instr->IsExceptionGenOp()) { |
| 637 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 638 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
| 638 } else { | 639 } else { |
| 639 OS::Print("Not at debugger stop.\n"); | 640 OS::Print("Not at debugger stop.\n"); |
| 640 } | 641 } |
| 641 } else if (strcmp(cmd, "trace") == 0) { | 642 } else if (strcmp(cmd, "trace") == 0) { |
| 642 FLAG_trace_sim = !FLAG_trace_sim; | 643 if (FLAG_trace_sim_after == -1) { |
| 643 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); | 644 FLAG_trace_sim_after = sim_->get_icount(); |
| 645 OS::Print("execution tracing on\n"); |
| 646 } else { |
| 647 FLAG_trace_sim_after = -1; |
| 648 OS::Print("execution tracing off\n"); |
| 649 } |
| 644 } else if (strcmp(cmd, "bt") == 0) { | 650 } else if (strcmp(cmd, "bt") == 0) { |
| 645 PrintBacktrace(); | 651 PrintBacktrace(); |
| 646 } else { | 652 } else { |
| 647 OS::Print("Unknown command: %s\n", cmd); | 653 OS::Print("Unknown command: %s\n", cmd); |
| 648 } | 654 } |
| 649 } | 655 } |
| 650 delete[] line; | 656 delete[] line; |
| 651 } | 657 } |
| 652 | 658 |
| 653 // Add all the breakpoints back to stop execution and enter the debugger | 659 // Add all the breakpoints back to stop execution and enter the debugger |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 // Returns the top of the stack area to enable checking for stack pointer | 1045 // Returns the top of the stack area to enable checking for stack pointer |
| 1040 // validity. | 1046 // validity. |
| 1041 uword Simulator::StackTop() const { | 1047 uword Simulator::StackTop() const { |
| 1042 // To be safe in potential stack underflows we leave some buffer above and | 1048 // To be safe in potential stack underflows we leave some buffer above and |
| 1043 // set the stack top. | 1049 // set the stack top. |
| 1044 return reinterpret_cast<uword>(stack_) + | 1050 return reinterpret_cast<uword>(stack_) + |
| 1045 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); | 1051 (Isolate::GetSpecifiedStackSize() + Isolate::kStackSizeBuffer); |
| 1046 } | 1052 } |
| 1047 | 1053 |
| 1048 | 1054 |
| 1055 bool Simulator::IsTracingExecution() const { |
| 1056 // Integer flag values are signed, so we must cast to unsigned. |
| 1057 // The default of -1 hence becomes the maximum unsigned value. |
| 1058 return (static_cast<uintptr_t>(icount_) > |
| 1059 static_cast<uintptr_t>(FLAG_trace_sim_after)); |
| 1060 } |
| 1061 |
| 1062 |
| 1049 intptr_t Simulator::ReadX(uword addr, Instr* instr) { | 1063 intptr_t Simulator::ReadX(uword addr, Instr* instr) { |
| 1050 if ((addr & 7) == 0) { | 1064 if ((addr & 7) == 0) { |
| 1051 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 1065 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 1052 return *ptr; | 1066 return *ptr; |
| 1053 } | 1067 } |
| 1054 UnalignedAccess("read", addr, instr); | 1068 UnalignedAccess("read", addr, instr); |
| 1055 return 0; | 1069 return 0; |
| 1056 } | 1070 } |
| 1057 | 1071 |
| 1058 | 1072 |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); | 1564 typedef void (*SimulatorBootstrapNativeCall)(NativeArguments* arguments); |
| 1551 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); | 1565 typedef void (*SimulatorNativeCall)(NativeArguments* arguments, uword target); |
| 1552 | 1566 |
| 1553 | 1567 |
| 1554 void Simulator::DoRedirectedCall(Instr* instr) { | 1568 void Simulator::DoRedirectedCall(Instr* instr) { |
| 1555 SimulatorSetjmpBuffer buffer(this); | 1569 SimulatorSetjmpBuffer buffer(this); |
| 1556 if (!setjmp(buffer.buffer_)) { | 1570 if (!setjmp(buffer.buffer_)) { |
| 1557 int64_t saved_lr = get_register(LR); | 1571 int64_t saved_lr = get_register(LR); |
| 1558 Redirection* redirection = Redirection::FromHltInstruction(instr); | 1572 Redirection* redirection = Redirection::FromHltInstruction(instr); |
| 1559 uword external = redirection->external_function(); | 1573 uword external = redirection->external_function(); |
| 1560 if (FLAG_trace_sim) { | 1574 if (IsTracingExecution()) { |
| 1561 OS::Print("Call to host function at 0x%" Pd "\n", external); | 1575 OS::Print("Call to host function at 0x%" Pd "\n", external); |
| 1562 } | 1576 } |
| 1563 | 1577 |
| 1564 if ((redirection->call_kind() == kRuntimeCall) || | 1578 if ((redirection->call_kind() == kRuntimeCall) || |
| 1565 (redirection->call_kind() == kBootstrapNativeCall) || | 1579 (redirection->call_kind() == kBootstrapNativeCall) || |
| 1566 (redirection->call_kind() == kNativeCall)) { | 1580 (redirection->call_kind() == kNativeCall)) { |
| 1567 // Set the top_exit_frame_info of this simulator to the native stack. | 1581 // Set the top_exit_frame_info of this simulator to the native stack. |
| 1568 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); | 1582 set_top_exit_frame_info(reinterpret_cast<uword>(&buffer)); |
| 1569 } | 1583 } |
| 1570 if (redirection->call_kind() == kRuntimeCall) { | 1584 if (redirection->call_kind() == kRuntimeCall) { |
| (...skipping 1694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3265 DecodeFP(instr); | 3279 DecodeFP(instr); |
| 3266 } else { | 3280 } else { |
| 3267 UnimplementedInstruction(instr); | 3281 UnimplementedInstruction(instr); |
| 3268 } | 3282 } |
| 3269 } | 3283 } |
| 3270 | 3284 |
| 3271 | 3285 |
| 3272 // Executes the current instruction. | 3286 // Executes the current instruction. |
| 3273 void Simulator::InstructionDecode(Instr* instr) { | 3287 void Simulator::InstructionDecode(Instr* instr) { |
| 3274 pc_modified_ = false; | 3288 pc_modified_ = false; |
| 3275 if (FLAG_trace_sim) { | 3289 if (IsTracingExecution()) { |
| 3290 OS::Print("%"Pu64" ", icount_); |
| 3276 const uword start = reinterpret_cast<uword>(instr); | 3291 const uword start = reinterpret_cast<uword>(instr); |
| 3277 const uword end = start + Instr::kInstrSize; | 3292 const uword end = start + Instr::kInstrSize; |
| 3278 Disassembler::Disassemble(start, end); | 3293 Disassembler::Disassemble(start, end); |
| 3279 } | 3294 } |
| 3280 | 3295 |
| 3281 if (instr->IsDPImmediateOp()) { | 3296 if (instr->IsDPImmediateOp()) { |
| 3282 DecodeDPImmediate(instr); | 3297 DecodeDPImmediate(instr); |
| 3283 } else if (instr->IsCompareBranchOp()) { | 3298 } else if (instr->IsCompareBranchOp()) { |
| 3284 DecodeCompareBranch(instr); | 3299 DecodeCompareBranch(instr); |
| 3285 } else if (instr->IsLoadStoreOp()) { | 3300 } else if (instr->IsLoadStoreOp()) { |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3470 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); | 3485 set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); |
| 3471 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); | 3486 set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); |
| 3472 buf->Longjmp(); | 3487 buf->Longjmp(); |
| 3473 } | 3488 } |
| 3474 | 3489 |
| 3475 } // namespace dart | 3490 } // namespace dart |
| 3476 | 3491 |
| 3477 #endif // !defined(HOST_ARCH_ARM64) | 3492 #endif // !defined(HOST_ARCH_ARM64) |
| 3478 | 3493 |
| 3479 #endif // defined TARGET_ARCH_ARM64 | 3494 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |