From 1bff3496b172b041fcedbef0893c1d0de6c4fbc5 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 31 Mar 2015 00:21:58 +0200 Subject: Fix a few typos Change-Id: Ia00949757a6f47babc1748f27e32a9644d6cc608 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4value_p.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 2b2d275b58..cd1aef86d7 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -97,8 +97,8 @@ struct Q_QML_PRIVATE_EXPORT Value /* We use two different ways of encoding JS values. One for 32bit and one for 64bit systems. - In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN) - is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the + In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double NaN (actually -qNaN) + is indicated by a number that has the top 13 bits set. The other values are usually set to 0 by the processor, and are thus free for us to store other data. We keep pointers in there for managed objects, and encode the other types using the free space given to use by the unused bits for NaN values. This also works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory. @@ -106,7 +106,7 @@ struct Q_QML_PRIVATE_EXPORT Value On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that will make the number a NaN. The Masks below are used for encoding the other types. - On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded + On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will get encoded with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These can be used, as the highest valid pointer on a 64 bit system is 2^48-1. -- cgit v1.2.3 From 175772b3de48f7b24d6ab28255eed28e7cb53eb1 Mon Sep 17 00:00:00 2001 From: Valery Kotov Date: Wed, 25 Mar 2015 20:17:08 +0200 Subject: QML Engine: Share data for ArrayBuffer created from QByteArray. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ExecutionEngine performs shallow copy of internal data for ArrayBuffer created from QByteArray. Change-Id: I514cd9708a7fbe9a989937fac62d00b464d7362d Reviewed-by: Simon Hausmann Reviewed-by: Valery Kotov Reviewed-by: Pasi Keränen --- src/qml/jsruntime/qv4arraybuffer.cpp | 26 ++++++++++++++++++++++++++ src/qml/jsruntime/qv4arraybuffer_p.h | 13 +++++-------- src/qml/jsruntime/qv4engine.cpp | 5 +---- 3 files changed, 32 insertions(+), 12 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index e42fcdc4fd..11664f1194 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -95,6 +95,13 @@ Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, size_t length) memset(data->data(), 0, length + 1); } +Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, const QByteArray& array) + : Heap::Object(e->emptyClass, e->arrayBufferPrototype.asObject()) + , data(const_cast(array).data_ptr()) +{ + data->ref.ref(); +} + Heap::ArrayBuffer::~ArrayBuffer() { if (!data->ref.deref()) @@ -108,6 +115,25 @@ QByteArray ArrayBuffer::asByteArray() const return QByteArray(ba); } +void ArrayBuffer::detach() { + if (!d()->data->ref.isShared()) + return; + + QTypedArrayData *oldData = d()->data; + + d()->data = QTypedArrayData::allocate(oldData->size + 1); + if (!d()->data) { + engine()->throwRangeError(QStringLiteral("ArrayBuffer: out of memory")); + return; + } + + memcpy(d()->data->data(), oldData->data(), oldData->size + 1); + + if (!oldData->ref.deref()) + QTypedArrayData::deallocate(oldData); +} + + void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index 9e19a83f1e..fe3150618d 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -48,6 +48,7 @@ struct ArrayBufferCtor : FunctionObject { struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object { ArrayBuffer(ExecutionEngine *e, size_t length); + ArrayBuffer(ExecutionEngine *e, const QByteArray& array); ~ArrayBuffer(); QTypedArrayData *data; @@ -74,15 +75,11 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object QByteArray asByteArray() const; uint byteLength() const { return d()->byteLength(); } - char *data() { - // ### detach if refcount > 1 - return d()->data->data(); - } - const char *constData() { - // ### detach if refcount > 1 - return d()->data->data(); - } + char *data() { detach(); return d()->data ? d()->data->data() : 0; } + const char *constData() { detach(); return d()->data ? d()->data->data() : 0; } +private: + void detach(); }; struct ArrayBufferPrototype: Object diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index eecf874e19..8c0df3ef04 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -585,10 +585,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *pr Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array) { Scope scope(this); - Scoped object(scope, memoryManager->alloc(this, array.size())); - if (!hasException) { - memcpy(object->d()->data->data(), array.data(), array.size()); - } + Scoped object(scope, memoryManager->alloc(this, array)); return object->d(); } -- cgit v1.2.3 From 497ccdc843975bfe20f5b24e083d17f01012efb9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 10 Apr 2015 12:34:36 +0200 Subject: Speed up binding evaluation Don't spend any cycles of determining the location of the binding (file, line, column) unless we really need that information. That's the case when the profiler is active or an error happens. Change-Id: Iae97808d500b88fed6a813e8b224aa6ebe04d3b6 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4functionobject.cpp | 12 ++++++++++++ src/qml/jsruntime/qv4functionobject_p.h | 4 ++++ 2 files changed, 16 insertions(+) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 5be638e909..f7433e6365 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -210,6 +210,18 @@ bool FunctionObject::isBoundFunction() const return d()->vtable == BoundFunction::staticVTable(); } +QQmlSourceLocation FunctionObject::sourceLocation() const +{ + if (isBinding()) { + Q_ASSERT(as()); + return static_cast(d())->bindingLocation; + } + QV4::Function *function = d()->function; + Q_ASSERT(function); + + return QQmlSourceLocation(function->sourceFile(), function->compiledFunction->location.line, function->compiledFunction->location.column); +} + DEFINE_OBJECT_VTABLE(FunctionCtor); Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 3433e7b8ca..560061a705 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -40,6 +40,8 @@ QT_BEGIN_NAMESPACE +struct QQmlSourceLocation; + namespace QV4 { namespace Heap { @@ -140,6 +142,8 @@ struct Q_QML_EXPORT FunctionObject: Object { bool isBinding() const; bool isBoundFunction() const; + QQmlSourceLocation sourceLocation() const; + static void markObjects(Heap::Base *that, ExecutionEngine *e); }; -- cgit v1.2.3 From b220a20552838fbafbbf126b9e50d148ae76518d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 10 Apr 2015 12:34:46 +0200 Subject: Speed up value type binding creation * Avoid calling QMetaType::construct/destruct(typeId, ...) as that requires repeated lookups in the type registry. Instead cache the constructor/destructor/etc. function addresses in the QQmlValueType singletons as QMetaType * Allocate memory for the gadget pointer lazily, to accommodate the common case of a value type binding by property reference. Change-Id: I98a3ac73453b8f80027c06401b4f29a9707949d2 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4engine.cpp | 5 ++--- src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 8c0df3ef04..dfc7745f56 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1738,9 +1738,8 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da { QV4::Scoped vtw(scope, value); - if (vtw && vtw->d()->metaType == type) { - vtw->toGadget(data); - return true; + if (vtw && vtw->typeId() == type) { + return vtw->toGadget(data); } } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 7a5890f8c4..50efff001d 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1835,7 +1835,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) if (!wrapper) return Encode::undefined(); - object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget()); + object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr); } QQmlPropertyData method; -- cgit v1.2.3 From 63877c930e8efa119ac16798ed546cdba68f818b Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Apr 2015 12:33:13 +0200 Subject: Avoid strict mode for the surrounding QML call contexts The strict mode is not necessary from a correctness point of view but comes with the extra cost that for each script binding additional caller and arguments accessor members are a installed on the internal class. Change-Id: I13b688bc8344ee2f027679821586ca7670d17cc5 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 09d7393da9..9330f10780 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -166,7 +166,7 @@ Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::F callData->argc = 0; callData->thisObject = Primitive::undefinedValue(); - strictMode = true; + strictMode = false; outer = function->scope(); activation = qml->d(); -- cgit v1.2.3 From d22db9e458828d403110fa0b9de1ca0c831d7e96 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Apr 2015 15:50:55 +0200 Subject: Speed up script binding initialization Don't spend any time repeatedly building the same internal class for the simple binding functions. We can do that once at engine construction time. Change-Id: I3777b5bd15ad4a8aaf78ae13bee27e8d8cadc2ee Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4engine.cpp | 4 ++++ src/qml/jsruntime/qv4engine_p.h | 1 + src/qml/jsruntime/qv4functionobject.cpp | 18 ++++++++++++------ src/qml/jsruntime/qv4functionobject_p.h | 4 ++++ 4 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index dfc7745f56..cbfac86e9f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -308,6 +308,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) functionPrototype = memoryManager->alloc(functionProtoClass, objectPrototype.asObject()); functionClass = emptyClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); + simpleScriptFunctionClass = functionClass->addMember(id_name, Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name); + simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length, Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length); protoClass = emptyClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index bcb74ab694..f01579be71 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -169,6 +169,7 @@ public: InternalClass *arrayClass; InternalClass *functionClass; + InternalClass *simpleScriptFunctionClass; InternalClass *protoClass; InternalClass *regExpExecArrayClass; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f7433e6365..7006a8892d 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -459,21 +459,27 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) DEFINE_OBJECT_VTABLE(SimpleScriptFunction); Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto) - : Heap::FunctionObject(scope, function, createProto) + : Heap::FunctionObject(function->compilationUnit->engine->simpleScriptFunctionClass, function->compilationUnit->engine->functionPrototype.asObject()) { + this->scope = scope->d(); + this->function = function; function->compilationUnit->addref(); Q_ASSERT(function); Q_ASSERT(function->code); - // global function - if (!scope) - return; - Scope s(scope); ScopedFunctionObject f(s, this); - f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); + if (createProto) { + ScopedString name(s, function->name()); + f->init(name, createProto); + f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); + } else { + f->ensureMemberIndex(s.engine, Index_Length); + memberData->data[Index_Name] = function->name(); + memberData->data[Index_Length] = Primitive::fromInt32(f->formalParameterCount()); + } if (scope->d()->strictMode) { ScopedProperty pd(s); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 560061a705..252ff40a1a 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -89,6 +89,10 @@ struct IndexedBuiltinFunction : FunctionObject { }; struct SimpleScriptFunction : FunctionObject { + enum { + Index_Name = FunctionObject::Index_Prototype + 1, + Index_Length + }; SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto); }; -- cgit v1.2.3 From ca4dbd5675ad3aabffb9fb92f19b53b4c5028981 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 31 Mar 2015 20:23:27 +0200 Subject: Address uninitialized pointer variables Coverity CID 10721, 84861, 86705, 85424, 85422, 85259, 84863, 84857 Change-Id: Ia86970b5ac4e0be9de01b79b618d33011da6a328 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4errorobject.cpp | 1 + src/qml/jsruntime/qv4functionobject.cpp | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'src/qml/jsruntime') diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 119ad93e63..9034dee6a0 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -60,6 +60,7 @@ using namespace QV4; Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype) : Heap::Object(ic, prototype) + , stack(Q_NULLPTR) { Scope scope(ic->engine); Scoped e(scope, this); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 7006a8892d..0a12d013ac 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -65,6 +65,7 @@ DEFINE_OBJECT_VTABLE(FunctionObject); Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) + , function(Q_NULLPTR) { Scope s(scope->engine()); ScopedFunctionObject f(s, this); @@ -74,6 +75,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String * Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto) : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) + , function(Q_NULLPTR) { Scope s(scope->engine()); ScopedString name(s, function->name()); @@ -84,6 +86,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto) : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) + , function(Q_NULLPTR) { Scope s(scope->engine()); ScopedFunctionObject f(s, this); @@ -94,6 +97,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) , scope(scope) + , function(Q_NULLPTR) { Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -104,6 +108,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name) : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject()) , scope(scope->d()) + , function(Q_NULLPTR) { Scope s(scope); ScopedFunctionObject f(s, this); @@ -114,6 +119,7 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject()) , scope(scope) + , function(Q_NULLPTR) { Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -124,6 +130,7 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype) : Heap::Object(ic, prototype) , scope(ic->engine->rootContext()) + , function(Q_NULLPTR) { Scope scope(ic->engine); ScopedObject o(scope, this); -- cgit v1.2.3