Move array data into it's own struct
authorLars Knoll <lars.knoll@digia.com>
Fri, 13 Dec 2013 12:31:32 +0000 (13:31 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 3 Jan 2014 16:09:23 +0000 (17:09 +0100)
First step of separating the array data from Object.

Change-Id: I5c857397f0ef53cff0807debdb1e405424e1046a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
16 files changed:
src/imports/dialogs-private/qquickfontlistmodel.cpp
src/qml/compiler/qv4isel_masm.cpp
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4jsonobject.cpp
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4regexpobject.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4serialize.cpp
src/qml/jsruntime/qv4stringobject.cpp
src/qml/qml/qqmllocale.cpp
src/qml/qml/v8/qv8engine.cpp

index 96d1824..e3601f2 100644 (file)
@@ -239,9 +239,9 @@ QQmlV4Handle QQuickFontListModel::pointSizes()
 
     Scoped<QV4::ArrayObject> a(scope, v4engine->newArrayObject());
     a->arrayReserve(size);
-    a->arrayDataLen = size;
+    a->arrayData.length = size;
     for (int i = 0; i < size; ++i)
-        a->arrayData[i].value = Primitive::fromInt32(pss.at(i));
+        a->arrayData.data[i].value = Primitive::fromInt32(pss.at(i));
     a->setArrayLengthUnchecked(size);
 
     return QQmlV4Handle(ScopedValue(scope, a.asReturnedValue()));
index 35097ba..e8038f1 100644 (file)
@@ -1069,12 +1069,12 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
         // get data, ScratchRegister holds index
         addr = _as->loadTempAddress(Assembler::ReturnValueRegister, tbase);
         _as->load64(addr, Assembler::ReturnValueRegister);
-        Address arrayDataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayDataLen));
+        Address dataLen(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData) + qOffsetOf(Object::ArrayData, length));
         Assembler::Jump outOfRange;
         if (needNegativeCheck)
             outOfRange = _as->branch32(Assembler::LessThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
-        Assembler::Jump outOfRange2 = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, arrayDataLen);
-        Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData));
+        Assembler::Jump outOfRange2 = _as->branch32(Assembler::GreaterThanOrEqual, Assembler::ScratchRegister, dataLen);
+        Address arrayData(Assembler::ReturnValueRegister, qOffsetOf(Object, arrayData) + qOffsetOf(Object::ArrayData, data));
         _as->load64(arrayData, Assembler::ReturnValueRegister);
         Q_ASSERT(sizeof(Property) == (1<<4));
         _as->lshift64(Assembler::TrustedImm32(4), Assembler::ScratchRegister);
index 3b58f68..9879f2a 100644 (file)
@@ -66,8 +66,8 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
 
         arrayReserve(context->callData->argc);
         for (int i = 0; i < context->callData->argc; ++i)
-            arrayData[i].value = context->callData->args[i];
-        arrayDataLen = context->callData->argc;
+            arrayData.data[i].value = context->callData->args[i];
+        arrayData.length = context->callData->argc;
         fullyCreated = true;
     } else {
         Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
@@ -97,14 +97,14 @@ void ArgumentsObject::fullyCreate()
     context->engine->requireArgumentsAccessors(numAccessors);
     for (uint i = 0; i < (uint)numAccessors; ++i) {
         mappedArguments.append(context->callData->args[i]);
-        arrayData[i] = context->engine->argumentsAccessors.at(i);
-        arrayAttributes[i] = Attr_Accessor;
+        arrayData.data[i] = context->engine->argumentsAccessors.at(i);
+        arrayData.attributes[i] = Attr_Accessor;
     }
     for (uint i = numAccessors; i < argCount; ++i) {
-        arrayData[i] = Property::fromValue(context->callData->args[i]);
-        arrayAttributes[i] = Attr_Data;
+        arrayData.data[i] = Property::fromValue(context->callData->args[i]);
+        arrayData.attributes[i] = Attr_Data;
     }
-    arrayDataLen = argCount;
+    arrayData.length = argCount;
 
     fullyCreated = true;
 }
@@ -115,17 +115,17 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
 
     Scope scope(ctx);
     uint pidx = propertyIndexFromArrayIndex(index);
-    Property *pd = arrayData + pidx;
+    Property *pd = arrayData.data + pidx;
     Property map;
     PropertyAttributes mapAttrs;
     bool isMapped = false;
     if (pd && index < (uint)mappedArguments.size())
-        isMapped = arrayAttributes && arrayAttributes[pidx].isAccessor() && pd->getter() == context->engine->argumentsAccessors.at(index).getter();
+        isMapped = arrayData.attributes && arrayData.attributes[pidx].isAccessor() && pd->getter() == context->engine->argumentsAccessors.at(index).getter();
 
     if (isMapped) {
         map = *pd;
-        mapAttrs = arrayAttributes[pidx];
-        arrayAttributes[pidx] = Attr_Data;
+        mapAttrs = arrayData.attributes[pidx];
+        arrayData.attributes[pidx] = Attr_Data;
         pd->value = mappedArguments.at(index);
     }
 
@@ -142,7 +142,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
 
         if (attrs.isWritable()) {
             *pd = map;
-            arrayAttributes[pidx] = mapAttrs;
+            arrayData.attributes[pidx] = mapAttrs;
         }
     }
 
index 1628cfe..9c7cb43 100644 (file)
@@ -73,8 +73,8 @@ ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
         len = callData->argc;
         a->arrayReserve(len);
         for (unsigned int i = 0; i < len; ++i)
-            a->arrayData[i].value = callData->args[i];
-        a->arrayDataLen = len;
+            a->arrayData.data[i].value = callData->args[i];
+        a->arrayData.length = len;
     }
     a->setArrayLengthUnchecked(len);
 
@@ -308,18 +308,18 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
         return Encode(newLen);
     }
 
-    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
+    if (!instance->protoHasArray() && instance->arrayData.length <= len) {
         for (int i = 0; i < ctx->callData->argc; ++i) {
-            if (!instance->sparseArray) {
-                if (len >= instance->arrayAlloc)
+            if (!instance->arrayData.sparse) {
+                if (len >= instance->arrayData.alloc)
                     instance->arrayReserve(len + 1);
-                instance->arrayData[len].value = ctx->callData->args[i];
-                if (instance->arrayAttributes)
-                    instance->arrayAttributes[len] = Attr_Data;
-                instance->arrayDataLen = len + 1;
+                instance->arrayData.data[len].value = ctx->callData->args[i];
+                if (instance->arrayData.attributes)
+                    instance->arrayData.attributes[len] = Attr_Data;
+                instance->arrayData.length = len + 1;
             } else {
                 uint j = instance->allocArrayValue(ctx->callData->args[i]);
-                instance->sparseArray->push_back(j, len);
+                instance->arrayData.sparse->push_back(j, len);
             }
             ++len;
         }
@@ -384,23 +384,23 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
 
     Property *front = 0;
     uint pidx = instance->propertyIndexFromArrayIndex(0);
-    if (pidx < UINT_MAX && !instance->arrayData[pidx].value.isEmpty())
-            front = instance->arrayData + pidx;
-
-    ScopedValue result(scope, front ? instance->getValue(front, instance->arrayAttributes ? instance->arrayAttributes[pidx] : Attr_Data) : Encode::undefined());
-
-    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
-        if (!instance->sparseArray) {
-            if (instance->arrayDataLen) {
-                ++instance->arrayOffset;
-                ++instance->arrayData;
-                --instance->arrayDataLen;
-                --instance->arrayAlloc;
-                if (instance->arrayAttributes)
-                    ++instance->arrayAttributes;
+    if (pidx < UINT_MAX && !instance->arrayData.data[pidx].value.isEmpty())
+            front = instance->arrayData.data + pidx;
+
+    ScopedValue result(scope, front ? instance->getValue(front, instance->arrayData.attributes ? instance->arrayData.attributes[pidx] : Attr_Data) : Encode::undefined());
+
+    if (!instance->protoHasArray() && instance->arrayData.length <= len) {
+        if (!instance->arrayData.sparse) {
+            if (instance->arrayData.length) {
+                ++instance->arrayData.offset;
+                ++instance->arrayData.data;
+                --instance->arrayData.length;
+                --instance->arrayData.alloc;
+                if (instance->arrayData.attributes)
+                    ++instance->arrayData.attributes;
             }
         } else {
-            uint idx = instance->sparseArray->pop_front();
+            uint idx = instance->arrayData.sparse->pop_front();
             instance->freeArrayValue(idx);
         }
     } else {
@@ -505,10 +505,10 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
 
     newArray->arrayReserve(deleteCount);
     for (uint i = 0; i < deleteCount; ++i) {
-        newArray->arrayData[i].value = instance->getIndexed(start + i);
+        newArray->arrayData.data[i].value = instance->getIndexed(start + i);
         if (scope.hasException())
             return Encode::undefined();
-        newArray->arrayDataLen = i + 1;
+        newArray->arrayData.length = i + 1;
     }
     newArray->setArrayLengthUnchecked(deleteCount);
 
@@ -571,26 +571,26 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
     uint len = getLength(ctx, instance);
 
     ScopedValue v(scope);
-    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
+    if (!instance->protoHasArray() && instance->arrayData.length <= len) {
         for (int i = ctx->callData->argc - 1; i >= 0; --i) {
             v = ctx->argument(i);
 
-            if (!instance->sparseArray) {
-                if (!instance->arrayOffset)
+            if (!instance->arrayData.sparse) {
+                if (!instance->arrayData.offset)
                     instance->getArrayHeadRoom();
 
-                --instance->arrayOffset;
-                --instance->arrayData;
-                ++instance->arrayDataLen;
-                ++instance->arrayAlloc;
-                if (instance->arrayAttributes) {
-                    --instance->arrayAttributes;
-                    *instance->arrayAttributes = Attr_Data;
+                --instance->arrayData.offset;
+                --instance->arrayData.data;
+                ++instance->arrayData.length;
+                ++instance->arrayData.alloc;
+                if (instance->arrayData.attributes) {
+                    --instance->arrayData.attributes;
+                    *instance->arrayData.attributes = Attr_Data;
                 }
-                instance->arrayData->value = v.asReturnedValue();
+                instance->arrayData.data->value = v.asReturnedValue();
             } else {
                 uint idx = instance->allocArrayValue(v);
-                instance->sparseArray->push_front(idx);
+                instance->arrayData.sparse->push_front(idx);
             }
         }
     } else {
index dc6f310..4538884 100644 (file)
@@ -353,9 +353,9 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
             for (quint32 i = 0; i < len; ++i)
                 callData->args[i] = arr->getIndexed(i);
         } else {
-            int alen = qMin(len, arr->arrayDataLen);
+            int alen = qMin(len, arr->arrayData.length);
             for (int i = 0; i < alen; ++i)
-                callData->args[i] = arr->arrayData[i].value;
+                callData->args[i] = arr->arrayData.data[i].value;
             for (quint32 i = alen; i < len; ++i)
                 callData->args[i] = Primitive::undefinedValue();
         }
index ecdb50b..787e530 100644 (file)
@@ -1058,8 +1058,8 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
     Scoped<ArrayObject> a(scope, engine->newArrayObject());
     a->arrayReserve(size);
     for (int i = 0; i < size; i++) {
-        a->arrayData[i].value = fromJsonValue(engine, array.at(i));
-        a->arrayDataLen = i + 1;
+        a->arrayData.data[i].value = fromJsonValue(engine, array.at(i));
+        a->arrayData.length = i + 1;
     }
     a->setArrayLengthUnchecked(size);
     return a.asReturnedValue();
index 7b0ddc6..fc54933 100644 (file)
@@ -93,10 +93,10 @@ Object::~Object()
 {
     if (memberData != inlineProperties)
         delete [] memberData;
-    delete [] (arrayData - (sparseArray ? 0 : arrayOffset));
-    if (arrayAttributes)
-        delete [] (arrayAttributes - (sparseArray ? 0 : arrayOffset));
-    delete sparseArray;
+    delete [] (arrayData.data - (arrayData.sparse ? 0 : arrayData.offset));
+    if (arrayData.attributes)
+        delete [] (arrayData.attributes - (arrayData.sparse ? 0 : arrayData.offset));
+    delete arrayData.sparse;
     _data = 0;
 }
 
@@ -253,13 +253,13 @@ void Object::markObjects(Managed *that, ExecutionEngine *e)
         }
     }
     if (o->flags & SimpleArray) {
-        for (uint i = 0; i < o->arrayDataLen; ++i)
-            o->arrayData[i].value.mark(e);
+        for (uint i = 0; i < o->arrayData.length; ++i)
+            o->arrayData.data[i].value.mark(e);
         return;
     } else {
-        for (uint i = 0; i < o->arrayDataLen; ++i) {
-            const Property &pd = o->arrayData[i];
-            if (o->arrayAttributes && o->arrayAttributes[i].isAccessor()) {
+        for (uint i = 0; i < o->arrayData.length; ++i) {
+            const Property &pd = o->arrayData.data[i];
+            if (o->arrayData.attributes && o->arrayData.attributes[i].isAccessor()) {
                 if (pd.getter())
                     pd.getter()->mark(e);
                 if (pd.setter())
@@ -320,10 +320,10 @@ Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs)
 {
     uint pidx = propertyIndexFromArrayIndex(index);
     if (pidx < UINT_MAX) {
-        Property *p = arrayData + pidx;
-        if (!p->value.isEmpty() && !(arrayAttributes && arrayAttributes[pidx].isGeneric())) {
+        Property *p = arrayData.data + pidx;
+        if (!p->value.isEmpty() && !(arrayData.attributes && arrayData.attributes[pidx].isGeneric())) {
             if (attrs)
-                *attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+                *attrs = arrayData.attributes ? arrayData.attributes[pidx] : PropertyAttributes(Attr_Data);
             return p;
         }
     }
@@ -368,10 +368,10 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr
     while (o) {
         uint pidx = o->propertyIndexFromArrayIndex(index);
         if (pidx < UINT_MAX) {
-            Property *p = o->arrayData + pidx;
+            Property *p = o->arrayData.data + pidx;
             if (!p->value.isEmpty()) {
                 if (attrs)
-                    *attrs = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+                    *attrs = o->arrayData.attributes ? o->arrayData.attributes[pidx] : PropertyAttributes(Attr_Data);
                 return p;
             }
         }
@@ -459,9 +459,9 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
     const Object *o = static_cast<const Object *>(m);
     uint pidx = o->propertyIndexFromArrayIndex(index);
     if (pidx < UINT_MAX) {
-        if (o->arrayAttributes)
-            return o->arrayAttributes[pidx];
-        if (!o->arrayData[pidx].value.isEmpty())
+        if (o->arrayData.attributes)
+            return o->arrayData.attributes[pidx];
+        if (!o->arrayData.data[pidx].value.isEmpty())
             return Attr_Data;
     }
     if (o->isStringObject()) {
@@ -572,9 +572,9 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name
         while (it->arrayNode != o->sparseArrayEnd()) {
             int k = it->arrayNode->key();
             uint pidx = it->arrayNode->value;
-            Property *p = o->arrayData + pidx;
+            Property *p = o->arrayData.data + pidx;
             it->arrayNode = it->arrayNode->nextNode();
-            PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+            PropertyAttributes a = o->arrayData.attributes ? o->arrayData.attributes[pidx] : PropertyAttributes(Attr_Data);
             if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
                 it->arrayIndex = k + 1;
                 *index = k;
@@ -587,10 +587,10 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name
         it->arrayIndex = UINT_MAX;
     }
     // dense arrays
-    while (it->arrayIndex < o->arrayDataLen) {
+    while (it->arrayIndex < o->arrayData.length) {
         uint pidx = o->propertyIndexFromArrayIndex(it->arrayIndex);
-        Property *p = o->arrayData + pidx;
-        PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+        Property *p = o->arrayData.data + pidx;
+        PropertyAttributes a = o->arrayData.attributes ? o->arrayData.attributes[pidx] : PropertyAttributes(Attr_Data);
         ++it->arrayIndex;
         if (!p->value.isEmpty()
             && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) {
@@ -653,10 +653,10 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
     while (o) {
         uint pidx = o->propertyIndexFromArrayIndex(index);
         if (pidx < UINT_MAX) {
-            if (!o->arrayData[pidx].value.isEmpty()) {
-                pd = o->arrayData + pidx;
-                if (o->arrayAttributes)
-                    attrs = o->arrayAttributes[pidx];
+            if (!o->arrayData.data[pidx].value.isEmpty()) {
+                pd = o->arrayData.data + pidx;
+                if (o->arrayData.attributes)
+                    attrs = o->arrayData.attributes[pidx];
                 break;
             }
         }
@@ -779,9 +779,9 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
     PropertyAttributes attrs;
 
     uint pidx = propertyIndexFromArrayIndex(index);
-    if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty()) {
-        pd = arrayData + pidx;
-        attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data);
+    if (pidx < UINT_MAX && !arrayData.data[pidx].value.isEmpty()) {
+        pd = arrayData.data + pidx;
+        attrs = arrayData.attributes ? arrayData.attributes[pidx] : PropertyAttributes(Attr_Data);
     }
 
     if (!pd && isStringObject()) {
@@ -876,16 +876,16 @@ bool Object::internalDeleteIndexedProperty(uint index)
     uint pidx = propertyIndexFromArrayIndex(index);
     if (pidx == UINT_MAX)
         return true;
-    if (arrayData[pidx].value.isEmpty())
+    if (arrayData.data[pidx].value.isEmpty())
         return true;
 
-    if (!arrayAttributes || arrayAttributes[pidx].isConfigurable()) {
-        arrayData[pidx].value = Primitive::emptyValue();
-        if (arrayAttributes)
-            arrayAttributes[pidx].clear();
-        if (sparseArray) {
-            arrayData[pidx].value.int_32 = arrayFreeList;
-            arrayFreeList = pidx;
+    if (!arrayData.attributes || arrayData.attributes[pidx].isConfigurable()) {
+        arrayData.data[pidx].value = Primitive::emptyValue();
+        if (arrayData.attributes)
+            arrayData.attributes[pidx].clear();
+        if (arrayData.sparse) {
+            arrayData.data[pidx].value.int_32 = arrayData.freeList;
+            arrayData.freeList = pidx;
         }
         return true;
     }
@@ -975,8 +975,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop
     // Clause 1
     {
         uint pidx = propertyIndexFromArrayIndex(index);
-        if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty())
-            current = arrayData + pidx;
+        if (pidx < UINT_MAX && !arrayData.data[pidx].value.isEmpty())
+            current = arrayData.data + pidx;
         if (!current && isStringObject())
             current = static_cast<StringObject *>(this)->getIndex(index);
     }
@@ -1008,8 +1008,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con
     PropertyAttributes cattrs = Attr_Data;
     if (!member.isNull())
         cattrs = internalClass->propertyData[current - memberData];
-    else if (arrayAttributes)
-        cattrs = arrayAttributes[current - arrayData];
+    else if (arrayData.attributes)
+        cattrs = arrayData.attributes[current - arrayData.data];
 
     // clause 6
     if (p.isSubset(attrs, *current, cattrs))
@@ -1067,8 +1067,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con
     } else {
         if (cattrs != Attr_Data)
             ensureArrayAttributes();
-        if (arrayAttributes)
-            arrayAttributes[current - arrayData] = cattrs;
+        if (arrayData.attributes)
+            arrayData.attributes[current - arrayData.data] = cattrs;
     }
     if (attrs.isAccessor())
         hasAccessorProperty = 1;
@@ -1102,17 +1102,17 @@ void Object::copyArrayData(Object *other)
             arraySet(i, (v = other->getIndexed(i)));
         }
     } else {
-        arrayReserve(other->arrayDataLen);
-        arrayDataLen = other->arrayDataLen;
-        memcpy(arrayData, other->arrayData, arrayDataLen*sizeof(Property));
+        arrayReserve(other->arrayData.length);
+        arrayData.length = other->arrayData.length;
+        memcpy(arrayData.data, other->arrayData.data, arrayData.length*sizeof(Property));
     }
 
-    arrayOffset = 0;
+    arrayData.offset = 0;
 
-    if (other->sparseArray) {
+    if (other->arrayData.sparse) {
         flags &= ~SimpleArray;
-        sparseArray = new SparseArray(*other->sparseArray);
-        arrayFreeList = other->arrayFreeList;
+        arrayData.sparse = new SparseArray(*other->arrayData.sparse);
+        arrayData.freeList = other->arrayData.freeList;
     }
 
     setArrayLengthUnchecked(other->arrayLength());
@@ -1136,27 +1136,27 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
             if (exists && __qmljs_strict_equal(value, v))
                 return Encode(i);
         }
-    } else if (sparseArray) {
-        for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
-            value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
+    } else if (arrayData.sparse) {
+        for (SparseArrayNode *n = arrayData.sparse->lowerBound(fromIndex); n != arrayData.sparse->end() && n->key() < endIndex; n = n->nextNode()) {
+            value = o->getValue(arrayData.data + n->value, arrayData.attributes ? arrayData.attributes[n->value] : Attr_Data);
             if (scope.hasException())
                 return Encode::undefined();
             if (__qmljs_strict_equal(value, v))
                 return Encode(n->key());
         }
     } else {
-        if (endIndex > arrayDataLen)
-            endIndex = arrayDataLen;
-        Property *pd = arrayData;
+        if (endIndex > arrayData.length)
+            endIndex = arrayData.length;
+        Property *pd = arrayData.data;
         Property *end = pd + endIndex;
         pd += fromIndex;
         while (pd < end) {
             if (!pd->value.isEmpty()) {
-                value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
+                value = o->getValue(pd, arrayData.attributes ? arrayData.attributes[pd - arrayData.data] : Attr_Data);
                 if (scope.hasException())
                     return Encode::undefined();
                 if (__qmljs_strict_equal(value, v))
-                    return Encode((uint)(pd - arrayData));
+                    return Encode((uint)(pd - arrayData.data));
             }
             ++pd;
         }
@@ -1166,47 +1166,47 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
 
 void Object::arrayConcat(const ArrayObject *other)
 {
-    int newLen = arrayDataLen + other->arrayLength();
-    if (other->sparseArray)
+    int newLen = arrayData.length + other->arrayLength();
+    if (other->arrayData.sparse)
         initSparse();
     // ### copy attributes as well!
-    if (sparseArray) {
-        if (other->sparseArray) {
-            for (const SparseArrayNode *it = other->sparseArray->begin(); it != other->sparseArray->end(); it = it->nextNode())
-                arraySet(arrayDataLen + it->key(), other->arrayData + it->value);
+    if (arrayData.sparse) {
+        if (other->arrayData.sparse) {
+            for (const SparseArrayNode *it = other->arrayData.sparse->begin(); it != other->arrayData.sparse->end(); it = it->nextNode())
+                arraySet(arrayData.length + it->key(), other->arrayData.data + it->value);
         } else {
-            int oldSize = arrayDataLen;
+            int oldSize = arrayData.length;
             arrayReserve(oldSize + other->arrayLength());
-            memcpy(arrayData + oldSize, other->arrayData, other->arrayLength()*sizeof(Property));
-            if (arrayAttributes)
-                std::fill(arrayAttributes + oldSize, arrayAttributes + oldSize + other->arrayLength(), PropertyAttributes(Attr_Data));
+            memcpy(arrayData.data + oldSize, other->arrayData.data, other->arrayLength()*sizeof(Property));
+            if (arrayData.attributes)
+                std::fill(arrayData.attributes + oldSize, arrayData.attributes + oldSize + other->arrayLength(), PropertyAttributes(Attr_Data));
             for (uint i = 0; i < other->arrayLength(); ++i) {
-                SparseArrayNode *n = sparseArray->insert(arrayDataLen + i);
+                SparseArrayNode *n = arrayData.sparse->insert(arrayData.length + i);
                 n->value = oldSize + i;
             }
         }
     } else {
         uint oldSize = arrayLength();
-        arrayReserve(oldSize + other->arrayDataLen);
-        if (oldSize > arrayDataLen) {
-            for (uint i = arrayDataLen; i < oldSize; ++i)
-                arrayData[i].value = Primitive::emptyValue();
+        arrayReserve(oldSize + other->arrayData.length);
+        if (oldSize > arrayData.length) {
+            for (uint i = arrayData.length; i < oldSize; ++i)
+                arrayData.data[i].value = Primitive::emptyValue();
         }
-        if (other->arrayAttributes) {
-            for (uint i = 0; i < other->arrayDataLen; ++i) {
+        if (other->arrayData.attributes) {
+            for (uint i = 0; i < other->arrayData.length; ++i) {
                 bool exists;
-                arrayData[oldSize + i].value = const_cast<ArrayObject *>(other)->getIndexed(i, &exists);
-                arrayDataLen = oldSize + i + 1;
-                if (arrayAttributes)
-                    arrayAttributes[oldSize + i] = Attr_Data;
+                arrayData.data[oldSize + i].value = const_cast<ArrayObject *>(other)->getIndexed(i, &exists);
+                arrayData.length = oldSize + i + 1;
+                if (arrayData.attributes)
+                    arrayData.attributes[oldSize + i] = Attr_Data;
                 if (!exists)
-                    arrayData[oldSize + i].value = Primitive::emptyValue();
+                    arrayData.data[oldSize + i].value = Primitive::emptyValue();
             }
         } else {
-            arrayDataLen = oldSize + other->arrayDataLen;
-            memcpy(arrayData + oldSize, other->arrayData, other->arrayDataLen*sizeof(Property));
-            if (arrayAttributes)
-                std::fill(arrayAttributes + oldSize, arrayAttributes + oldSize + other->arrayDataLen, PropertyAttributes(Attr_Data));
+            arrayData.length = oldSize + other->arrayData.length;
+            memcpy(arrayData.data + oldSize, other->arrayData.data, other->arrayData.length*sizeof(Property));
+            if (arrayData.attributes)
+                std::fill(arrayData.attributes + oldSize, arrayData.attributes + oldSize + other->arrayData.length, PropertyAttributes(Attr_Data));
         }
     }
     setArrayLengthUnchecked(newLen);
@@ -1214,36 +1214,36 @@ void Object::arrayConcat(const ArrayObject *other)
 
 void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len)
 {
-    if (!arrayDataLen)
+    if (!arrayData.length)
         return;
 
-    if (sparseArray) {
+    if (arrayData.sparse) {
         context->throwUnimplemented(QStringLiteral("Object::sort unimplemented for sparse arrays"));
         return;
     }
 
-    if (len > arrayDataLen)
-        len = arrayDataLen;
+    if (len > arrayData.length)
+        len = arrayData.length;
 
     // The spec says the sorting goes through a series of get,put and delete operations.
     // this implies that the attributes don't get sorted around.
     // behavior of accessor properties is implementation defined. We simply turn them all
     // into data properties and then sort. This is in line with the sentence above.
-    if (arrayAttributes) {
+    if (arrayData.attributes) {
         for (uint i = 0; i < len; i++) {
-            if ((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty()) {
+            if ((arrayData.attributes && arrayData.attributes[i].isGeneric()) || arrayData.data[i].value.isEmpty()) {
                 while (--len > i)
-                    if (!((arrayAttributes && arrayAttributes[len].isGeneric())|| arrayData[len].value.isEmpty()))
+                    if (!((arrayData.attributes && arrayData.attributes[len].isGeneric())|| arrayData.data[len].value.isEmpty()))
                         break;
-                arrayData[i].value = getValue(arrayData + len, arrayAttributes[len]);
-                arrayData[len].value = Primitive::emptyValue();
-                if (arrayAttributes) {
-                    arrayAttributes[i] = Attr_Data;
-                    arrayAttributes[len].clear();
+                arrayData.data[i].value = getValue(arrayData.data + len, arrayData.attributes[len]);
+                arrayData.data[len].value = Primitive::emptyValue();
+                if (arrayData.attributes) {
+                    arrayData.attributes[i] = Attr_Data;
+                    arrayData.attributes[len].clear();
                 }
-            } else if (arrayAttributes[i].isAccessor()) {
-                arrayData[i].value = getValue(arrayData + i, arrayAttributes[i]);
-                arrayAttributes[i] = Attr_Data;
+            } else if (arrayData.attributes[i].isAccessor()) {
+                arrayData.data[i].value = getValue(arrayData.data + i, arrayData.attributes[i]);
+                arrayData.attributes[i] = Attr_Data;
             }
         }
     }
@@ -1257,38 +1257,38 @@ void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const Va
 
     if (!len)
         return;
-    Property *begin = arrayData;
+    Property *begin = arrayData.data;
     std::sort(begin, begin + len, lessThan);
 }
 
 
 void Object::initSparse()
 {
-    if (!sparseArray) {
+    if (!arrayData.sparse) {
         flags &= ~SimpleArray;
-        sparseArray = new SparseArray;
-        for (uint i = 0; i < arrayDataLen; ++i) {
-            if (!((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty())) {
-                SparseArrayNode *n = sparseArray->insert(i);
-                n->value = i + arrayOffset;
+        arrayData.sparse = new SparseArray;
+        for (uint i = 0; i < arrayData.length; ++i) {
+            if (!((arrayData.attributes && arrayData.attributes[i].isGeneric()) || arrayData.data[i].value.isEmpty())) {
+                SparseArrayNode *n = arrayData.sparse->insert(i);
+                n->value = i + arrayData.offset;
             }
         }
 
-        uint off = arrayOffset;
-        if (!arrayOffset) {
-            arrayFreeList = arrayDataLen;
+        uint off = arrayData.offset;
+        if (!arrayData.offset) {
+            arrayData.freeList = arrayData.length;
         } else {
-            arrayFreeList = 0;
-            arrayData -= off;
-            arrayAlloc += off;
+            arrayData.freeList = 0;
+            arrayData.data -= off;
+            arrayData.alloc += off;
             int o = off;
             for (int i = 0; i < o - 1; ++i) {
-                arrayData[i].value = Primitive::fromInt32(i + 1);
+                arrayData.data[i].value = Primitive::fromInt32(i + 1);
             }
-            arrayData[o - 1].value = Primitive::fromInt32(arrayDataLen + off);
+            arrayData.data[o - 1].value = Primitive::fromInt32(arrayData.length + off);
         }
-        for (uint i = arrayDataLen + off; i < arrayAlloc; ++i) {
-            arrayData[i].value = Primitive::fromInt32(i + 1);
+        for (uint i = arrayData.length + off; i < arrayData.alloc; ++i) {
+            arrayData.data[i].value = Primitive::fromInt32(i + 1);
         }
     }
 }
@@ -1297,39 +1297,39 @@ void Object::arrayReserve(uint n)
 {
     if (n < 8)
         n = 8;
-    if (n >= arrayAlloc) {
+    if (n >= arrayData.alloc) {
         uint off;
-        if (sparseArray) {
-            assert(arrayFreeList == arrayAlloc);
+        if (arrayData.sparse) {
+            assert(arrayData.freeList == arrayData.alloc);
             // ### FIXME
-            arrayDataLen = arrayAlloc;
+            arrayData.length = arrayData.alloc;
             off = 0;
         } else {
-            off = arrayOffset;
+            off = arrayData.offset;
         }
-        arrayAlloc = qMax(n, 2*arrayAlloc);
-        Property *newArrayData = new Property[arrayAlloc + off];
-        if (arrayData) {
-            memcpy(newArrayData + off, arrayData, sizeof(Property)*arrayDataLen);
-            delete [] (arrayData - off);
+        arrayData.alloc = qMax(n, 2*arrayData.alloc);
+        Property *newArrayData = new Property[arrayData.alloc + off];
+        if (arrayData.data) {
+            memcpy(newArrayData + off, arrayData.data, sizeof(Property)*arrayData.length);
+            delete [] (arrayData.data - off);
         }
-        arrayData = newArrayData + off;
-        if (sparseArray) {
-            for (uint i = arrayFreeList; i < arrayAlloc; ++i) {
-                arrayData[i].value = Primitive::emptyValue();
-                arrayData[i].value = Primitive::fromInt32(i + 1);
+        arrayData.data = newArrayData + off;
+        if (arrayData.sparse) {
+            for (uint i = arrayData.freeList; i < arrayData.alloc; ++i) {
+                arrayData.data[i].value = Primitive::emptyValue();
+                arrayData.data[i].value = Primitive::fromInt32(i + 1);
             }
         }
 
-        if (arrayAttributes) {
-            PropertyAttributes *newAttrs = new PropertyAttributes[arrayAlloc];
-            memcpy(newAttrs, arrayAttributes, sizeof(PropertyAttributes)*arrayDataLen);
-            delete [] (arrayAttributes - off);
+        if (arrayData.attributes) {
+            PropertyAttributes *newAttrs = new PropertyAttributes[arrayData.alloc];
+            memcpy(newAttrs, arrayData.attributes, sizeof(PropertyAttributes)*arrayData.length);
+            delete [] (arrayData.attributes - off);
 
-            arrayAttributes = newAttrs;
-            if (sparseArray) {
-                for (uint i = arrayFreeList; i < arrayAlloc; ++i)
-                    arrayAttributes[i] = Attr_Invalid;
+            arrayData.attributes = newAttrs;
+            if (arrayData.sparse) {
+                for (uint i = arrayData.freeList; i < arrayData.alloc; ++i)
+                    arrayData.attributes[i] = Attr_Invalid;
             }
         }
     }
@@ -1337,17 +1337,17 @@ void Object::arrayReserve(uint n)
 
 void Object::ensureArrayAttributes()
 {
-    if (arrayAttributes)
+    if (arrayData.attributes)
         return;
 
     flags &= ~SimpleArray;
-    uint off = sparseArray ? 0 : arrayOffset;
-    arrayAttributes = new PropertyAttributes[arrayAlloc + off];
-    arrayAttributes += off;
-    for (uint i = 0; i < arrayDataLen; ++i)
-        arrayAttributes[i] = Attr_Data;
-    for (uint i = arrayDataLen; i < arrayAlloc; ++i)
-        arrayAttributes[i] = Attr_Invalid;
+    uint off = arrayData.sparse ? 0 : arrayData.offset;
+    arrayData.attributes = new PropertyAttributes[arrayData.alloc + off];
+    arrayData.attributes += off;
+    for (uint i = 0; i < arrayData.length; ++i)
+        arrayData.attributes[i] = Attr_Data;
+    for (uint i = arrayData.length; i < arrayData.alloc; ++i)
+        arrayData.attributes[i] = Attr_Invalid;
 }
 
 
@@ -1359,48 +1359,48 @@ bool Object::setArrayLength(uint newLen) {
     uint oldLen = arrayLength();
     bool ok = true;
     if (newLen < oldLen) {
-        if (sparseArray) {
-            SparseArrayNode *begin = sparseArray->lowerBound(newLen);
-            if (begin != sparseArray->end()) {
-                SparseArrayNode *it = sparseArray->end()->previousNode();
+        if (arrayData.sparse) {
+            SparseArrayNode *begin = arrayData.sparse->lowerBound(newLen);
+            if (begin != arrayData.sparse->end()) {
+                SparseArrayNode *it = arrayData.sparse->end()->previousNode();
                 while (1) {
-                    Property &pd = arrayData[it->value];
-                    if (arrayAttributes) {
-                        if (!arrayAttributes[it->value].isConfigurable()) {
+                    Property &pd = arrayData.data[it->value];
+                    if (arrayData.attributes) {
+                        if (!arrayData.attributes[it->value].isConfigurable()) {
                             ok = false;
                             newLen = it->key() + 1;
                             break;
                         } else {
-                            arrayAttributes[it->value].clear();
+                            arrayData.attributes[it->value].clear();
                         }
                     }
                     pd.value.tag = Value::Empty_Type;
-                    pd.value.int_32 = arrayFreeList;
-                    arrayFreeList = it->value;
+                    pd.value.int_32 = arrayData.freeList;
+                    arrayData.freeList = it->value;
                     bool brk = (it == begin);
                     SparseArrayNode *prev = it->previousNode();
-                    sparseArray->erase(it);
+                    arrayData.sparse->erase(it);
                     if (brk)
                         break;
                     it = prev;
                 }
             }
         } else {
-            Property *it = arrayData + arrayDataLen;
-            const Property *begin = arrayData + newLen;
+            Property *it = arrayData.data + arrayData.length;
+            const Property *begin = arrayData.data + newLen;
             while (--it >= begin) {
-                if (arrayAttributes) {
-                    if (!arrayAttributes[it - arrayData].isEmpty() && !arrayAttributes[it - arrayData].isConfigurable()) {
+                if (arrayData.attributes) {
+                    if (!arrayData.attributes[it - arrayData.data].isEmpty() && !arrayData.attributes[it - arrayData.data].isConfigurable()) {
                         ok = false;
-                        newLen = it - arrayData + 1;
+                        newLen = it - arrayData.data + 1;
                         break;
                     } else {
-                        arrayAttributes[it - arrayData].clear();
+                        arrayData.attributes[it - arrayData.data].clear();
                     }
                     it->value = Primitive::emptyValue();
                 }
             }
-            arrayDataLen = newLen;
+            arrayData.length = newLen;
         }
     } else {
         if (newLen >= 0x100000)
@@ -1426,8 +1426,8 @@ ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
     int len = list.count();
     arrayReserve(len);
     for (int ii = 0; ii < len; ++ii) {
-        arrayData[ii].value = Encode(engine->newString(list.at(ii)));
-        arrayDataLen = ii + 1;
+        arrayData.data[ii].value = Encode(engine->newString(list.at(ii)));
+        arrayData.length = ii + 1;
     }
     setArrayLengthUnchecked(len);
 }
index 5c03b1f..5f6cd87 100644 (file)
@@ -109,15 +109,18 @@ struct Q_QML_EXPORT Object: Managed {
     uint memberDataAlloc;
     Property *memberData;
 
-    union {
-        uint arrayFreeList;
-        uint arrayOffset;
+    struct ArrayData {
+        union {
+            uint freeList;
+            uint offset;
+        };
+        uint length;
+        uint alloc;
+        PropertyAttributes *attributes;
+        Property *data;
+        SparseArray *sparse;
     };
-    uint arrayDataLen;
-    uint arrayAlloc;
-    PropertyAttributes *arrayAttributes;
-    Property *arrayData;
-    SparseArray *sparseArray;
+    ArrayData arrayData;
 
     enum {
         InlinePropertySize = 4
@@ -177,42 +180,42 @@ struct Q_QML_EXPORT Object: Managed {
     // Array handling
 
     uint allocArrayValue() {
-        uint idx = arrayFreeList;
-        if (arrayAlloc <= arrayFreeList)
-            arrayReserve(arrayAlloc + 1);
-        arrayFreeList = arrayData[arrayFreeList].value.uint_32;
-        if (arrayAttributes)
-            arrayAttributes[idx].setType(PropertyAttributes::Data);
+        uint idx = arrayData.freeList;
+        if (arrayData.alloc <= arrayData.freeList)
+            arrayReserve(arrayData.alloc + 1);
+        arrayData.freeList = arrayData.data[arrayData.freeList].value.uint_32;
+        if (arrayData.attributes)
+            arrayData.attributes[idx].setType(PropertyAttributes::Data);
         return idx;
     }
 
     uint allocArrayValue(const ValueRef v) {
         uint idx = allocArrayValue();
-        Property *pd = &arrayData[idx];
+        Property *pd = &arrayData.data[idx];
         pd->value = *v;
         return idx;
     }
     void freeArrayValue(int idx) {
-        Property &pd = arrayData[idx];
+        Property &pd = arrayData.data[idx];
         pd.value.tag = Value::Empty_Type;
-        pd.value.int_32 = arrayFreeList;
-        arrayFreeList = idx;
-        if (arrayAttributes)
-            arrayAttributes[idx].clear();
+        pd.value.int_32 = arrayData.freeList;
+        arrayData.freeList = idx;
+        if (arrayData.attributes)
+            arrayData.attributes[idx].clear();
     }
 
     void getArrayHeadRoom() {
-        assert(!sparseArray && !arrayOffset);
-        arrayOffset = qMax(arrayDataLen >> 2, (uint)16);
-        Property *newArray = new Property[arrayOffset + arrayAlloc];
-        memcpy(newArray + arrayOffset, arrayData, arrayDataLen*sizeof(Property));
-        delete [] arrayData;
-        arrayData = newArray + arrayOffset;
-        if (arrayAttributes) {
-            PropertyAttributes *newAttrs = new PropertyAttributes[arrayOffset + arrayAlloc];
-            memcpy(newAttrs + arrayOffset, arrayAttributes, arrayDataLen*sizeof(PropertyAttributes));
-            delete [] arrayAttributes;
-            arrayAttributes = newAttrs + arrayOffset;
+        assert(!arrayData.sparse && !arrayData.offset);
+        arrayData.offset = qMax(arrayData.length >> 2, (uint)16);
+        Property *newArray = new Property[arrayData.offset + arrayData.alloc];
+        memcpy(newArray + arrayData.offset, arrayData.data, arrayData.length*sizeof(Property));
+        delete [] arrayData.data;
+        arrayData.data = newArray + arrayData.offset;
+        if (arrayData.attributes) {
+            PropertyAttributes *newAttrs = new PropertyAttributes[arrayData.offset + arrayData.alloc];
+            memcpy(newAttrs + arrayData.offset, arrayData.attributes, arrayData.length*sizeof(PropertyAttributes));
+            delete [] arrayData.attributes;
+            arrayData.attributes = newAttrs + arrayData.offset;
         }
     }
 
@@ -232,12 +235,12 @@ public:
 
     uint propertyIndexFromArrayIndex(uint index) const
     {
-        if (!sparseArray) {
-            if (index >= arrayDataLen)
+        if (!arrayData.sparse) {
+            if (index >= arrayData.length)
                 return UINT_MAX;
             return index;
         } else {
-            SparseArrayNode *n = sparseArray->findNode(index);
+            SparseArrayNode *n = arrayData.sparse->findNode(index);
             if (!n)
                 return UINT_MAX;
             return n->value;
@@ -248,25 +251,25 @@ public:
         uint pidx = propertyIndexFromArrayIndex(index);
         if (pidx == UINT_MAX)
             return 0;
-        return arrayData + pidx;
+        return arrayData.data + pidx;
     }
 
     Property *nonSparseArrayAt(uint index) const {
-        if (sparseArray)
+        if (arrayData.sparse)
             return 0;
-        if (index >= arrayDataLen)
+        if (index >= arrayData.length)
             return 0;
-        return arrayData + index;
+        return arrayData.data + index;
     }
 
     void push_back(const ValueRef v);
 
-    SparseArrayNode *sparseArrayBegin() { return sparseArray ? sparseArray->begin() : 0; }
-    SparseArrayNode *sparseArrayEnd() { return sparseArray ? sparseArray->end() : 0; }
+    SparseArrayNode *sparseArrayBegin() { return arrayData.sparse ? arrayData.sparse->begin() : 0; }
+    SparseArrayNode *sparseArrayEnd() { return arrayData.sparse ? arrayData.sparse->end() : 0; }
 
     void arrayConcat(const ArrayObject *other);
-    void arraySort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint arrayDataLen);
-    ReturnedValue arrayIndexOf(const ValueRef v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o);
+    void arraySort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint dataLen);
+    ReturnedValue arrayIndexOf(const ValueRef v, uint fromIndex, uint dataLen, ExecutionContext *ctx, Object *o);
 
     void arrayReserve(uint n);
     void ensureArrayAttributes();
@@ -276,7 +279,7 @@ public:
         Scoped<Object> p(scope, this);
 
         while ((p = p->prototype()))
-            if (p->arrayDataLen)
+            if (p->arrayData.length)
                 return true;
 
         return false;
@@ -400,14 +403,14 @@ inline void Object::setArrayLengthUnchecked(uint l)
 inline void Object::push_back(const ValueRef v)
 {
     uint idx = arrayLength();
-    if (!sparseArray) {
-        if (idx >= arrayAlloc)
+    if (!arrayData.sparse) {
+        if (idx >= arrayData.alloc)
             arrayReserve(idx + 1);
-        arrayData[idx].value = *v;
-        arrayDataLen = idx + 1;
+        arrayData.data[idx].value = *v;
+        arrayData.length = idx + 1;
     } else {
         uint idx = allocArrayValue(v);
-        sparseArray->push_back(idx, arrayLength());
+        arrayData.sparse->push_back(idx, arrayLength());
     }
     setArrayLengthUnchecked(idx + 1);
 }
@@ -417,33 +420,33 @@ inline Property *Object::arrayInsert(uint index, PropertyAttributes attributes)
         hasAccessorProperty = 1;
 
     Property *pd;
-    if (!sparseArray && (index < 0x1000 || index < arrayDataLen + (arrayDataLen >> 2))) {
-        if (index >= arrayAlloc)
+    if (!arrayData.sparse && (index < 0x1000 || index < arrayData.length + (arrayData.length >> 2))) {
+        if (index >= arrayData.alloc)
             arrayReserve(index + 1);
-        if (index >= arrayDataLen) {
+        if (index >= arrayData.length) {
             // mark possible hole in the array
-            for (uint i = arrayDataLen; i < index; ++i) {
-                arrayData[i].value = Primitive::emptyValue();
-                if (arrayAttributes)
-                    arrayAttributes[i].clear();
+            for (uint i = arrayData.length; i < index; ++i) {
+                arrayData.data[i].value = Primitive::emptyValue();
+                if (arrayData.attributes)
+                    arrayData.attributes[i].clear();
             }
-            arrayDataLen = index + 1;
+            arrayData.length = index + 1;
         }
-        pd = arrayData + index;
+        pd = arrayData.data + index;
     } else {
         initSparse();
-        SparseArrayNode *n = sparseArray->insert(index);
+        SparseArrayNode *n = arrayData.sparse->insert(index);
         if (n->value == UINT_MAX)
             n->value = allocArrayValue();
-        pd = arrayData + n->value;
+        pd = arrayData.data + n->value;
     }
     if (index >= arrayLength())
         setArrayLengthUnchecked(index + 1);
-    if (arrayAttributes || attributes != Attr_Data) {
-        if (!arrayAttributes)
+    if (arrayData.attributes || attributes != Attr_Data) {
+        if (!arrayData.attributes)
             ensureArrayAttributes();
         attributes.resolve();
-        arrayAttributes[pd - arrayData] = attributes;
+        arrayData.attributes[pd - arrayData.data] = attributes;
     }
     return pd;
 }
index 2e631bd..31287d0 100644 (file)
@@ -272,9 +272,9 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
     o->internalClass = o->internalClass->sealed();
 
     o->ensureArrayAttributes();
-    for (uint i = 0; i < o->arrayDataLen; ++i) {
-        if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
-            o->arrayAttributes[i].setConfigurable(false);
+    for (uint i = 0; i < o->arrayData.length; ++i) {
+        if (!(o->arrayData.attributes[i].isGeneric() || o->arrayData.data[i].value.isEmpty()))
+            o->arrayData.attributes[i].setConfigurable(false);
     }
 
     return o.asReturnedValue();
@@ -295,11 +295,11 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
     o->internalClass = o->internalClass->frozen();
 
     o->ensureArrayAttributes();
-    for (uint i = 0; i < o->arrayDataLen; ++i) {
-        if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
-            o->arrayAttributes[i].setConfigurable(false);
-        if (o->arrayAttributes[i].isData())
-            o->arrayAttributes[i].setWritable(false);
+    for (uint i = 0; i < o->arrayData.length; ++i) {
+        if (!(o->arrayData.attributes[i].isGeneric() || o->arrayData.data[i].value.isEmpty()))
+            o->arrayData.attributes[i].setConfigurable(false);
+        if (o->arrayData.attributes[i].isData())
+            o->arrayData.attributes[i].setWritable(false);
     }
     return o.asReturnedValue();
 }
@@ -328,15 +328,15 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
     if (o->internalClass != o->internalClass->sealed())
         return Encode(false);
 
-    if (!o->arrayDataLen)
+    if (!o->arrayData.length)
         return Encode(true);
 
-    if (!o->arrayAttributes)
+    if (!o->arrayData.attributes)
         return Encode(false);
 
-    for (uint i = 0; i < o->arrayDataLen; ++i) {
-        if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
-            if (o->arrayAttributes[i].isConfigurable())
+    for (uint i = 0; i < o->arrayData.length; ++i) {
+        if (!(o->arrayData.attributes[i].isGeneric() || o->arrayData.data[i].value.isEmpty()))
+            if (o->arrayData.attributes[i].isConfigurable())
                 return Encode(false);
     }
 
@@ -356,15 +356,15 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
     if (o->internalClass != o->internalClass->frozen())
         return Encode(false);
 
-    if (!o->arrayDataLen)
+    if (!o->arrayData.length)
         return Encode(true);
 
-    if (!o->arrayAttributes)
+    if (!o->arrayData.attributes)
         return Encode(false);
 
-    for (uint i = 0; i < o->arrayDataLen; ++i) {
-        if (!(o->arrayAttributes[i].isGeneric() || o->arrayData[i].value.isEmpty()))
-            if (o->arrayAttributes[i].isConfigurable() || o->arrayAttributes[i].isWritable())
+    for (uint i = 0; i < o->arrayData.length; ++i) {
+        if (!(o->arrayData.attributes[i].isGeneric() || o->arrayData.data[i].value.isEmpty()))
+            if (o->arrayData.attributes[i].isConfigurable() || o->arrayData.attributes[i].isWritable())
                 return Encode(false);
     }
 
index 61f92a0..4293cca 100644 (file)
@@ -1690,8 +1690,8 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
         QV4::Scoped<ArrayObject> array(scope, v4->newArrayObject());
         array->arrayReserve(list.count());
         for (int ii = 0; ii < list.count(); ++ii) {
-            array->arrayData[ii].value = QV4::QObjectWrapper::wrap(v4, list.at(ii));
-            array->arrayDataLen = ii + 1;
+            array->arrayData.data[ii].value = QV4::QObjectWrapper::wrap(v4, list.at(ii));
+            array->arrayData.length = ii + 1;
         }
         array->setArrayLengthUnchecked(list.count());
         return array.asReturnedValue();
index 425fb8a..e8d92ef 100644 (file)
@@ -347,8 +347,8 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
     for (int i = 0; i < len; ++i) {
         int start = matchOffsets[i * 2];
         int end = matchOffsets[i * 2 + 1];
-        array->arrayData[i].value = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
-        array->arrayDataLen = i + 1;
+        array->arrayData.data[i].value = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+        array->arrayData.length = i + 1;
     }
     array->setArrayLengthUnchecked(len);
 
index 011607f..304a4a4 100644 (file)
@@ -591,9 +591,9 @@ ReturnedValue __qmljs_get_element(ExecutionContext *ctx, const ValueRef object,
     if (idx < UINT_MAX) {
         uint pidx = o->propertyIndexFromArrayIndex(idx);
         if (pidx < UINT_MAX) {
-            if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
-                if (!o->arrayData[pidx].value.isEmpty())
-                    return o->arrayData[pidx].value.asReturnedValue();
+            if (!o->arrayData.attributes || o->arrayData.attributes[pidx].isData()) {
+                if (!o->arrayData.data[pidx].value.isEmpty())
+                    return o->arrayData.data[pidx].value.asReturnedValue();
             }
         }
 
@@ -617,19 +617,19 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val
     if (idx < UINT_MAX) {
         uint pidx = o->propertyIndexFromArrayIndex(idx);
         if (pidx < UINT_MAX) {
-            if (o->arrayAttributes && !o->arrayAttributes[pidx].isEmpty() && !o->arrayAttributes[pidx].isWritable()) {
+            if (o->arrayData.attributes && !o->arrayData.attributes[pidx].isEmpty() && !o->arrayData.attributes[pidx].isWritable()) {
                 if (ctx->strictMode)
                     ctx->throwTypeError();
                 return;
             }
 
-            Property *p = o->arrayData + pidx;
-            if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
+            Property *p = o->arrayData.data + pidx;
+            if (!o->arrayData.attributes || o->arrayData.attributes[pidx].isData()) {
                 p->value = *value;
                 return;
             }
 
-            if (o->arrayAttributes[pidx].isAccessor()) {
+            if (o->arrayData.attributes[pidx].isAccessor()) {
                 FunctionObject *setter = p->setter();
                 if (!setter) {
                     if (ctx->strictMode)
@@ -1131,8 +1131,8 @@ ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values,
     // This should rather be done when required
     a->arrayReserve(length);
     if (length) {
-        a->arrayDataLen = length;
-        Property *pd = a->arrayData;
+        a->arrayData.length = length;
+        Property *pd = a->arrayData.data;
         for (uint i = 0; i < length; ++i) {
             pd->value = values[i];
             ++pd;
index ee325db..b199c86 100644 (file)
@@ -390,8 +390,8 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
         array->arrayReserve(seqLength);
         for (quint32 ii = 0; ii < seqLength; ++ii) {
             value = deserialize(data, engine);
-            array->arrayData[ii].value = value.asReturnedValue();
-            array->arrayDataLen = ii + 1;
+            array->arrayData.data[ii].value = value.asReturnedValue();
+            array->arrayData.length = ii + 1;
         }
         array->setArrayLengthUnchecked(seqLength);
         QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
index 39667f0..3d90c81 100644 (file)
@@ -145,7 +145,7 @@ Property *StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRe
             *index = it->arrayIndex;
             ++it->arrayIndex;
             if (attrs)
-                *attrs = s->arrayAttributes ? s->arrayAttributes[it->arrayIndex] : PropertyAttributes(Attr_NotWritable|Attr_NotConfigurable);
+                *attrs = s->arrayData.attributes ? s->arrayData.attributes[it->arrayIndex] : PropertyAttributes(Attr_NotWritable|Attr_NotConfigurable);
             return s->__getOwnProperty__(*index);
         }
         it->arrayNode = s->sparseArrayBegin();
index c814298..94cf268 100644 (file)
@@ -554,12 +554,12 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
 
     QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
     result->arrayReserve(days.size());
-    result->arrayDataLen = days.size();
+    result->arrayData.length = days.size();
     for (int i = 0; i < days.size(); ++i) {
         int day = days.at(i);
         if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
             day = 0;
-        result->arrayData[i].value = QV4::Primitive::fromInt32(day);
+        result->arrayData.data[i].value = QV4::Primitive::fromInt32(day);
     }
     result->setArrayLengthUnchecked(days.size());
 
@@ -577,8 +577,8 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx)
     QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject());
     result->arrayReserve(langs.size());
     for (int i = 0; i < langs.size(); ++i) {
-        result->arrayData[i].value = ctx->engine->newString(langs.at(i));
-        result->arrayDataLen = i + 1;
+        result->arrayData.data[i].value = ctx->engine->newString(langs.at(i));
+        result->arrayData.length = i + 1;
     }
 
     result->setArrayLengthUnchecked(langs.size());
index 33f5a00..88d56bf 100644 (file)
@@ -197,8 +197,8 @@ static QV4::ReturnedValue arrayFromStringList(QV8Engine *engine, const QStringLi
     int len = list.count();
     a->arrayReserve(len);
     for (int ii = 0; ii < len; ++ii) {
-        a->arrayData[ii].value = QV4::Encode(e->newString(list.at(ii)));
-        a->arrayDataLen = ii + 1;
+        a->arrayData.data[ii].value = QV4::Encode(e->newString(list.at(ii)));
+        a->arrayData.length = ii + 1;
     }
     a->setArrayLengthUnchecked(len);
     return a.asReturnedValue();
@@ -212,8 +212,8 @@ static QV4::ReturnedValue arrayFromVariantList(QV8Engine *engine, const QVariant
     int len = list.count();
     a->arrayReserve(len);
     for (int ii = 0; ii < len; ++ii) {
-        a->arrayData[ii].value = engine->fromVariant(list.at(ii));
-        a->arrayDataLen = ii + 1;
+        a->arrayData.data[ii].value = engine->fromVariant(list.at(ii));
+        a->arrayData.length = ii + 1;
     }
     a->setArrayLengthUnchecked(len);
     return a.asReturnedValue();
@@ -326,8 +326,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
             QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
             a->arrayReserve(list.count());
             for (int ii = 0; ii < list.count(); ++ii) {
-                a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
-                a->arrayDataLen = ii + 1;
+                a->arrayData.data[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
+                a->arrayData.length = ii + 1;
             }
             a->setArrayLengthUnchecked(list.count());
             return a.asReturnedValue();
@@ -542,8 +542,8 @@ QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst)
     QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
     a->arrayReserve(lst.size());
     for (int i = 0; i < lst.size(); i++) {
-        a->arrayData[i].value = variantToJS(lst.at(i));
-        a->arrayDataLen = i + 1;
+        a->arrayData.data[i].value = variantToJS(lst.at(i));
+        a->arrayData.length = i + 1;
     }
     a->setArrayLengthUnchecked(lst.size());
     return a.asReturnedValue();