aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4object.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-10-13 22:08:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-14 21:59:56 +0200
commit668eca2b9343cf5d79dc1faa6c251595e2e84918 (patch)
treebae99ec4065b0e20ba3bbf2fab89434d43d12f07 /src/qml/jsruntime/qv4object.cpp
parent669e6b434f015982d2e5e9f48ef72d8e8eebb0ac (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.cpp63
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;
}