Allocate the ArrayData object and it's data together
authorSimon Hausmann <simon.hausmann@digia.com>
Fri, 24 Jan 2014 13:29:40 +0000 (14:29 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 24 Jan 2014 13:32:37 +0000 (14:32 +0100)
Reduce the amount of allocations required for Arrays, and
allows freeing the array data more easily in the GC.

Change-Id: I3e3213f089c45c83a227038ce444aa60b2735b7f
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/qv4engine.cpp
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectproto.cpp

index 8f1c030..5dedd59 100644 (file)
@@ -91,9 +91,7 @@ void ArgumentsObject::fullyCreate()
 
     uint numAccessors = qMin((int)context->function->formalParameterCount, context->realArgumentCount);
     uint argCount = qMin(context->realArgumentCount, context->callData->argc);
-    arrayReserve(argCount);
-    initSparseArray();
-    arrayData->ensureAttributes();
+    ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true);
     context->engine->requireArgumentsAccessors(numAccessors);
     for (uint i = 0; i < (uint)numAccessors; ++i) {
         mappedArguments.append(context->callData->args[i]);
index 7626a33..9c6ff94 100644 (file)
@@ -41,6 +41,7 @@
 #include "qv4arraydata_p.h"
 #include "qv4object_p.h"
 #include "qv4functionobject_p.h"
+#include "qv4mm_p.h"
 
 using namespace QV4;
 
@@ -48,7 +49,7 @@ const ArrayVTable SimpleArrayData::static_vtbl =
 {
     DEFINE_MANAGED_VTABLE_INT(SimpleArrayData),
     SimpleArrayData::Simple,
-    SimpleArrayData::reserve,
+    SimpleArrayData::reallocate,
     SimpleArrayData::get,
     SimpleArrayData::put,
     SimpleArrayData::putArray,
@@ -65,7 +66,7 @@ const ArrayVTable SparseArrayData::static_vtbl =
 {
     DEFINE_MANAGED_VTABLE_INT(SparseArrayData),
     ArrayData::Sparse,
-    SparseArrayData::reserve,
+    SparseArrayData::reallocate,
     SparseArrayData::get,
     SparseArrayData::put,
     SparseArrayData::putArray,
@@ -79,72 +80,134 @@ const ArrayVTable SparseArrayData::static_vtbl =
 };
 
 
-void SimpleArrayData::getHeadRoom(ArrayData *d)
+void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes)
 {
-    SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
-    Q_ASSERT(dd);
-    Q_ASSERT(!dd->offset);
-    dd->offset = qMax(dd->len >> 2, (uint)16);
-    SafeValue *newArray = new SafeValue[dd->offset + dd->alloc];
-    memcpy(newArray + dd->offset, dd->data, dd->len*sizeof(SafeValue));
-    delete [] dd->data;
-    dd->data = newArray + dd->offset;
-    if (dd->attrs) {
-        PropertyAttributes *newAttrs = new PropertyAttributes[dd->offset + dd->alloc];
-        memcpy(newAttrs + dd->offset, dd->attrs, dd->len*sizeof(PropertyAttributes));
-        delete [] dd->attrs;
-        dd->attrs = newAttrs + dd->offset;
+    ArrayData *d = o->arrayData;
+
+    uint oldAlloc = 0;
+    uint toCopy = 0;
+    if (alloc < 8)
+        alloc = 8;
+
+    if (d) {
+        bool hasAttrs = d->attrs;
+        enforceAttributes |= hasAttrs;
+
+        if (!offset && alloc <= d->alloc && newType == d->type && hasAttrs == enforceAttributes)
+            return;
+
+        oldAlloc = d->alloc;
+        if (d->type < Sparse) {
+            offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset);
+            toCopy = static_cast<SimpleArrayData *>(d)->len;
+        } else {
+            Q_ASSERT(!offset);
+            toCopy = d->alloc;
+            newType = Sparse;
+        }
+    }
+    if (enforceAttributes && newType == Simple)
+        newType = Complex;
+
+    alloc = qMax(alloc, 2*oldAlloc) + offset;
+    size_t size = alloc*sizeof(SafeValue);
+    if (enforceAttributes)
+        size += alloc*sizeof(PropertyAttributes);
+
+    if (newType < Sparse) {
+        size += sizeof(SimpleArrayData);
+        SimpleArrayData *newData = static_cast<SimpleArrayData *>(o->engine()->memoryManager->allocManaged(size));
+        new (newData) SimpleArrayData(o->engine());
+        newData->alloc = alloc - offset;
+        newData->type = newType;
+        newData->data = reinterpret_cast<SafeValue *>(newData + 1) + offset;
+        newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) + offset : 0;
+        newData->offset = offset;
+        newData->len = d ? static_cast<SimpleArrayData *>(d)->len : 0;
+        o->arrayData = newData;
+    } else {
+        size += sizeof(SparseArrayData);
+        SparseArrayData *newData = static_cast<SparseArrayData *>(o->engine()->memoryManager->allocManaged(size));
+        new (newData) SparseArrayData(o->engine());
+        newData->alloc = alloc;
+        newData->type = newType;
+        newData->data = reinterpret_cast<SafeValue *>(newData + 1);
+        newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) : 0;
+        o->arrayData = newData;
     }
-}
 
-void SimpleArrayData::reserve(ArrayData *d, uint n)
-{
-    SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
-    if (n < 8)
-        n = 8;
-    if (n <= dd->alloc)
+    if (d) {
+        memcpy(o->arrayData->data, d->data, sizeof(SafeValue)*toCopy);
+        if (enforceAttributes) {
+            if (d->attrs)
+                memcpy(o->arrayData->attrs, d->attrs, sizeof(PropertyAttributes)*toCopy);
+            else
+                for (uint i = 0; i < toCopy; ++i)
+                    o->arrayData->attrs[i] = Attr_Data;
+        }
+    }
+
+    if (newType != Sparse)
         return;
 
-    dd->alloc = qMax(n, 2*dd->alloc);
-    SafeValue *newArrayData = new SafeValue[dd->alloc + dd->offset];
-    if (dd->data) {
-        memcpy(newArrayData + dd->offset, dd->data, sizeof(SafeValue)*dd->len);
-        delete [] (dd->data - dd->offset);
+    SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData);
+    if (d && d->type == Sparse) {
+        SparseArrayData *old = static_cast<SparseArrayData *>(d);
+        newData->sparse = old->sparse;
+        old->sparse = 0;
+        newData->freeList = old->freeList;
+        return;
     }
-    dd->data = newArrayData + dd->offset;
-
-    if (dd->attrs) {
-        PropertyAttributes *newAttrs = new PropertyAttributes[dd->alloc];
-        memcpy(newAttrs, dd->attrs, sizeof(PropertyAttributes)*dd->len);
-        delete [] (dd->attrs - dd->offset);
 
-        dd->attrs = newAttrs;
+    newData->sparse = new SparseArray;
+    uint *lastFree = &newData->freeList;
+    for (uint i = 0; i < toCopy; ++i) {
+        if (!newData->data[i].isEmpty()) {
+            SparseArrayNode *n = newData->sparse->insert(i);
+            n->value = i;
+        } else {
+            *lastFree = i;
+            newData->data[i].tag = Value::Empty_Type;
+            lastFree = &newData->data[i].uint_32;
+        }
+    }
+    for (uint i = toCopy; i < newData->alloc; ++i) {
+        *lastFree = i;
+        newData->data[i].tag = Value::Empty_Type;
+        lastFree = &newData->data[i].uint_32;
     }
+    *lastFree = newData->alloc;
+
+    // ### Could explicitly free the old data
 }
 
-void ArrayData::ensureAttributes()
+
+void SimpleArrayData::getHeadRoom(Object *o)
 {
-    if (attrs)
+    SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
+    Q_ASSERT(dd);
+    Q_ASSERT(!dd->offset);
+    uint offset = qMax(dd->len >> 2, (uint)16);
+    realloc(o, Simple, offset, 0, false);
+}
+
+ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
+{
+    realloc(o, Simple, 0, n, enforceAttributes);
+    return o->arrayData;
+}
+
+void ArrayData::ensureAttributes(Object *o)
+{
+    if (o->arrayData && o->arrayData->attrs)
         return;
 
-    uint off = 0;
-    if (type == Simple) {
-        type = Complex;
-        off = static_cast<SimpleArrayData *>(this)->offset;
-    }
-    attrs = new PropertyAttributes[alloc + off];
-    attrs += off;
-    for (uint i = 0; i < alloc; ++i)
-        attrs[i] = Attr_Data;
+    ArrayData::realloc(o, Simple, 0, 0, true);
 }
 
 
-void SimpleArrayData::destroy(Managed *d)
+void SimpleArrayData::destroy(Managed *)
 {
-    SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
-    delete [] (dd->data - dd->offset);
-    if (dd->attrs)
-        delete [] (dd->attrs - dd->offset);
 }
 
 void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e)
@@ -209,8 +272,11 @@ void SimpleArrayData::push_front(Object *o, SafeValue *values, uint n)
     SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
     Q_ASSERT(!dd->attrs);
     for (int i = n - 1; i >= 0; --i) {
-        if (!dd->offset)
-            getHeadRoom(dd);
+        if (!dd->offset) {
+            getHeadRoom(o);
+            dd = static_cast<SimpleArrayData *>(o->arrayData);
+        }
+
 
         --dd->offset;
         --dd->data;
@@ -265,8 +331,10 @@ uint SimpleArrayData::length(const ArrayData *d)
 bool SimpleArrayData::putArray(Object *o, uint index, SafeValue *values, uint n)
 {
     SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData);
-    if (index + n > dd->alloc)
-        reserve(dd, index + n + 1);
+    if (index + n > dd->alloc) {
+        reallocate(o, index + n + 1, false);
+        dd = static_cast<SimpleArrayData *>(o->arrayData);
+    }
     for (uint i = dd->len; i < index; ++i)
         dd->data[i] = Primitive::emptyValue();
     for (uint i = 0; i < n; ++i)
@@ -300,9 +368,6 @@ void SparseArrayData::destroy(Managed *d)
 {
     SparseArrayData *dd = static_cast<SparseArrayData *>(d);
     delete dd->sparse;
-    delete [] dd->data;
-    if (dd->attrs)
-        delete [] dd->attrs;
 }
 
 void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
@@ -313,42 +378,23 @@ void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
         dd->data[i].mark(e);
 }
 
-void SparseArrayData::reserve(ArrayData *d, uint n)
+ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
 {
-    if (n < 8)
-        n = 8;
-    if (n <= d->alloc)
-        return;
-
-    SparseArrayData *dd = static_cast<SparseArrayData *>(d);
-    uint oldAlloc = dd->alloc;
-    dd->alloc = qMax(n, 2*dd->alloc);
-    SafeValue *newArrayData = new SafeValue[dd->alloc];
-    if (dd->data) {
-        memcpy(newArrayData, dd->data, sizeof(SafeValue)*oldAlloc);
-        delete [] dd->data;
-    }
-    dd->data = newArrayData;
-    if (dd->attrs) {
-        PropertyAttributes *newAttrs = new PropertyAttributes[dd->alloc];
-        memcpy(newAttrs, dd->attrs, sizeof(PropertyAttributes)*oldAlloc);
-        delete [] dd->attrs;
-        dd->attrs = newAttrs;
-    }
-    for (uint i = oldAlloc; i < dd->alloc; ++i)
-        dd->data[i] = Primitive::fromInt32(i + 1);
+    realloc(o, Sparse, 0, n, enforceAttributes);
+    return o->arrayData;
 }
 
 // double slots are required for accessor properties
-uint SparseArrayData::allocate(ArrayData *d, bool doubleSlot)
+uint SparseArrayData::allocate(Object *o, bool doubleSlot)
 {
-    Q_ASSERT(d->type == ArrayData::Sparse);
-    SparseArrayData *dd = static_cast<SparseArrayData *>(d);
+    Q_ASSERT(o->arrayData->type == ArrayData::Sparse);
+    SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData);
     if (doubleSlot) {
         uint *last = &dd->freeList;
         while (1) {
             if (*last + 1 >= dd->alloc) {
-                reserve(d, d->alloc + 2);
+                reallocate(o, o->arrayData->alloc + 2, true);
+                dd = static_cast<SparseArrayData *>(o->arrayData);
                 last = &dd->freeList;
             }
 
@@ -356,14 +402,16 @@ uint SparseArrayData::allocate(ArrayData *d, bool doubleSlot)
                 // found two slots in a row
                 uint idx = *last;
                 *last = dd->data[*last + 1].uint_32;
-                d->attrs[idx] = Attr_Accessor;
+                o->arrayData->attrs[idx] = Attr_Accessor;
                 return idx;
             }
             last = &dd->data[*last].uint_32;
         }
     } else {
-        if (dd->alloc == dd->freeList)
-            reserve(d, d->alloc + 2);
+        if (dd->alloc == dd->freeList) {
+            reallocate(o, o->arrayData->alloc + 2, false);
+            dd = static_cast<SparseArrayData *>(o->arrayData);
+        }
         uint idx = dd->freeList;
         dd->freeList = dd->data[idx].uint_32;
         if (dd->attrs)
@@ -388,7 +436,7 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value)
     SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
     Q_ASSERT(n->value == UINT_MAX || !o->arrayData->attrs || !o->arrayData->attrs[n->value].isAccessor());
     if (n->value == UINT_MAX)
-        n->value = allocate(o->arrayData);
+        n->value = allocate(o);
     o->arrayData->data[n->value] = value;
     if (o->arrayData->attrs)
         o->arrayData->attrs[n->value] = Attr_Data;
@@ -434,14 +482,16 @@ void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes att
 {
     SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData);
     SparseArrayNode *n = d->sparse->insert(index);
-    if (n->value == UINT_MAX)
-        n->value = allocate(d, attrs.isAccessor());
+    if (n->value == UINT_MAX) {
+        n->value = allocate(o, attrs.isAccessor());
+        d = static_cast<SparseArrayData *>(o->arrayData);
+    }
     else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
         // need to convert the slot
         free(d, n->value);
-        n->value = allocate(d, attrs.isAccessor());
+        n->value = allocate(o, attrs.isAccessor());
     }
-    d->attrs[n->value] = attrs;
+    o->arrayData->attrs[n->value] = attrs;
 }
 
 PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index)
@@ -456,7 +506,7 @@ void SparseArrayData::push_front(Object *o, SafeValue *values, uint n)
 {
     Q_ASSERT(!o->arrayData->attrs);
     for (int i = n - 1; i >= 0; --i) {
-        uint idx = allocate(o->arrayData);
+        uint idx = allocate(o);
         o->arrayData->data[idx] = values[i];
         static_cast<SparseArrayData *>(o->arrayData)->sparse->push_front(idx);
     }
@@ -576,7 +626,7 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
     o->initSparseArray();
     SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index);
     if (n->value == UINT_MAX)
-        n->value = SparseArrayData::allocate(o->arrayData, isAccessor);
+        n->value = SparseArrayData::allocate(o, isAccessor);
     return reinterpret_cast<Property *>(o->arrayData->data + n->value);
 }
 
@@ -604,14 +654,13 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu
         if (!sparse->sparse->nEntries())
             return;
 
-        SimpleArrayData *d = new (context->engine->memoryManager) SimpleArrayData(context->engine);
-        thisObject->arrayData = d;
-        d->vtable()->reserve(d, sparse->sparse->nEntries());
+        thisObject->arrayData = 0;
+        ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse->nEntries(), sparse->attrs ? true : false);
+        SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData);
 
         SparseArrayNode *n = sparse->sparse->begin();
         uint i = 0;
         if (sparse->attrs) {
-            d->ensureAttributes();
             while (n != sparse->sparse->end()) {
                 if (n->value >= len)
                     break;
index ea6c95b..48b17a2 100644 (file)
@@ -64,7 +64,7 @@ struct ArrayVTable
 {
     ManagedVTable managedVTable;
     uint type;
-    void (*reserve)(ArrayData *d, uint n);
+    ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
     ReturnedValue (*get)(const ArrayData *d, uint index);
     bool (*put)(Object *o, uint index, ValueRef value);
     bool (*putArray)(Object *o, uint index, SafeValue *values, uint n);
@@ -82,10 +82,6 @@ struct Q_QML_EXPORT ArrayData : public Managed
 {
     ArrayData(InternalClass *ic)
         : Managed(ic)
-        , alloc(0)
-        , type(0)
-        , attrs(0)
-        , data(0)
     {
     }
 
@@ -97,7 +93,7 @@ struct Q_QML_EXPORT ArrayData : public Managed
     };
 
     uint alloc;
-    uint type;
+    Type type;
     PropertyAttributes *attrs;
     SafeValue *data;
 
@@ -113,7 +109,6 @@ struct Q_QML_EXPORT ArrayData : public Managed
     bool hasAttributes() const {
         return this && attrs;
     }
-    void ensureAttributes();
     PropertyAttributes attributes(int i) const {
         Q_ASSERT(this);
         return attrs ? vtable()->attribute(this, i) : Attr_Data;
@@ -132,6 +127,9 @@ struct Q_QML_EXPORT ArrayData : public Managed
     }
     inline Property *getProperty(uint index) const;
 
+    static void ensureAttributes(Object *o);
+    static void realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes);
+
     static void sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint dataLen);
     static uint append(Object *obj, const ArrayObject *otherObj, uint n);
     static Property *insert(Object *o, uint index, bool isAccessor = false);
@@ -143,15 +141,13 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData
 
     SimpleArrayData(ExecutionEngine *engine)
         : ArrayData(engine->emptyClass)
-        , len(0)
-        , offset(0)
     { setVTable(staticVTable()); }
 
     uint len;
     uint offset;
 
-    static void getHeadRoom(ArrayData *d);
-    static void reserve(ArrayData *d, uint n);
+    static void getHeadRoom(Object *o);
+    static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
 
     static void destroy(Managed *d);
     static void markObjects(Managed *d, ExecutionEngine *e);
@@ -174,20 +170,18 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
 
     SparseArrayData(ExecutionEngine *engine)
         : ArrayData(engine->emptyClass)
-        , freeList(0)
-        , sparse(0)
     { setVTable(staticVTable()); }
 
     uint freeList;
     SparseArray *sparse;
 
-    static uint allocate(ArrayData *d, bool doubleSlot = false);
+    static uint allocate(Object *o, bool doubleSlot = false);
     static void free(ArrayData *d, uint idx);
 
     static void destroy(Managed *d);
     static void markObjects(Managed *d, ExecutionEngine *e);
 
-    static void reserve(ArrayData *d, uint n);
+    static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
     static ReturnedValue get(const ArrayData *d, uint index);
     static bool put(Object *o, uint index, ValueRef value);
     static bool putArray(Object *o, uint index, SafeValue *values, uint n);
index 995c711..b967741 100644 (file)
@@ -504,6 +504,8 @@ Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
     ArrayObject *object = new (memoryManager) ArrayObject(this);
 
     if (count) {
+        Scope scope(this);
+        ScopedValue protectArray(scope, object);
         if (count < 0x1000)
             object->arrayReserve(count);
         object->setArrayLengthUnchecked(count);
index 86c7ab1..93ad51d 100644 (file)
@@ -1107,22 +1107,18 @@ void Object::copyArrayData(Object *other)
         }
     } else {
         Q_ASSERT(!arrayData && other->arrayData);
+        ArrayData::realloc(this, other->arrayData->type, 0, other->arrayData->alloc, other->arrayData->attrs);
         if (other->arrayType() == ArrayData::Sparse) {
             SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData);
-            SparseArrayData *dd = new (engine()->memoryManager) SparseArrayData(engine());
-            dd->type = ArrayData::Sparse;
+            SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData);
             dd->sparse = new SparseArray(*od->sparse);
             dd->freeList = od->freeList;
-            arrayData = dd;
-        }
-        arrayReserve(other->arrayData->alloc);
-        if (other->arrayType() != ArrayData::Sparse) {
+        } else {
             SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData);
             d->len = static_cast<SimpleArrayData *>(other->arrayData)->len;
             d->offset = 0;
         }
         memcpy(arrayData->data, other->arrayData->data, arrayData->alloc*sizeof(SafeValue));
-
     }
     setArrayLengthUnchecked(other->getLength());
 }
@@ -1164,47 +1160,7 @@ void Object::initSparseArray()
     if (arrayType() == ArrayData::Sparse)
         return;
 
-    SparseArrayData *data = new (engine()->memoryManager) SparseArrayData(engine());
-    data->type = ArrayData::Sparse;
-    data->sparse = new SparseArray;
-    if (!arrayData) {
-        arrayData = data;
-        return;
-    }
-    SimpleArrayData *simple = static_cast<SimpleArrayData *>(arrayData);
-
-    uint oldOffset = simple->offset;
-    uint length = simple->ArrayData::length();
-    data->data = simple->data - simple->offset;
-    data->attrs = simple->attrs;
-    data->alloc = simple->alloc;
-    simple->data = 0;
-    simple->attrs = 0;
-    // ### explicitly free old data? delete simple;
-    arrayData = data;
-
-    uint *lastFree = &data->freeList;
-    for (uint i = 0; i < oldOffset; ++i) {
-        *lastFree = i;
-        data->data[i].tag = Value::Empty_Type;
-        lastFree = &data->data[i].uint_32;
-    }
-    for (uint i = 0; i < length; ++i) {
-        if (!data->data[i + oldOffset].isEmpty()) {
-            SparseArrayNode *n = data->sparse->insert(i);
-            n->value = i + oldOffset;
-        } else {
-            *lastFree = i + oldOffset;
-            data->data[i + oldOffset].tag = Value::Empty_Type;
-            lastFree = &data->data[i + oldOffset].uint_32;
-        }
-    }
-    for (uint i = length + oldOffset; i < data->alloc; ++i) {
-        *lastFree = i;
-        data->data[i].tag = Value::Empty_Type;
-        lastFree = &data->data[i].uint_32;
-    }
-    *lastFree = data->alloc;
+    ArrayData::realloc(this, ArrayData::Sparse, 0, 0, false);
 }
 
 
index 9c272ce..ca54388 100644 (file)
@@ -197,7 +197,7 @@ public:
     void setArrayAttributes(uint i, PropertyAttributes a) {
         Q_ASSERT(arrayData);
         if (arrayData->attrs || a != Attr_Data) {
-            arrayData->ensureAttributes();
+            ArrayData::ensureAttributes(this);
             a.resolve();
             arrayData->vtable()->setAttribute(this, i, a);
         }
@@ -216,13 +216,12 @@ public:
     }
 
     inline void arrayReserve(uint n) {
-        arrayCreate();
-        arrayData->vtable()->reserve(arrayData, n);
+        ArrayData::realloc(this, ArrayData::Simple, 0, n, false);
     }
 
     void arrayCreate() {
         if (!arrayData)
-            arrayData = new (engine()->memoryManager) SimpleArrayData(engine());
+            ArrayData::realloc(this, ArrayData::Simple, 0, 0, false);
 #ifdef CHECK_SPARSE_ARRAYS
         initSparseArray();
 #endif
@@ -383,7 +382,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()->reallocate(this, index + 1, false);
     }
     setArrayAttributes(index, attributes);
     Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
index e8623d1..51d6b8d 100644 (file)
@@ -273,7 +273,7 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
     o->internalClass = o->internalClass->sealed();
 
     if (o->arrayData) {
-        o->arrayData->ensureAttributes();
+        ArrayData::ensureAttributes(o.getPointer());
         for (uint i = 0; i < o->arrayData->alloc; ++i) {
             if (!o->arrayData->isEmpty(i))
                 o->arrayData->attrs[i].setConfigurable(false);
@@ -298,7 +298,7 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
     o->internalClass = o->internalClass->frozen();
 
     if (o->arrayData) {
-        o->arrayData->ensureAttributes();
+        ArrayData::ensureAttributes(o.getPointer());
         for (uint i = 0; i < o->arrayData->alloc; ++i) {
             if (!o->arrayData->isEmpty(i))
                 o->arrayData->attrs[i].setConfigurable(false);