diff options
| author | Lars Knoll <lars.knoll@digia.com> | 2013-10-13 22:08:59 +0200 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-14 21:59:56 +0200 |
| commit | 668eca2b9343cf5d79dc1faa6c251595e2e84918 (patch) | |
| tree | bae99ec4065b0e20ba3bbf2fab89434d43d12f07 /src/qml/jsruntime/qv4object.cpp | |
| parent | 669e6b434f015982d2e5e9f48ef72d8e8eebb0ac (diff) | |
Avoid creating array attributes if possible
Holes in arrays should be represented by an empty
value, not by creating/setting array attributes.
Reason is that the creation is irreversable, and slows
down execution. This speeds up crypto.js by 10%
Change-Id: I2e5472575479a5f2dbe53f59ecb8ed3aeab1be7a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4object.cpp')
| -rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 63 |
1 files changed, 28 insertions, 35 deletions
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index a07e5dfe1d..0ccd8e6f62 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -304,14 +304,10 @@ Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs) uint pidx = propertyIndexFromArrayIndex(index); if (pidx < UINT_MAX) { Property *p = arrayData + pidx; - if (!arrayAttributes || arrayAttributes[pidx].isData()) { + if (!p->value.isEmpty() && !(arrayAttributes && arrayAttributes[pidx].isGeneric())) { if (attrs) *attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data); return p; - } else if (arrayAttributes[pidx].isAccessor()) { - if (attrs) - *attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Accessor); - return p; } } if (isStringObject()) { @@ -356,7 +352,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr uint pidx = o->propertyIndexFromArrayIndex(index); if (pidx < UINT_MAX) { Property *p = o->arrayData + pidx; - if (!o->arrayAttributes || !o->arrayAttributes[pidx].isGeneric()) { + if (!p->value.isEmpty()) { if (attrs) *attrs = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data); return p; @@ -448,7 +444,8 @@ PropertyAttributes Object::queryIndexed(const Managed *m, uint index) if (pidx < UINT_MAX) { if (o->arrayAttributes) return o->arrayAttributes[pidx]; - return Attr_Data; + if (!o->arrayData[pidx].value.isEmpty()) + return Attr_Data; } if (o->isStringObject()) { Property *p = static_cast<const StringObject *>(o)->getIndex(index); @@ -578,7 +575,7 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name Property *p = o->arrayData + pidx; PropertyAttributes a = o->arrayAttributes ? o->arrayAttributes[pidx] : PropertyAttributes(Attr_Data); ++it->arrayIndex; - if ((!o->arrayAttributes || !o->arrayAttributes[pidx].isGeneric()) + if (!p->value.isEmpty() && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) { *index = it->arrayIndex - 1; if (attrs) @@ -639,7 +636,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) while (o) { uint pidx = o->propertyIndexFromArrayIndex(index); if (pidx < UINT_MAX) { - if (!o->arrayAttributes || !o->arrayAttributes[pidx].isGeneric()) { + if (!o->arrayData[pidx].value.isEmpty()) { pd = o->arrayData + pidx; if (o->arrayAttributes) attrs = o->arrayAttributes[pidx]; @@ -757,13 +754,9 @@ void Object::internalPutIndexed(uint index, const ValueRef value) PropertyAttributes attrs; uint pidx = propertyIndexFromArrayIndex(index); - if (pidx < UINT_MAX) { - if (arrayAttributes && arrayAttributes[pidx].isGeneric()) { - pidx = UINT_MAX; - } else { - pd = arrayData + pidx; - attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data); - } + if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty()) { + pd = arrayData + pidx; + attrs = arrayAttributes ? arrayAttributes[pidx] : PropertyAttributes(Attr_Data); } if (!pd && isStringObject()) { @@ -852,14 +845,13 @@ bool Object::internalDeleteIndexedProperty(uint index) uint pidx = propertyIndexFromArrayIndex(index); if (pidx == UINT_MAX) return true; - if (arrayAttributes && arrayAttributes[pidx].isGeneric()) + if (arrayData[pidx].value.isEmpty()) return true; if (!arrayAttributes || arrayAttributes[pidx].isConfigurable()) { - arrayData[pidx].value = Primitive::undefinedValue(); - if (!arrayAttributes) - ensureArrayAttributes(); - arrayAttributes[pidx].clear(); + arrayData[pidx].value = Primitive::emptyValue(); + if (arrayAttributes) + arrayAttributes[pidx].clear(); if (sparseArray) { arrayData[pidx].value.int_32 = arrayFreeList; arrayFreeList = pidx; @@ -951,7 +943,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop // Clause 1 { uint pidx = propertyIndexFromArrayIndex(index); - if (pidx < UINT_MAX && (!arrayAttributes || !arrayAttributes[pidx].isGeneric())) + if (pidx < UINT_MAX && !arrayData[pidx].value.isEmpty()) current = arrayData + pidx; if (!current && isStringObject()) current = static_cast<StringObject *>(this)->getIndex(index); @@ -1000,7 +992,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, con } // clause 8 - if (attrs.isGeneric()) + if (attrs.isGeneric() || current->value.isEmpty()) goto accept; // clause 9 @@ -1120,7 +1112,7 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd Property *end = pd + endIndex; pd += fromIndex; while (pd < end) { - if (!arrayAttributes || !arrayAttributes[pd - arrayData].isGeneric()) { + if (!pd->value.isEmpty()) { value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data); if (__qmljs_strict_equal(value, v)) return Encode((uint)(pd - arrayData)); @@ -1156,8 +1148,8 @@ void Object::arrayConcat(const ArrayObject *other) int oldSize = arrayLength(); arrayReserve(oldSize + other->arrayDataLen); if (oldSize > arrayDataLen) { - ensureArrayAttributes(); - std::fill(arrayAttributes + arrayDataLen, arrayAttributes + oldSize, PropertyAttributes()); + for (int i = arrayDataLen; i < oldSize; ++i) + arrayData[i].value = Primitive::emptyValue(); } if (other->arrayAttributes) { for (int i = 0; i < other->arrayDataLen; ++i) { @@ -1166,10 +1158,8 @@ void Object::arrayConcat(const ArrayObject *other) arrayDataLen = oldSize + i + 1; if (arrayAttributes) arrayAttributes[oldSize + i] = Attr_Data; - if (!exists) { - ensureArrayAttributes(); - arrayAttributes[oldSize + i].clear(); - } + if (!exists) + arrayData[oldSize + i].value = Primitive::emptyValue(); } } else { arrayDataLen = oldSize + other->arrayDataLen; @@ -1200,13 +1190,16 @@ void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const Va // into data properties and then sort. This is in line with the sentence above. if (arrayAttributes) { for (uint i = 0; i < len; i++) { - if (arrayAttributes[i].isGeneric()) { + if ((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty()) { while (--len > i) - if (!arrayAttributes[len].isGeneric()) + if (!((arrayAttributes && arrayAttributes[len].isGeneric())|| arrayData[len].value.isEmpty())) break; arrayData[i].value = getValue(arrayData + len, arrayAttributes[len]); - arrayAttributes[i] = Attr_Data; - arrayAttributes[len].clear(); + arrayData[len].value = Primitive::emptyValue(); + if (arrayAttributes) { + arrayAttributes[i] = Attr_Data; + arrayAttributes[len].clear(); + } } else if (arrayAttributes[i].isAccessor()) { arrayData[i].value = getValue(arrayData + i, arrayAttributes[i]); arrayAttributes[i] = Attr_Data; @@ -1235,7 +1228,7 @@ void Object::initSparse() if (!sparseArray) { sparseArray = new SparseArray; for (int i = 0; i < arrayDataLen; ++i) { - if (!arrayAttributes || !arrayAttributes[i].isGeneric()) { + if (!((arrayAttributes && arrayAttributes[i].isGeneric()) || arrayData[i].value.isEmpty())) { SparseArrayNode *n = sparseArray->insert(i); n->value = i + arrayOffset; } |
