diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 15:04:42 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 15:32:19 +0200 |
commit | 07782f48f4318a7261f1b0ddcd686b19ec812e36 (patch) | |
tree | 3fa2aa3a1170ad7ebaf5b1641cdce19a941ca480 /src/qml/jsruntime | |
parent | 50fcdfd705c2ad9560641986bf4152b017ee8bb6 (diff) | |
parent | f15a90e5d10465e66698209a5d88f1e63ae336fa (diff) |
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts:
src/qml/qml/qqmlbinding.cpp
src/qml/jsruntime/qv4arraybuffer.cpp
src/qml/jsruntime/qv4functionobject.cpp
Change-Id: Ic752e9dfd69b282093651c9234c110a49762f06d
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4arraybuffer.cpp | 26 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraybuffer_p.h | 13 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4errorobject.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 37 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 6 |
10 files changed, 84 insertions, 26 deletions
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 432d70f151..145e400c20 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.as<QV4::Object>()) + , data(const_cast<QByteArray&>(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<char> *oldData = d()->data; + + d()->data = QTypedArrayData<char>::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<char>::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 cbcde18793..a7f9e92c80 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<char> *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/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 6d3ba2c516..0ef7d56c4d 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -167,7 +167,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(); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 9b9a2349a9..8859f73bd7 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -308,6 +308,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.as<Object>()); 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); @@ -585,10 +589,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *pr Heap::ArrayBuffer *ExecutionEngine::newArrayBuffer(const QByteArray &array) { Scope scope(this); - Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array.size())); - if (!hasException) { - memcpy(object->d()->data->data(), array.data(), array.size()); - } + Scoped<ArrayBuffer> object(scope, memoryManager->alloc<ArrayBuffer>(this, array)); return object->d(); } @@ -1741,9 +1742,8 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da { QV4::Scoped<QV4::QQmlValueTypeWrapper> 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/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index e59e96f534..33dce48737 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -171,6 +171,7 @@ public: InternalClass *arrayClass; InternalClass *functionClass; + InternalClass *simpleScriptFunctionClass; InternalClass *protoClass; InternalClass *regExpExecArrayClass; diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index d9d8ed6d20..2c5795e8b3 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -62,6 +62,7 @@ using namespace QV4; Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype) : Heap::Object(ic, prototype) + , stack(Q_NULLPTR) { Scope scope(ic->engine); Scoped<QV4::ErrorObject> e(scope, this); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f5db520348..5a68cf6b79 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.objectValue()) , 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.objectValue()) , 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.objectValue()) , 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.objectValue()) , 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.objectValue()) , 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.objectValue()) , 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); @@ -209,6 +216,18 @@ bool FunctionObject::isBoundFunction() const return d()->vtable == BoundFunction::staticVTable(); } +QQmlSourceLocation FunctionObject::sourceLocation() const +{ + if (isBinding()) { + Q_ASSERT(as<const QV4::QQmlBindingFunction>()); + return static_cast<QV4::Heap::QQmlBindingFunction *>(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) @@ -446,21 +465,27 @@ ReturnedValue ScriptFunction::call(const 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.as<QV4::Object>()) { + 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 d13ecb98fb..2aa5d95831 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 { @@ -87,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); }; @@ -136,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); }; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 34414cd220..a7810563c9 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1836,7 +1836,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) const if (!wrapper) return Encode::undefined(); - object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget()); + object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadgetPtr); } QQmlPropertyData method; diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index ae1e8fbd32..7deb2098ac 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -54,8 +54,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. @@ -63,7 +63,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. |