From 8e87197c2afa19df1fb15cb9b6b3cc17c3d4c0d6 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Thu, 1 Apr 2010 15:29:26 +1000
Subject: Optimization: Improve allocation strategy for
 QDeclarativeDeclarativeData

This improves the declarative/creation/itemtree_qml benchmark by 6%
---
 src/corelib/kernel/qobject.cpp                     |  8 ++--
 src/corelib/kernel/qobject_p.h                     |  5 +--
 src/declarative/qml/qdeclarativecompiler.cpp       | 45 ++++++++++++++--------
 .../qml/qdeclarativedeclarativedata_p.h            |  8 +++-
 src/declarative/qml/qdeclarativeengine.cpp         | 14 +++++++
 src/declarative/qml/qdeclarativeinstruction.cpp    |  2 +
 src/declarative/qml/qdeclarativeinstruction_p.h    |  7 ++++
 src/declarative/qml/qdeclarativemetatype.cpp       | 10 +++++
 src/declarative/qml/qdeclarativemetatype_p.h       |  4 ++
 src/declarative/qml/qdeclarativevme.cpp            | 22 ++++++++++-
 10 files changed, 101 insertions(+), 24 deletions(-)

diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index dbc6be2..dfd6a08 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -125,8 +125,10 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
     }
 }
 
+void (*QDeclarativeData::destroyed)(QDeclarativeData *, QObject *) = 0;
+void (*QDeclarativeData::parentChanged)(QDeclarativeData *, QObject *, QObject *) = 0;
+
 QObjectData::~QObjectData() {}
-QDeclarativeData::~QDeclarativeData() {}
 
 QObjectPrivate::QObjectPrivate(int version)
     : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
@@ -876,7 +878,7 @@ QObject::~QObject()
     }
 
     if (d->declarativeData)
-        d->declarativeData->destroyed(this);
+        QDeclarativeData::destroyed(d->declarativeData, this);
 
     {
         QMutex *signalSlotMutex = 0;
@@ -2025,7 +2027,7 @@ void QObjectPrivate::setParent_helper(QObject *o)
         }
     }
     if (!wasDeleted && declarativeData)
-        declarativeData->parentChanged(q, o);
+        QDeclarativeData::parentChanged(declarativeData, q, o);
 }
 
 /*!
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 3b59abb..e5d904c 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -87,9 +87,8 @@ enum { QObjectPrivateVersion = QT_VERSION };
 class Q_CORE_EXPORT QDeclarativeData
 {
 public:
-    virtual ~QDeclarativeData();
-    virtual void destroyed(QObject *) = 0;
-    virtual void parentChanged(QObject *, QObject *) = 0;
+    static void (*destroyed)(QDeclarativeData *, QObject *);
+    static void (*parentChanged)(QDeclarativeData *, QObject *, QObject *);
 };
 
 class Q_CORE_EXPORT QObjectPrivate : public QObjectData
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 56af5f5..27fecfb 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -881,23 +881,38 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj)
     }
 
     // Create the object
-    QDeclarativeInstruction create;
-    create.type = QDeclarativeInstruction::CreateObject;
-    create.line = obj->location.start.line;
-    create.create.column = obj->location.start.column;
-    create.create.data = -1;
-    if (!obj->custom.isEmpty())
-        create.create.data = output->indexForByteArray(obj->custom);
-    create.create.type = obj->type;
-    if (!output->types.at(create.create.type).type && 
-        !obj->bindingBitmask.isEmpty()) {
-        Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
-        create.create.bindingBits = 
-            output->indexForByteArray(obj->bindingBitmask);
+    if (obj->custom.isEmpty() && output->types.at(obj->type).type &&
+        obj != compileState.root) {
+
+        QDeclarativeInstruction create;
+        create.type = QDeclarativeInstruction::CreateSimpleObject;
+        create.line = obj->location.start.line;
+        create.createSimple.create = output->types.at(obj->type).type->createFunction();
+        create.createSimple.typeSize = output->types.at(obj->type).type->createSize();
+        create.createSimple.column = obj->location.start.column;
+        output->bytecode << create;
+
     } else {
-        create.create.bindingBits = -1;
+
+        QDeclarativeInstruction create;
+        create.type = QDeclarativeInstruction::CreateObject;
+        create.line = obj->location.start.line;
+        create.create.column = obj->location.start.column;
+        create.create.data = -1;
+        if (!obj->custom.isEmpty())
+            create.create.data = output->indexForByteArray(obj->custom);
+        create.create.type = obj->type;
+        if (!output->types.at(create.create.type).type && 
+            !obj->bindingBitmask.isEmpty()) {
+            Q_ASSERT(obj->bindingBitmask.size() % 4 == 0);
+            create.create.bindingBits = 
+                output->indexForByteArray(obj->bindingBitmask);
+        } else {
+            create.create.bindingBits = -1;
+        }
+        output->bytecode << create;
+
     }
-    output->bytecode << create;
 
     // Setup the synthesized meta object if necessary
     if (!obj->metadata.isEmpty()) {
diff --git a/src/declarative/qml/qdeclarativedeclarativedata_p.h b/src/declarative/qml/qdeclarativedeclarativedata_p.h
index d1d063a..dfc3113 100644
--- a/src/declarative/qml/qdeclarativedeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedeclarativedata_p.h
@@ -64,6 +64,10 @@ class QDeclarativeAbstractBinding;
 class QDeclarativeContext;
 class QDeclarativePropertyCache;
 class QDeclarativeContextData;
+// This class is structured in such a way, that simply zero'ing it is the
+// default state for elemental object allocations.  This is crucial in the
+// workings of the QDeclarativeInstruction::CreateSimpleObject instruction.
+// Don't change anything here without first considering that case!
 class Q_AUTOTEST_EXPORT QDeclarativeDeclarativeData : public QDeclarativeData
 {
 public:
@@ -73,8 +77,8 @@ public:
           bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), 
           attachedProperties(0), propertyCache(0), guards(0) {}
 
-    virtual void destroyed(QObject *);
-    virtual void parentChanged(QObject *, QObject *);
+    void destroyed(QObject *);
+    void parentChanged(QObject *, QObject *);
 
     void setImplicitDestructible() {
         if (!explicitIndestructibleSet) indestructible = false;
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 3e570e5..65dd72b 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -346,6 +346,17 @@ Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer);
 typedef QMap<QString, QString> StringStringMap;
 Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri
 
+
+static void QDeclarativeDeclarativeData_destroyed(QDeclarativeData *d, QObject *o)
+{
+    static_cast<QDeclarativeDeclarativeData *>(d)->destroyed(o);
+}
+
+static void QDeclarativeDeclarativeData_parentChanged(QDeclarativeData *d, QObject *o, QObject *p)
+{
+    static_cast<QDeclarativeDeclarativeData *>(d)->parentChanged(o, p);
+}
+
 void QDeclarativeEnginePrivate::init()
 {
     Q_Q(QDeclarativeEngine);
@@ -353,6 +364,9 @@ void QDeclarativeEnginePrivate::init()
     qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
     qRegisterMetaType<QScriptValue>("QScriptValue");
 
+    QDeclarativeData::destroyed = QDeclarativeDeclarativeData_destroyed;
+    QDeclarativeData::parentChanged = QDeclarativeDeclarativeData_parentChanged;
+
     contextClass = new QDeclarativeContextScriptClass(q);
     objectClass = new QDeclarativeObjectScriptClass(q);
     valueTypeClass = new QDeclarativeValueTypeScriptClass(q);
diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp
index 9083ab3..36e5a2d 100644
--- a/src/declarative/qml/qdeclarativeinstruction.cpp
+++ b/src/declarative/qml/qdeclarativeinstruction.cpp
@@ -60,6 +60,8 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx)
         break;
     case QDeclarativeInstruction::CreateObject:
         qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+    case QDeclarativeInstruction::CreateSimpleObject:
+        qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize;
         break;
     case QDeclarativeInstruction::SetId:
         qWarning().nospace() << idx << "\t\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t" << primitives.at(instr->setId.value);
diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h
index 877179d..1f3c964 100644
--- a/src/declarative/qml/qdeclarativeinstruction_p.h
+++ b/src/declarative/qml/qdeclarativeinstruction_p.h
@@ -74,6 +74,7 @@ public:
         //                      top of the stack.
         Init,                     /* init */
         CreateObject,             /* create */
+        CreateSimpleObject,       /* createSimple */
         SetId,                    /* setId */
         SetDefault,
         CreateComponent,          /* createComponent */
@@ -175,6 +176,11 @@ public:
         int bindingBits;
         ushort column;
     };
+    struct CreateSimpleInstruction {
+        void (*create)(void *);
+        int typeSize;
+        ushort column;
+    };
     struct StoreMetaInstruction {
         int data;
         int aliasData;
@@ -305,6 +311,7 @@ public:
     union {
         InitInstruction init;
         CreateInstruction create;
+        CreateSimpleInstruction createSimple;
         StoreMetaInstruction storeMeta;
         SetIdInstruction setId;
         AssignValueSourceInstruction assignValueSource;
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index c512d97..6f99f95 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -313,6 +313,16 @@ QDeclarativeCustomParser *QDeclarativeType::customParser() const
     return d->m_customParser;
 }
 
+QDeclarativeType::CreateFunc QDeclarativeType::createFunction() const
+{
+    return d->m_newFunc;
+}
+
+int QDeclarativeType::createSize() const
+{
+    return d->m_allocationSize;
+}
+
 bool QDeclarativeType::isCreatable() const
 {
     return d->m_newFunc != 0;
diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h
index b3ec5e3..96e3c74 100644
--- a/src/declarative/qml/qdeclarativemetatype_p.h
+++ b/src/declarative/qml/qdeclarativemetatype_p.h
@@ -115,6 +115,10 @@ public:
     QObject *create() const;
     void create(QObject **, void **, size_t) const;
 
+    typedef void (*CreateFunc)(void *);
+    CreateFunc createFunction() const;
+    int createSize() const;
+
     QDeclarativeCustomParser *customParser() const;
 
     bool isCreatable() const;
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 2338bc3..6498e6c 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -236,13 +236,33 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
                         } 
                     } else { 
 			    QDeclarative_setParent_noEvent(o, parent);
-       //                 o->setParent(parent); 
                     } 
                 }
                 stack.push(o);
             }
             break;
 
+        case QDeclarativeInstruction::CreateSimpleObject:
+            {
+                QObject *o = (QObject *)operator new(instr.createSimple.typeSize + 
+                                                     sizeof(QDeclarativeDeclarativeData));   
+                ::bzero(o, instr.createSimple.typeSize + sizeof(QDeclarativeDeclarativeData));                             
+                instr.createSimple.create(o);
+
+                QDeclarativeDeclarativeData *ddata = 
+                    (QDeclarativeDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize);
+                ddata->lineNumber = instr.line;
+                ddata->columnNumber = instr.createSimple.column;
+
+                QObjectPrivate::get(o)->declarativeData = ddata;                                                      
+                ctxt->addObject(o);                                                                                   
+                QObject *parent = stack.top();                                                                    
+                QDeclarative_setParent_noEvent(o, parent);                                                        
+
+                stack.push(o);
+            }
+            break;
+
         case QDeclarativeInstruction::SetId:
             {
                 QObject *target = stack.top();
-- 
cgit v0.12