OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 | 5 |
6 // Declares a Simulator for ARM instructions if we are not generating a native | 6 // Declares a Simulator for ARM instructions if we are not generating a native |
7 // ARM binary. This Simulator allows us to run and debug ARM code generation on | 7 // ARM binary. This Simulator allows us to run and debug ARM code generation on |
8 // regular desktop machines. | 8 // regular desktop machines. |
9 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, | 9 // V8 calls into generated code by "calling" the CALL_GENERATED_CODE macro, |
10 // which will start execution in the Simulator or forwards to the real entry | 10 // which will start execution in the Simulator or forwards to the real entry |
11 // on a ARM HW platform. | 11 // on a ARM HW platform. |
12 | 12 |
13 #ifndef V8_ARM_SIMULATOR_ARM_H_ | 13 #ifndef V8_ARM_SIMULATOR_ARM_H_ |
14 #define V8_ARM_SIMULATOR_ARM_H_ | 14 #define V8_ARM_SIMULATOR_ARM_H_ |
15 | 15 |
16 #include "src/allocation.h" | 16 #include "src/allocation.h" |
17 #include "src/base/lazy-instance.h" | |
18 #include "src/base/platform/mutex.h" | |
17 | 19 |
18 #if !defined(USE_SIMULATOR) | 20 #if !defined(USE_SIMULATOR) |
19 // Running without a simulator on a native arm platform. | 21 // Running without a simulator on a native arm platform. |
20 | 22 |
21 namespace v8 { | 23 namespace v8 { |
22 namespace internal { | 24 namespace internal { |
23 | 25 |
24 // When running without a simulator we call the entry directly. | 26 // When running without a simulator we call the entry directly. |
25 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ | 27 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ |
26 (entry(p0, p1, p2, p3, p4)) | 28 (entry(p0, p1, p2, p3, p4)) |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
422 | 424 |
423 // A stop is enabled, meaning the simulator will stop when meeting the | 425 // A stop is enabled, meaning the simulator will stop when meeting the |
424 // instruction, if bit 31 of watched_stops_[code].count is unset. | 426 // instruction, if bit 31 of watched_stops_[code].count is unset. |
425 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times | 427 // The value watched_stops_[code].count & ~(1 << 31) indicates how many times |
426 // the breakpoint was hit or gone through. | 428 // the breakpoint was hit or gone through. |
427 struct StopCountAndDesc { | 429 struct StopCountAndDesc { |
428 uint32_t count; | 430 uint32_t count; |
429 char* desc; | 431 char* desc; |
430 }; | 432 }; |
431 StopCountAndDesc watched_stops_[kNumOfWatchedStops]; | 433 StopCountAndDesc watched_stops_[kNumOfWatchedStops]; |
434 | |
435 // Syncronization primitives. See ARM DDI 0406C.b, A2.9. | |
436 class DataMonitor { | |
437 public: | |
438 DataMonitor(); | |
439 | |
440 // Read and write exclusive. The writes return the strex status: 0 if the | |
441 // write succeeds, and 1 if the write fails. | |
442 uint8_t ReadExBU(Simulator* simulator, int32_t addr); | |
443 int WriteExB(Simulator* simulator, | |
444 int32_t addr, | |
445 uint8_t value); | |
446 | |
447 uint16_t ReadExHU(Simulator* simulator, int32_t addr, Instruction* instr); | |
448 int WriteExH(Simulator* simulator, | |
449 int32_t addr, | |
450 uint16_t value, | |
451 Instruction* instr); | |
452 | |
453 int ReadExW(Simulator* simulator, int32_t addr, Instruction* instr); | |
454 int WriteExW(Simulator* simulator, | |
455 int32_t addr, | |
456 int value, | |
457 Instruction* instr); | |
458 | |
459 private: | |
460 // Common code for exclusive loads/stores. WriteExInternal returns true if | |
461 // the write will succeed. | |
462 void ReadExInternal_Locked(int32_t addr); | |
463 bool WriteExInternal_Locked(int32_t addr); | |
464 | |
465 void RemoveNode_Locked(); | |
466 void PrependNode_Locked(); | |
467 DataMonitor* FirstNodeWithTaggedAddr_Locked(int32_t addr); | |
468 | |
469 // The exclusive range of a tagged address has an implementation defined | |
470 // size, with a minimum size of the access size, and a maximum size of 128 | |
471 // bytes. | |
472 static const int32_t kAddrMask = ~7; | |
473 | |
474 enum class Access { | |
475 Open, | |
476 Exclusive, | |
477 }; | |
478 | |
479 static base::LazyMutex mutex_; | |
480 | |
481 Access access_state_; | |
482 int32_t tagged_addr_; | |
483 | |
484 // An Isolate's DataMonitor is only in this linked list if it currently has | |
485 // exclusive access for some address range. | |
jbramley
2016/05/31 16:58:47
The global monitor remembers a single outstanding
binji
2016/06/01 21:06:40
I was writing this as though each Simulator is one
| |
486 static DataMonitor* head_; | |
jbramley
2016/05/31 16:58:47
I can't see how the list is allocated. Does this c
binji
2016/06/01 21:06:40
Each DataMonitor is a node in the list, so it is a
| |
487 DataMonitor* next_; | |
488 DataMonitor* prev_; | |
489 }; | |
490 | |
491 DataMonitor data_monitor_; | |
432 }; | 492 }; |
433 | 493 |
434 | 494 |
435 // When running with the simulator transition into simulated execution at this | 495 // When running with the simulator transition into simulated execution at this |
436 // point. | 496 // point. |
437 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ | 497 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \ |
438 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ | 498 reinterpret_cast<Object*>(Simulator::current(isolate)->Call( \ |
439 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) | 499 FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4)) |
440 | 500 |
441 #define CALL_GENERATED_FP_INT(isolate, entry, p0, p1) \ | 501 #define CALL_GENERATED_FP_INT(isolate, entry, p0, p1) \ |
(...skipping 25 matching lines...) Expand all Loading... | |
467 static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { | 527 static inline void UnregisterCTryCatch(v8::internal::Isolate* isolate) { |
468 Simulator::current(isolate)->PopAddress(); | 528 Simulator::current(isolate)->PopAddress(); |
469 } | 529 } |
470 }; | 530 }; |
471 | 531 |
472 } // namespace internal | 532 } // namespace internal |
473 } // namespace v8 | 533 } // namespace v8 |
474 | 534 |
475 #endif // !defined(USE_SIMULATOR) | 535 #endif // !defined(USE_SIMULATOR) |
476 #endif // V8_ARM_SIMULATOR_ARM_H_ | 536 #endif // V8_ARM_SIMULATOR_ARM_H_ |
OLD | NEW |