aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-24 13:56:37 +0200
committerLars Knoll <lars.knoll@qt.io>2018-08-25 08:30:04 +0000
commit7bdb46c5aae3da345653fe91fbe9281b39015497 (patch)
tree779aac192deb1a971df1e52c3fca2b90c013de9c /src/qml/jsruntime
parent860807b22ab4f7d1c55ce69bb7711dcc777ceefa (diff)
Clean up the code handling reads and writes into typed arrays
This is a preparation for supporting atomic operations on Typed arrays. Change-Id: I91d00f3aee3f35fc22e74ee010ed2cbec2d46aae Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp199
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h33
3 files changed, 98 insertions, 140 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c1a4b67d60..351bca1ce7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -513,7 +513,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
static_cast<IntrinsicTypedArrayPrototype *>(intrinsicTypedArrayPrototype())
->init(this, static_cast<IntrinsicTypedArrayCtor *>(intrinsicTypedArrayCtor()));
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
+ for (int i = 0; i < NTypedArrayTypes; ++i) {
static_cast<Value &>(typedArrayCtors[i]) = memoryManager->allocate<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
static_cast<Value &>(typedArrayPrototype[i]) = memoryManager->allocate<TypedArrayPrototype>(Heap::TypedArray::Type(i));
typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].as<Object>()));
@@ -549,8 +549,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
globalObject->defineDefaultProperty(QStringLiteral("Set"), *setCtor());
globalObject->defineDefaultProperty(QStringLiteral("Map"), *mapCtor());
- for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
- globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name())->toQString(), typedArrayCtors[i]);
+ for (int i = 0; i < NTypedArrayTypes; ++i)
+ globalObject->defineDefaultProperty((str = typedArrayCtors[i].as<FunctionObject>()->name()), typedArrayCtors[i]);
ScopedObject o(scope);
globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->allocate<MathObject>()));
globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->allocate<JsonObject>()));
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 456a577b52..656c9238cc 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -55,7 +55,7 @@ DEFINE_OBJECT_VTABLE(TypedArrayCtor);
DEFINE_OBJECT_VTABLE(TypedArrayPrototype);
DEFINE_OBJECT_VTABLE(TypedArray);
-Q_STATIC_ASSERT((int)ExecutionEngine::NTypedArrayTypes == (int)Heap::TypedArray::NTypes);
+Q_STATIC_ASSERT((int)ExecutionEngine::NTypedArrayTypes == (int)NTypedArrayTypes);
static inline int toInt32(Value v)
{
@@ -73,144 +73,97 @@ static inline double toDouble(Value v)
return v.doubleValue();
}
-ReturnedValue Int8ArrayRead(const char *data, int index)
-{
- return Encode((int)(signed char)data[index]);
-}
+struct ClampedUInt8 {
+ quint8 c;
+};
-void Int8ArrayWrite(char *data, int index, const Value &value)
-{
- int n = toInt32(value);
- signed char v = static_cast<signed char>(n);
- data[index] = v;
+template <typename T>
+ReturnedValue typeToValue(T t) {
+ return Encode(t);
}
-ReturnedValue UInt8ArrayRead(const char *data, int index)
-{
- return Encode((int)(unsigned char)data[index]);
+template <>
+ReturnedValue typeToValue(ClampedUInt8 t) {
+ return Encode(t.c);
}
-void UInt8ArrayWrite(char *data, int index, const Value &value)
+template <typename T>
+T valueToType(Value value)
{
+ Q_ASSERT(value.isNumber());
int n = toInt32(value);
- unsigned char v = static_cast<unsigned char>(uint(n));
- data[index] = v;
+ return static_cast<T>(n);
}
-void UInt8ClampedArrayWrite(char *data, int index, const Value &value)
+template <>
+ClampedUInt8 valueToType(Value value)
{
Q_ASSERT(value.isNumber());
- if (value.isInteger()) {
- data[index] = (char)(unsigned char)qBound(0, value.integerValue(), 255);
- return;
- }
+ if (value.isInteger())
+ return { static_cast<quint8>(qBound(0, value.integerValue(), 255)) };
Q_ASSERT(value.isDouble());
double d = value.doubleValue();
// ### is there a way to optimise this?
- if (d <= 0 || std::isnan(d)) {
- data[index] = 0;
- return;
- }
- if (d >= 255) {
- data[index] = (char)(255);
- return;
- }
+ if (d <= 0 || std::isnan(d))
+ return { 0 };
+ if (d >= 255)
+ return { 255 };
double f = std::floor(d);
- if (f + 0.5 < d) {
- data[index] = (unsigned char)(f + 1);
- return;
- }
- if (d < f + 0.5) {
- data[index] = (unsigned char)(f);
- return;
- }
- if (int(f) % 2) {
+ if (f + 0.5 < d)
+ return { (quint8)(f + 1) };
+ if (d < f + 0.5)
+ return { (quint8)(f) };
+ if (int(f) % 2)
// odd number
- data[index] = (unsigned char)(f + 1);
- return;
- }
- data[index] = (unsigned char)(f);
-}
-
-ReturnedValue Int16ArrayRead(const char *data, int index)
-{
- return Encode((int)*(const short *)(data + index));
+ return { (quint8)(f + 1) };
+ return { (quint8)(f) };
}
-void Int16ArrayWrite(char *data, int index, const Value &value)
+template <>
+float valueToType(Value value)
{
- int n = toInt32(value);
- short v = static_cast<short>(n);
- *(short *)(data + index) = v;
-}
-
-ReturnedValue UInt16ArrayRead(const char *data, int index)
-{
- return Encode((int)*(const unsigned short *)(data + index));
-}
-
-void UInt16ArrayWrite(char *data, int index, const Value &value)
-{
- int n = toInt32(value);
- unsigned short v = static_cast<unsigned short>(n);
- *(unsigned short *)(data + index) = v;
-}
-
-ReturnedValue Int32ArrayRead(const char *data, int index)
-{
- return Encode(*(const int *)(data + index));
-}
-
-void Int32ArrayWrite(char *data, int index, const Value &value)
-{
- int v = toInt32(value);
- *(int *)(data + index) = v;
-}
-
-ReturnedValue UInt32ArrayRead(const char *data, int index)
-{
- return Encode(*(const unsigned int *)(data + index));
-}
-
-void UInt32ArrayWrite(char *data, int index, const Value &value)
-{
- int n = toInt32(value);
- unsigned v = static_cast<unsigned>(n);
- *(unsigned int *)(data + index) = v;
+ Q_ASSERT(value.isNumber());
+ double d = toDouble(value);
+ return static_cast<float>(d);
}
-ReturnedValue Float32ArrayRead(const char *data, int index)
+template <>
+double valueToType(Value value)
{
- return Encode(*(const float *)(data + index));
+ Q_ASSERT(value.isNumber());
+ return toDouble(value);
}
-void Float32ArrayWrite(char *data, int index, const Value &value)
-{
- float v = toDouble(value);
- *(float *)(data + index) = v;
+template <typename T>
+ReturnedValue read(const char *data) {
+ return typeToValue(*reinterpret_cast<const T *>(data));
}
-
-ReturnedValue Float64ArrayRead(const char *data, int index)
+template <typename T>
+void write(char *data, Value value)
{
- return Encode(*(const double *)(data + index));
+ *reinterpret_cast<T *>(data) = valueToType<T>(value);
}
-void Float64ArrayWrite(char *data, int index, const Value &value)
+template<typename T>
+constexpr TypedArrayOperations TypedArrayOperations::create(const char *name)
{
- double v = toDouble(value);
- *(double *)(data + index) = v;
+ return { sizeof(T),
+ name,
+ ::read<T>,
+ ::write<T>
+ };
}
-const TypedArrayOperations operations[Heap::TypedArray::NTypes] = {
- { 1, "Int8Array", Int8ArrayRead, Int8ArrayWrite },
- { 1, "Uint8Array", UInt8ArrayRead, UInt8ArrayWrite },
- { 1, "Uint8ClampedArray", UInt8ArrayRead, UInt8ClampedArrayWrite },
- { 2, "Int16Array", Int16ArrayRead, Int16ArrayWrite },
- { 2, "Uint16Array", UInt16ArrayRead, UInt16ArrayWrite },
- { 4, "Int32Array", Int32ArrayRead, Int32ArrayWrite },
- { 4, "Uint32Array", UInt32ArrayRead, UInt32ArrayWrite },
- { 4, "Float32Array", Float32ArrayRead, Float32ArrayWrite },
- { 8, "Float64Array", Float64ArrayRead, Float64ArrayWrite },
+const TypedArrayOperations operations[NTypedArrayTypes] = {
+ TypedArrayOperations::create<qint8>("Int8Array"),
+ TypedArrayOperations::create<quint8>("Uint8Array"),
+ TypedArrayOperations::create<ClampedUInt8>("Uint8ClampedArray"),
+ TypedArrayOperations::create<qint16>("Int16Array"),
+ TypedArrayOperations::create<quint16>("Uint16Array"),
+ TypedArrayOperations::create<qint32>("Int32Array"),
+ TypedArrayOperations::create<quint32>("Uint32Array"),
+ TypedArrayOperations::create<float>("Float32Array"),
+ TypedArrayOperations::create<double>("Float64Array")
};
@@ -281,8 +234,8 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
TypedArrayWrite write =array->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.setRawValue(read(src, i*srcElementSize));
- write(dest, i*destElementSize, val);
+ val.setRawValue(read(src + i*srcElementSize));
+ write(dest + i*destElementSize, val);
}
}
@@ -354,7 +307,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
val = val->convertedToNumber();
if (scope.engine->hasException)
return Encode::undefined();
- array->d()->type->write(b, 0, val);
+ array->d()->type->write(b, val);
if (scope.engine->hasException)
return Encode::undefined();
++idx;
@@ -373,14 +326,14 @@ ReturnedValue TypedArrayCtor::virtualCall(const FunctionObject *f, const Value *
void Heap::TypedArray::init(Type t)
{
Object::init();
- type = operations + t;
- arrayType = t;
+ type = operations + static_cast<int>(t);
+ arrayType = static_cast<int>(t);
}
Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t)
{
Scope scope(e);
- Scoped<InternalClass> ic(scope, e->newInternalClass(staticVTable(), e->typedArrayPrototype + t));
+ Scoped<InternalClass> ic(scope, e->newInternalClass(staticVTable(), e->typedArrayPrototype + static_cast<int>(t)));
return e->memoryManager->allocObject<TypedArray>(ic->d(), t);
}
@@ -404,7 +357,7 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
}
if (hasProperty)
*hasProperty = true;
- return a->d()->type->read(a->d()->buffer->data->data(), byteOffset);
+ return a->d()->type->read(a->d()->buffer->data->data() + byteOffset);
}
bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
@@ -430,7 +383,7 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
Value v = Primitive::fromReturnedValue(value.convertedToNumber());
if (scope.hasException() || a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- a->d()->type->write(a->d()->buffer->data->data(), byteOffset, v);
+ a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
return true;
}
@@ -441,12 +394,12 @@ void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(3));
ctor->defineReadonlyProperty(engine->id_prototype(), *this);
- ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
+ ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[static_cast<int>(ctor->d()->type)].bytesPerElement));
ctor->setPrototypeOf(engine->intrinsicTypedArrayCtor());
setPrototypeOf(engine->intrinsicTypedArrayPrototype());
defineDefaultProperty(engine->id_constructor(), (o = ctor));
- defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
+ defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[static_cast<int>(ctor->d()->type)].bytesPerElement));
}
ReturnedValue IntrinsicTypedArrayPrototype::method_get_buffer(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -586,7 +539,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b
if (v->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- arguments[0] = v->d()->type->read(data, byteOffset + k * bytesPerElement);
+ arguments[0] = v->d()->type->read(data + byteOffset + k * bytesPerElement);
arguments[1] = Primitive::fromDouble(k);
arguments[2] = v;
@@ -635,7 +588,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_fill(const FunctionObject *b,
uint byteOffset = v->d()->byteOffset;
while (k < fin) {
- v->d()->type->write(data, byteOffset + k * bytesPerElement, value);
+ v->d()->type->write(data + byteOffset + k * bytesPerElement, value);
k++;
}
@@ -1259,7 +1212,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
val = val->convertedToNumber();
if (scope.hasException() || buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- a->d()->type->write(b, 0, val);
+ a->d()->type->write(b, val);
if (scope.engine->hasException)
RETURN_UNDEFINED();
++idx;
@@ -1299,8 +1252,8 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
TypedArrayWrite write = a->d()->type->write;
for (uint i = 0; i < l; ++i) {
Primitive val;
- val.setRawValue(read(src, i*srcElementSize));
- write(dest, i*elementSize, val);
+ val.setRawValue(read(src + i*srcElementSize));
+ write(dest + i*elementSize, val);
}
if (srcCopy)
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 11b3a0dabf..a5eabb168c 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -60,10 +60,26 @@ namespace QV4 {
struct ArrayBuffer;
-typedef ReturnedValue (*TypedArrayRead)(const char *data, int index);
-typedef void (*TypedArrayWrite)(char *data, int index, const Value &value);
+typedef ReturnedValue (*TypedArrayRead)(const char *data);
+typedef void (*TypedArrayWrite)(char *data, Value value);
+
+enum TypedArrayType {
+ Int8Array,
+ UInt8Array,
+ UInt8ClampedArray,
+ Int16Array,
+ UInt16Array,
+ Int32Array,
+ UInt32Array,
+ Float32Array,
+ Float64Array,
+ NTypedArrayTypes
+};
struct TypedArrayOperations {
+ template<typename T>
+ static constexpr TypedArrayOperations create(const char *name);
+
int bytesPerElement;
const char *name;
TypedArrayRead read;
@@ -81,18 +97,7 @@ namespace Heap {
DECLARE_HEAP_OBJECT(TypedArray, Object) {
DECLARE_MARKOBJECTS(TypedArray);
- enum Type {
- Int8Array,
- UInt8Array,
- UInt8ClampedArray,
- Int16Array,
- UInt16Array,
- Int32Array,
- UInt32Array,
- Float32Array,
- Float64Array,
- NTypes
- };
+ using Type = TypedArrayType;
void init(Type t);
};