From 5c25379cd1889dc16187c0ec62f32d2b17a320cf Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 9 Jan 2014 11:05:08 +0100 Subject: Save memory on array data Store a simple vector of Values in the array data, instead of a Vector of Property's. This halfes the memory consumption on 64bit and simplifies our code. If an indexed property gets converted to an accessor property, we simply convert the ArrayData into a SparseArrayData. Add support in SparseArrayData to allocate double slots (two Value's) to hold a full Property in case someone sets an accessor on an indexed property. Some methods still return a Property*, but this is safe, as only the first Value in the Property pointer will ever get accessed if the Property doesn't contain an accessor. Change-Id: Ic9b0f309b09a2772a328d947a10faaf3be9fe56f Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4object_p.h | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'src/qml/jsruntime/qv4object_p.h') diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index f99191a24c..de44d5cfd3 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -136,7 +136,7 @@ struct Q_QML_EXPORT Object: Managed { bool hasOwnProperty(const StringRef name) const; bool hasOwnProperty(uint index) const; - bool __defineOwnProperty__(ExecutionContext *ctx, Property *current, const StringRef member, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs); bool __defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs); bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs); bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs); @@ -209,17 +209,15 @@ public: void arrayCreate() { if (!arrayData) arrayData = new ArrayData; +#ifdef CHECK_SPARSE_ARRAYS + initSparseArray(); +#endif } void initSparseArray(); SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast(arrayData)->sparse->begin() : 0; } SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast(arrayData)->sparse->end() : 0; } - inline Property *arrayInsert(uint index) { - arrayCreate(); - return ArrayData::insert(this, index); - } - inline bool protoHasArray() { Scope scope(engine()); Scoped p(scope, this); @@ -344,7 +342,6 @@ inline void Object::setArrayLengthUnchecked(uint l) inline void Object::push_back(const ValueRef v) { arrayCreate(); - Q_ASSERT(!arrayData->isSparse()); uint idx = getLength(); arrayReserve(idx + 1); @@ -355,12 +352,21 @@ inline void Object::push_back(const ValueRef v) inline void Object::arraySet(uint index, const Property &p, PropertyAttributes attributes) { - if (attributes.isAccessor()) + // ### Clean up + arrayCreate(); + if (attributes.isAccessor()) { hasAccessorProperty = 1; - - Property *pd = arrayInsert(index); - *pd = p; + initSparseArray(); + } else if (index > 0x1000 && index > 2*arrayData->alloc) { + initSparseArray(); + } else { + arrayData->vtable->reserve(arrayData, index + 1); + } arrayData->setAttributes(index, attributes); + Property *pd = ArrayData::insert(this, index, attributes.isAccessor()); + pd->value = p.value; + if (attributes.isAccessor()) + pd->set = p.set; if (isArrayObject() && index >= getLength()) setArrayLengthUnchecked(index + 1); } @@ -368,7 +374,11 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a inline void Object::arraySet(uint index, ValueRef value) { - Property *pd = arrayInsert(index); + arrayCreate(); + if (index > 0x1000 && index > 2*arrayData->alloc) { + initSparseArray(); + } + Property *pd = ArrayData::insert(this, index); pd->value = value ? *value : Primitive::undefinedValue(); if (isArrayObject() && index >= getLength()) setArrayLengthUnchecked(index + 1); -- cgit v1.2.3