diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-24 12:03:12 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-08-25 08:30:00 +0000 |
commit | 860807b22ab4f7d1c55ce69bb7711dcc777ceefa (patch) | |
tree | 5fbec31ef6ec7bc87353dc51fae0124ef3838753 /src/qml/jsruntime/qv4arraybuffer.cpp | |
parent | dd9a6999b674a9197eabbea96b1e5a34c22a8aab (diff) |
Implement support for SharedArrayBuffer
We'll still need to hook this up with Worker threads to become
useful.
Change-Id: Iedae7307edd76368aeba163731856ebe9b32c6b6
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4arraybuffer.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4arraybuffer.cpp | 120 |
1 files changed, 91 insertions, 29 deletions
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index dc8bce12a0..9b5a983fdf 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. @@ -45,14 +45,46 @@ using namespace QV4; +DEFINE_OBJECT_VTABLE(SharedArrayBufferCtor); DEFINE_OBJECT_VTABLE(ArrayBufferCtor); +DEFINE_OBJECT_VTABLE(SharedArrayBuffer); DEFINE_OBJECT_VTABLE(ArrayBuffer); +void Heap::SharedArrayBufferCtor::init(QV4::ExecutionContext *scope) +{ + Heap::FunctionObject::init(scope, QStringLiteral("SharedArrayBuffer")); +} + void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope) { Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer")); } +ReturnedValue SharedArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) +{ + Scope scope(f); + if (newTarget->isUndefined()) + return scope.engine->throwTypeError(); + + qint64 len = argc ? argv[0].toIndex() : 0; + if (scope.engine->hasException) + return Encode::undefined(); + if (len < 0 || len >= INT_MAX) + return scope.engine->throwRangeError(QStringLiteral("SharedArrayBuffer: Invalid length.")); + + Scoped<SharedArrayBuffer> a(scope, scope.engine->memoryManager->allocate<SharedArrayBuffer>(len)); + if (scope.engine->hasException) + return Encode::undefined(); + + return a->asReturnedValue(); +} + +ReturnedValue SharedArrayBufferCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int) +{ + return f->engine()->throwTypeError(); +} + + ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *) { ExecutionEngine *v4 = f->engine(); @@ -73,12 +105,6 @@ ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, return a->asReturnedValue(); } - -ReturnedValue ArrayBufferCtor::virtualCall(const FunctionObject *f, const Value *, const Value *, int) -{ - return f->engine()->throwTypeError(); -} - ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value *, const Value *argv, int argc) { if (argc < 1) @@ -92,7 +118,7 @@ ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value } -void Heap::ArrayBuffer::init(size_t length) +void Heap::SharedArrayBuffer::init(size_t length) { Object::init(); if (length < UINT_MAX) @@ -103,16 +129,18 @@ void Heap::ArrayBuffer::init(size_t length) } data->size = int(length); memset(data->data(), 0, length + 1); + isShared = true; } -void Heap::ArrayBuffer::init(const QByteArray& array) +void Heap::SharedArrayBuffer::init(const QByteArray& array) { Object::init(); data = const_cast<QByteArray&>(array).data_ptr(); data->ref.ref(); + isShared = true; } -void Heap::ArrayBuffer::destroy() +void Heap::SharedArrayBuffer::destroy() { if (data && !data->ref.deref()) QTypedArrayData<char>::deallocate(data); @@ -145,66 +173,100 @@ void ArrayBuffer::detach() { } -void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) +void SharedArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1)); ctor->defineReadonlyProperty(engine->id_prototype(), (o = this)); - ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1); ctor->addSymbolSpecies(); defineDefaultProperty(engine->id_constructor(), (o = ctor)); defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr); defineDefaultProperty(QStringLiteral("slice"), method_slice, 2); - defineDefaultProperty(QStringLiteral("toString"), method_toString, 0); - ScopedString name(scope, engine->newString(QStringLiteral("ArrayBuffer"))); + ScopedString name(scope, engine->newString(QStringLiteral("SharedArrayBuffer"))); defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name); } -ReturnedValue ArrayBufferPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int) +ReturnedValue SharedArrayBufferPrototype::method_get_byteLength(const FunctionObject *b, const Value *thisObject, const Value *, int) { - const ArrayBuffer *a = thisObject->as<ArrayBuffer>(); - if (!a || a->isDetachedBuffer() || a->isSharedArrayBuffer()) + const SharedArrayBuffer *a = thisObject->as<SharedArrayBuffer>(); + if (!a || a->isDetachedBuffer() || !a->isSharedArrayBuffer()) return b->engine()->throwTypeError(); return Encode(a->d()->data->size); } -ReturnedValue ArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) +ReturnedValue SharedArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { - ExecutionEngine *v4 = b->engine(); - const ArrayBuffer *a = thisObject->as<ArrayBuffer>(); - if (!a || a->isDetachedBuffer() || a->isSharedArrayBuffer()) - return v4->throwTypeError(); + return slice(b, thisObject, argv, argc, true); +} + +ReturnedValue SharedArrayBufferPrototype::slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc, bool shared) +{ + Scope scope(b); + const SharedArrayBuffer *a = thisObject->as<SharedArrayBuffer>(); + if (!a || a->isDetachedBuffer() || (a->isSharedArrayBuffer() != shared)) + return scope.engine->throwTypeError(); double start = argc > 0 ? argv[0].toInteger() : 0; double end = (argc < 2 || argv[1].isUndefined()) ? a->d()->data->size : argv[1].toInteger(); - if (v4->hasException) + if (scope.hasException()) return QV4::Encode::undefined(); double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size); double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size); - Scope scope(v4); - const FunctionObject *constructor = a->speciesConstructor(scope, scope.engine->arrayBufferCtor()); + const FunctionObject *constructor = a->speciesConstructor(scope, shared ? scope.engine->sharedArrayBufferCtor() : scope.engine->arrayBufferCtor()); if (!constructor) - return v4->throwTypeError(); + return scope.engine->throwTypeError(); double newLen = qMax(final - first, 0.); ScopedValue argument(scope, QV4::Encode(newLen)); - QV4::Scoped<ArrayBuffer> newBuffer(scope, constructor->callAsConstructor(argument, 1)); + QV4::Scoped<SharedArrayBuffer> newBuffer(scope, constructor->callAsConstructor(argument, 1)); if (!newBuffer || newBuffer->d()->data->size < (int)newLen || - newBuffer->isDetachedBuffer() || newBuffer->isSharedArrayBuffer() || + newBuffer->isDetachedBuffer() || (newBuffer->isSharedArrayBuffer() != shared) || newBuffer->sameValue(*a) || a->isDetachedBuffer()) - return v4->throwTypeError(); + return scope.engine->throwTypeError(); memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen); return newBuffer->asReturnedValue(); } + +void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) +{ + Scope scope(engine); + ScopedObject o(scope); + ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1)); + ctor->defineReadonlyProperty(engine->id_prototype(), (o = this)); + ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1); + ctor->addSymbolSpecies(); + + defineDefaultProperty(engine->id_constructor(), (o = ctor)); + defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, nullptr); + defineDefaultProperty(QStringLiteral("slice"), method_slice, 2); + defineDefaultProperty(QStringLiteral("toString"), method_toString, 0); + ScopedString name(scope, engine->newString(QStringLiteral("ArrayBuffer"))); + defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name); +} + +ReturnedValue ArrayBufferPrototype::method_get_byteLength(const FunctionObject *f, const Value *thisObject, const Value *, int) +{ + const ArrayBuffer *a = thisObject->as<ArrayBuffer>(); + if (!a || a->isDetachedBuffer() || a->isSharedArrayBuffer()) + return f->engine()->throwTypeError(); + + return Encode(a->d()->data->size); +} + +ReturnedValue ArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) +{ + return slice(b, thisObject, argv, argc, false); +} + ReturnedValue ArrayBufferPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int) { ExecutionEngine *v4 = b->engine(); |