diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 469081e68393831586e6fbf436a3151f48878ddb..c40f50153d0f518455c0b8f0b6fbb4958d3997e8 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -119,7 +119,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt while (alloc < requested) alloc *= 2; - size_t size = sizeof(ArrayData::Data) + alloc*sizeof(Value); + size_t size = sizeof(ArrayData::Data) + (alloc - 1)*sizeof(Value); if (enforceAttributes) size += alloc*sizeof(PropertyAttributes); @@ -137,7 +137,6 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } newData->setAlloc(alloc); newData->setType(newType); - newData->d()->arrayData = reinterpret_cast<Value *>(newData->d() + 1); newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->arrayData + alloc) : 0); o->setArrayData(newData); @@ -417,10 +416,10 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) ReturnedValue SparseArrayData::get(const ArrayData *d, uint index) { const SparseArrayData *s = static_cast<const SparseArrayData *>(d); - SparseArrayNode *n = s->sparse()->findNode(index); - if (!n) + index = s->mappedIndex(index); + if (index == UINT_MAX) return Primitive::emptyValue().asReturnedValue(); - return s->arrayData()[n->value].asReturnedValue(); + return s->arrayData()[index].asReturnedValue(); } bool SparseArrayData::put(Object *o, uint index, ValueRef value) @@ -428,7 +427,7 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) if (value->isEmpty()) return true; - const SparseArrayData *s = static_cast<const SparseArrayData *>(o->arrayData()); + SparseArrayData *s = static_cast<SparseArrayData *>(o->arrayData()); SparseArrayNode *n = s->sparse()->insert(index); Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor()); if (n->value == UINT_MAX) @@ -442,6 +441,7 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) bool SparseArrayData::del(Object *o, uint index) { SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData()); + SparseArrayNode *n = dd->sparse()->findNode(index); if (!n) return true; @@ -567,14 +567,14 @@ bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n) } -uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) +uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n) { Q_ASSERT(!obj->arrayData()->hasAttributes()); if (!n) return obj->getLength(); - const ArrayData *other = otherObj->arrayData(); + ArrayData *other = otherObj->arrayData(); if (other->isSparse()) obj->initSparseArray(); @@ -584,7 +584,7 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) uint oldSize = obj->getLength(); if (other->isSparse()) { - const SparseArrayData *os = static_cast<const SparseArrayData *>(other); + SparseArrayData *os = static_cast<SparseArrayData *>(other); if (otherObj->hasAccessorProperty() && other->hasAttributes()) { Scope scope(obj->engine()); ScopedValue v(scope); @@ -599,7 +599,7 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) obj->arraySet(oldSize + it->key(), ValueRef(os->arrayData()[it->value])); } } else { - const SimpleArrayData *os = static_cast<const SimpleArrayData *>(other); + SimpleArrayData *os = static_cast<SimpleArrayData *>(other); uint toCopy = n; uint chunk = toCopy; if (chunk > os->alloc() - os->d()->offset) @@ -628,7 +628,7 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor) d->data(i) = Primitive::emptyValue(); d->len() = index + 1; } - return reinterpret_cast<Property *>(d->d()->arrayData + d->realIndex(index)); + return reinterpret_cast<Property *>(d->d()->arrayData + d->mappedIndex(index)); } } diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index cd080baa4aef6a208e6ab9f9855cedb0fdb2db27..70c581d75d94b194127dbafc703d0736e71beb04 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -98,7 +98,7 @@ struct Q_QML_EXPORT ArrayData : public Managed uint offset; SparseArray *sparse; }; - Value *arrayData; + Value arrayData[1]; }; V4_MANAGED(Managed) @@ -109,8 +109,8 @@ struct Q_QML_EXPORT ArrayData : public Managed void setType(Type t) { d()->type = t; } PropertyAttributes *attrs() const { return d()->attrs; } void setAttrs(PropertyAttributes *a) { d()->attrs = a; } - Value *arrayData() const { return d()->arrayData; } - Value *&arrayData() { return d()->arrayData; } + const Value *arrayData() const { return &d()->arrayData[0]; } + Value *arrayData() { return &d()->arrayData[0]; } const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass()->vtable); } bool isSparse() const { return this && type() == Sparse; } @@ -140,13 +140,13 @@ struct Q_QML_EXPORT ArrayData : public Managed return Primitive::emptyValue().asReturnedValue(); return vtable()->get(this, i); } - inline Property *getProperty(uint index) const; + inline Property *getProperty(uint index); static void ensureAttributes(Object *o); static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes); static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen); - static uint append(Object *obj, const ArrayObject *otherObj, uint n); + static uint append(Object *obj, ArrayObject *otherObj, uint n); static Property *insert(Object *o, uint index, bool isAccessor = false); }; @@ -160,14 +160,14 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData }; V4_ARRAYDATA - uint realIndex(uint index) const { return (index + d()->offset) % d()->alloc; } - Value data(uint index) const { return d()->arrayData[realIndex(index)]; } - Value &data(uint index) { return d()->arrayData[realIndex(index)]; } + uint mappedIndex(uint index) const { return (index + d()->offset) % d()->alloc; } + Value data(uint index) const { return d()->arrayData[mappedIndex(index)]; } + Value &data(uint index) { return d()->arrayData[mappedIndex(index)]; } - Property *getProperty(uint index) const { + Property *getProperty(uint index) { if (index >= len()) return 0; - index = realIndex(index); + index = mappedIndex(index); if (d()->arrayData[index].isEmpty()) return 0; return reinterpret_cast<Property *>(d()->arrayData + index); @@ -209,6 +209,20 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData static uint allocate(Object *o, bool doubleSlot = false); static void free(ArrayData *d, uint idx); + Property *getProperty(uint index) { + SparseArrayNode *n = sparse()->findNode(index); + if (!n) + return 0; + return reinterpret_cast<Property *>(arrayData() + n->value); + } + + uint mappedIndex(uint index) const { + SparseArrayNode *n = sparse()->findNode(index); + if (!n) + return UINT_MAX; + return n->value; + } + static void destroy(Managed *d); static void markObjects(Managed *d, ExecutionEngine *e); @@ -226,19 +240,16 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData }; -inline Property *ArrayData::getProperty(uint index) const +inline Property *ArrayData::getProperty(uint index) { if (!this) return 0; if (type() != Sparse) { - const SimpleArrayData *that = static_cast<const SimpleArrayData *>(this); + SimpleArrayData *that = static_cast<SimpleArrayData *>(this); return that->getProperty(index); } else { - const SparseArrayData *that = static_cast<const SparseArrayData *>(this); - SparseArrayNode *n = that->sparse()->findNode(index); - if (!n) - return 0; - return reinterpret_cast<Property *>(that->arrayData() + n->value); + SparseArrayData *that = static_cast<SparseArrayData *>(this); + return that->getProperty(index); } } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 1b2532018e9013374f000ecf6ef4f8c6d7471b27..d53ca013b4695492877ed2c619b1b5036f6600d6 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1075,9 +1075,8 @@ void Object::copyArrayData(Object *other) } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){ // do it the slow way ScopedValue v(scope); - const SparseArrayData *osa = static_cast<const SparseArrayData *>(other->arrayData()); - for (const SparseArrayNode *it = osa->sparse()->begin(); - it != osa->sparse()->end(); it = it->nextNode()) { + SparseArrayData *osa = static_cast<SparseArrayData *>(other->arrayData()); + for (const SparseArrayNode *it = osa->sparse()->begin(); it != osa->sparse()->end(); it = it->nextNode()) { v = other->getValue(reinterpret_cast<Property *>(osa->arrayData() + it->value), other->arrayData()->attrs()[it->value]); arraySet(it->key(), v); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 86e4e78d28c18871d4590f46ab6bc0c13988e780..4e9d1527c28cd557403bbb9691518259cd991808 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -114,8 +114,7 @@ struct Q_QML_EXPORT Object: Managed { Members &memberData() { return d()->memberData; } const Members &memberData() const { return d()->memberData; } - const ArrayData *arrayData() const { return d()->arrayData; } - ArrayData *arrayData() { return d()->arrayData; } + ArrayData *arrayData() const { return d()->arrayData; } void setArrayData(ArrayData *a) { d()->arrayData = a; } Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData().data() + index); }