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

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

Issue 2999853002: [vm] Implement more efficient CAS in simarm/simarm64 modes, v.2 (Closed)
Patch Set: Include simulator.h explicitly where it is required 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_arm.h ('k') | runtime/vm/simulator_arm64.h » ('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) 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> // 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_ARM) 9 #if defined(TARGET_ARCH_ARM)
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_arm.h" 17 #include "vm/constants_arm.h"
18 #include "vm/cpu.h" 18 #include "vm/cpu.h"
19 #include "vm/disassembler.h" 19 #include "vm/disassembler.h"
20 #include "vm/lockers.h"
21 #include "vm/native_arguments.h" 20 #include "vm/native_arguments.h"
22 #include "vm/os_thread.h" 21 #include "vm/os_thread.h"
23 #include "vm/stack_frame.h" 22 #include "vm/stack_frame.h"
24 23
25 namespace dart { 24 namespace dart {
26 25
27 DEFINE_FLAG(uint64_t, 26 DEFINE_FLAG(uint64_t,
28 trace_sim_after, 27 trace_sim_after,
29 ULLONG_MAX, 28 ULLONG_MAX,
30 "Trace simulator execution after instruction count reached."); 29 "Trace simulator execution after instruction count reached.");
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 } 651 }
653 // Copy the newly read line into the result. 652 // Copy the newly read line into the result.
654 memmove(result + offset, line_buf, len); 653 memmove(result + offset, line_buf, len);
655 offset += len; 654 offset += len;
656 } 655 }
657 ASSERT(result != NULL); 656 ASSERT(result != NULL);
658 result[offset] = '\0'; 657 result[offset] = '\0';
659 return result; 658 return result;
660 } 659 }
661 660
662 // Synchronization primitives support.
663 Mutex* Simulator::exclusive_access_lock_ = NULL;
664 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = {
665 {NULL, 0}};
666 int Simulator::next_address_tag_ = 0;
667
668 void Simulator::InitOnce() { 661 void Simulator::InitOnce() {
669 // Setup exclusive access state lock.
670 exclusive_access_lock_ = new Mutex();
671 } 662 }
672 663
673 Simulator::Simulator() { 664 Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) {
674 // Setup simulator support first. Some of this information is needed to 665 // Setup simulator support first. Some of this information is needed to
675 // setup the architecture state. 666 // setup the architecture state.
676 // We allocate the stack here, the size is computed as the sum of 667 // We allocate the stack here, the size is computed as the sum of
677 // the size specified by the user and the buffer space needed for 668 // the size specified by the user and the buffer space needed for
678 // handling stack overflow exceptions. To be safe in potential 669 // handling stack overflow exceptions. To be safe in potential
679 // stack underflows we also add some underflow buffer space. 670 // stack underflows we also add some underflow buffer space.
680 stack_ = 671 stack_ =
681 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + 672 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer +
682 kSimulatorStackUnderflowSize)]; 673 kSimulatorStackUnderflowSize)];
683 pc_modified_ = false; 674 pc_modified_ = false;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 int8_t Simulator::ReadB(uword addr) { 1008 int8_t Simulator::ReadB(uword addr) {
1018 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1009 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1019 return *ptr; 1010 return *ptr;
1020 } 1011 }
1021 1012
1022 void Simulator::WriteB(uword addr, uint8_t value) { 1013 void Simulator::WriteB(uword addr, uint8_t value) {
1023 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1014 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1024 *ptr = value; 1015 *ptr = value;
1025 } 1016 }
1026 1017
1027 // Synchronization primitives support.
1028 void Simulator::SetExclusiveAccess(uword addr) {
1029 Thread* thread = Thread::Current();
1030 ASSERT(thread != NULL);
1031 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
1032 int i = 0;
1033 // Find an entry for this thread in the exclusive access state.
1034 while ((i < kNumAddressTags) &&
1035 (exclusive_access_state_[i].thread != thread)) {
1036 i++;
1037 }
1038 // Round-robin replacement of previously used entries.
1039 if (i == kNumAddressTags) {
1040 i = next_address_tag_;
1041 if (++next_address_tag_ == kNumAddressTags) {
1042 next_address_tag_ = 0;
1043 }
1044 exclusive_access_state_[i].thread = thread;
1045 }
1046 // Remember the address being reserved.
1047 exclusive_access_state_[i].addr = addr;
1048 }
1049
1050 bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
1051 Thread* thread = Thread::Current();
1052 ASSERT(thread != NULL);
1053 ASSERT(addr != 0);
1054 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread());
1055 bool result = false;
1056 for (int i = 0; i < kNumAddressTags; i++) {
1057 if (exclusive_access_state_[i].thread == thread) {
1058 // Check whether the current thread's address reservation matches.
1059 if (exclusive_access_state_[i].addr == addr) {
1060 result = true;
1061 }
1062 exclusive_access_state_[i].addr = 0;
1063 } else if (exclusive_access_state_[i].addr == addr) {
1064 // Other threads with matching address lose their reservations.
1065 exclusive_access_state_[i].addr = 0;
1066 }
1067 }
1068 return result;
1069 }
1070
1071 void Simulator::ClearExclusive() { 1018 void Simulator::ClearExclusive() {
1072 MutexLocker ml(exclusive_access_lock_); 1019 exclusive_access_addr_ = 0;
1073 // Remove the reservation for this thread. 1020 exclusive_access_value_ = 0;
1074 SetExclusiveAccess(0);
1075 } 1021 }
1076 1022
1077 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { 1023 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
1078 MutexLocker ml(exclusive_access_lock_); 1024 exclusive_access_addr_ = addr;
1079 SetExclusiveAccess(addr); 1025 exclusive_access_value_ = ReadW(addr, instr);
1080 return ReadW(addr, instr); 1026 return exclusive_access_value_;
1081 } 1027 }
1082 1028
1083 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { 1029 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
1084 MutexLocker ml(exclusive_access_lock_); 1030 // In a well-formed code store-exclusive instruction should always follow
1085 bool write_allowed = HasExclusiveAccessAndOpen(addr); 1031 // a corresponding load-exclusive instruction with the same address.
1086 if (write_allowed) { 1032 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr));
1087 WriteW(addr, value, instr); 1033 if (exclusive_access_addr_ != addr) {
1034 return 1; // Failure.
1035 }
1036
1037 uword old_value = exclusive_access_value_;
1038 ClearExclusive();
1039
1040 if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr),
1041 old_value, value) == old_value) {
1088 return 0; // Success. 1042 return 0; // Success.
1089 } 1043 }
1090 return 1; // Failure. 1044 return 1; // Failure.
1091 } 1045 }
1092 1046
1093 uword Simulator::CompareExchange(uword* address,
1094 uword compare_value,
1095 uword new_value) {
1096 MutexLocker ml(exclusive_access_lock_);
1097 // We do not get a reservation as it would be guaranteed to be found when
1098 // writing below. No other thread is able to make a reservation while we
1099 // hold the lock.
1100 uword value = *address;
1101 if (value == compare_value) {
1102 *address = new_value;
1103 // Same effect on exclusive access state as a successful STREX.
1104 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
1105 } else {
1106 // Same effect on exclusive access state as an LDREX.
1107 SetExclusiveAccess(reinterpret_cast<uword>(address));
1108 }
1109 return value;
1110 }
1111
1112 uint32_t Simulator::CompareExchangeUint32(uint32_t* address,
1113 uint32_t compare_value,
1114 uint32_t new_value) {
1115 COMPILE_ASSERT(sizeof(uword) == sizeof(uint32_t));
1116 return CompareExchange(reinterpret_cast<uword*>(address),
1117 static_cast<uword>(compare_value),
1118 static_cast<uword>(new_value));
1119 }
1120
1121 // Returns the top of the stack area to enable checking for stack pointer 1047 // Returns the top of the stack area to enable checking for stack pointer
1122 // validity. 1048 // validity.
1123 uword Simulator::StackTop() const { 1049 uword Simulator::StackTop() const {
1124 // To be safe in potential stack underflows we leave some buffer above and 1050 // To be safe in potential stack underflows we leave some buffer above and
1125 // set the stack top. 1051 // set the stack top.
1126 return StackBase() + 1052 return StackBase() +
1127 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); 1053 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer);
1128 } 1054 }
1129 1055
1130 bool Simulator::IsTracingExecution() const { 1056 bool Simulator::IsTracingExecution() const {
(...skipping 2699 matching lines...) Expand 10 before | Expand all | Expand 10 after
3830 set_register(CODE_REG, code); 3756 set_register(CODE_REG, code);
3831 set_register(PP, pp); 3757 set_register(PP, pp);
3832 buf->Longjmp(); 3758 buf->Longjmp();
3833 } 3759 }
3834 3760
3835 } // namespace dart 3761 } // namespace dart
3836 3762
3837 #endif // defined(USING_SIMULATOR) 3763 #endif // defined(USING_SIMULATOR)
3838 3764
3839 #endif // defined TARGET_ARCH_ARM 3765 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | runtime/vm/simulator_arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698