Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS) | 9 #if defined(TARGET_ARCH_MIPS) |
| 10 | 10 |
| 11 // Only build the simulator if not compiling for real MIPS hardware. | 11 // Only build the simulator if not compiling for real MIPS hardware. |
| 12 #if !defined(HOST_ARCH_MIPS) | 12 #if !defined(HOST_ARCH_MIPS) |
| 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_mips.h" | 17 #include "vm/constants_mips.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/thread.h" | 22 #include "vm/thread.h" |
| 22 | 23 |
| 23 namespace dart { | 24 namespace dart { |
| 24 | 25 |
| 25 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); | 26 DEFINE_FLAG(bool, trace_sim, false, "Trace simulator execution."); |
| 26 DEFINE_FLAG(int, stop_sim_at, 0, "Address to stop simulator at."); | 27 DEFINE_FLAG(int, stop_sim_at, 0, |
| 28 "Instruction address or instruction count to stop simulator at."); | |
| 27 | 29 |
| 28 | 30 |
| 29 // This macro provides a platform independent use of sscanf. The reason for | 31 // This macro provides a platform independent use of sscanf. The reason for |
| 30 // SScanF not being implemented in a platform independent way through | 32 // SScanF not being implemented in a platform independent way through |
| 31 // OS in the same way as SNPrint is that the Windows C Run-Time | 33 // OS in the same way as SNPrint is that the Windows C Run-Time |
| 32 // Library does not provide vsscanf. | 34 // Library does not provide vsscanf. |
| 33 #define SScanF sscanf // NOLINT | 35 #define SScanF sscanf // NOLINT |
| 34 | 36 |
| 35 | 37 |
| 36 // SimulatorSetjmpBuffer are linked together, and the last created one | 38 // SimulatorSetjmpBuffer are linked together, and the last created one |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 void Debug(); | 89 void Debug(); |
| 88 char* ReadLine(const char* prompt); | 90 char* ReadLine(const char* prompt); |
| 89 | 91 |
| 90 private: | 92 private: |
| 91 Simulator* sim_; | 93 Simulator* sim_; |
| 92 | 94 |
| 93 bool GetValue(char* desc, uint32_t* value); | 95 bool GetValue(char* desc, uint32_t* value); |
| 94 bool GetFValue(char* desc, double* value); | 96 bool GetFValue(char* desc, double* value); |
| 95 bool GetDValue(char* desc, double* value); | 97 bool GetDValue(char* desc, double* value); |
| 96 | 98 |
| 99 static intptr_t GetApproximateTokenIndex(const Code& code, uword pc); | |
| 100 | |
| 101 static void PrintDartFrame(uword pc, uword fp, uword sp, | |
| 102 const Function& function, | |
| 103 intptr_t token_pos, | |
| 104 bool is_optimized, | |
| 105 bool is_inlined); | |
| 106 void PrintBacktrace(); | |
| 107 | |
| 97 static const int32_t kSimulatorBreakpointInstruction = | 108 static const int32_t kSimulatorBreakpointInstruction = |
| 98 Instr::kBreakPointInstruction | | 109 Instr::kBreakPointInstruction | |
| 99 (Instr::kSimulatorBreakCode << kBreakCodeShift); | 110 (Instr::kSimulatorBreakCode << kBreakCodeShift); |
| 100 | 111 |
| 101 // Set or delete a breakpoint. Returns true if successful. | 112 // Set or delete a breakpoint. Returns true if successful. |
| 102 bool SetBreakpoint(Instr* breakpc); | 113 bool SetBreakpoint(Instr* breakpc); |
| 103 bool DeleteBreakpoint(Instr* breakpc); | 114 bool DeleteBreakpoint(Instr* breakpc); |
| 104 | 115 |
| 105 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 116 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
| 106 // execution to skip past breakpoints when run from the debugger. | 117 // execution to skip past breakpoints when run from the debugger. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 return false; | 207 return false; |
| 197 } | 208 } |
| 198 *value = *(reinterpret_cast<uint32_t*>(addr)); | 209 *value = *(reinterpret_cast<uint32_t*>(addr)); |
| 199 return true; | 210 return true; |
| 200 } | 211 } |
| 201 } | 212 } |
| 202 if (strcmp("pc", desc) == 0) { | 213 if (strcmp("pc", desc) == 0) { |
| 203 *value = sim_->get_pc(); | 214 *value = sim_->get_pc(); |
| 204 return true; | 215 return true; |
| 205 } | 216 } |
| 217 if (strcmp("icount", desc) == 0) { | |
| 218 *value = sim_->get_icount(); | |
| 219 return true; | |
| 220 } | |
| 206 bool retval = SScanF(desc, "0x%x", value) == 1; | 221 bool retval = SScanF(desc, "0x%x", value) == 1; |
| 207 if (!retval) { | 222 if (!retval) { |
| 208 retval = SScanF(desc, "%x", value) == 1; | 223 retval = SScanF(desc, "%x", value) == 1; |
| 209 } | 224 } |
| 210 return retval; | 225 return retval; |
| 211 } | 226 } |
| 212 | 227 |
| 213 | 228 |
| 214 bool SimulatorDebugger::GetFValue(char* desc, double* value) { | 229 bool SimulatorDebugger::GetFValue(char* desc, double* value) { |
| 215 FRegister freg = LookupFRegisterByName(desc); | 230 FRegister freg = LookupFRegisterByName(desc); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 244 return false; | 259 return false; |
| 245 } | 260 } |
| 246 *value = *(reinterpret_cast<double*>(addr)); | 261 *value = *(reinterpret_cast<double*>(addr)); |
| 247 return true; | 262 return true; |
| 248 } | 263 } |
| 249 } | 264 } |
| 250 return false; | 265 return false; |
| 251 } | 266 } |
| 252 | 267 |
| 253 | 268 |
| 269 intptr_t SimulatorDebugger::GetApproximateTokenIndex(const Code& code, | |
| 270 uword pc) { | |
| 271 intptr_t token_pos = -1; | |
| 272 const PcDescriptors& descriptors = | |
| 273 PcDescriptors::Handle(code.pc_descriptors()); | |
| 274 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind); | |
| 275 while (iter.MoveNext()) { | |
| 276 if (iter.Pc() == pc) { | |
| 277 return iter.TokenPos(); | |
| 278 } else if ((token_pos <= 0) && (iter.Pc() > pc)) { | |
| 279 token_pos = iter.TokenPos(); | |
| 280 } | |
| 281 } | |
| 282 return token_pos; | |
| 283 } | |
| 284 | |
| 285 | |
| 286 void SimulatorDebugger::PrintDartFrame(uword pc, uword fp, uword sp, | |
| 287 const Function& function, | |
| 288 intptr_t token_pos, | |
| 289 bool is_optimized, | |
| 290 bool is_inlined) { | |
| 291 const Script& script = Script::Handle(function.script()); | |
| 292 const String& func_name = String::Handle(function.QualifiedUserVisibleName()); | |
| 293 const String& url = String::Handle(script.url()); | |
| 294 intptr_t line = -1; | |
| 295 intptr_t column = -1; | |
| 296 if (token_pos >= 0) { | |
| 297 script.GetTokenLocation(token_pos, &line, &column); | |
| 298 } | |
| 299 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd | |
| 300 ":%" Pd ")\n", | |
| 301 pc, fp, sp, | |
| 302 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "", | |
| 303 func_name.ToCString(), | |
| 304 url.ToCString(), | |
| 305 line, column); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 void SimulatorDebugger::PrintBacktrace() { | |
| 310 StackFrameIterator frames(sim_->get_register(FP), | |
| 311 sim_->get_register(SP), | |
| 312 sim_->get_pc(), | |
| 313 StackFrameIterator::kDontValidateFrames); | |
| 314 StackFrame* frame = frames.NextFrame(); | |
| 315 ASSERT(frame != NULL); | |
| 316 Function& function = Function::Handle(); | |
| 317 Function& inlined_function = Function::Handle(); | |
| 318 Code& code = Code::Handle(); | |
| 319 Code& unoptimized_code = Code::Handle(); | |
| 320 while (frame != NULL) { | |
| 321 if (frame->IsDartFrame()) { | |
| 322 code = frame->LookupDartCode(); | |
| 323 function = code.function(); | |
| 324 if (code.is_optimized()) { | |
| 325 // For optimized frames, extract all the inlined functions if any | |
| 326 // into the stack trace. | |
| 327 InlinedFunctionsIterator it(code, frame->pc()); | |
| 328 while (!it.Done()) { | |
| 329 // Print each inlined frame with its pc in the corresponding | |
| 330 // unoptimized frame. | |
| 331 inlined_function = it.function(); | |
| 332 unoptimized_code = it.code(); | |
| 333 uword unoptimized_pc = it.pc(); | |
| 334 it.Advance(); | |
| 335 if (!it.Done()) { | |
| 336 PrintDartFrame(unoptimized_pc, frame->fp(), frame->sp(), | |
| 337 inlined_function, | |
| 338 GetApproximateTokenIndex(unoptimized_code, | |
| 339 unoptimized_pc), | |
| 340 true, true); | |
| 341 } | |
| 342 } | |
| 343 // Print the optimized inlining frame below. | |
| 344 } | |
| 345 PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), | |
| 346 function, | |
| 347 GetApproximateTokenIndex(code, frame->pc()), | |
| 348 code.is_optimized(), false); | |
| 349 } else { | |
| 350 OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n", | |
| 351 frame->pc(), frame->fp(), frame->sp(), | |
| 352 frame->IsEntryFrame() ? "entry" : | |
| 353 frame->IsExitFrame() ? "exit" : | |
| 354 frame->IsStubFrame() ? "stub" : "invalid"); | |
| 355 } | |
| 356 frame = frames.NextFrame(); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 | |
| 254 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { | 361 bool SimulatorDebugger::SetBreakpoint(Instr* breakpc) { |
| 255 // Check if a breakpoint can be set. If not return without any side-effects. | 362 // Check if a breakpoint can be set. If not return without any side-effects. |
| 256 if (sim_->break_pc_ != NULL) { | 363 if (sim_->break_pc_ != NULL) { |
| 257 return false; | 364 return false; |
| 258 } | 365 } |
| 259 | 366 |
| 260 // Set the breakpoint. | 367 // Set the breakpoint. |
| 261 sim_->break_pc_ = breakpc; | 368 sim_->break_pc_ = breakpc; |
| 262 sim_->break_instr_ = breakpc->InstructionBits(); | 369 sim_->break_instr_ = breakpc->InstructionBits(); |
| 263 // Not setting the breakpoint instruction in the code itself. It will be set | 370 // Not setting the breakpoint instruction in the code itself. It will be set |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 OS::Print("c/cont -- continue execution\n" | 445 OS::Print("c/cont -- continue execution\n" |
| 339 "disasm -- disassemble instrs at current pc location\n" | 446 "disasm -- disassemble instrs at current pc location\n" |
| 340 " other variants are:\n" | 447 " other variants are:\n" |
| 341 " disasm <address>\n" | 448 " disasm <address>\n" |
| 342 " disasm <address> <number_of_instructions>\n" | 449 " disasm <address> <number_of_instructions>\n" |
| 343 " by default 10 instrs are disassembled\n" | 450 " by default 10 instrs are disassembled\n" |
| 344 "del -- delete breakpoints\n" | 451 "del -- delete breakpoints\n" |
| 345 "gdb -- transfer control to gdb\n" | 452 "gdb -- transfer control to gdb\n" |
| 346 "h/help -- print this help string\n" | 453 "h/help -- print this help string\n" |
| 347 "break <address> -- set break point at specified address\n" | 454 "break <address> -- set break point at specified address\n" |
| 348 "p/print <reg or value or *addr> -- print integer value\n" | 455 "p/print <reg or icount or value or *addr> -- print integer\n" |
| 349 "pf/printfloat <freg or *addr> -- print float value\n" | 456 "pf/printfloat <freg or *addr> -- print float value\n" |
| 350 "po/printobject <*reg or *addr> -- print object\n" | 457 "po/printobject <*reg or *addr> -- print object\n" |
| 351 "si/stepi -- single step an instruction\n" | 458 "si/stepi -- single step an instruction\n" |
| 459 "trace -- toggle execution tracing mode\n" | |
| 460 "bt -- print backtrace\n" | |
| 352 "unstop -- if current pc is a stop instr make it a nop\n" | 461 "unstop -- if current pc is a stop instr make it a nop\n" |
| 353 "q/quit -- Quit the debugger and exit the program\n"); | 462 "q/quit -- Quit the debugger and exit the program\n"); |
| 354 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { | 463 } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) { |
| 355 OS::Print("Quitting\n"); | 464 OS::Print("Quitting\n"); |
| 356 OS::Exit(0); | 465 OS::Exit(0); |
| 357 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { | 466 } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { |
| 358 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 467 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| 359 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 468 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
| 360 // Execute the one instruction we broke at with breakpoints disabled. | 469 // Execute the one instruction we broke at with breakpoints disabled. |
| 361 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); | 470 sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc())); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 OS::Print("deleting breakpoint failed\n"); | 585 OS::Print("deleting breakpoint failed\n"); |
| 477 } | 586 } |
| 478 } else if (strcmp(cmd, "unstop") == 0) { | 587 } else if (strcmp(cmd, "unstop") == 0) { |
| 479 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; | 588 intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize; |
| 480 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); | 589 Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc); |
| 481 if (stop_instr->IsBreakPoint()) { | 590 if (stop_instr->IsBreakPoint()) { |
| 482 stop_instr->SetInstructionBits(Instr::kNopInstruction); | 591 stop_instr->SetInstructionBits(Instr::kNopInstruction); |
| 483 } else { | 592 } else { |
| 484 OS::Print("Not at debugger stop.\n"); | 593 OS::Print("Not at debugger stop.\n"); |
| 485 } | 594 } |
| 595 } else if (strcmp(cmd, "trace") == 0) { | |
| 596 FLAG_trace_sim = !FLAG_trace_sim; | |
| 597 OS::Print("execution tracing %s\n", FLAG_trace_sim ? "on" : "off"); | |
| 598 } else if (strcmp(cmd, "bt") == 0) { | |
| 599 PrintBacktrace(); | |
| 486 } else { | 600 } else { |
| 487 OS::Print("Unknown command: %s\n", cmd); | 601 OS::Print("Unknown command: %s\n", cmd); |
| 488 } | 602 } |
| 489 } | 603 } |
| 490 delete[] line; | 604 delete[] line; |
| 491 } | 605 } |
| 492 | 606 |
| 493 // Add all the breakpoints back to stop execution and enter the debugger | 607 // Add all the breakpoints back to stop execution and enter the debugger |
| 494 // shell when hit. | 608 // shell when hit. |
| 495 RedoBreakpoints(); | 609 RedoBreakpoints(); |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1056 // Same effect on exclusive access state as a successful SC. | 1170 // Same effect on exclusive access state as a successful SC. |
| 1057 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); | 1171 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
| 1058 } else { | 1172 } else { |
| 1059 // Same effect on exclusive access state as an LL. | 1173 // Same effect on exclusive access state as an LL. |
| 1060 SetExclusiveAccess(reinterpret_cast<uword>(address)); | 1174 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
| 1061 } | 1175 } |
| 1062 return value; | 1176 return value; |
| 1063 } | 1177 } |
| 1064 | 1178 |
| 1065 | 1179 |
| 1066 bool Simulator::OverflowFrom(int32_t alu_out, | |
| 1067 int32_t left, int32_t right, bool addition) { | |
| 1068 bool overflow; | |
| 1069 if (addition) { | |
| 1070 // Operands have the same sign. | |
| 1071 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | |
| 1072 // And operands and result have different sign. | |
| 1073 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 1074 } else { | |
| 1075 // Operands have different signs. | |
| 1076 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) | |
| 1077 // And first operand and result have different signs. | |
| 1078 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | |
| 1079 } | |
| 1080 return overflow; | |
| 1081 } | |
| 1082 | |
| 1083 | |
| 1084 // Calls into the Dart runtime are based on this interface. | 1180 // Calls into the Dart runtime are based on this interface. |
| 1085 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); | 1181 typedef void (*SimulatorRuntimeCall)(NativeArguments arguments); |
| 1086 | 1182 |
| 1087 // Calls to leaf Dart runtime functions are based on this interface. | 1183 // Calls to leaf Dart runtime functions are based on this interface. |
| 1088 typedef int32_t (*SimulatorLeafRuntimeCall)( | 1184 typedef int32_t (*SimulatorLeafRuntimeCall)( |
| 1089 int32_t r0, int32_t r1, int32_t r2, int32_t r3); | 1185 int32_t r0, int32_t r1, int32_t r2, int32_t r3); |
| 1090 | 1186 |
| 1091 // Calls to leaf float Dart runtime functions are based on this interface. | 1187 // Calls to leaf float Dart runtime functions are based on this interface. |
| 1092 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); | 1188 typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1); |
| 1093 | 1189 |
| (...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2165 } | 2261 } |
| 2166 pc_ += Instr::kInstrSize; | 2262 pc_ += Instr::kInstrSize; |
| 2167 } | 2263 } |
| 2168 | 2264 |
| 2169 | 2265 |
| 2170 void Simulator::ExecuteDelaySlot() { | 2266 void Simulator::ExecuteDelaySlot() { |
| 2171 ASSERT(pc_ != kEndSimulatingPC); | 2267 ASSERT(pc_ != kEndSimulatingPC); |
| 2172 delay_slot_ = true; | 2268 delay_slot_ = true; |
| 2173 icount_++; | 2269 icount_++; |
| 2174 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); | 2270 Instr* instr = Instr::At(pc_ + Instr::kInstrSize); |
| 2175 if ((FLAG_stop_sim_at != 0) && (icount_ == FLAG_stop_sim_at)) { | 2271 if (FLAG_stop_sim_at != 0) { |
| 2176 SimulatorDebugger dbg(this); | 2272 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { |
| 2177 dbg.Stop(instr, "Instruction count reached"); | 2273 SimulatorDebugger dbg(this); |
| 2274 dbg.Stop(instr, "Instruction count reached"); | |
| 2275 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | |
| 2276 SimulatorDebugger dbg(this); | |
| 2277 dbg.Stop(instr, "Instruction address reached"); | |
| 2278 } | |
| 2178 } | 2279 } |
| 2179 InstructionDecode(instr); | 2280 InstructionDecode(instr); |
| 2180 delay_slot_ = false; | 2281 delay_slot_ = false; |
| 2181 } | 2282 } |
| 2182 | 2283 |
| 2183 | 2284 |
| 2184 void Simulator::Execute() { | 2285 void Simulator::Execute() { |
| 2185 if (FLAG_stop_sim_at == 0) { | 2286 if (FLAG_stop_sim_at == 0) { |
| 2186 // Fast version of the dispatch loop without checking whether the simulator | 2287 // Fast version of the dispatch loop without checking whether the simulator |
| 2187 // should be stopping at a particular executed instruction. | 2288 // should be stopping at a particular executed instruction. |
| 2188 while (pc_ != kEndSimulatingPC) { | 2289 while (pc_ != kEndSimulatingPC) { |
| 2189 icount_++; | 2290 icount_++; |
| 2190 Instr* instr = Instr::At(pc_); | 2291 Instr* instr = Instr::At(pc_); |
| 2191 if (IsIllegalAddress(pc_)) { | 2292 if (IsIllegalAddress(pc_)) { |
| 2192 HandleIllegalAccess(pc_, instr); | 2293 HandleIllegalAccess(pc_, instr); |
| 2193 } else { | 2294 } else { |
| 2194 InstructionDecode(instr); | 2295 InstructionDecode(instr); |
| 2195 } | 2296 } |
| 2196 } | 2297 } |
| 2197 } else { | 2298 } else { |
| 2198 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 2299 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 2199 // we reach the particular instruction count. | 2300 // we reach the particular instruction count or address. |
| 2200 while (pc_ != kEndSimulatingPC) { | 2301 while (pc_ != kEndSimulatingPC) { |
| 2201 icount_++; | 2302 icount_++; |
| 2202 Instr* instr = Instr::At(pc_); | 2303 Instr* instr = Instr::At(pc_); |
| 2203 if (icount_ == FLAG_stop_sim_at) { | 2304 if (static_cast<int>(icount_) == FLAG_stop_sim_at) { |
| 2204 SimulatorDebugger dbg(this); | 2305 SimulatorDebugger dbg(this); |
| 2205 dbg.Stop(instr, "Instruction count reached"); | 2306 dbg.Stop(instr, "Instruction count reached"); |
| 2307 } else if (reinterpret_cast<int>(instr) == FLAG_stop_sim_at) { | |
|
zra
2014/12/05 17:41:03
Is this useful? Won't the address you want be diff
| |
| 2308 SimulatorDebugger dbg(this); | |
| 2309 dbg.Stop(instr, "Instruction address reached"); | |
| 2206 } else { | 2310 } else { |
| 2207 if (IsIllegalAddress(pc_)) { | 2311 if (IsIllegalAddress(pc_)) { |
| 2208 HandleIllegalAccess(pc_, instr); | 2312 HandleIllegalAccess(pc_, instr); |
| 2209 } else { | 2313 } else { |
| 2210 InstructionDecode(instr); | 2314 InstructionDecode(instr); |
| 2211 } | 2315 } |
| 2212 } | 2316 } |
| 2213 } | 2317 } |
| 2214 } | 2318 } |
| 2215 } | 2319 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2376 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); | 2480 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); |
| 2377 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); | 2481 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); |
| 2378 buf->Longjmp(); | 2482 buf->Longjmp(); |
| 2379 } | 2483 } |
| 2380 | 2484 |
| 2381 } // namespace dart | 2485 } // namespace dart |
| 2382 | 2486 |
| 2383 #endif // !defined(HOST_ARCH_MIPS) | 2487 #endif // !defined(HOST_ARCH_MIPS) |
| 2384 | 2488 |
| 2385 #endif // defined TARGET_ARCH_MIPS | 2489 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |