| 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> // 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" | |
| 20 #include "vm/native_arguments.h" | 19 #include "vm/native_arguments.h" |
| 21 #include "vm/os_thread.h" | 20 #include "vm/os_thread.h" |
| 22 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
| 23 | 22 |
| 24 namespace dart { | 23 namespace dart { |
| 25 | 24 |
| 26 DEFINE_FLAG(uint64_t, | 25 DEFINE_FLAG(uint64_t, |
| 27 trace_sim_after, | 26 trace_sim_after, |
| 28 ULLONG_MAX, | 27 ULLONG_MAX, |
| 29 "Trace simulator execution after instruction count reached."); | 28 "Trace simulator execution after instruction count reached."); |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 } | 698 } |
| 700 // Copy the newly read line into the result. | 699 // Copy the newly read line into the result. |
| 701 memmove(result + offset, line_buf, len); | 700 memmove(result + offset, line_buf, len); |
| 702 offset += len; | 701 offset += len; |
| 703 } | 702 } |
| 704 ASSERT(result != NULL); | 703 ASSERT(result != NULL); |
| 705 result[offset] = '\0'; | 704 result[offset] = '\0'; |
| 706 return result; | 705 return result; |
| 707 } | 706 } |
| 708 | 707 |
| 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 | |
| 715 void Simulator::InitOnce() { | 708 void Simulator::InitOnce() { |
| 716 // Setup exclusive access state lock. | |
| 717 exclusive_access_lock_ = new Mutex(); | |
| 718 } | 709 } |
| 719 | 710 |
| 720 Simulator::Simulator() { | 711 Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) { |
| 721 // Setup simulator support first. Some of this information is needed to | 712 // Setup simulator support first. Some of this information is needed to |
| 722 // setup the architecture state. | 713 // setup the architecture state. |
| 723 // We allocate the stack here, the size is computed as the sum of | 714 // We allocate the stack here, the size is computed as the sum of |
| 724 // the size specified by the user and the buffer space needed for | 715 // the size specified by the user and the buffer space needed for |
| 725 // handling stack overflow exceptions. To be safe in potential | 716 // handling stack overflow exceptions. To be safe in potential |
| 726 // stack underflows we also add some underflow buffer space. | 717 // stack underflows we also add some underflow buffer space. |
| 727 stack_ = | 718 stack_ = |
| 728 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + | 719 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
| 729 kSimulatorStackUnderflowSize)]; | 720 kSimulatorStackUnderflowSize)]; |
| 730 pc_modified_ = false; | 721 pc_modified_ = false; |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 int8_t Simulator::ReadB(uword addr) { | 1090 int8_t Simulator::ReadB(uword addr) { |
| 1100 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1091 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
| 1101 return *ptr; | 1092 return *ptr; |
| 1102 } | 1093 } |
| 1103 | 1094 |
| 1104 void Simulator::WriteB(uword addr, uint8_t value) { | 1095 void Simulator::WriteB(uword addr, uint8_t value) { |
| 1105 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1096 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
| 1106 *ptr = value; | 1097 *ptr = value; |
| 1107 } | 1098 } |
| 1108 | 1099 |
| 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 | |
| 1153 void Simulator::ClearExclusive() { | 1100 void Simulator::ClearExclusive() { |
| 1154 MutexLocker ml(exclusive_access_lock_); | 1101 exclusive_access_addr_ = 0; |
| 1155 // Remove the reservation for this thread. | 1102 exclusive_access_value_ = 0; |
| 1156 SetExclusiveAccess(0); | |
| 1157 } | 1103 } |
| 1158 | 1104 |
| 1159 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { | 1105 intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) { |
| 1160 MutexLocker ml(exclusive_access_lock_); | 1106 exclusive_access_addr_ = addr; |
| 1161 SetExclusiveAccess(addr); | 1107 exclusive_access_value_ = ReadX(addr, instr); |
| 1162 return ReadX(addr, instr); | 1108 return exclusive_access_value_; |
| 1163 } | 1109 } |
| 1164 | 1110 |
| 1165 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { | 1111 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
| 1166 MutexLocker ml(exclusive_access_lock_); | 1112 exclusive_access_addr_ = addr; |
| 1167 SetExclusiveAccess(addr); | 1113 exclusive_access_value_ = ReadWU(addr, instr); |
| 1168 return ReadWU(addr, instr); | 1114 return exclusive_access_value_; |
| 1169 } | 1115 } |
| 1170 | 1116 |
| 1171 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) { | 1117 intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) { |
| 1172 MutexLocker ml(exclusive_access_lock_); | 1118 // In a well-formed code store-exclusive instruction should always follow |
| 1173 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1119 // a corresponding load-exclusive instruction with the same address. |
| 1174 if (write_allowed) { | 1120 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); |
| 1175 WriteX(addr, value, instr); | 1121 if (exclusive_access_addr_ != addr) { |
| 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) { |
| 1176 return 0; // Success. | 1130 return 0; // Success. |
| 1177 } | 1131 } |
| 1178 return 1; // Failure. | 1132 return 1; // Failure. |
| 1179 } | 1133 } |
| 1180 | 1134 |
| 1181 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { | 1135 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
| 1182 MutexLocker ml(exclusive_access_lock_); | 1136 // In a well-formed code store-exclusive instruction should always follow |
| 1183 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1137 // a corresponding load-exclusive instruction with the same address. |
| 1184 if (write_allowed) { | 1138 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); |
| 1185 WriteW(addr, value, instr); | 1139 if (exclusive_access_addr_ != addr) { |
| 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) { |
| 1186 return 0; // Success. | 1148 return 0; // Success. |
| 1187 } | 1149 } |
| 1188 return 1; // Failure. | 1150 return 1; // Failure. |
| 1189 } | 1151 } |
| 1190 | 1152 |
| 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 | |
| 1229 // Unsupported instructions use Format to print an error and stop execution. | 1153 // Unsupported instructions use Format to print an error and stop execution. |
| 1230 void Simulator::Format(Instr* instr, const char* format) { | 1154 void Simulator::Format(Instr* instr, const char* format) { |
| 1231 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, | 1155 OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr, |
| 1232 format); | 1156 format); |
| 1233 UNIMPLEMENTED(); | 1157 UNIMPLEMENTED(); |
| 1234 } | 1158 } |
| 1235 | 1159 |
| 1236 // Calculate and set the Negative and Zero flags. | 1160 // Calculate and set the Negative and Zero flags. |
| 1237 void Simulator::SetNZFlagsW(int32_t val) { | 1161 void Simulator::SetNZFlagsW(int32_t val) { |
| 1238 n_flag_ = (val < 0); | 1162 n_flag_ = (val < 0); |
| (...skipping 2331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3570 set_register(NULL, CODE_REG, code); | 3494 set_register(NULL, CODE_REG, code); |
| 3571 set_register(NULL, PP, pp); | 3495 set_register(NULL, PP, pp); |
| 3572 buf->Longjmp(); | 3496 buf->Longjmp(); |
| 3573 } | 3497 } |
| 3574 | 3498 |
| 3575 } // namespace dart | 3499 } // namespace dart |
| 3576 | 3500 |
| 3577 #endif // !defined(USING_SIMULATOR) | 3501 #endif // !defined(USING_SIMULATOR) |
| 3578 | 3502 |
| 3579 #endif // defined TARGET_ARCH_ARM64 | 3503 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |