Skip to content

Commit 408896a

Browse files
Ivica BogosavljevicCommit Bot
authored andcommitted
MIPS: Implement 64-bit atomics in software
MIPS architecture doesn't have support for 64-bit atomics. It is possible to implement them using 32-bit atomics, but the process is involved and takes time. For the time being support 64-bit atomics using runtime. Bug: v8:8100 Change-Id: I8c732ea9975c46be70643a1e722d78938c8a70de Reviewed-on: https://chromium-review.googlesource.com/1251521 Commit-Queue: Ivica Bogosavljevic <[email protected]> Reviewed-by: Jakob Kummerow <[email protected]> Cr-Commit-Position: refs/heads/master@{#56331}
1 parent 393b17a commit 408896a

4 files changed

Lines changed: 115 additions & 6 deletions

File tree

BUILD.gn

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,6 +2975,15 @@ v8_source_set("v8_base") {
29752975
sources += [ "$target_gen_dir/debug-support.cc" ]
29762976
deps += [ ":postmortem-metadata" ]
29772977
}
2978+
2979+
# Platforms that don't have CAS support need to link atomic library
2980+
# to implement atomic memory access
2981+
if (v8_current_cpu == "mips" || v8_current_cpu == "mipsel" ||
2982+
v8_current_cpu == "mips64" || v8_current_cpu == "mips64el" ||
2983+
v8_current_cpu == "ppc" || v8_current_cpu == "ppc64" ||
2984+
v8_current_cpu == "s390" || v8_current_cpu == "s390x") {
2985+
libs = [ "atomic" ]
2986+
}
29782987
}
29792988

29802989
v8_source_set("torque_base") {

src/builtins/builtins-sharedarraybuffer-gen.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,13 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
215215
BIND(&u32);
216216
Return(ChangeUint32ToTagged(AtomicLoad(MachineType::Uint32(), backing_store,
217217
WordShl(index_word, 2))));
218+
#if V8_TARGET_ARCH_MIPS
219+
BIND(&i64);
220+
Return(CallRuntime(Runtime::kAtomicsLoad64, context, array, index_integer));
218221

222+
BIND(&u64);
223+
Return(CallRuntime(Runtime::kAtomicsLoad64, context, array, index_integer));
224+
#else
219225
BIND(&i64);
220226
// This uses Uint64() intentionally: AtomicLoad is not implemented for
221227
// Int64(), which is fine because the machine instruction only cares
@@ -226,7 +232,7 @@ TF_BUILTIN(AtomicsLoad, SharedArrayBufferBuiltinsAssembler) {
226232
BIND(&u64);
227233
Return(BigIntFromUnsigned64(AtomicLoad(MachineType::Uint64(), backing_store,
228234
WordShl(index_word, 3))));
229-
235+
#endif
230236
// This shouldn't happen, we've already validated the type.
231237
BIND(&other);
232238
Unreachable();
@@ -266,9 +272,7 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
266272
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
267273
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
268274
};
269-
Label* case_labels[] = {
270-
&u8, &u8, &u16, &u16, &u32, &u32,
271-
};
275+
Label* case_labels[] = {&u8, &u8, &u16, &u16, &u32, &u32};
272276
Switch(instance_type, &other, case_values, case_labels,
273277
arraysize(case_labels));
274278

@@ -288,6 +292,10 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
288292
Return(value_integer);
289293

290294
BIND(&u64);
295+
#if V8_TARGET_ARCH_MIPS
296+
Return(CallRuntime(Runtime::kAtomicsStore64, context, array, index_integer,
297+
value));
298+
#else
291299
TNode<BigInt> value_bigint = ToBigInt(CAST(context), CAST(value));
292300
#if DEBUG
293301
DebugSanityCheckAtomicIndex(array, index_word32, context);
@@ -299,6 +307,7 @@ TF_BUILTIN(AtomicsStore, SharedArrayBufferBuiltinsAssembler) {
299307
AtomicStore(MachineRepresentation::kWord64, backing_store,
300308
WordShl(index_word, 3), var_low.value(), high);
301309
Return(value_bigint);
310+
#endif
302311

303312
// This shouldn't happen, we've already validated the type.
304313
BIND(&other);

src/runtime/runtime-atomics.cc

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ namespace internal {
2121
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64 || \
2222
V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_S390X
2323

24-
// Note: 32-bit platforms may need ldflags += [ "-latomic" ] in BUILD.gn.
25-
2624
namespace {
2725

2826
#if V8_CC_GNU
@@ -31,9 +29,20 @@ namespace {
3129
// can be slow. Good to know, but we don't have a choice.
3230
#ifdef V8_TARGET_ARCH_32_BIT
3331
#pragma GCC diagnostic push
32+
#pragma GCC diagnostic ignored "-Wpragmas"
3433
#pragma GCC diagnostic ignored "-Watomic-alignment"
3534
#endif // V8_TARGET_ARCH_32_BIT
3635

36+
template <typename T>
37+
inline T LoadSeqCst(T* p) {
38+
return __atomic_load_n(p, __ATOMIC_SEQ_CST);
39+
}
40+
41+
template <typename T>
42+
inline void StoreSeqCst(T* p, T value) {
43+
__atomic_store_n(p, value, __ATOMIC_SEQ_CST);
44+
}
45+
3746
template <typename T>
3847
inline T ExchangeSeqCst(T* p, T value) {
3948
return __atomic_exchange_n(p, value, __ATOMIC_SEQ_CST);
@@ -128,6 +137,16 @@ ATOMIC_OPS(uint32_t, 32, long) /* NOLINT(runtime/int) */
128137
ATOMIC_OPS(int64_t, 64, __int64)
129138
ATOMIC_OPS(uint64_t, 64, __int64)
130139

140+
template <typename T>
141+
inline T LoadSeqCst(T* p) {
142+
UNREACHABLE();
143+
}
144+
145+
template <typename T>
146+
inline void StoreSeqCst(T* p, T value) {
147+
UNREACHABLE();
148+
}
149+
131150
#undef ATOMIC_OPS
132151

133152
#undef InterlockedExchange32
@@ -216,6 +235,23 @@ inline Object* ToObject(Isolate* isolate, uint64_t t) {
216235
return *BigInt::FromUint64(isolate, t);
217236
}
218237

238+
template <typename T>
239+
struct Load {
240+
static inline Object* Do(Isolate* isolate, void* buffer, size_t index) {
241+
T result = LoadSeqCst(static_cast<T*>(buffer) + index);
242+
return ToObject(isolate, result);
243+
}
244+
};
245+
246+
template <typename T>
247+
struct Store {
248+
static inline void Do(Isolate* isolate, void* buffer, size_t index,
249+
Handle<Object> obj) {
250+
T value = FromObject<T>(obj);
251+
StoreSeqCst(static_cast<T*>(buffer) + index, value);
252+
}
253+
};
254+
219255
template <typename T>
220256
struct Exchange {
221257
static inline Object* Do(Isolate* isolate, void* buffer, size_t index,
@@ -347,6 +383,55 @@ Object* GetModifySetValueInBuffer(Arguments args, Isolate* isolate) {
347383
UNREACHABLE();
348384
}
349385

386+
RUNTIME_FUNCTION(Runtime_AtomicsLoad64) {
387+
HandleScope scope(isolate);
388+
DCHECK_EQ(2, args.length());
389+
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
390+
CONVERT_SIZE_ARG_CHECKED(index, 1);
391+
CHECK(sta->GetBuffer()->is_shared());
392+
393+
uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
394+
sta->byte_offset();
395+
396+
DCHECK(sta->type() == kExternalBigInt64Array ||
397+
sta->type() == kExternalBigUint64Array);
398+
// SharedArrayBuffers are not neuterable.
399+
CHECK_LT(index, NumberToSize(sta->length()));
400+
if (sta->type() == kExternalBigInt64Array) {
401+
return Load<int64_t>::Do(isolate, source, index);
402+
}
403+
DCHECK(sta->type() == kExternalBigUint64Array);
404+
return Load<uint64_t>::Do(isolate, source, index);
405+
}
406+
407+
RUNTIME_FUNCTION(Runtime_AtomicsStore64) {
408+
HandleScope scope(isolate);
409+
DCHECK_EQ(3, args.length());
410+
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sta, 0);
411+
CONVERT_SIZE_ARG_CHECKED(index, 1);
412+
CONVERT_ARG_HANDLE_CHECKED(Object, value_obj, 2);
413+
CHECK(sta->GetBuffer()->is_shared());
414+
415+
uint8_t* source = static_cast<uint8_t*>(sta->GetBuffer()->backing_store()) +
416+
sta->byte_offset();
417+
418+
Handle<BigInt> bigint;
419+
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, bigint,
420+
BigInt::FromObject(isolate, value_obj));
421+
422+
DCHECK(sta->type() == kExternalBigInt64Array ||
423+
sta->type() == kExternalBigUint64Array);
424+
// SharedArrayBuffers are not neuterable.
425+
CHECK_LT(index, NumberToSize(sta->length()));
426+
if (sta->type() == kExternalBigInt64Array) {
427+
Store<int64_t>::Do(isolate, source, index, bigint);
428+
return *bigint;
429+
}
430+
DCHECK(sta->type() == kExternalBigUint64Array);
431+
Store<uint64_t>::Do(isolate, source, index, bigint);
432+
return *bigint;
433+
}
434+
350435
RUNTIME_FUNCTION(Runtime_AtomicsExchange) {
351436
return GetModifySetValueInBuffer<Exchange>(args, isolate);
352437
}
@@ -441,6 +526,10 @@ RUNTIME_FUNCTION(Runtime_AtomicsXor) {
441526

442527
#else
443528

529+
RUNTIME_FUNCTION(Runtime_AtomicsLoad64) { UNREACHABLE(); }
530+
531+
RUNTIME_FUNCTION(Runtime_AtomicsStore64) { UNREACHABLE(); }
532+
444533
RUNTIME_FUNCTION(Runtime_AtomicsExchange) { UNREACHABLE(); }
445534

446535
RUNTIME_FUNCTION(Runtime_AtomicsCompareExchange) { UNREACHABLE(); }

src/runtime/runtime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ namespace internal {
5555
F(TrySliceSimpleNonFastElements, 3, 1)
5656

5757
#define FOR_EACH_INTRINSIC_ATOMICS(F) \
58+
F(AtomicsLoad64, 2, 1) \
59+
F(AtomicsStore64, 3, 1) \
5860
F(AtomicsAdd, 3, 1) \
5961
F(AtomicsAnd, 3, 1) \
6062
F(AtomicsCompareExchange, 4, 1) \

0 commit comments

Comments
 (0)