mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-01 12:57:31 +09:00
Support BigInt Atomics waiters
This commit is contained in:
parent
b16be96044
commit
93085352cd
2 changed files with 205 additions and 15 deletions
|
|
@ -47,6 +47,7 @@
|
||||||
#include "builtin/AtomicsObject.h"
|
#include "builtin/AtomicsObject.h"
|
||||||
|
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
|
#include "mozilla/Casting.h"
|
||||||
#include "mozilla/FloatingPoint.h"
|
#include "mozilla/FloatingPoint.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
|
@ -59,6 +60,7 @@
|
||||||
#include "jit/AtomicOperations.h"
|
#include "jit/AtomicOperations.h"
|
||||||
#include "jit/InlinableNatives.h"
|
#include "jit/InlinableNatives.h"
|
||||||
#include "js/Class.h"
|
#include "js/Class.h"
|
||||||
|
#include "vm/BigIntType.h"
|
||||||
#include "vm/GlobalObject.h"
|
#include "vm/GlobalObject.h"
|
||||||
#include "vm/HelperThreads.h"
|
#include "vm/HelperThreads.h"
|
||||||
#include "vm/Time.h"
|
#include "vm/Time.h"
|
||||||
|
|
@ -123,6 +125,68 @@ GetTypedArrayIndex(JSContext* cx, HandleValue v, Handle<TypedArrayObject*> view,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsWaitableTypedArray(Scalar::Type viewType)
|
||||||
|
{
|
||||||
|
return viewType == Scalar::Int32 || viewType == Scalar::BigInt64;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
GetWaiterByteOffset(Handle<TypedArrayObject*> view, uint32_t offset)
|
||||||
|
{
|
||||||
|
return view->byteOffset() + offset * TypedArrayElemSize(view->type());
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
BigIntToRawBits(Scalar::Type viewType, BigInt* value)
|
||||||
|
{
|
||||||
|
if (viewType == Scalar::BigInt64)
|
||||||
|
return uint64_t(BigInt::toInt64(value));
|
||||||
|
MOZ_ASSERT(viewType == Scalar::BigUint64);
|
||||||
|
return BigInt::toUint64(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
BigIntToRawBits(JSContext* cx, Scalar::Type viewType, HandleValue value, uint64_t* bits)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(Scalar::isBigIntType(viewType));
|
||||||
|
|
||||||
|
RootedBigInt bigint(cx, ToBigInt(cx, value));
|
||||||
|
if (!bigint)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*bits = BigIntToRawBits(viewType, bigint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
SetBigIntResult(JSContext* cx, Scalar::Type viewType, uint64_t bits, MutableHandleValue result)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(Scalar::isBigIntType(viewType));
|
||||||
|
|
||||||
|
BigInt* bigint = viewType == Scalar::BigInt64
|
||||||
|
? BigInt::createFromInt64(cx, mozilla::BitwiseCast<int64_t>(bits))
|
||||||
|
: BigInt::createFromUint64(cx, bits);
|
||||||
|
if (!bigint)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
result.setBigInt(bigint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
WaitValueMatches(Handle<TypedArrayObject*> view, uint32_t offset, uint64_t expected)
|
||||||
|
{
|
||||||
|
SharedMem<void*> viewData = view->viewDataShared();
|
||||||
|
if (view->type() == Scalar::BigInt64) {
|
||||||
|
return jit::AtomicOperations::loadSafeWhenRacy(viewData.cast<uint64_t*>() + offset) ==
|
||||||
|
expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32_t(jit::AtomicOperations::loadSafeWhenRacy(viewData.cast<int32_t*>() + offset)) ==
|
||||||
|
uint32_t(expected);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t
|
static int32_t
|
||||||
CompareExchange(Scalar::Type viewType, int32_t oldCandidate, int32_t newCandidate,
|
CompareExchange(Scalar::Type viewType, int32_t oldCandidate, int32_t newCandidate,
|
||||||
SharedMem<void*> viewData, uint32_t offset, bool* badArrayType = nullptr)
|
SharedMem<void*> viewData, uint32_t offset, bool* badArrayType = nullptr)
|
||||||
|
|
@ -193,6 +257,20 @@ js::atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp)
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (Scalar::isBigIntType(view->type())) {
|
||||||
|
uint64_t oldCandidate;
|
||||||
|
if (!BigIntToRawBits(cx, view->type(), oldv, &oldCandidate))
|
||||||
|
return false;
|
||||||
|
uint64_t newCandidate;
|
||||||
|
if (!BigIntToRawBits(cx, view->type(), newv, &newCandidate))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64_t result = jit::AtomicOperations::compareExchangeSeqCst(
|
||||||
|
view->viewDataShared().cast<uint64_t*>() + offset, oldCandidate, newCandidate);
|
||||||
|
return SetBigIntResult(cx, view->type(), result, r);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t oldCandidate;
|
int32_t oldCandidate;
|
||||||
if (!ToInt32(cx, oldv, &oldCandidate))
|
if (!ToInt32(cx, oldv, &oldCandidate))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -261,6 +339,22 @@ js::atomics_load(JSContext* cx, unsigned argc, Value* vp)
|
||||||
r.setNumber(v);
|
r.setNumber(v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Scalar::BigInt64: {
|
||||||
|
int64_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<int64_t*>() + offset);
|
||||||
|
BigInt* bigint = BigInt::createFromInt64(cx, v);
|
||||||
|
if (!bigint)
|
||||||
|
return false;
|
||||||
|
r.setBigInt(bigint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case Scalar::BigUint64: {
|
||||||
|
uint64_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint64_t*>() + offset);
|
||||||
|
BigInt* bigint = BigInt::createFromUint64(cx, v);
|
||||||
|
if (!bigint)
|
||||||
|
return false;
|
||||||
|
r.setBigInt(bigint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return ReportBadArrayType(cx);
|
return ReportBadArrayType(cx);
|
||||||
}
|
}
|
||||||
|
|
@ -339,6 +433,25 @@ ExchangeOrStore(JSContext* cx, unsigned argc, Value* vp)
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (Scalar::isBigIntType(view->type())) {
|
||||||
|
RootedBigInt bigint(cx, ToBigInt(cx, valv));
|
||||||
|
if (!bigint)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64_t value = BigIntToRawBits(view->type(), bigint);
|
||||||
|
if (op == DoStore) {
|
||||||
|
jit::AtomicOperations::storeSeqCst(view->viewDataShared().cast<uint64_t*>() + offset,
|
||||||
|
value);
|
||||||
|
r.setBigInt(bigint);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t result = jit::AtomicOperations::exchangeSeqCst(
|
||||||
|
view->viewDataShared().cast<uint64_t*>() + offset, value);
|
||||||
|
return SetBigIntResult(cx, view->type(), result, r);
|
||||||
|
}
|
||||||
|
|
||||||
double integerValue;
|
double integerValue;
|
||||||
if (!ToInteger(cx, valv, &integerValue))
|
if (!ToInteger(cx, valv, &integerValue))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -382,6 +495,24 @@ AtomicsBinop(JSContext* cx, HandleValue objv, HandleValue idxv, HandleValue valv
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (Scalar::isBigIntType(view->type())) {
|
||||||
|
uint64_t value;
|
||||||
|
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SharedMem<uint64_t*> addr = view->viewDataShared().cast<uint64_t*>() + offset;
|
||||||
|
uint64_t old = jit::AtomicOperations::loadSeqCst(addr);
|
||||||
|
for (;;) {
|
||||||
|
uint64_t replacement = T::operate64(old, value);
|
||||||
|
uint64_t observed = jit::AtomicOperations::compareExchangeSeqCst(addr, old,
|
||||||
|
replacement);
|
||||||
|
if (observed == old)
|
||||||
|
return SetBigIntResult(cx, view->type(), old, r);
|
||||||
|
old = observed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t numberValue;
|
int32_t numberValue;
|
||||||
if (!ToInt32(cx, valv, &numberValue))
|
if (!ToInt32(cx, valv, &numberValue))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -436,6 +567,7 @@ class PerformAdd
|
||||||
public:
|
public:
|
||||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAddSeqCst)
|
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAddSeqCst)
|
||||||
static int32_t perform(int32_t x, int32_t y) { return x + y; }
|
static int32_t perform(int32_t x, int32_t y) { return x + y; }
|
||||||
|
static uint64_t operate64(uint64_t x, uint64_t y) { return x + y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -450,6 +582,7 @@ class PerformSub
|
||||||
public:
|
public:
|
||||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchSubSeqCst)
|
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchSubSeqCst)
|
||||||
static int32_t perform(int32_t x, int32_t y) { return x - y; }
|
static int32_t perform(int32_t x, int32_t y) { return x - y; }
|
||||||
|
static uint64_t operate64(uint64_t x, uint64_t y) { return x - y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -464,6 +597,7 @@ class PerformAnd
|
||||||
public:
|
public:
|
||||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAndSeqCst)
|
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchAndSeqCst)
|
||||||
static int32_t perform(int32_t x, int32_t y) { return x & y; }
|
static int32_t perform(int32_t x, int32_t y) { return x & y; }
|
||||||
|
static uint64_t operate64(uint64_t x, uint64_t y) { return x & y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -478,6 +612,7 @@ class PerformOr
|
||||||
public:
|
public:
|
||||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchOrSeqCst)
|
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchOrSeqCst)
|
||||||
static int32_t perform(int32_t x, int32_t y) { return x | y; }
|
static int32_t perform(int32_t x, int32_t y) { return x | y; }
|
||||||
|
static uint64_t operate64(uint64_t x, uint64_t y) { return x | y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -492,6 +627,7 @@ class PerformXor
|
||||||
public:
|
public:
|
||||||
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchXorSeqCst)
|
INTEGRAL_TYPES_FOR_EACH(jit::AtomicOperations::fetchXorSeqCst)
|
||||||
static int32_t perform(int32_t x, int32_t y) { return x ^ y; }
|
static int32_t perform(int32_t x, int32_t y) { return x ^ y; }
|
||||||
|
static uint64_t operate64(uint64_t x, uint64_t y) { return x ^ y; }
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -736,7 +872,7 @@ class FutexWaiter
|
||||||
bool isWaiting() const;
|
bool isWaiting() const;
|
||||||
void notify();
|
void notify();
|
||||||
|
|
||||||
uint32_t offset; // int32 element index within the SharedArrayBuffer
|
uint32_t offset; // byte offset within the SharedArrayBuffer
|
||||||
enum WaiterKind {
|
enum WaiterKind {
|
||||||
Sync,
|
Sync,
|
||||||
Async
|
Async
|
||||||
|
|
@ -970,14 +1106,21 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
||||||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||||
if (!GetSharedTypedArray(cx, objv, &view))
|
if (!GetSharedTypedArray(cx, objv, &view))
|
||||||
return false;
|
return false;
|
||||||
if (view->type() != Scalar::Int32)
|
if (!IsWaitableTypedArray(view->type()))
|
||||||
return ReportBadArrayType(cx);
|
return ReportBadArrayType(cx);
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
int32_t value;
|
uint64_t value = 0;
|
||||||
if (!ToInt32(cx, valv, &value))
|
if (view->type() == Scalar::BigInt64) {
|
||||||
return false;
|
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int32_t int32Value;
|
||||||
|
if (!ToInt32(cx, valv, &int32Value))
|
||||||
|
return false;
|
||||||
|
value = uint32_t(int32Value);
|
||||||
|
}
|
||||||
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
||||||
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -989,8 +1132,7 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
||||||
// and it provides the necessary memory fence.
|
// and it provides the necessary memory fence.
|
||||||
AutoLockFutexAPI lock;
|
AutoLockFutexAPI lock;
|
||||||
|
|
||||||
SharedMem<int32_t*> addr = view->viewDataShared().cast<int32_t*>() + offset;
|
if (!WaitValueMatches(view, offset, value)) {
|
||||||
if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) {
|
|
||||||
r.setString(cx->names().futexNotEqual);
|
r.setString(cx->names().futexNotEqual);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -998,7 +1140,7 @@ js::atomics_wait(JSContext* cx, unsigned argc, Value* vp)
|
||||||
Rooted<SharedArrayBufferObject*> sab(cx, view->bufferShared());
|
Rooted<SharedArrayBufferObject*> sab(cx, view->bufferShared());
|
||||||
SharedArrayRawBuffer* sarb = sab->rawBufferObject();
|
SharedArrayRawBuffer* sarb = sab->rawBufferObject();
|
||||||
|
|
||||||
FutexWaiter w(offset, rt);
|
FutexWaiter w(GetWaiterByteOffset(view, offset), rt);
|
||||||
AddWaiter(sarb, &w);
|
AddWaiter(sarb, &w);
|
||||||
|
|
||||||
FutexRuntime::WaitResult result = FutexRuntime::FutexOK;
|
FutexRuntime::WaitResult result = FutexRuntime::FutexOK;
|
||||||
|
|
@ -1031,14 +1173,21 @@ js::atomics_waitAsync(JSContext* cx, unsigned argc, Value* vp)
|
||||||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||||
if (!GetSharedTypedArray(cx, objv, &view))
|
if (!GetSharedTypedArray(cx, objv, &view))
|
||||||
return false;
|
return false;
|
||||||
if (view->type() != Scalar::Int32)
|
if (!IsWaitableTypedArray(view->type()))
|
||||||
return ReportBadArrayType(cx);
|
return ReportBadArrayType(cx);
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
int32_t value;
|
uint64_t value = 0;
|
||||||
if (!ToInt32(cx, valv, &value))
|
if (view->type() == Scalar::BigInt64) {
|
||||||
return false;
|
if (!BigIntToRawBits(cx, view->type(), valv, &value))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
int32_t int32Value;
|
||||||
|
if (!ToInt32(cx, valv, &int32Value))
|
||||||
|
return false;
|
||||||
|
value = uint32_t(int32Value);
|
||||||
|
}
|
||||||
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
mozilla::Maybe<mozilla::TimeDuration> timeout;
|
||||||
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
if (!GetWaitTimeout(cx, timeoutv, &timeout))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1070,8 +1219,7 @@ js::atomics_waitAsync(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
AutoLockFutexAPI lock;
|
AutoLockFutexAPI lock;
|
||||||
|
|
||||||
SharedMem<int32_t*> addr = view->viewDataShared().cast<int32_t*>() + offset;
|
if (!WaitValueMatches(view, offset, value)) {
|
||||||
if (jit::AtomicOperations::loadSafeWhenRacy(addr) != value) {
|
|
||||||
immediateResult.setString(cx->names().futexNotEqual);
|
immediateResult.setString(cx->names().futexNotEqual);
|
||||||
} else if (timeout.isSome() && timeout->ToMilliseconds() == 0.0) {
|
} else if (timeout.isSome() && timeout->ToMilliseconds() == 0.0) {
|
||||||
immediateResult.setString(cx->names().futexTimedOut);
|
immediateResult.setString(cx->names().futexTimedOut);
|
||||||
|
|
@ -1083,6 +1231,7 @@ js::atomics_waitAsync(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task->waiter()->offset = GetWaiterByteOffset(view, offset);
|
||||||
AddWaiter(sarb, task->waiter());
|
AddWaiter(sarb, task->waiter());
|
||||||
task->setInWaiterList();
|
task->setInWaiterList();
|
||||||
isAsync = true;
|
isAsync = true;
|
||||||
|
|
@ -1111,11 +1260,12 @@ js::atomics_notify(JSContext* cx, unsigned argc, Value* vp)
|
||||||
Rooted<TypedArrayObject*> view(cx, nullptr);
|
Rooted<TypedArrayObject*> view(cx, nullptr);
|
||||||
if (!GetSharedTypedArray(cx, objv, &view))
|
if (!GetSharedTypedArray(cx, objv, &view))
|
||||||
return false;
|
return false;
|
||||||
if (view->type() != Scalar::Int32)
|
if (!IsWaitableTypedArray(view->type()))
|
||||||
return ReportBadArrayType(cx);
|
return ReportBadArrayType(cx);
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
if (!GetTypedArrayIndex(cx, idxv, view, &offset))
|
||||||
return false;
|
return false;
|
||||||
|
offset = GetWaiterByteOffset(view, offset);
|
||||||
double count;
|
double count;
|
||||||
if (countv.isUndefined()) {
|
if (countv.isUndefined()) {
|
||||||
count = mozilla::PositiveInfinity<double>();
|
count = mozilla::PositiveInfinity<double>();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,46 @@ if (typeof SharedArrayBuffer === "function" && typeof Atomics === "object" &&
|
||||||
});
|
});
|
||||||
drainJobQueue();
|
drainJobQueue();
|
||||||
assertEq(timedOut, "timed-out");
|
assertEq(timedOut, "timed-out");
|
||||||
|
|
||||||
|
if (typeof BigInt64Array === "function") {
|
||||||
|
const bigSab = new SharedArrayBuffer(16);
|
||||||
|
const i64 = new BigInt64Array(bigSab);
|
||||||
|
const u64 = new BigUint64Array(bigSab);
|
||||||
|
|
||||||
|
assertEq(Atomics.store(i64, 0, -1n), -1n);
|
||||||
|
assertEq(Atomics.load(i64, 0), -1n);
|
||||||
|
assertEq(Atomics.load(u64, 0), 18446744073709551615n);
|
||||||
|
assertEq(Atomics.exchange(i64, 0, 7n), -1n);
|
||||||
|
assertEq(Atomics.compareExchange(i64, 0, 7n, 10n), 7n);
|
||||||
|
assertEq(Atomics.add(i64, 0, 5n), 10n);
|
||||||
|
assertEq(Atomics.load(i64, 0), 15n);
|
||||||
|
assertEq(Atomics.sub(i64, 0, 20n), 15n);
|
||||||
|
assertEq(Atomics.load(i64, 0), -5n);
|
||||||
|
assertEq(Atomics.and(u64, 0, 7n), 18446744073709551611n);
|
||||||
|
assertEq(Atomics.or(u64, 0, 8n), 3n);
|
||||||
|
assertEq(Atomics.xor(u64, 0, 15n), 11n);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => Atomics.waitAsync(u64, 0, 0n), TypeError);
|
||||||
|
|
||||||
|
result = Atomics.waitAsync(i64, 1, 1n, 10);
|
||||||
|
assertEq(result.async, false);
|
||||||
|
assertEq(result.value, "not-equal");
|
||||||
|
|
||||||
|
result = Atomics.waitAsync(i64, 1, 0n, 0);
|
||||||
|
assertEq(result.async, false);
|
||||||
|
assertEq(result.value, "timed-out");
|
||||||
|
|
||||||
|
let offsetView = new BigInt64Array(bigSab, 8);
|
||||||
|
result = Atomics.waitAsync(offsetView, 0, 0n);
|
||||||
|
assertEq(result.async, true);
|
||||||
|
notified = undefined;
|
||||||
|
result.value.then(value => {
|
||||||
|
notified = value;
|
||||||
|
});
|
||||||
|
assertEq(Atomics.notify(i64, 1, 1), 1);
|
||||||
|
drainJobQueue();
|
||||||
|
assertEq(notified, "ok");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof reportCompare === "function")
|
if (typeof reportCompare === "function")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue