Start implement new Object creation pattern
authorLars Knoll <lars.knoll@digia.com>
Thu, 8 May 2014 12:35:30 +0000 (14:35 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 22 Jul 2014 11:49:14 +0000 (13:49 +0200)
Create objects through a static create() method that returns a pointer
to the objects Data. This will later on simplify breaking the
direct connection between Object and Object::Data.

Change-Id: Id8daa3c766429bc36f432868e1957846147c96b6
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/imports/localstorage/plugin.cpp
src/particles/qquickv4particledata.cpp
src/qml/jsruntime/qv4managed.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4memberdata_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4scopedvalue_p.h
src/quick/items/qquickview.cpp
src/quick/items/qquickview_p.h
src/quick/items/qquickwindowmodule.cpp

index 143c129..651b8d4 100644 (file)
@@ -104,6 +104,13 @@ class QQmlSqlDatabaseWrapper : public Object
 public:
     enum Type { Database, Query, Rows };
     struct Data : Object::Data {
+        Data(ExecutionEngine *e)
+            : Object::Data(e)
+        {
+            setVTable(staticVTable());
+            type = Database;
+        }
+
         Type type;
         QSqlDatabase database;
 
@@ -130,14 +137,10 @@ public:
 
     V4_OBJECT
 
-    QQmlSqlDatabaseWrapper(QV8Engine *e)
-        : Object(QV8Engine::getV4(e))
+    static Data *create(QV8Engine *engine)
     {
-        setVTable(staticVTable());
-        d()->type = Database;
-        d()->inTransaction = false;
-        d()->readonly = false;
-        d()->forwardOnly = false;
+        QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
+        return new (e) Data(e);
     }
 
     ~QQmlSqlDatabaseWrapper() {
@@ -325,7 +328,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
             }
         }
         if (query.exec()) {
-            QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, new (scope.engine->memoryManager) QQmlSqlDatabaseWrapper(engine));
+            QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(engine));
             QV4::ScopedObject p(scope, databaseData(engine)->rowsProto.value());
             rows->setPrototype(p.getPointer());
             rows->d()->type = QQmlSqlDatabaseWrapper::Rows;
@@ -402,7 +405,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
     if (from_version != r->d()->version)
         V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->d()->version));
 
-    Scoped<QQmlSqlDatabaseWrapper> w(scope, new (scope.engine->memoryManager) QQmlSqlDatabaseWrapper(engine));
+    Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(engine));
     ScopedObject p(scope, databaseData(engine)->queryProto.value());
     w->setPrototype(p.getPointer());
     w->d()->type = QQmlSqlDatabaseWrapper::Query;
@@ -455,7 +458,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
 
     QSqlDatabase db = r->d()->database;
 
-    Scoped<QQmlSqlDatabaseWrapper> w(scope, new (scope.engine->memoryManager) QQmlSqlDatabaseWrapper(engine));
+    Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(engine));
     QV4::ScopedObject p(scope, databaseData(engine)->queryProto.value());
     w->setPrototype(p.getPointer());
     w->d()->type = QQmlSqlDatabaseWrapper::Query;
@@ -733,7 +736,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
             database.open();
     }
 
-    QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, new (scope.engine->memoryManager) QQmlSqlDatabaseWrapper(engine));
+    QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(engine));
     QV4::ScopedObject p(scope, databaseData(engine)->databaseProto.value());
     db->setPrototype(p.getPointer());
     db->d()->database = database;
index 58e37ab..cfe99af 100644 (file)
@@ -274,6 +274,12 @@ QT_BEGIN_NAMESPACE
 struct QV4ParticleData : public QV4::Object
 {
     struct Data : QV4::Object::Data {
+        Data(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
+            : Object::Data(engine)
+            , datum(datum)
+        {
+            setVTable(QV4ParticleData::staticVTable());
+        }
         QQuickParticleData* datum;//TODO: Guard needed?
     };
     struct {
@@ -281,15 +287,6 @@ struct QV4ParticleData : public QV4::Object
     } __data;
 
     V4_OBJECT
-    QV4ParticleData(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
-        : Object(engine)
-    {
-        setVTable(staticVTable());
-        d()->datum = datum;
-    }
-
-    static void destroy(Managed *that)
-    { that->as<QV4ParticleData>()->~QV4ParticleData(); }
 };
 
 DEFINE_OBJECT_VTABLE(QV4ParticleData);
@@ -523,7 +520,7 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData
     QV8ParticleDataDeletable *d = particleV8Data(engine);
     QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
     QV4::Scope scope(v4);
-    QV4::ScopedObject o(scope, new (v4->memoryManager) QV4ParticleData(v4, datum));
+    QV4::ScopedObject o(scope, new (v4) QV4ParticleData::Data(v4, datum));
     QV4::ScopedObject p(scope, d->proto.value());
     o->setPrototype(p.getPointer());
     m_v4Value = o;
index 3b0bdd0..5613e65 100644 (file)
@@ -164,7 +164,22 @@ void Managed::setVTable(const ManagedVTable *vt)
     d()->internalClass = internalClass()->changeVTable(vt);
 }
 
+void Managed::Data::setVTable(const ManagedVTable *vt)
+{
+    Q_ASSERT(internalClass);
+    internalClass = internalClass->changeVTable(vt);
+}
+
+
 bool Managed::isEqualTo(Managed *, Managed *)
 {
     return false;
 }
+
+
+void *Managed::Data::operator new(size_t size, ExecutionEngine *e)
+{
+    assert(e);
+
+    return e->memoryManager->allocManaged(size);
+}
index c70b717..729e835 100644 (file)
@@ -176,26 +176,41 @@ const QV4::ObjectVTable classname::static_vtbl =    \
     advanceIterator                            \
 }
 
+struct HeapObject {
+
+};
+
 struct Q_QML_PRIVATE_EXPORT Managed
 {
-    struct Data {
+    struct Data : HeapObject {
+        Data() {}
+        Data(InternalClass *internal)
+            : internalClass(internal)
+            , inUse(1)
+            , extensible(1)
+        {
+            // ####
+//            Q_ASSERT(internal && internal->vtable);
+        }
         InternalClass *internalClass;
-        union {
-            uint _data;
-            struct {
-                uchar markBit :  1;
-                uchar inUse   :  1;
-                uchar extensible : 1; // used by Object
-                uchar _unused : 1;
-                uchar needsActivation : 1; // used by FunctionObject
-                uchar strictMode : 1; // used by FunctionObject
-                uchar bindingKeyFlag : 1;
-                uchar hasAccessorProperty : 1;
-                uchar _type;
-                mutable uchar subtype;
-                uchar _flags;
-            };
+        struct {
+            uchar markBit :  1;
+            uchar inUse   :  1;
+            uchar extensible : 1; // used by Object
+            uchar _unused : 1;
+            uchar needsActivation : 1; // used by FunctionObject
+            uchar strictMode : 1; // used by FunctionObject
+            uchar bindingKeyFlag : 1;
+            uchar hasAccessorProperty : 1;
+            uchar _type;
+            mutable uchar subtype;
+            uchar _flags;
         };
+
+        void setVTable(const ManagedVTable *vt);
+
+        void *operator new(size_t size, ExecutionEngine *e);
+        void *operator new(size_t, Managed *m) { return m; }
     };
     Data data;
     V4_MANAGED
@@ -214,12 +229,8 @@ private:
 
 protected:
     Managed(InternalClass *internal)
+        : data(internal)
     {
-        Q_ASSERT(internal && internal->vtable);
-        d()->internalClass = internal;
-        d()->_data = 0;
-        d()->inUse = 1;
-        d()->extensible = 1;
     }
 
 public:
index 41e0260..f5f2305 100644 (file)
@@ -51,11 +51,17 @@ namespace QV4 {
 struct MemberData : Managed
 {
     struct Data : Managed::Data {
-        uint size;
+        union {
+            uint size;
+            double _dummy;
+        };
         Value data[1];
     };
     struct {
-        uint size;
+        union {
+            uint size;
+            double _dummy;
+        };
         Value data[1];
     } __data;
 
index a9218ca..9abfb25 100644 (file)
@@ -70,6 +70,16 @@ using namespace QV4;
 
 DEFINE_OBJECT_VTABLE(Object);
 
+Object::Data::Data(InternalClass *internalClass)
+    : Managed::Data(internalClass)
+{
+    if (internalClass->size) {
+        Scope scope(internalClass->engine);
+        ScopedObject o(scope, this);
+        o->memberData().ensureIndex(internalClass->engine, internalClass->size);
+    }
+}
+
 Object::Object(ExecutionEngine *engine)
     : Managed(engine->objectClass)
 {
index 19105b1..4ba27cc 100644 (file)
@@ -104,6 +104,12 @@ struct URIErrorPrototype;
 
 struct Q_QML_EXPORT Object: Managed {
     struct Data : Managed::Data {
+        Data(ExecutionEngine *engine)
+            : Managed::Data(engine->objectClass)
+        {
+        }
+        Data(InternalClass *internal = 0);
+
         Members memberData;
         ArrayData *arrayData;
     };
index dfaa7e6..5a7852f 100644 (file)
@@ -215,6 +215,16 @@ struct Scoped
         ++scope.size;
 #endif
     }
+    Scoped(const Scope &scope, HeapObject *o)
+    {
+        Value v;
+        v.m = reinterpret_cast<Managed *>(o);
+        ptr = scope.engine->jsStackTop++;
+        setPointer(value_cast<T>(v));
+#ifndef QT_NO_DEBUG
+        ++scope.size;
+#endif
+    }
     Scoped(const Scope &scope, const ScopedValue &v)
     {
         ptr = scope.engine->jsStackTop++;
@@ -280,6 +290,12 @@ struct Scoped
 #endif
     }
 
+    Scoped<T> &operator=(HeapObject *o) {
+        Value v;
+        v.m = reinterpret_cast<Managed *>(o);
+        setPointer(value_cast<T>(v));
+        return *this;
+    }
     Scoped<T> &operator=(const Value &v) {
         setPointer(value_cast<T>(v));
         return *this;
index 1a5058f..5e26cbe 100644 (file)
@@ -58,11 +58,10 @@ QT_BEGIN_NAMESPACE
 
 DEFINE_OBJECT_VTABLE(QQuickRootItemMarker);
 
-QQuickRootItemMarker::QQuickRootItemMarker(QQmlEngine *engine, QQuickWindow *window)
-    : QV4::Object(QQmlEnginePrivate::getV4Engine(engine))
+QQuickRootItemMarker::Data *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
 {
-    d()->window = window;
-    setVTable(staticVTable());
+    QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
+    return new (e) Data(e, window);
 }
 
 void QQuickRootItemMarker::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e)
@@ -91,7 +90,7 @@ void QQuickViewPrivate::init(QQmlEngine* e)
     {
         QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data());
         QV4::Scope scope(v4);
-        QV4::Scoped<QQuickRootItemMarker> v(scope, new (v4->memoryManager) QQuickRootItemMarker(engine.data(), q));
+        QV4::Scoped<QQuickRootItemMarker> v(scope, QQuickRootItemMarker::create(engine.data(), q));
         rootItemMarker = v;
     }
 
index e73d5aa..8b35500 100644 (file)
@@ -105,6 +105,13 @@ public:
 struct QQuickRootItemMarker : public QV4::Object
 {
     struct Data : QV4::Object::Data {
+        Data(QV4::ExecutionEngine *engine, QQuickWindow *window)
+            : Object::Data(engine)
+            , window(window)
+        {
+            setVTable(staticVTable());
+        }
+
         QQuickWindow *window;
     };
     struct {
@@ -113,12 +120,7 @@ struct QQuickRootItemMarker : public QV4::Object
 
     V4_OBJECT
 
-    QQuickRootItemMarker(QQmlEngine *engine, QQuickWindow *window);
-
-    static void destroy(Managed *that)
-    {
-        static_cast<QQuickRootItemMarker*>(that)->~QQuickRootItemMarker();
-    }
+    static Data *create(QQmlEngine *engine, QQuickWindow *window);
 
     static void markObjects(Managed *that, QV4::ExecutionEngine *e);
 
index 91388ea..51053ea 100644 (file)
@@ -102,7 +102,7 @@ protected:
         {
             QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(e);
             QV4::Scope scope(v4);
-            QV4::ScopedObject v(scope, new (v4->memoryManager) QQuickRootItemMarker(e, this));
+            QV4::ScopedObject v(scope, QQuickRootItemMarker::create(e, this));
             rootItemMarker = v;
         }
     }