Turn ArrayData into a Managed object
authorLars Knoll <lars.knoll@digia.com>
Mon, 20 Jan 2014 15:01:26 +0000 (16:01 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 23 Jan 2014 20:47:27 +0000 (21:47 +0100)
Memory manage ArrayData. Once the ArrayData is moved
to be inline inside the object, this will save quite
some time for allocating and freeing arrays.

Change-Id: I19a520161d41bfe3d83f377af0b41db4ac5b99e4
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4arraydata.cpp
src/qml/jsruntime/qv4arraydata_p.h
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4managed.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4string.cpp

index 5e4debd..4a3c3c1 100644 (file)
@@ -51,12 +51,12 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
     , context(context)
     , fullyCreated(false)
 {
-    setArrayType(ArrayData::Complex);
-
     ExecutionEngine *v4 = context->engine;
     Scope scope(v4);
     ScopedObject protectThis(scope, this);
 
+    setArrayType(ArrayData::Complex);
+
     if (context->strictMode) {
         Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
         Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
index 933449b..a71aa12 100644 (file)
@@ -46,9 +46,8 @@ using namespace QV4;
 
 const ArrayVTable SimpleArrayData::static_vtbl =
 {
+    DEFINE_MANAGED_VTABLE_INT(SimpleArrayData),
     SimpleArrayData::Simple,
-    SimpleArrayData::destroy,
-    SimpleArrayData::markObjects,
     SimpleArrayData::reserve,
     SimpleArrayData::get,
     SimpleArrayData::put,
@@ -64,9 +63,8 @@ const ArrayVTable SimpleArrayData::static_vtbl =
 
 const ArrayVTable SparseArrayData::static_vtbl =
 {
+    DEFINE_MANAGED_VTABLE_INT(SparseArrayData),
     ArrayData::Sparse,
-    SparseArrayData::destroy,
-    SparseArrayData::markObjects,
     SparseArrayData::reserve,
     SparseArrayData::get,
     SparseArrayData::put,
@@ -141,20 +139,20 @@ void ArrayData::ensureAttributes()
 }
 
 
-void SimpleArrayData::destroy(ArrayData *d)
+void SimpleArrayData::destroy(Managed *d)
 {
     SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
     delete [] (dd->data - dd->offset);
     if (dd->attrs)
         delete [] (dd->attrs - dd->offset);
-    delete dd;
 }
 
-void SimpleArrayData::markObjects(ArrayData *d, ExecutionEngine *e)
+void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e)
 {
-    uint l = static_cast<SimpleArrayData *>(d)->len;
+    SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
+    uint l = dd->len;
     for (uint i = 0; i < l; ++i)
-        d->data[i].mark(e);
+        dd->data[i].mark(e);
 }
 
 ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index)
@@ -298,20 +296,21 @@ void SparseArrayData::free(ArrayData *d, uint idx)
 }
 
 
-void SparseArrayData::destroy(ArrayData *d)
+void SparseArrayData::destroy(Managed *d)
 {
-    delete static_cast<SparseArrayData *>(d)->sparse;
-    delete [] d->data;
-    if (d->attrs)
-        delete [] d->attrs;
-    delete d;
+    SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+    delete dd->sparse;
+    delete [] dd->data;
+    if (dd->attrs)
+        delete [] dd->attrs;
 }
 
-void SparseArrayData::markObjects(ArrayData *d, ExecutionEngine *e)
+void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
 {
-    uint l = d->alloc;
+    SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+    uint l = dd->alloc;
     for (uint i = 0; i < l; ++i)
-        d->data[i].mark(e);
+        dd->data[i].mark(e);
 }
 
 void SparseArrayData::reserve(ArrayData *d, uint n)
@@ -603,9 +602,9 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
         if (!sparse->sparse->nEntries())
             return;
 
-        SimpleArrayData *d = new SimpleArrayData;
+        SimpleArrayData *d = new (context->engine->memoryManager) SimpleArrayData(context->engine);
         thisObject->arrayData = d;
-        d->vtable->reserve(d, sparse->sparse->nEntries());
+        d->vtable()->reserve(d, sparse->sparse->nEntries());
 
         SparseArrayNode *n = sparse->sparse->begin();
         uint i = 0;
@@ -645,8 +644,7 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
             }
 
         }
-
-        sparse->ArrayData::destroy();
+        // ### explicitly delete sparse
     } else {
         SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
         if (len > d->len)
index 9d9e570..e0f8964 100644 (file)
@@ -50,13 +50,20 @@ QT_BEGIN_NAMESPACE
 
 namespace QV4 {
 
+#define V4_ARRAYDATA \
+    public: \
+        Q_MANAGED_CHECK \
+        static const QV4::ArrayVTable static_vtbl; \
+        static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+        template <typename T> \
+        QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+
 struct ArrayData;
 
 struct ArrayVTable
 {
+    ManagedVTable managedVTable;
     uint type;
-    void (*destroy)(ArrayData *d);
-    void (*markObjects)(ArrayData *, ExecutionEngine *e);
     void (*reserve)(ArrayData *d, uint n);
     ReturnedValue (*get)(const ArrayData *d, uint index);
     bool (*put)(ArrayData *d, uint index, ValueRef value);
@@ -71,10 +78,10 @@ struct ArrayVTable
 };
 
 
-struct Q_QML_EXPORT ArrayData
+struct Q_QML_EXPORT ArrayData : public Managed
 {
-    ArrayData()
-        : vtable(0)
+    ArrayData(InternalClass *ic)
+        : Managed(ic)
         , alloc(0)
         , type(0)
         , attrs(0)
@@ -89,18 +96,18 @@ struct Q_QML_EXPORT ArrayData
         Custom = 3
     };
 
-    const ArrayVTable *vtable;
     uint alloc;
     uint type;
     PropertyAttributes *attrs;
     SafeValue *data;
 
+    const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); }
     bool isSparse() const { return this && type == Sparse; }
 
     uint length() const {
         if (!this)
             return 0;
-        return vtable->length(this);
+        return vtable()->length(this);
     }
 
     bool hasAttributes() const {
@@ -109,60 +116,52 @@ struct Q_QML_EXPORT ArrayData
     void ensureAttributes();
     PropertyAttributes attributes(int i) const {
         Q_ASSERT(this);
-        return attrs ? vtable->attribute(this, i) : Attr_Data;
+        return attrs ? vtable()->attribute(this, i) : Attr_Data;
     }
     void setAttributes(uint i, PropertyAttributes a) {
         Q_ASSERT(this);
         if (attrs || a != Attr_Data) {
             ensureAttributes();
             a.resolve();
-            vtable->setAttribute(this, i, a);
+            vtable()->setAttribute(this, i, a);
         }
     }
 
     bool isEmpty(uint i) const {
         if (!this)
             return true;
-        return (vtable->get(this, i) == Primitive::emptyValue().asReturnedValue());
+        return (vtable()->get(this, i) == Primitive::emptyValue().asReturnedValue());
     }
 
 
-    inline void destroy() {
-        vtable->destroy(this);
-    }
-
-    inline void markObjects(ExecutionEngine *e) {
-        vtable->markObjects(this, e);
-    }
-
     inline void push_front(SafeValue *values, uint nValues) {
-        vtable->push_front(this, values, nValues);
+        vtable()->push_front(this, values, nValues);
     }
     inline ReturnedValue pop_front() {
-        return vtable->pop_front(this);
+        return vtable()->pop_front(this);
     }
     inline uint push_back(uint l, uint n, SafeValue *values) {
-        vtable->putArray(this, l, values, n);
+        vtable()->putArray(this, l, values, n);
         return length();
     }
     inline bool deleteIndex(uint index) {
-        return vtable->del(this, index);
+        return vtable()->del(this, index);
     }
     inline uint truncate(uint newLen) {
         if (!this)
             return newLen;
-        return vtable->truncate(this, newLen);
+        return vtable()->truncate(this, newLen);
     }
     bool put(uint index, ValueRef value) {
-        return vtable->put(this, index, value);
+        return vtable()->put(this, index, value);
     }
     bool put(uint index, SafeValue *values, uint n) {
-        return vtable->putArray(this, index, values, n);
+        return vtable()->putArray(this, index, values, n);
     }
     ReturnedValue get(uint i) const {
         if (!this)
             return Primitive::emptyValue().asReturnedValue();
-        return vtable->get(this, i);
+        return vtable()->get(this, i);
     }
     inline Property *getProperty(uint index) const;
 
@@ -173,11 +172,13 @@ struct Q_QML_EXPORT ArrayData
 
 struct Q_QML_EXPORT SimpleArrayData : public ArrayData
 {
-    SimpleArrayData()
-        : ArrayData()
+    V4_ARRAYDATA
+
+    SimpleArrayData(ExecutionEngine *engine)
+        : ArrayData(engine->emptyClass)
         , len(0)
         , offset(0)
-    { vtable = &static_vtbl; }
+    { setVTable(staticVTable()); }
 
     uint len;
     uint offset;
@@ -185,8 +186,8 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData
     static void getHeadRoom(ArrayData *d);
     static void reserve(ArrayData *d, uint n);
 
-    static void destroy(ArrayData *d);
-    static void markObjects(ArrayData *d, ExecutionEngine *e);
+    static void destroy(Managed *d);
+    static void markObjects(Managed *d, ExecutionEngine *e);
 
     static ReturnedValue get(const ArrayData *d, uint index);
     static bool put(ArrayData *d, uint index, ValueRef value);
@@ -198,17 +199,17 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData
     static ReturnedValue pop_front(ArrayData *d);
     static uint truncate(ArrayData *d, uint newLen);
     static uint length(const ArrayData *d);
-
-    static const ArrayVTable static_vtbl;
-
 };
 
 struct Q_QML_EXPORT SparseArrayData : public ArrayData
 {
-    SparseArrayData()
-        : freeList(0)
+    V4_ARRAYDATA
+
+    SparseArrayData(ExecutionEngine *engine)
+        : ArrayData(engine->emptyClass)
+        , freeList(0)
         , sparse(0)
-    { vtable = &static_vtbl; }
+    { setVTable(staticVTable()); }
 
     uint freeList;
     SparseArray *sparse;
@@ -216,8 +217,8 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
     static uint allocate(ArrayData *d, bool doubleSlot = false);
     static void free(ArrayData *d, uint idx);
 
-    static void destroy(ArrayData *d);
-    static void markObjects(ArrayData *d, ExecutionEngine *e);
+    static void destroy(Managed *d);
+    static void markObjects(Managed *d, ExecutionEngine *e);
 
     static void reserve(ArrayData *d, uint n);
     static ReturnedValue get(const ArrayData *d, uint index);
@@ -230,8 +231,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
     static ReturnedValue pop_front(ArrayData *d);
     static uint truncate(ArrayData *d, uint newLen);
     static uint length(const ArrayData *d);
-
-    static const ArrayVTable static_vtbl;
 };
 
 
index d17a6cc..cc712c7 100644 (file)
 
 using namespace QV4;
 
-const ManagedVTable ExecutionContext::static_vtbl =
-{
-    ExecutionContext::IsExecutionContext,
-    ExecutionContext::IsString,
-    ExecutionContext::IsObject,
-    ExecutionContext::IsFunctionObject,
-    ExecutionContext::IsErrorObject,
-    0,
-    ExecutionContext::MyType,
-    "ExecutionContext",
-    destroy,
-    markObjects,
-    isEqualTo
-};
+DEFINE_MANAGED_VTABLE(ExecutionContext);
 
 CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
 {
index 671ac5d..1f4030a 100644 (file)
@@ -52,6 +52,7 @@ const ManagedVTable Managed::static_vtbl =
     Managed::IsObject,
     Managed::IsFunctionObject,
     Managed::IsErrorObject,
+    Managed::IsArrayData,
     0,
     Managed::MyType,
     "Managed",
index e97217b..da2aab6 100644 (file)
@@ -97,7 +97,8 @@ struct ManagedVTable
     uint isObject : 1;
     uint isFunctionObject : 1;
     uint isErrorObject : 1;
-    uint unused : 19;
+    uint isArrayData : 1;
+    uint unused : 18;
     uint type : 8;
     const char *className;
     void (*destroy)(Managed *);
@@ -125,39 +126,31 @@ struct ObjectVTable
     void (*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes);
 };
 
-#define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl =    \
+#define DEFINE_MANAGED_VTABLE_INT(classname) \
 {     \
     classname::IsExecutionContext,   \
     classname::IsString,   \
     classname::IsObject,   \
     classname::IsFunctionObject,   \
     classname::IsErrorObject,   \
+    classname::IsArrayData,   \
     0,                                          \
     classname::MyType,                          \
     #classname,                                 \
     destroy,                                    \
     markObjects,                                \
-    isEqualTo,                                  \
+    isEqualTo                                  \
 }
 
 
+#define DEFINE_MANAGED_VTABLE(classname) \
+const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname)
+
+
 #define DEFINE_OBJECT_VTABLE(classname) \
 const QV4::ObjectVTable classname::static_vtbl =    \
 {     \
-    { \
-        classname::IsExecutionContext,   \
-        classname::IsString,   \
-        classname::IsObject,   \
-        classname::IsFunctionObject,   \
-        classname::IsErrorObject,   \
-        0,                                          \
-        classname::MyType,                          \
-        #classname,                                 \
-        destroy,                                    \
-        markObjects,                                \
-        isEqualTo,                                  \
-    }, \
+    DEFINE_MANAGED_VTABLE_INT(classname), \
     call,                                       \
     construct,                                  \
     0,                                          \
@@ -178,19 +171,7 @@ const QV4::ObjectVTable classname::static_vtbl =    \
 #define DEFINE_MANAGED_VTABLE_WITH_NAME(classname, name) \
 const QV4::ObjectVTable classname::static_vtbl =    \
 {                                               \
-    { \
-        classname::IsExecutionContext,   \
-        classname::IsString,   \
-        classname::IsObject,   \
-        classname::IsFunctionObject,   \
-        classname::IsErrorObject,   \
-        0,                                          \
-        classname::MyType,                          \
-        #name,                                 \
-        destroy,                                    \
-        markObjects,                                \
-        isEqualTo,                                  \
-    }, \
+    DEFINE_MANAGED_VTABLE_INT(name), \
     call,                                       \
     construct,                                  \
     0,                                          \
@@ -211,19 +192,7 @@ const QV4::ObjectVTable classname::static_vtbl =    \
 #define DEFINE_MANAGED_VTABLE_WITH_DELETABLES(classname) \
 const QV4::ObjectVTable classname::static_vtbl =    \
 {                                               \
-    { \
-        classname::IsExecutionContext,   \
-        classname::IsString,   \
-        classname::IsObject,   \
-        classname::IsFunctionObject,   \
-        classname::IsErrorObject,   \
-        0,                                          \
-        classname::MyType,                          \
-        #classname,                                 \
-        destroy,                                    \
-        markObjects,                                \
-        isEqualTo,                                  \
-    }, \
+    DEFINE_MANAGED_VTABLE_INT(classname), \
     call,                                       \
     construct,                                  \
     collectDeletables,                          \
@@ -249,7 +218,8 @@ struct Q_QML_EXPORT Managed
         IsString = false,
         IsObject = false,
         IsFunctionObject = false,
-        IsErrorObject = false
+        IsErrorObject = false,
+        IsArrayData = false
     };
 private:
     void *operator new(size_t);
index f45c40e..89e32c4 100644 (file)
@@ -91,8 +91,6 @@ Object::~Object()
 {
     if (memberData != inlineProperties)
         delete [] memberData;
-    if (arrayData)
-        arrayData->destroy();
     _data = 0;
 }
 
@@ -235,7 +233,7 @@ void Object::markObjects(Managed *that, ExecutionEngine *e)
         }
     }
     if (o->arrayData)
-        o->arrayData->markObjects(e);
+        o->arrayData->mark(e);
 }
 
 void Object::ensureMemberIndex(uint idx)
@@ -1111,7 +1109,7 @@ void Object::copyArrayData(Object *other)
         Q_ASSERT(!arrayData && other->arrayData);
         if (other->arrayType() == ArrayData::Sparse) {
             SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData);
-            SparseArrayData *dd = new SparseArrayData;
+            SparseArrayData *dd = new (engine()->memoryManager) SparseArrayData(engine());
             dd->type = ArrayData::Sparse;
             dd->sparse = new SparseArray(*od->sparse);
             dd->freeList = od->freeList;
@@ -1162,7 +1160,7 @@ void Object::initSparseArray()
     if (arrayType() == ArrayData::Sparse)
         return;
 
-    SparseArrayData *data = new SparseArrayData;
+    SparseArrayData *data = new (engine()->memoryManager) SparseArrayData(engine());
     data->type = ArrayData::Sparse;
     data->sparse = new SparseArray;
     if (!arrayData) {
@@ -1178,7 +1176,7 @@ void Object::initSparseArray()
     data->alloc = simple->alloc;
     simple->data = 0;
     simple->attrs = 0;
-    delete simple;
+    // ### explicitly free old data? delete simple;
     arrayData = data;
 
     uint *lastFree = &data->freeList;
index 2f2b7cf..0572c4e 100644 (file)
@@ -204,12 +204,12 @@ public:
 
     inline void arrayReserve(uint n) {
         arrayCreate();
-        arrayData->vtable->reserve(arrayData, n);
+        arrayData->vtable()->reserve(arrayData, n);
     }
 
     void arrayCreate() {
         if (!arrayData)
-            arrayData = new SimpleArrayData;
+            arrayData = new (engine()->memoryManager) SimpleArrayData(engine());
 #ifdef CHECK_SPARSE_ARRAYS
         initSparseArray();
 #endif
@@ -370,7 +370,7 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a
     } else if (index > 0x1000 && index > 2*arrayData->alloc) {
         initSparseArray();
     } else {
-        arrayData->vtable->reserve(arrayData, index + 1);
+        arrayData->vtable()->reserve(arrayData, index + 1);
     }
     arrayData->setAttributes(index, attributes);
     Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
index 15d27b3..3d0328d 100644 (file)
@@ -103,19 +103,7 @@ static uint toArrayIndex(const char *ch, const char *end, bool *ok)
 
 const ObjectVTable String::static_vtbl =
 {
-    {
-        String::IsExecutionContext,
-        String::IsString,
-        String::IsObject,
-        String::IsFunctionObject,
-        String::IsErrorObject,
-        0,
-        String::MyType,
-        "String",
-        destroy,
-        markObjects,
-        isEqualTo
-    },
+    DEFINE_MANAGED_VTABLE_INT(String),
     0,
     0,
     0 /*collectDeletables*/,