| Index: src/arm64/simulator-arm64.cc
|
| diff --git a/src/arm64/simulator-arm64.cc b/src/arm64/simulator-arm64.cc
|
| index 3c49b21e52d274373ce07b2c548162aa4d7f5981..83b4cf7ee8954f0838a8389eb3a5c971558eb5a2 100644
|
| --- a/src/arm64/simulator-arm64.cc
|
| +++ b/src/arm64/simulator-arm64.cc
|
| @@ -55,9 +55,6 @@
|
| TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : "";
|
| TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
|
|
|
| -// static
|
| -base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
|
| - LAZY_INSTANCE_INITIALIZER;
|
|
|
| // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
|
| void Simulator::TraceSim(const char* format, ...) {
|
| @@ -432,7 +429,6 @@
|
|
|
|
|
| Simulator::~Simulator() {
|
| - global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
|
| delete[] reinterpret_cast<byte*>(stack_);
|
| if (FLAG_log_instruction_stats) {
|
| delete instrument_;
|
| @@ -1632,15 +1628,6 @@
|
| uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
|
| uintptr_t stack = 0;
|
|
|
| - base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
| - if (instr->IsLoad()) {
|
| - local_monitor_.NotifyLoad(address);
|
| - } else {
|
| - local_monitor_.NotifyStore(address);
|
| - global_monitor_.Pointer()->NotifyStore_Locked(address,
|
| - &global_monitor_processor_);
|
| - }
|
| -
|
| // Handle the writeback for stores before the store. On a CPU the writeback
|
| // and the store are atomic, but when running on the simulator it is possible
|
| // to be interrupted in between. The simulator is not thread safe and V8 does
|
| @@ -1743,19 +1730,6 @@
|
| uintptr_t address2 = address + access_size;
|
| uintptr_t stack = 0;
|
|
|
| - base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
| - if (instr->IsLoad()) {
|
| - local_monitor_.NotifyLoad(address);
|
| - local_monitor_.NotifyLoad(address2);
|
| - } else {
|
| - local_monitor_.NotifyStore(address);
|
| - local_monitor_.NotifyStore(address2);
|
| - global_monitor_.Pointer()->NotifyStore_Locked(address,
|
| - &global_monitor_processor_);
|
| - global_monitor_.Pointer()->NotifyStore_Locked(address2,
|
| - &global_monitor_processor_);
|
| - }
|
| -
|
| // Handle the writeback for stores before the store. On a CPU the writeback
|
| // and the store are atomic, but when running on the simulator it is possible
|
| // to be interrupted in between. The simulator is not thread safe and V8 does
|
| @@ -1879,9 +1853,6 @@
|
| uintptr_t address = instr->LiteralAddress();
|
| unsigned rt = instr->Rt();
|
|
|
| - base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
| - local_monitor_.NotifyLoad(address);
|
| -
|
| switch (instr->Mask(LoadLiteralMask)) {
|
| // Use _no_log variants to suppress the register trace (LOG_REGS,
|
| // LOG_FP_REGS), then print a more detailed log.
|
| @@ -1935,81 +1906,8 @@
|
| }
|
| }
|
|
|
| -Simulator::TransactionSize Simulator::get_transaction_size(unsigned size) {
|
| - switch (size) {
|
| - case 0:
|
| - return TransactionSize::None;
|
| - case 1:
|
| - return TransactionSize::Byte;
|
| - case 2:
|
| - return TransactionSize::HalfWord;
|
| - case 4:
|
| - return TransactionSize::Word;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - return TransactionSize::None;
|
| -}
|
| -
|
| void Simulator::VisitLoadStoreAcquireRelease(Instruction* instr) {
|
| - unsigned rs = instr->Rs();
|
| - unsigned rt = instr->Rt();
|
| - unsigned rn = instr->Rn();
|
| - LoadStoreAcquireReleaseOp op = static_cast<LoadStoreAcquireReleaseOp>(
|
| - instr->Mask(LoadStoreAcquireReleaseMask));
|
| - int32_t is_acquire_release = instr->LoadStoreXAcquireRelease();
|
| - int32_t is_not_exclusive = instr->LoadStoreXNotExclusive();
|
| - int32_t is_load = instr->LoadStoreXLoad();
|
| - int32_t is_pair = instr->LoadStoreXPair();
|
| - DCHECK_NE(is_acquire_release, 0);
|
| - DCHECK_EQ(is_not_exclusive, 0); // Non exclusive unimplemented.
|
| - DCHECK_EQ(is_pair, 0); // Pair unimplemented.
|
| - unsigned access_size = 1 << instr->LoadStoreXSizeLog2();
|
| - uintptr_t address = LoadStoreAddress(rn, 0, AddrMode::Offset);
|
| - DCHECK(address % access_size == 0);
|
| - base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
|
| - if (is_load != 0) {
|
| - local_monitor_.NotifyLoadExcl(address, get_transaction_size(access_size));
|
| - global_monitor_.Pointer()->NotifyLoadExcl_Locked(
|
| - address, &global_monitor_processor_);
|
| - switch (op) {
|
| - case LDAXR_b:
|
| - set_wreg_no_log(rt, MemoryRead<uint8_t>(address));
|
| - break;
|
| - case LDAXR_h:
|
| - set_wreg_no_log(rt, MemoryRead<uint16_t>(address));
|
| - break;
|
| - case LDAXR_w:
|
| - set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
|
| - break;
|
| - default:
|
| - UNIMPLEMENTED();
|
| - }
|
| - LogRead(address, access_size, rt);
|
| - } else {
|
| - if (local_monitor_.NotifyStoreExcl(address,
|
| - get_transaction_size(access_size)) &&
|
| - global_monitor_.Pointer()->NotifyStoreExcl_Locked(
|
| - address, &global_monitor_processor_)) {
|
| - switch (op) {
|
| - case STLXR_b:
|
| - MemoryWrite<uint8_t>(address, wreg(rt));
|
| - break;
|
| - case STLXR_h:
|
| - MemoryWrite<uint16_t>(address, wreg(rt));
|
| - break;
|
| - case STLXR_w:
|
| - MemoryWrite<uint32_t>(address, wreg(rt));
|
| - break;
|
| - default:
|
| - UNIMPLEMENTED();
|
| - }
|
| - LogWrite(address, access_size, rt);
|
| - set_wreg(rs, 0);
|
| - } else {
|
| - set_wreg(rs, 1);
|
| - }
|
| - }
|
| + // TODO(binji)
|
| }
|
|
|
| void Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) {
|
| @@ -3979,186 +3877,6 @@
|
| delete[] format;
|
| }
|
|
|
| -Simulator::LocalMonitor::LocalMonitor()
|
| - : access_state_(MonitorAccess::Open),
|
| - tagged_addr_(0),
|
| - size_(TransactionSize::None) {}
|
| -
|
| -void Simulator::LocalMonitor::Clear() {
|
| - access_state_ = MonitorAccess::Open;
|
| - tagged_addr_ = 0;
|
| - size_ = TransactionSize::None;
|
| -}
|
| -
|
| -void Simulator::LocalMonitor::NotifyLoad(uintptr_t addr) {
|
| - if (access_state_ == MonitorAccess::Exclusive) {
|
| - // A non exclusive load could clear the local monitor. As a result, it's
|
| - // most strict to unconditionally clear the local monitor on load.
|
| - Clear();
|
| - }
|
| -}
|
| -
|
| -void Simulator::LocalMonitor::NotifyLoadExcl(uintptr_t addr,
|
| - TransactionSize size) {
|
| - access_state_ = MonitorAccess::Exclusive;
|
| - tagged_addr_ = addr;
|
| - size_ = size;
|
| -}
|
| -
|
| -void Simulator::LocalMonitor::NotifyStore(uintptr_t addr) {
|
| - if (access_state_ == MonitorAccess::Exclusive) {
|
| - // A non exclusive store could clear the local monitor. As a result, it's
|
| - // most strict to unconditionally clear the local monitor on store.
|
| - Clear();
|
| - }
|
| -}
|
| -
|
| -bool Simulator::LocalMonitor::NotifyStoreExcl(uintptr_t addr,
|
| - TransactionSize size) {
|
| - if (access_state_ == MonitorAccess::Exclusive) {
|
| - // It is allowed for a processor to require that the address matches
|
| - // exactly (B2.10.1), so this comparison does not mask addr.
|
| - if (addr == tagged_addr_ && size_ == size) {
|
| - Clear();
|
| - return true;
|
| - } else {
|
| - // It is implementation-defined whether an exclusive store to a
|
| - // non-tagged address will update memory. As a result, it's most strict
|
| - // to unconditionally clear the local monitor.
|
| - Clear();
|
| - return false;
|
| - }
|
| - } else {
|
| - DCHECK(access_state_ == MonitorAccess::Open);
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -Simulator::GlobalMonitor::Processor::Processor()
|
| - : access_state_(MonitorAccess::Open),
|
| - tagged_addr_(0),
|
| - next_(nullptr),
|
| - prev_(nullptr),
|
| - failure_counter_(0) {}
|
| -
|
| -void Simulator::GlobalMonitor::Processor::Clear_Locked() {
|
| - access_state_ = MonitorAccess::Open;
|
| - tagged_addr_ = 0;
|
| -}
|
| -
|
| -void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(
|
| - uintptr_t addr) {
|
| - access_state_ = MonitorAccess::Exclusive;
|
| - tagged_addr_ = addr;
|
| -}
|
| -
|
| -void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
|
| - uintptr_t addr, bool is_requesting_processor) {
|
| - if (access_state_ == MonitorAccess::Exclusive) {
|
| - // A non exclusive store could clear the global monitor. As a result, it's
|
| - // most strict to unconditionally clear global monitors on store.
|
| - Clear_Locked();
|
| - }
|
| -}
|
| -
|
| -bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
|
| - uintptr_t addr, bool is_requesting_processor) {
|
| - if (access_state_ == MonitorAccess::Exclusive) {
|
| - if (is_requesting_processor) {
|
| - // It is allowed for a processor to require that the address matches
|
| - // exactly (B2.10.2), so this comparison does not mask addr.
|
| - if (addr == tagged_addr_) {
|
| - Clear_Locked();
|
| - // Introduce occasional stxr failures. This is to simulate the
|
| - // behavior of hardware, which can randomly fail due to background
|
| - // cache evictions.
|
| - if (failure_counter_++ >= kMaxFailureCounter) {
|
| - failure_counter_ = 0;
|
| - return false;
|
| - } else {
|
| - return true;
|
| - }
|
| - }
|
| - } else if ((addr & kExclusiveTaggedAddrMask) ==
|
| - (tagged_addr_ & kExclusiveTaggedAddrMask)) {
|
| - // Check the masked addresses when responding to a successful lock by
|
| - // another processor so the implementation is more conservative (i.e. the
|
| - // granularity of locking is as large as possible.)
|
| - Clear_Locked();
|
| - return false;
|
| - }
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
|
| -
|
| -void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(uintptr_t addr,
|
| - Processor* processor) {
|
| - processor->NotifyLoadExcl_Locked(addr);
|
| - PrependProcessor_Locked(processor);
|
| -}
|
| -
|
| -void Simulator::GlobalMonitor::NotifyStore_Locked(uintptr_t addr,
|
| - Processor* processor) {
|
| - // Notify each processor of the store operation.
|
| - for (Processor* iter = head_; iter; iter = iter->next_) {
|
| - bool is_requesting_processor = iter == processor;
|
| - iter->NotifyStore_Locked(addr, is_requesting_processor);
|
| - }
|
| -}
|
| -
|
| -bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(uintptr_t addr,
|
| - Processor* processor) {
|
| - DCHECK(IsProcessorInLinkedList_Locked(processor));
|
| - if (processor->NotifyStoreExcl_Locked(addr, true)) {
|
| - // Notify the other processors that this StoreExcl succeeded.
|
| - for (Processor* iter = head_; iter; iter = iter->next_) {
|
| - if (iter != processor) {
|
| - iter->NotifyStoreExcl_Locked(addr, false);
|
| - }
|
| - }
|
| - return true;
|
| - } else {
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
|
| - Processor* processor) const {
|
| - return head_ == processor || processor->next_ || processor->prev_;
|
| -}
|
| -
|
| -void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
|
| - if (IsProcessorInLinkedList_Locked(processor)) {
|
| - return;
|
| - }
|
| -
|
| - if (head_) {
|
| - head_->prev_ = processor;
|
| - }
|
| - processor->prev_ = nullptr;
|
| - processor->next_ = head_;
|
| - head_ = processor;
|
| -}
|
| -
|
| -void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
|
| - base::LockGuard<base::Mutex> lock_guard(&mutex);
|
| - if (!IsProcessorInLinkedList_Locked(processor)) {
|
| - return;
|
| - }
|
| -
|
| - if (processor->prev_) {
|
| - processor->prev_->next_ = processor->next_;
|
| - } else {
|
| - head_ = processor->next_;
|
| - }
|
| - if (processor->next_) {
|
| - processor->next_->prev_ = processor->prev_;
|
| - }
|
| - processor->prev_ = nullptr;
|
| - processor->next_ = nullptr;
|
| -}
|
|
|
| #endif // USE_SIMULATOR
|
|
|
|
|