AtomicOperations-mips-shared.h (6247B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* For documentation, see jit/AtomicOperations.h */ 8 9 #ifndef jit_mips_shared_AtomicOperations_mips_shared_h 10 #define jit_mips_shared_AtomicOperations_mips_shared_h 11 12 #include "mozilla/Assertions.h" 13 14 #include "builtin/AtomicsObject.h" 15 #include "vm/Uint8Clamped.h" 16 17 #if !defined(__clang__) && !defined(__GNUC__) 18 # error "This file only for gcc-compatible compilers" 19 #endif 20 21 inline bool js::jit::AtomicOperations::hasAtomic8() { return true; } 22 23 inline bool js::jit::AtomicOperations::isLockfree8() { 24 MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0)); 25 MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0)); 26 MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0)); 27 MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0)); 28 return true; 29 } 30 31 inline void js::jit::AtomicOperations::fenceSeqCst() { 32 __atomic_thread_fence(__ATOMIC_SEQ_CST); 33 } 34 35 namespace js { 36 namespace jit { 37 38 inline void AtomicPause() { asm volatile("sync" ::: "memory"); } 39 40 } // namespace jit 41 } // namespace js 42 43 inline void js::jit::AtomicOperations::pause() { AtomicPause(); } 44 45 template <typename T> 46 inline T js::jit::AtomicOperations::loadSeqCst(T* addr) { 47 static_assert(sizeof(T) <= sizeof(void*), 48 "atomics supported up to pointer size only"); 49 T v; 50 __atomic_load(addr, &v, __ATOMIC_SEQ_CST); 51 return v; 52 } 53 54 template <typename T> 55 inline void js::jit::AtomicOperations::storeSeqCst(T* addr, T val) { 56 static_assert(sizeof(T) <= sizeof(void*), 57 "atomics supported up to pointer size only"); 58 __atomic_store(addr, &val, __ATOMIC_SEQ_CST); 59 } 60 61 template <typename T> 62 inline T js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, 63 T newval) { 64 static_assert(sizeof(T) <= sizeof(void*), 65 "atomics supported up to pointer size only"); 66 __atomic_compare_exchange(addr, &oldval, &newval, false, __ATOMIC_SEQ_CST, 67 __ATOMIC_SEQ_CST); 68 return oldval; 69 } 70 71 template <typename T> 72 inline T js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val) { 73 static_assert(sizeof(T) <= sizeof(void*), 74 "atomics supported up to pointer size only"); 75 return __atomic_fetch_add(addr, val, __ATOMIC_SEQ_CST); 76 } 77 78 template <typename T> 79 inline T js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val) { 80 static_assert(sizeof(T) <= sizeof(void*), 81 "atomics supported up to pointer size only"); 82 return __atomic_fetch_sub(addr, val, __ATOMIC_SEQ_CST); 83 } 84 85 template <typename T> 86 inline T js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val) { 87 static_assert(sizeof(T) <= sizeof(void*), 88 "atomics supported up to pointer size only"); 89 return __atomic_fetch_and(addr, val, __ATOMIC_SEQ_CST); 90 } 91 92 template <typename T> 93 inline T js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val) { 94 static_assert(sizeof(T) <= sizeof(void*), 95 "atomics supported up to pointer size only"); 96 return __atomic_fetch_or(addr, val, __ATOMIC_SEQ_CST); 97 } 98 99 template <typename T> 100 inline T js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val) { 101 static_assert(sizeof(T) <= sizeof(void*), 102 "atomics supported up to pointer size only"); 103 return __atomic_fetch_xor(addr, val, __ATOMIC_SEQ_CST); 104 } 105 106 template <typename T> 107 inline T js::jit::AtomicOperations::loadSafeWhenRacy(T* addr) { 108 static_assert(sizeof(T) <= sizeof(void*), 109 "atomics supported up to pointer size only"); 110 T v; 111 __atomic_load(addr, &v, __ATOMIC_RELAXED); 112 return v; 113 } 114 115 namespace js { 116 namespace jit { 117 118 template <> 119 inline uint8_clamped js::jit::AtomicOperations::loadSafeWhenRacy( 120 uint8_clamped* addr) { 121 uint8_t v; 122 __atomic_load((uint8_t*)addr, &v, __ATOMIC_RELAXED); 123 return uint8_clamped(v); 124 } 125 126 template <> 127 inline float js::jit::AtomicOperations::loadSafeWhenRacy(float* addr) { 128 return *addr; 129 } 130 131 template <> 132 inline double js::jit::AtomicOperations::loadSafeWhenRacy(double* addr) { 133 return *addr; 134 } 135 136 } // namespace jit 137 } // namespace js 138 139 template <typename T> 140 inline void js::jit::AtomicOperations::storeSafeWhenRacy(T* addr, T val) { 141 static_assert(sizeof(T) <= sizeof(void*), 142 "atomics supported up to pointer size only"); 143 __atomic_store(addr, &val, __ATOMIC_RELAXED); 144 } 145 146 namespace js { 147 namespace jit { 148 149 template <> 150 inline void js::jit::AtomicOperations::storeSafeWhenRacy(uint8_clamped* addr, 151 uint8_clamped val) { 152 __atomic_store((uint8_t*)addr, (uint8_t*)&val, __ATOMIC_RELAXED); 153 } 154 155 template <> 156 inline void js::jit::AtomicOperations::storeSafeWhenRacy(float* addr, 157 float val) { 158 *addr = val; 159 } 160 161 template <> 162 inline void js::jit::AtomicOperations::storeSafeWhenRacy(double* addr, 163 double val) { 164 *addr = val; 165 } 166 167 } // namespace jit 168 } // namespace js 169 170 inline void js::jit::AtomicOperations::memcpySafeWhenRacy(void* dest, 171 const void* src, 172 size_t nbytes) { 173 MOZ_ASSERT(!((char*)dest <= (char*)src && (char*)src < (char*)dest + nbytes)); 174 MOZ_ASSERT(!((char*)src <= (char*)dest && (char*)dest < (char*)src + nbytes)); 175 ::memcpy(dest, src, nbytes); 176 } 177 178 inline void js::jit::AtomicOperations::memmoveSafeWhenRacy(void* dest, 179 const void* src, 180 size_t nbytes) { 181 ::memmove(dest, src, nbytes); 182 } 183 184 template <typename T> 185 inline T js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val) { 186 static_assert(sizeof(T) <= sizeof(void*), 187 "atomics supported up to pointer size only"); 188 T v; 189 __atomic_exchange(addr, &val, &v, __ATOMIC_SEQ_CST); 190 return v; 191 } 192 193 #endif // jit_mips_shared_AtomicOperations_mips_shared_h