Implement most remaining methods of Atomics
The only missing ones now are wait() and wake(). Change-Id: I2c0ee78cdd8a249e0e841861dd4b76c4665b0ae0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
e4e220fb56
commit
83ded6108a
|
@ -138,9 +138,31 @@ ReturnedValue Atomics::method_and(const FunctionObject *f, const Value *, const
|
|||
return atomicReadModifyWrite(f, argv, argc, AtomicAnd);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_compareExchange(const FunctionObject *f, const Value *, const Value *, int)
|
||||
ReturnedValue Atomics::method_compareExchange(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
{
|
||||
return f->engine()->throwTypeError();
|
||||
Scope scope(f);
|
||||
if (!argc)
|
||||
return scope.engine->throwTypeError();
|
||||
|
||||
SharedArrayBuffer *buffer = validateSharedIntegerTypedArray(scope, argv[0]);
|
||||
if (!buffer)
|
||||
return Encode::undefined();
|
||||
const TypedArray &a = static_cast<const TypedArray &>(argv[0]);
|
||||
int index = validateAtomicAccess(scope, a, argc > 1 ? argv[1] : Primitive::undefinedValue());
|
||||
if (index < 0)
|
||||
return Encode::undefined();
|
||||
|
||||
Value expected = Primitive::fromReturnedValue((argc > 2 ? argv[2] : Primitive::undefinedValue()).convertedToNumber());
|
||||
if (scope.hasException())
|
||||
return Encode::undefined();
|
||||
Value v = Primitive::fromReturnedValue((argc > 3 ? argv[3] : Primitive::undefinedValue()).convertedToNumber());
|
||||
if (scope.hasException())
|
||||
return Encode::undefined();
|
||||
|
||||
int bytesPerElement = a.d()->type->bytesPerElement;
|
||||
int byteOffset = a.d()->byteOffset + index * bytesPerElement;
|
||||
|
||||
return a.d()->type->atomicCompareExchange(buffer->data() + byteOffset, expected, v);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_exchange(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
|
@ -148,14 +170,40 @@ ReturnedValue Atomics::method_exchange(const FunctionObject *f, const Value *, c
|
|||
return atomicReadModifyWrite(f, argv, argc, AtomicExchange);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_isLockFree(const FunctionObject *f, const Value *, const Value *, int)
|
||||
ReturnedValue Atomics::method_isLockFree(const FunctionObject *, const Value *, const Value *argv, int argc)
|
||||
{
|
||||
return f->engine()->throwTypeError();
|
||||
if (!argc)
|
||||
return Encode(false);
|
||||
double n = argv[0].toInteger();
|
||||
if (n == 4.)
|
||||
return Encode(true);
|
||||
if (n == 2.)
|
||||
return Encode(QAtomicOps<unsigned short>::isTestAndSetNative());
|
||||
#ifdef Q_ATOMIC_INT8_IS_SUPPORTED
|
||||
if (n == 1.)
|
||||
return Encode(QAtomicOps<unsigned char>::isTestAndSetNative());
|
||||
#endif
|
||||
return Encode(false);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_load(const FunctionObject *f, const Value *, const Value *, int)
|
||||
ReturnedValue Atomics::method_load(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
{
|
||||
return f->engine()->throwTypeError();
|
||||
Scope scope(f);
|
||||
if (!argc)
|
||||
return scope.engine->throwTypeError();
|
||||
|
||||
SharedArrayBuffer *buffer = validateSharedIntegerTypedArray(scope, argv[0]);
|
||||
if (!buffer)
|
||||
return Encode::undefined();
|
||||
const TypedArray &a = static_cast<const TypedArray &>(argv[0]);
|
||||
int index = validateAtomicAccess(scope, a, argc > 1 ? argv[1] : Primitive::undefinedValue());
|
||||
if (index < 0)
|
||||
return Encode::undefined();
|
||||
|
||||
int bytesPerElement = a.d()->type->bytesPerElement;
|
||||
int byteOffset = a.d()->byteOffset + index * bytesPerElement;
|
||||
|
||||
return a.d()->type->atomicLoad(buffer->data() + byteOffset);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_or(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
|
@ -163,9 +211,28 @@ ReturnedValue Atomics::method_or(const FunctionObject *f, const Value *, const V
|
|||
return atomicReadModifyWrite(f, argv, argc, AtomicOr);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_store(const FunctionObject *f, const Value *, const Value *, int)
|
||||
ReturnedValue Atomics::method_store(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
{
|
||||
return f->engine()->throwTypeError();
|
||||
Scope scope(f);
|
||||
if (!argc)
|
||||
return scope.engine->throwTypeError();
|
||||
|
||||
SharedArrayBuffer *buffer = validateSharedIntegerTypedArray(scope, argv[0]);
|
||||
if (!buffer)
|
||||
return Encode::undefined();
|
||||
const TypedArray &a = static_cast<const TypedArray &>(argv[0]);
|
||||
int index = validateAtomicAccess(scope, a, argc > 1 ? argv[1] : Primitive::undefinedValue());
|
||||
if (index < 0)
|
||||
return Encode::undefined();
|
||||
|
||||
Value v = Primitive::fromReturnedValue((argc > 2 ? argv[2] : Primitive::undefinedValue()).convertedToNumber());
|
||||
if (scope.hasException())
|
||||
return Encode::undefined();
|
||||
|
||||
int bytesPerElement = a.d()->type->bytesPerElement;
|
||||
int byteOffset = a.d()->byteOffset + index * bytesPerElement;
|
||||
|
||||
return a.d()->type->atomicStore(buffer->data() + byteOffset, v);
|
||||
}
|
||||
|
||||
ReturnedValue Atomics::method_sub(const FunctionObject *f, const Value *, const Value *argv, int argc)
|
||||
|
|
|
@ -149,7 +149,7 @@ template <typename T>
|
|||
ReturnedValue atomicAdd(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndAddOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ template <typename T>
|
|||
ReturnedValue atomicAnd(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndAndOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ template <typename T>
|
|||
ReturnedValue atomicExchange(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndStoreOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ template <typename T>
|
|||
ReturnedValue atomicOr(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndOrOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ template <typename T>
|
|||
ReturnedValue atomicSub(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndSubOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
@ -194,11 +194,40 @@ template <typename T>
|
|||
ReturnedValue atomicXor(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps< T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
value = QAtomicOps<T>::fetchAndXorOrdered(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ReturnedValue atomicCompareExchange(char *data, Value expected, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
T exp = valueToType<T>(expected);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
T old;
|
||||
QAtomicOps<T>::testAndSetOrdered(*mem, exp, value, &old);
|
||||
return typeToValue(old);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ReturnedValue atomicLoad(char *data)
|
||||
{
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
T val = QAtomicOps<T>::load(*mem);
|
||||
return typeToValue(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ReturnedValue atomicStore(char *data, Value v)
|
||||
{
|
||||
T value = valueToType<T>(v);
|
||||
typename QAtomicOps<T>::Type *mem = reinterpret_cast<typename QAtomicOps<T>::Type *>(data);
|
||||
QAtomicOps<T>::store(*mem, value);
|
||||
return typeToValue(value);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
constexpr TypedArrayOperations TypedArrayOperations::create(const char *name)
|
||||
{
|
||||
|
@ -206,7 +235,10 @@ constexpr TypedArrayOperations TypedArrayOperations::create(const char *name)
|
|||
name,
|
||||
::read<T>,
|
||||
::write<T>,
|
||||
{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }
|
||||
{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr },
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -217,7 +249,10 @@ constexpr TypedArrayOperations TypedArrayOperations::createWithAtomics(const cha
|
|||
name,
|
||||
::read<T>,
|
||||
::write<T>,
|
||||
{ ::atomicAdd<T>, ::atomicAnd<T>, ::atomicExchange<T>, ::atomicOr<T>, ::atomicSub<T>, ::atomicXor<T> }
|
||||
{ ::atomicAdd<T>, ::atomicAnd<T>, ::atomicExchange<T>, ::atomicOr<T>, ::atomicSub<T>, ::atomicXor<T> },
|
||||
::atomicCompareExchange<T>,
|
||||
::atomicLoad<T>,
|
||||
::atomicStore<T>
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ struct TypedArrayOperations {
|
|||
typedef ReturnedValue (*Read)(const char *data);
|
||||
typedef void (*Write)(char *data, Value value);
|
||||
typedef ReturnedValue (*AtomicModify)(char *data, Value value);
|
||||
typedef ReturnedValue (*AtomicCompareExchange)(char *data, Value expected, Value v);
|
||||
typedef ReturnedValue (*AtomicLoad)(char *data);
|
||||
typedef ReturnedValue (*AtomicStore)(char *data, Value value);
|
||||
|
||||
template<typename T>
|
||||
static constexpr TypedArrayOperations create(const char *name);
|
||||
|
@ -98,6 +101,9 @@ struct TypedArrayOperations {
|
|||
Read read;
|
||||
Write write;
|
||||
AtomicModify atomicModifyOps[AtomicModifyOps::NAtomicModifyOps];
|
||||
AtomicCompareExchange atomicCompareExchange;
|
||||
AtomicLoad atomicLoad;
|
||||
AtomicStore atomicStore;
|
||||
};
|
||||
|
||||
namespace Heap {
|
||||
|
|
|
@ -134,8 +134,6 @@ built-ins/AsyncFunction/instance-prototype-property.js fails
|
|||
built-ins/AsyncGeneratorPrototype/next/name.js fails
|
||||
built-ins/AsyncGeneratorPrototype/return/name.js fails
|
||||
built-ins/AsyncGeneratorPrototype/throw/name.js fails
|
||||
built-ins/Atomics/isLockFree/corner-cases.js fails
|
||||
built-ins/Atomics/isLockFree/value.js fails
|
||||
built-ins/Atomics/wait/did-timeout.js fails
|
||||
built-ins/Atomics/wait/good-views.js fails
|
||||
built-ins/Atomics/wait/nan-timeout.js fails
|
||||
|
|
Loading…
Reference in New Issue