Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: runtime/vm/simulator_arm64.cc

Issue 3000803003: Revert "[vm] Implement more efficient CAS in simarm/simarm64 modes" (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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> // NOLINT 5 #include <setjmp.h> // NOLINT
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(USING_SIMULATOR) 12 #if defined(USING_SIMULATOR)
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/native_arguments.h" 20 #include "vm/native_arguments.h"
20 #include "vm/os_thread.h" 21 #include "vm/os_thread.h"
21 #include "vm/stack_frame.h" 22 #include "vm/stack_frame.h"
22 23
23 namespace dart { 24 namespace dart {
24 25
25 DEFINE_FLAG(uint64_t, 26 DEFINE_FLAG(uint64_t,
26 trace_sim_after, 27 trace_sim_after,
27 ULLONG_MAX, 28 ULLONG_MAX,
28 "Trace simulator execution after instruction count reached."); 29 "Trace simulator execution after instruction count reached.");
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 } 699 }
699 // Copy the newly read line into the result. 700 // Copy the newly read line into the result.
700 memmove(result + offset, line_buf, len); 701 memmove(result + offset, line_buf, len);
701 offset += len; 702 offset += len;
702 } 703 }
703 ASSERT(result != NULL); 704 ASSERT(result != NULL);
704 result[offset] = '\0'; 705 result[offset] = '\0';
705 return result; 706 return result;
706 } 707 }
707 708
709 // Synchronization primitives support.
710 Mutex* Simulator::exclusive_access_lock_ = NULL;
711 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = {
712 {NULL, 0}};
713 int Simulator::next_address_tag_ = 0;
714
708 void Simulator::InitOnce() { 715 void Simulator::InitOnce() {
716 // Setup exclusive access state lock.
717 exclusive_access_lock_ = new Mutex();
709 } 718 }
710 719
711 Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) { 720 Simulator::Simulator() {
712 // Setup simulator support first. Some of this information is needed to 721 // Setup simulator support first. Some of this information is needed to
713 // setup the architecture state. 722 // setup the architecture state.
714 // We allocate the stack here, the size is computed as the sum of 723 // We allocate the stack here, the size is computed as the sum of
715 // the size specified by the user and the buffer space needed for 724 // the size specified by the user and the buffer space needed for
716 // handling stack overflow exceptions. To be safe in potential 725 // handling stack overflow exceptions. To be safe in potential
717 // stack underflows we also add some underflow buffer space. 726 // stack underflows we also add some underflow buffer space.
718 stack_ = 727 stack_ =
719 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + 728 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer +
720 kSimulatorStackUnderflowSize)]; 729 kSimulatorStackUnderflowSize)];
721 pc_modified_ = false; 730 pc_modified_ = false;
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 int8_t Simulator::ReadB(uword addr) { 1099 int8_t Simulator::ReadB(uword addr) {
1091 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1100 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1092 return *ptr; 1101 return *ptr;
1093 } 1102 }
1094 1103
1095 void Simulator::WriteB(uword addr, uint8_t value) { 1104 void Simulator::WriteB(uword addr, uint8_t value) {
1096 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1105 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1097 *ptr = value; 1106 *ptr = value;
1098 } 1107 }
1099 1108
1109 // Synchronization primitives support.
1110 void Simulator::SetExclusiveAccess(uword addr) {
1111 Thread* thread = Thread::Current();
1112 ASSERT(thread != NULL);
1113 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
1114 int i = 0;
1115 // Find an entry for this thread in the exclusive access state.
1116 while ((i < kNumAddressTags) &&
1117 (exclusive_access_state_[i].thread != thread)) {
1118 i++;
1119 }
1120 // Round-robin replacement of previously used entries.
1121 if (i == kNumAddressTags) {
1122 i = next_address_tag_;
1123 if (++next_address_tag_ == kNumAddressTags) {
1124 next_address_tag_ = 0;
1125 }
1126 exclusive_access_state_[i].thread = thread;
1127 }
1128 // Remember the address being reserved.
1129 exclusive_access_state_[i].addr = addr;
1130 }
1131
1132 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
1133 Thread* thread = Thread::Current();
1134 ASSERT(thread != NULL);
1135 ASSERT(addr != 0);
1136 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
1137 bool result = false;
1138 for (int i = 0; i < kNumAddressTags; i++) {
1139 if (exclusive_access_state_[i].thread == thread) {
1140 // Check whether the current threads address reservation matches.
1141 if (exclusive_access_state_[i].addr == addr) {
1142 result = true;
1143 }
1144 exclusive_access_state_[i].addr = 0;
1145 } else if (exclusive_access_state_[i].addr == addr) {
1146 // Other threads with matching address lose their reservations.
1147 exclusive_access_state_[i].addr = 0;
1148 }
1149 }
1150 return result;
1151 }
1152
1100 void Simulator::ClearExclusive() { 1153 void Simulator::ClearExclusive() {
1101 exclusive_access_addr_ = 0; 1154 MutexLocker ml(exclusive_access_lock_);
1102 exclusive_access_value_ = 0; 1155 // Remove the reservation for this thread.
1156 SetExclusiveAccess(0);
1103 } 1157 }
1104 1158
1105 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { 1159 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) {
1106 exclusive_access_addr_ = addr; 1160 MutexLocker ml(exclusive_access_lock_);
1107 exclusive_access_value_ = ReadX(addr, instr); 1161 SetExclusiveAccess(addr);
1108 return exclusive_access_value_; 1162 return ReadX(addr, instr);
1109 } 1163 }
1110 1164
1111 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { 1165 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
1112 exclusive_access_addr_ = addr; 1166 MutexLocker ml(exclusive_access_lock_);
1113 exclusive_access_value_ = ReadWU(addr, instr); 1167 SetExclusiveAccess(addr);
1114 return exclusive_access_value_; 1168 return ReadWU(addr, instr);
1115 } 1169 }
1116 1170
1117 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) { 1171 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) {
1118 // In a well-formed code store-exclusive instruction should always follow 1172 MutexLocker ml(exclusive_access_lock_);
1119 // a corresponding load-exclusive instruction with the same address. 1173 bool write_allowed = HasExclusiveAccessAndOpen(addr);
1120 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); 1174 if (write_allowed) {
1121 if (exclusive_access_addr_ != addr) { 1175 WriteX(addr, value, instr);
1122 return 1; // Failure.
1123 }
1124
1125 uword old_value = exclusive_access_value_;
1126 ClearExclusive();
1127
1128 if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr),
1129 old_value, value) == old_value) {
1130 return 0; // Success. 1176 return 0; // Success.
1131 } 1177 }
1132 return 1; // Failure. 1178 return 1; // Failure.
1133 } 1179 }
1134 1180
1135 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { 1181 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
1136 // In a well-formed code store-exclusive instruction should always follow 1182 MutexLocker ml(exclusive_access_lock_);
1137 // a corresponding load-exclusive instruction with the same address. 1183 bool write_allowed = HasExclusiveAccessAndOpen(addr);
1138 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); 1184 if (write_allowed) {
1139 if (exclusive_access_addr_ != addr) { 1185 WriteW(addr, value, instr);
1140 return 1; // Failure.
1141 }
1142
1143 uint32_t old_value = static_cast<uint32_t>(exclusive_access_value_);
1144 ClearExclusive();
1145
1146 if (AtomicOperations::CompareAndSwapUint32(reinterpret_cast<uint32_t*>(addr),
1147 old_value, value) == old_value) {
1148 return 0; // Success. 1186 return 0; // Success.
1149 } 1187 }
1150 return 1; // Failure. 1188 return 1; // Failure.
1151 } 1189 }
1152 1190
1191 uword Simulator::CompareExchange(uword* address,
1192 uword compare_value,
1193 uword new_value) {
1194 MutexLocker ml(exclusive_access_lock_);
1195 // We do not get a reservation as it would be guaranteed to be found when
1196 // writing below. No other thread is able to make a reservation while we
1197 // hold the lock.
1198 uword value = *address;
1199 if (value == compare_value) {
1200 *address = new_value;
1201 // Same effect on exclusive access state as a successful STREX.
1202 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
1203 } else {
1204 // Same effect on exclusive access state as an LDREX.
1205 SetExclusiveAccess(reinterpret_cast<uword>(address));
1206 }
1207 return value;
1208 }
1209
1210 uint32_t Simulator::CompareExchangeUint32(uint32_t* address,
1211 uint32_t compare_value,
1212 uint32_t new_value) {
1213 MutexLocker ml(exclusive_access_lock_);
1214 // We do not get a reservation as it would be guaranteed to be found when
1215 // writing below. No other thread is able to make a reservation while we
1216 // hold the lock.
1217 uint32_t value = *address;
1218 if (value == compare_value) {
1219 *address = new_value;
1220 // Same effect on exclusive access state as a successful STREX.
1221 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
1222 } else {
1223 // Same effect on exclusive access state as an LDREX.
1224 SetExclusiveAccess(reinterpret_cast<uword>(address));
1225 }
1226 return value;
1227 }
1228
1153 // Unsupported instructions use Format to print an error and stop execution. 1229 // Unsupported instructions use Format to print an error and stop execution.
1154 void Simulator::Format(Instr* instr, const char* format) { 1230 void Simulator::Format(Instr* instr, const char* format) {
1155 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, 1231 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
1156 format); 1232 format);
1157 UNIMPLEMENTED(); 1233 UNIMPLEMENTED();
1158 } 1234 }
1159 1235
1160 // Calculate and set the Negative and Zero flags. 1236 // Calculate and set the Negative and Zero flags.
1161 void Simulator::SetNZFlagsW(int32_t val) { 1237 void Simulator::SetNZFlagsW(int32_t val) {
1162 n_flag_ = (val < 0); 1238 n_flag_ = (val < 0);
(...skipping 2331 matching lines...) Expand 10 before | Expand all | Expand 10 after
3494 set_register(NULL, CODE_REG, code); 3570 set_register(NULL, CODE_REG, code);
3495 set_register(NULL, PP, pp); 3571 set_register(NULL, PP, pp);
3496 buf->Longjmp(); 3572 buf->Longjmp();
3497 } 3573 }
3498 3574
3499 } // namespace dart 3575 } // namespace dart
3500 3576
3501 #endif // !defined(USING_SIMULATOR) 3577 #endif // !defined(USING_SIMULATOR)
3502 3578
3503 #endif // defined TARGET_ARCH_ARM64 3579 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/vm_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698