aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2014-11-19 18:12:21 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2014-12-28 18:39:51 +0100
commitb7bcde88a35c0dba8bf78b829b60a634137fc778 (patch)
tree34395bdc64775394b8406511c86924c05a9ce73c /src
parent7dd5895854087c006d9ec58ada6899df6020b3c6 (diff)
Removed usage of QQmlValueType in QQmlValueTypeWrapper
QQmlValueType doesn't have anything really necessary :). Some code it has, but that was only called from the wrapper, so it was moved there. This also reduces one level of memory allocation for the wrapper. In theory the allocation for the JavaScript wrapper could be changed to be the size of the wrapper _plus_ the size needed for the gadget. However in anticipation of wanting to be able to move objects, we can't do that as we can't memmove() gadgets around - they might contain pointers to memory areas within. Change-Id: Icb5a6f5513e3b2c87f6639f6f7b1fb572af08137 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp47
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h26
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp200
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h9
-rw-r--r--src/qml/qml/v8/qv8engine_p.h1
6 files changed, 138 insertions, 147 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 7acd588b22..1af82ff25f 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1842,7 +1842,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (!wrapper)
return Encode::undefined();
- object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->type->gadget());
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget());
}
QQmlPropertyData method;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 20f3027e4c..e22e0f8fdc 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -192,24 +192,16 @@ QQmlValueType::~QQmlValueType()
void QQmlValueType::read(QObject *obj, int idx)
{
- readProperty(obj, idx, gadgetPtr);
-}
-
-void QQmlValueType::readVariantValue(QObject *obj, int idx, QVariant *into)
-{
- // important: must not change the userType of the variant
- readProperty(obj, idx, into);
+ void *a[] = { gadgetPtr, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
}
void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
{
Q_ASSERT(gadgetPtr);
- writeProperty(obj, idx, flags, gadgetPtr);
-}
-
-void QQmlValueType::writeVariantValue(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, QVariant *from)
-{
- writeProperty(obj, idx, flags, from);
+ int status = -1;
+ void *a[] = { gadgetPtr, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
QVariant QQmlValueType::value()
@@ -225,35 +217,6 @@ void QQmlValueType::setValue(const QVariant &value)
QMetaType::construct(typeId, gadgetPtr, value.constData());
}
-bool QQmlValueType::isEqual(const QVariant &other) const
-{
- Q_ASSERT(gadgetPtr);
- return QVariant(typeId, gadgetPtr) == other;
-}
-
-QString QQmlValueType::toString() const
-{
- const QMetaObject *mo = metaObject();
- const int toStringIndex = mo->indexOfMethod("toString()");
- if (toStringIndex != -1) {
- QString result;
- void *args[] = { &result, 0 };
- _metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), QMetaObject::InvokeMetaMethod, toStringIndex, args);
- return result;
- }
- QString result = QString::fromUtf8(QMetaType::typeName(typeId));
- result += QLatin1Char('(');
- const int propCount = mo->propertyCount();
- for (int i = 0; i < propCount; ++i) {
- QVariant value = mo->property(i).read(this);
- result += value.toString();
- if (i < propCount - 1)
- result += QStringLiteral(", ");
- }
- result += QLatin1Char(')');
- return result;
-}
-
QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
{
return this;
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index cd9e51957d..5c411f0e57 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -63,42 +63,16 @@ public:
QQmlValueType(int userType, const QMetaObject *metaObject);
~QQmlValueType();
void read(QObject *, int);
- void readVariantValue(QObject *, int, QVariant *);
void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags);
- void writeVariantValue(QObject *, int, QQmlPropertyPrivate::WriteFlags, QVariant *);
QVariant value();
void setValue(const QVariant &);
- QString toString() const;
- bool isEqual(const QVariant &value) const;
-
- void *gadget() const { return gadgetPtr; }
-
- inline int userType() const
- {
- return typeId;
-
- }
// ---- dynamic meta object data interface
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *);
virtual void objectDestroyed(QObject *);
virtual int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv);
// ----
-protected:
- inline void readProperty(QObject *obj, int idx, void *p)
- {
- void *a[] = { p, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
- }
-
- inline void writeProperty(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, void *p)
- {
- int status = -1;
- void *a[] = { p, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
- }
-
private:
const QMetaObject *_metaObject;
int typeId;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 8de5df9792..8ed1169ec7 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -79,10 +79,31 @@ using namespace QV4;
Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
: Heap::Object(engine)
+ , gadgetPtr(0)
{
setVTable(QV4::QQmlValueTypeWrapper::staticVTable());
}
+Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
+{
+ if (gadgetPtr)
+ QMetaType::destroy(metaType, gadgetPtr);
+}
+
+void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
+{
+ Q_ASSERT(metaType == value.userType());
+ QMetaType::destruct(metaType, gadgetPtr);
+ QMetaType::construct(metaType, gadgetPtr, value.constData());
+}
+
+QVariant Heap::QQmlValueTypeWrapper::toVariant() const
+{
+ Q_ASSERT(gadgetPtr);
+ return QVariant(metaType, gadgetPtr);
+}
+
+
Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine)
: Heap::QQmlValueTypeWrapper(engine)
{
@@ -99,33 +120,39 @@ bool QQmlValueTypeReference::readReferenceValue() const
if (writebackProperty.userType() == QMetaType::QVariant) {
// variant-containing-value-type reference
QVariant variantReferenceValue;
- d()->type->readVariantValue(d()->object, d()->property, &variantReferenceValue);
+
+ void *a[] = { &variantReferenceValue, 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, a);
+
int variantReferenceType = variantReferenceValue.userType();
- if (variantReferenceType != d()->type->userType()) {
+ if (variantReferenceType != d()->metaType) {
// This is a stale VariantReference. That is, the variant has been
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
// possible, or return false if it is not a value type.
if (QQmlValueTypeFactory::isValueType(variantReferenceType)) {
- QQmlValueType *vt = 0;
QQmlPropertyCache *cache = 0;
- if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType)) {
- vt = new QQmlValueType(variantReferenceType, mo);
+ if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType))
cache = QQmlEnginePrivate::get(engine())->cache(mo);
- }
- d()->type.reset(vt);
+ if (d()->gadgetPtr)
+ QMetaType::destroy(d()->metaType, d()->gadgetPtr);
+ d()->gadgetPtr = 0;
d()->propertyCache = cache;
- if (!d()->type) {
+ d()->metaType = variantReferenceType;
+ if (cache) {
+ d()->gadgetPtr = QMetaType::create(d()->metaType);
+ } else {
return false;
}
} else {
return false;
}
}
- d()->type->setValue(variantReferenceValue);
+ d()->setValue(variantReferenceValue);
} else {
// value-type reference
- d()->type->read(d()->object, d()->property);
+ void *args[] = { d()->gadget(), 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args);
}
return true;
}
@@ -149,8 +176,10 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
r->setPrototype(proto);
- r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->object = object; r->d()->property = property;
+ r->d()->object = object; r->d()->property = property;
r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
return r->asReturnedValue();
}
@@ -162,8 +191,10 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
r->setPrototype(proto);
- r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->type->setValue(value);
r->d()->propertyCache = QQmlEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
+ r->d()->setValue(value);
return r->asReturnedValue();
}
@@ -172,7 +203,7 @@ QVariant QQmlValueTypeWrapper::toVariant() const
if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return QVariant();
- return d()->type->value();
+ return d()->toVariant();
}
void QQmlValueTypeWrapper::destroy(Heap::Base *that)
@@ -209,9 +240,7 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
if (QQmlValueTypeReference *ref = as<QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return false;
- if (d()->type->isEqual(value))
- return true;
- return (value == d()->type->value());
+ return (value == d()->toVariant());
}
ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
@@ -226,7 +255,19 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
if (QQmlValueTypeReference *ref = w->as<QQmlValueTypeReference>())
if (!ref->readReferenceValue())
return Encode::undefined();
- return Encode(ctx->engine()->newString(w->d()->type->toString()));
+
+ QString result = QString::fromUtf8(QMetaType::typeName(w->d()->metaType));
+ result += QLatin1Char('(');
+ const QMetaObject *mo = w->d()->propertyCache->metaObject();
+ const int propCount = mo->propertyCount();
+ for (int i = 0; i < propCount; ++i) {
+ QVariant value = mo->property(i).readOnGadget(w->d()->gadget());
+ result += value.toString();
+ if (i < propCount - 1)
+ result += QStringLiteral(", ");
+ }
+ result += QLatin1Char(')');
+ return Encode(ctx->engine()->newString(result));
}
ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
@@ -235,10 +276,6 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = m->engine();
- // ### Remove this once we can do proper this calls.
- if (name == v4->id_toString)
- return Object::get(m, name, hasProperty);
-
// Note: readReferenceValue() can change the reference->type.
if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
if (!reference->readReferenceValue())
@@ -263,10 +300,13 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
if (result->propType == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
- QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args); \
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args); \
return QV4::Encode(constructor(v)); \
}
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ void *gadget = r->d()->gadget();
+
// These four types are the most common used by the value type wrappers
VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
VALUE_TYPE_LOAD(QMetaType::Int, int, int);
@@ -275,7 +315,7 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope
QVariant v(result->propType, (void *)0);
void *args[] = { v.data(), 0 };
- QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args);
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args);
return v4->v8Engine->fromVariant(v);
#undef VALUE_TYPE_ACCESSOR
}
@@ -289,80 +329,90 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value)
return;
Scoped<QQmlValueTypeWrapper> r(scope, static_cast<QQmlValueTypeWrapper *>(m));
+ Scoped<QQmlValueTypeReference> reference(scope, m->d());
- QByteArray propName = name->toQString().toUtf8();
- if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ int writeBackPropertyType = -1;
+
+ if (reference) {
QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
if (!writebackProperty.isWritable() || !reference->readReferenceValue())
return;
- // we lookup the index after readReferenceValue() since it can change the reference->type.
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
+ writeBackPropertyType = writebackProperty.userType();
+ }
+
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
+ if (!pd)
+ return;
+ QMetaProperty property = metaObject->property(pd->coreIndex);
+ Q_ASSERT(property.isValid());
+
+ QQmlBinding *newBinding = 0;
+
+ QV4::ScopedFunctionObject f(scope, value);
+ if (reference && f) {
+ if (!f->bindingKeyFlag()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ Scoped<String> e(scope, v4->newString(error));
+ v4->throwError(e);
return;
- QMetaProperty p = r->d()->type->metaObject()->property(index);
-
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (f) {
- if (!f->bindingKeyFlag()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
- Scoped<String> e(scope, v4->newString(error));
- v4->throwError(e);
- return;
- }
+ }
- QQmlContextData *context = QmlContextWrapper::callingContext(v4);
+ QQmlContextData *context = QmlContextWrapper::callingContext(v4);
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = reference->d()->object->metaObject()->property(reference->d()->property).userType();
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = index;
- cacheData.valueTypePropType = p.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData, context);
+ }
+ if (reference) {
QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, index, newBinding);
+ QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
if (oldBinding)
oldBinding->destroy();
+ }
- if (!f) {
- QVariant v = v4->v8Engine->toVariant(value, -1);
+ if (newBinding)
+ return;
- if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
- v = v.toInt();
+ QVariant v = v4->v8Engine->toVariant(value, property.userType());
- p.write(reference->d()->type.data(), v);
+ if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
+ v = v.toInt();
- if (writebackProperty.userType() == QMetaType::QVariant) {
- QVariant variantReferenceValue = r->d()->type->value();
- reference->d()->type->writeVariantValue(reference->d()->object, reference->d()->property, 0, &variantReferenceValue);
- } else {
- reference->d()->type->write(reference->d()->object, reference->d()->property, 0);
- }
- }
+ void *gadget = r->d()->gadget();
+ property.writeOnGadget(gadget, v);
- } else {
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
- return;
- QVariant v = v4->v8Engine->toVariant(value, -1);
+ if (reference) {
+ if (writeBackPropertyType == QMetaType::QVariant) {
+ QVariant variantReferenceValue = r->d()->toVariant();
- QMetaProperty p = r->d()->type->metaObject()->property(index);
- p.write(r->d()->type.data(), v);
+ int flags = 0;
+ int status = -1;
+ void *a[] = { &variantReferenceValue, 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
+
+ } else {
+ int flags = 0;
+ int status = -1;
+ void *a[] = { r->d()->gadget(), 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
+ }
}
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 24031800cd..ad883266bd 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -53,7 +53,6 @@
QT_BEGIN_NAMESPACE
-class QQmlValueType;
class QV8Engine;
namespace QV4 {
@@ -62,8 +61,14 @@ namespace Heap {
struct QQmlValueTypeWrapper : Object {
QQmlValueTypeWrapper(ExecutionEngine *engine);
+ ~QQmlValueTypeWrapper();
mutable QQmlRefPointer<QQmlPropertyCache> propertyCache;
- mutable QScopedPointer<QQmlValueType> type;
+ mutable void *gadgetPtr;
+ mutable int metaType;
+
+ void setValue(const QVariant &value) const;
+ QVariant toVariant() const;
+ void *gadget() const { return gadgetPtr; }
};
}
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 4a6737a131..18b59f0157 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -158,7 +158,6 @@ private:
class QObject;
class QQmlEngine;
-class QQmlValueType;
class QNetworkAccessManager;
class QQmlContextData;