aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-04-22 15:04:42 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-04-22 15:32:19 +0200
commit07782f48f4318a7261f1b0ddcd686b19ec812e36 (patch)
tree3fa2aa3a1170ad7ebaf5b1641cdce19a941ca480 /src/qml/jsruntime
parent50fcdfd705c2ad9560641986bf4152b017ee8bb6 (diff)
parentf15a90e5d10465e66698209a5d88f1e63ae336fa (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.cpp26
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h13
-rw-r--r--src/qml/jsruntime/qv4context.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp14
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp37
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4value_p.h6
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.