return Value::undefinedValue();
}
+ if (len < 0x1000)
+ a->arrayReserve(len);
} else {
len = ctx->argumentCount;
- for (unsigned int i = 0; i < len; ++i) {
- a->arraySet(i, ctx->argument(i));
- }
+ a->arrayReserve(len);
+ for (unsigned int i = 0; i < len; ++i)
+ fillDescriptor(a->arrayData + i, ctx->argument(i));
+ a->arrayDataLen = len;
}
a->setArrayLengthUnchecked(len);
}
for (uint i = 0; i < ctx->argumentCount; ++i) {
- quint32 k = result->arrayLength();
Value arg = ctx->argument(i);
if (ArrayObject *elt = arg.asArrayObject())
result->arrayConcat(elt);
else
- result->arraySet(k, arg);
+ result->arraySet(getLength(ctx, result), arg);
}
return Value::fromObject(result);
bool protoHasArray = false;
Object *p = instance;
while ((p = p->prototype))
- if (p->arrayLength())
+ if (p->arrayDataLen)
protoHasArray = true;
- if (!protoHasArray && len == instance->arrayLength()) {
+ if (!protoHasArray && instance->arrayDataLen <= len) {
for (uint i = 0; i < ctx->argumentCount; ++i) {
Value v = ctx->argument(i);
- instance->push_back(v);
+
+ if (!instance->sparseArray) {
+ if (len >= instance->arrayAlloc)
+ instance->arrayReserve(len + 1);
+ fillDescriptor(instance->arrayData + len, v);
+ instance->arrayDataLen = len + 1;
+ } else {
+ uint i = instance->allocArrayValue(v);
+ instance->sparseArray->push_back(i, len);
+ }
+ ++len;
}
} else {
for (uint i = 0; i < ctx->argumentCount; ++i)
instance->__put__(ctx, len + i, ctx->argument(i));
+ len += ctx->argumentCount;
}
- uint newLen = len + ctx->argumentCount;
- if (!instance->isArrayObject())
- instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(newLen));
+ if (instance->isArrayObject())
+ instance->setArrayLengthUnchecked(len);
+ else
+ instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len));
- if (newLen < INT_MAX)
- return Value::fromInt32(newLen);
- return Value::fromDouble((double)newLen);
+ if (len < INT_MAX)
+ return Value::fromInt32(len);
+ return Value::fromDouble((double)len);
}
bool protoHasArray = false;
Object *p = instance;
while ((p = p->prototype))
- if (p->arrayLength())
+ if (p->arrayDataLen)
protoHasArray = true;
- if (!protoHasArray && len >= instance->arrayLength()) {
- instance->pop_front();
+ if (!protoHasArray && instance->arrayDataLen <= len) {
+ if (!instance->sparseArray) {
+ if (instance->arrayDataLen) {
+ ++instance->arrayOffset;
+ ++instance->arrayData;
+ --instance->arrayDataLen;
+ --instance->arrayAlloc;
+ }
+ } else {
+ uint idx = instance->sparseArray->pop_front();
+ instance->freeArrayValue(idx);
+ }
} else {
// do it the slow way
for (uint k = 1; k < len; ++k) {
instance->__delete__(ctx, len - 1);
}
- if (!instance->isArrayObject())
+ if (instance->isArrayObject())
+ instance->setArrayLengthUnchecked(len - 1);
+ else
instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(len - 1));
return result;
}
for (uint i = start; i < end; ++i) {
bool exists;
Value v = o->__get__(ctx, i, &exists);
- if (exists)
+ if (exists) {
result->arraySet(n, v);
+ }
++n;
}
return Value::fromObject(result);
uint deleteCount = (uint)qMin(qMax(ctx->argument(1).toInteger(ctx), 0.), (double)(len - start));
- newArray->arrayData.resize(deleteCount);
- PropertyDescriptor *pd = newArray->arrayData.data();
+ newArray->arrayReserve(deleteCount);
+ PropertyDescriptor *pd = newArray->arrayData;
for (uint i = 0; i < deleteCount; ++i) {
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Enabled;
pd->value = instance->__get__(ctx, start + i);
++pd;
}
+ newArray->arrayDataLen = deleteCount;
newArray->setArrayLengthUnchecked(deleteCount);
uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2;
bool protoHasArray = false;
Object *p = instance;
while ((p = p->prototype))
- if (p->arrayLength())
+ if (p->arrayDataLen)
protoHasArray = true;
- if (!protoHasArray && len >= instance->arrayLength()) {
+ if (!protoHasArray && instance->arrayDataLen <= len) {
for (int i = ctx->argumentCount - 1; i >= 0; --i) {
Value v = ctx->argument(i);
- instance->push_front(v);
+
+ if (!instance->sparseArray) {
+ if (!instance->arrayOffset)
+ instance->getArrayHeadRoom();
+
+ --instance->arrayOffset;
+ --instance->arrayData;
+ ++instance->arrayDataLen;
+ fillDescriptor(instance->arrayData, v);
+ } else {
+ uint idx = instance->allocArrayValue(v);
+ instance->sparseArray->push_front(idx);
+ }
}
} else {
for (uint k = len; k > 0; --k) {
for (uint i = 0; i < ctx->argumentCount; ++i)
instance->__put__(ctx, i, ctx->argument(i));
}
+
uint newLen = len + ctx->argumentCount;
- if (!instance->isArrayObject())
+ if (instance->isArrayObject())
+ instance->setArrayLengthUnchecked(newLen);
+ else
instance->__put__(ctx, ctx->engine->id_length, Value::fromDouble(newLen));
if (newLen < INT_MAX)
Value thisArg = ctx->argument(1);
ArrayObject *a = ctx->engine->newArrayObject(ctx);
+ a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
for (uint k = 0; k < len; ++k) {
Value thisArg = ctx->argument(1);
ArrayObject *a = ctx->engine->newArrayObject(ctx);
+ a->arrayReserve(len);
uint to = 0;
for (uint k = 0; k < len; ++k) {
if (o) {
stringify.replacerFunction = o->asFunctionObject();
if (o->isArrayObject()) {
- for (uint i = 0; i < o->arrayLength(); ++i) {
+ uint arrayLen = o->arrayLength();
+ for (uint i = 0; i < arrayLen; ++i) {
Value v = o->__get__(ctx, i);
if (v.asNumberObject() || v.asStringObject() || v.isNumber())
v = __qmljs_to_string(v, ctx);
//
Object::~Object()
{
- delete memberData;
+ delete [] memberData;
+ delete [] (arrayData - (sparseArray ? 0 : arrayOffset));
delete sparseArray;
}
memberDataAlloc = qMax((uint)8, 2*memberDataAlloc);
PropertyDescriptor *newMemberData = new PropertyDescriptor[memberDataAlloc];
memcpy(newMemberData, memberData, sizeof(PropertyDescriptor)*memberDataSize);
- delete memberData;
+ delete [] memberData;
memberData = newMemberData;
}
e->valueIndex = memberDataSize;
void Object::copyArrayData(Object *other)
{
- arrayLen = other->arrayLen;
- arrayData = other->arrayData;
- arrayFreeList = other->arrayFreeList;
- if (other->sparseArray)
+ arrayReserve(other->arrayDataLen);
+ arrayDataLen = other->arrayDataLen;
+ memcpy(arrayData, other->arrayData, arrayDataLen*sizeof(PropertyDescriptor));
+ arrayOffset = 0;
+ if (other->sparseArray) {
sparseArray = new SparseArray(*other->sparseArray);
+ arrayFreeList = other->arrayFreeList;
+ }
if (isArrayObject())
- setArrayLengthUnchecked(arrayLen);
+ setArrayLengthUnchecked(other->arrayLength());
}
bool protoHasArray = false;
Object *p = o;
while ((p = p->prototype))
- if (p->arrayLength())
+ if (p->arrayDataLen)
protoHasArray = true;
if (protoHasArray) {
return Value::fromDouble(i);
}
} else if (sparseArray) {
- for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n && n->key() < endIndex; n = n->nextNode()) {
+ for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
bool exists;
Value value = o->getValueChecked(ctx, arrayDecriptor(n->value), &exists);
if (exists && __qmljs_strict_equal(value, v))
return Value::fromDouble(n->key());
}
} else {
- if ((int) endIndex > arrayData.size())
- endIndex = arrayData.size();
- PropertyDescriptor *pd = arrayData.data() + arrayOffset;
+ if ((int) endIndex > arrayDataLen)
+ endIndex = arrayDataLen;
+ PropertyDescriptor *pd = arrayData;
PropertyDescriptor *end = pd + endIndex;
pd += fromIndex;
while (pd < end) {
bool exists;
Value value = o->getValueChecked(ctx, pd, &exists);
if (exists && __qmljs_strict_equal(value, v))
- return Value::fromDouble(pd - arrayOffset - arrayData.constData());
+ return Value::fromDouble(pd - arrayData);
++pd;
}
}
void Object::arrayConcat(const ArrayObject *other)
{
- int newLen = arrayLen + other->arrayLength();
+ int newLen = arrayDataLen + other->arrayLength();
if (other->sparseArray)
initSparse();
if (sparseArray) {
if (other->sparseArray) {
for (const SparseArrayNode *it = other->sparseArray->begin(); it != other->sparseArray->end(); it = it->nextNode())
- arraySet(arrayLen + it->key(), other->arrayDecriptor(it->value));
+ arraySet(arrayDataLen + it->key(), other->arrayDecriptor(it->value));
} else {
- int oldSize = arrayData.size();
- arrayData.resize(oldSize + other->arrayLength());
- memcpy(arrayData.data() + oldSize, other->arrayData.constData() + other->arrayOffset, other->arrayLength()*sizeof(PropertyDescriptor));
+ int oldSize = arrayDataLen;
+ arrayReserve(oldSize + other->arrayLength());
+ memcpy(arrayData + oldSize, other->arrayData, other->arrayLength()*sizeof(PropertyDescriptor));
for (uint i = 0; i < other->arrayLength(); ++i) {
- SparseArrayNode *n = sparseArray->insert(arrayLen + i);
+ SparseArrayNode *n = sparseArray->insert(arrayDataLen + i);
n->value = oldSize + i;
}
}
} else {
- int oldSize = arrayData.size();
- arrayData.resize(oldSize + other->arrayLength());
- memcpy(arrayData.data() + oldSize, other->arrayData.constData() + other->arrayOffset, other->arrayLength()*sizeof(PropertyDescriptor));
+ int oldSize = arrayLength();
+ arrayReserve(oldSize + other->arrayDataLen);
+ if (oldSize > arrayDataLen) {
+ PropertyDescriptor generic;
+ generic.type = PropertyDescriptor::Generic;
+ generic.writable = PropertyDescriptor::Undefined;
+ generic.value = Value::undefinedValue();
+ std::fill(arrayData + arrayDataLen, arrayData + oldSize, generic);
+ }
+ arrayDataLen = oldSize + other->arrayDataLen;
+ memcpy(arrayData + oldSize, other->arrayData, other->arrayDataLen*sizeof(PropertyDescriptor));
}
setArrayLengthUnchecked(newLen);
}
void Object::arraySort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint len)
{
+ if (!arrayDataLen)
+ return;
+
if (sparseArray) {
context->throwUnimplemented("Object::sort unimplemented for sparse arrays");
return;
}
ArrayElementLessThan lessThan(context, thisObject, comparefn);
- if (len > arrayData.size() - arrayOffset)
- len = arrayData.size() - arrayOffset;
- PropertyDescriptor *begin = arrayData.begin() + arrayOffset;
+ if (len > arrayDataLen)
+ len = arrayDataLen;
+
+ PropertyDescriptor *begin = arrayData;
std::sort(begin, begin + len, lessThan);
}
{
if (!sparseArray) {
sparseArray = new SparseArray;
- for (int i = arrayOffset; i < arrayData.size(); ++i) {
- SparseArrayNode *n = sparseArray->insert(i - arrayOffset);
- n->value = i;
+ for (int i = 0; i < arrayDataLen; ++i) {
+ SparseArrayNode *n = sparseArray->insert(i);
+ n->value = i + arrayOffset;
}
- if (arrayOffset) {
- int o = arrayOffset;
+ uint off = arrayOffset;
+ if (!arrayOffset) {
+ arrayFreeList = arrayDataLen;
+ } else {
+ arrayFreeList = 0;
+ arrayData -= off;
+ arrayAlloc += off;
+ int o = off;
for (int i = 0; i < o - 1; ++i) {
arrayData[i].type = PropertyDescriptor::Generic;
arrayData[i].value = Value::fromInt32(i + 1);
}
arrayData[o - 1].type = PropertyDescriptor::Generic;
- arrayData[o - 1].value = Value::fromInt32(arrayData.size());
- arrayFreeList = 0;
- } else {
- arrayFreeList = arrayData.size();
+ arrayData[o - 1].value = Value::fromInt32(arrayDataLen + off);
+ }
+ for (int i = arrayDataLen + off; i < arrayAlloc; ++i) {
+ arrayData[i].type = PropertyDescriptor::Generic;
+ arrayData[i].value = Value::fromInt32(i + 1);
}
}
}
-void Object::setArrayLengthUnchecked(uint l)
+void Object::arrayReserve(uint n)
{
- arrayLen = l;
- if (isArrayObject()) {
- // length is always the first property of an array
- PropertyDescriptor &lengthProperty = memberData[ArrayObject::LengthPropertyIndex];
- lengthProperty.value = Value::fromUInt32(l);
+ if (n < 8)
+ n = 8;
+ if (n >= arrayAlloc) {
+ uint off;
+ if (sparseArray) {
+ assert(arrayFreeList == arrayAlloc);
+ // ### FIXME
+ arrayDataLen = arrayAlloc;
+ off = 0;
+ } else {
+ off = arrayOffset;
+ }
+ arrayAlloc = qMax(n, 2*arrayAlloc);
+ PropertyDescriptor *newArrayData = new PropertyDescriptor[arrayAlloc];
+ memcpy(newArrayData, arrayData, sizeof(PropertyDescriptor)*arrayDataLen);
+ delete [] (arrayData - off);
+ arrayData = newArrayData;
+ if (sparseArray) {
+ for (uint i = arrayFreeList; i < arrayAlloc; ++i) {
+ arrayData[i].type = PropertyDescriptor::Generic;
+ arrayData[i].value = Value::fromInt32(i + 1);
+ }
+ } else {
+ arrayOffset = 0;
+ }
}
}
+
bool Object::setArrayLength(uint newLen) {
assert(isArrayObject());
const PropertyDescriptor *lengthProperty = memberData + ArrayObject::LengthPropertyIndex;
if (newLen < oldLen) {
if (sparseArray) {
SparseArrayNode *begin = sparseArray->lowerBound(newLen);
- SparseArrayNode *it = sparseArray->end()->previousNode();
- while (1) {
- PropertyDescriptor &pd = arrayData[it->value];
- if (pd.type != PropertyDescriptor::Generic && !pd.isConfigurable()) {
- ok = false;
- newLen = it->key() + 1;
- break;
+ if (begin != sparseArray->end()) {
+ SparseArrayNode *it = sparseArray->end()->previousNode();
+ while (1) {
+ PropertyDescriptor &pd = arrayData[it->value];
+ if (pd.type != PropertyDescriptor::Generic && !pd.isConfigurable()) {
+ ok = false;
+ newLen = it->key() + 1;
+ break;
+ }
+ pd.type = PropertyDescriptor::Generic;
+ pd.value.tag = Value::_Undefined_Type;
+ pd.value.int_32 = arrayFreeList;
+ arrayFreeList = it->value;
+ bool brk = (it == begin);
+ SparseArrayNode *prev = it->previousNode();
+ sparseArray->erase(it);
+ if (brk)
+ break;
+ it = prev;
}
- pd.type = PropertyDescriptor::Generic;
- pd.value.tag = Value::_Undefined_Type;
- pd.value.int_32 = arrayFreeList;
- arrayFreeList = it->value;
- bool brk = (it == begin);
- SparseArrayNode *prev = it->previousNode();
- sparseArray->erase(it);
- if (brk)
- break;
- it = prev;
}
} else {
- PropertyDescriptor *it = arrayData.data() + arrayData.size();
- const PropertyDescriptor *begin = arrayData.constData() + arrayOffset + newLen;
+ PropertyDescriptor *it = arrayData + arrayDataLen;
+ const PropertyDescriptor *begin = arrayData + newLen;
while (--it >= begin) {
if (it->type != PropertyDescriptor::Generic && !it->isConfigurable()) {
ok = false;
- newLen = it - arrayData.data() + arrayOffset + 1;
+ newLen = it - arrayData + 1;
break;
}
}
- arrayData.resize(newLen + arrayOffset);
+ arrayDataLen = newLen;
}
} else {
if (newLen >= 0x100000)
void Object::markArrayObjects() const
{
- uint i = sparseArray ? 0 : arrayOffset;
- for (; i < (uint)arrayData.size(); ++i) {
- const PropertyDescriptor &pd = arrayData.at(i);
+ for (uint i = 0; i < arrayDataLen; ++i) {
+ const PropertyDescriptor &pd = arrayData[i];
if (pd.isData()) {
if (Managed *m = pd.value.asManaged())
m->mark();
uint memberDataAlloc;
PropertyDescriptor *memberData;
- uint arrayLen;
union {
uint arrayFreeList;
uint arrayOffset;
};
- QVector<PropertyDescriptor> arrayData;
+ uint arrayDataLen;
+ uint arrayAlloc;
+ PropertyDescriptor *arrayData;
SparseArray *sparseArray;
Object()
: prototype(0)
, memberDataSize(0), memberDataAlloc(0), memberData(0)
- , arrayLen(0), arrayOffset(0), sparseArray(0) { type = Type_Object; }
+ , arrayOffset(0), arrayDataLen(0), arrayAlloc(0), sparseArray(0) { type = Type_Object; }
virtual ~Object();
// Array handling
- void fillDescriptor(PropertyDescriptor *pd, Value v)
+ static void fillDescriptor(PropertyDescriptor *pd, Value v)
{
pd->type = PropertyDescriptor::Data;
pd->writable = PropertyDescriptor::Enabled;
uint allocArrayValue() {
uint idx = arrayFreeList;
- if (arrayData.size() <= (int)arrayFreeList)
- arrayData.resize(++arrayFreeList);
- else
- arrayFreeList = arrayData.at(arrayFreeList).value.integerValue();
+ if (arrayAlloc <= arrayFreeList)
+ arrayReserve(arrayAlloc + 1);
+ arrayFreeList = arrayData[arrayFreeList].value.integerValue();
return idx;
}
}
PropertyDescriptor *arrayDecriptor(uint index) {
- PropertyDescriptor *pd = arrayData.data() + index;
- if (!sparseArray)
- pd += arrayOffset;
- return pd;
+ return arrayData + index;
}
const PropertyDescriptor *arrayDecriptor(uint index) const {
- const PropertyDescriptor *pd = arrayData.data() + index;
- if (!sparseArray)
- pd += arrayOffset;
- return pd;
+ return arrayData + index;
}
void getArrayHeadRoom() {
assert(!sparseArray && !arrayOffset);
- arrayOffset = qMax(arrayData.size() >> 2, 16);
- QVector<PropertyDescriptor> newValues(arrayData.size() + arrayOffset);
- memcpy(newValues.data() + arrayOffset, arrayData.constData(), arrayData.size()*sizeof(PropertyDescriptor));
- arrayData = newValues;
+ arrayOffset = qMax(arrayDataLen >> 2, (uint)16);
+ PropertyDescriptor *newArray = new PropertyDescriptor[arrayOffset + arrayAlloc];
+ memcpy(newArray + arrayOffset, arrayData, arrayDataLen*sizeof(PropertyDescriptor));
+ delete [] arrayData;
+ arrayData = newArray + arrayOffset;
}
public:
void copyArrayData(Object *other);
void initSparse();
- uint arrayLength() const { return arrayLen; }
+ uint arrayLength() const;
bool setArrayLength(uint newLen);
void setArrayLengthUnchecked(uint l);
PropertyDescriptor *arrayInsert(uint index) {
PropertyDescriptor *pd;
- if (!sparseArray && (index < 0x1000 || index < arrayLen + (arrayLen >> 2))) {
- if (index + arrayOffset >= (uint)arrayData.size()) {
- arrayData.resize(arrayOffset + index + 1);
- for (uint i = arrayLen + 1; i < index; ++i) {
+ if (!sparseArray && (index < 0x1000 || index < arrayDataLen + (arrayDataLen >> 2))) {
+ if (index >= arrayAlloc)
+ arrayReserve(index + 1);
+ if (index >= arrayDataLen) {
+ for (uint i = arrayDataLen; i < index; ++i) {
arrayData[i].type = PropertyDescriptor::Generic;
+ arrayData[i].writable = PropertyDescriptor::Undefined;
arrayData[i].value.tag = Value::_Undefined_Type;
}
+ arrayDataLen = index + 1;
}
pd = arrayDecriptor(index);
} else {
n->value = allocArrayValue();
pd = arrayDecriptor(n->value);
}
- if (index >= arrayLen)
+ if (index >= arrayLength())
setArrayLengthUnchecked(index + 1);
return pd;
}
}
bool deleteArrayIndex(uint index) {
- if (index >= arrayLen)
- return true;
PropertyDescriptor *pd = 0;
if (!sparseArray) {
+ if (index >= arrayDataLen)
+ return true;
pd = arrayAt(index);
} else {
SparseArrayNode *n = sparseArray->findNode(index);
if (!pd->isConfigurable())
return false;
pd->type = PropertyDescriptor::Generic;
- pd->value.tag = Value::_Undefined_Type;
+ pd->value = Value::undefinedValue();
if (sparseArray) {
pd->value.int_32 = arrayFreeList;
- arrayFreeList = pd - arrayData.constData();
+ arrayFreeList = pd - arrayData;
}
return true;
}
PropertyDescriptor *arrayAt(uint index) {
if (!sparseArray) {
- if (index >= arrayData.size() - arrayOffset)
+ if (index >= arrayDataLen)
return 0;
- return arrayData.data() + index + arrayOffset;
+ return arrayData + index;
} else {
SparseArrayNode *n = sparseArray->findNode(index);
if (!n)
return 0;
- return arrayData.data() + n->value;
+ return arrayData + n->value;
}
}
const PropertyDescriptor *nonSparseArrayAt(uint index) const {
if (sparseArray)
return 0;
- index += arrayOffset;
- if (index >= (uint)arrayData.size())
+ if (index >= arrayDataLen)
return 0;
- return arrayData.constData() + index;
+ return arrayData + index;
}
PropertyDescriptor *nonSparseArrayAtRef(uint index) {
if (sparseArray)
return 0;
- index += arrayOffset;
- if (index >= (uint)arrayData.size())
+ if (index >= arrayDataLen)
return 0;
- return arrayData.data() + index;
+ return arrayData + index;
}
const PropertyDescriptor *arrayAt(uint index) const {
if (!sparseArray) {
- if (index >= arrayData.size() - arrayOffset)
+ if (index >= arrayDataLen)
return 0;
- return arrayData.constData() + index + arrayOffset;
+ return arrayData + index;
} else {
SparseArrayNode *n = sparseArray->findNode(index);
if (!n)
return 0;
- return arrayData.constData() + n->value;
+ return arrayData + n->value;
}
}
void markArrayObjects() const;
- void push_front(Value v) {
- if (!sparseArray) {
- if (!arrayOffset)
- getArrayHeadRoom();
-
- PropertyDescriptor pd;
- fillDescriptor(&pd, v);
- --arrayOffset;
- arrayData[arrayOffset] = pd;
- } else {
- uint idx = allocArrayValue(v);
- sparseArray->push_front(idx);
- }
- setArrayLengthUnchecked(arrayLen + 1);
- }
PropertyDescriptor *front() {
PropertyDescriptor *pd = 0;
if (!sparseArray) {
- if (arrayLen)
- pd = arrayData.data() + arrayOffset;
+ if (arrayDataLen)
+ pd = arrayData;
} else {
SparseArrayNode *n = sparseArray->findNode(0);
if (n)
return 0;
return pd;
}
- void pop_front() {
- if (!arrayLen)
- return;
- if (!sparseArray) {
- ++arrayOffset;
- } else {
- uint idx = sparseArray->pop_front();
- freeArrayValue(idx);
- }
- setArrayLengthUnchecked(arrayLen - 1);
- }
void push_back(Value v) {
+ uint idx = arrayLength();
if (!sparseArray) {
- PropertyDescriptor pd;
- fillDescriptor(&pd, v);
- arrayData.append(pd);
+ if (idx >= arrayAlloc)
+ arrayReserve(idx + 1);
+ fillDescriptor(arrayData + idx, v);
+ arrayDataLen = idx + 1;
} else {
uint idx = allocArrayValue(v);
- sparseArray->push_back(idx, arrayLen);
+ sparseArray->push_back(idx, arrayLength());
}
- setArrayLengthUnchecked(arrayLen + 1);
- }
- PropertyDescriptor *back() {
- PropertyDescriptor *pd = 0;
- if (!sparseArray) {
- if (arrayLen)
- pd = arrayData.data() + arrayOffset + arrayLen;
- } else {
- SparseArrayNode *n = sparseArray->findNode(arrayLen - 1);
- if (n)
- pd = arrayDecriptor(n->value);
- }
- if (pd && pd->type == PropertyDescriptor::Generic)
- return 0;
- return pd;
- }
- void pop_back() {
- if (!arrayLen)
- return;
- if (!sparseArray) {
- arrayData.resize(arrayData.size() - 1);
- } else {
- uint idx = sparseArray->pop_back(arrayLen);
- if (idx != UINT_MAX)
- freeArrayValue(idx);
- }
- setArrayLengthUnchecked(arrayLen - 1);
+ setArrayLengthUnchecked(idx + 1);
}
- SparseArrayNode *sparseArrayLowerBound(uint idx) { return sparseArray ? sparseArray->lowerBound(idx) : 0; }
SparseArrayNode *sparseArrayBegin() { return sparseArray ? sparseArray->begin() : 0; }
SparseArrayNode *sparseArrayEnd() { return sparseArray ? sparseArray->end() : 0; }
void arrayConcat(const ArrayObject *other);
- void arraySort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint arrayLen);
- Value arrayIndexOf(Value v, uint fromIndex, uint arrayLen, ExecutionContext *ctx, Object *o);
+ void arraySort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint arrayDataLen);
+ Value arrayIndexOf(Value v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o);
+ void arrayReserve(uint n);
protected:
virtual void markObjects();
};
ArrayObject(ExecutionContext *ctx) { init(ctx); }
- ArrayObject(ExecutionContext *ctx, const QVector<PropertyDescriptor> &value): Object() {
- init(ctx);
- arrayData = value;
- setArrayLengthUnchecked(value.size());
- }
void init(ExecutionContext *context);
};
+inline uint Object::arrayLength() const
+{
+ if (isArrayObject()) {
+ // length is always the first property of an array
+ Value v = memberData[ArrayObject::LengthPropertyIndex].value;
+ if (v.isInteger())
+ return v.integerValue();
+ return Value::toUInt32(v.doubleValue());
+ }
+ return 0;
+}
+
+inline void Object::setArrayLengthUnchecked(uint l)
+{
+ if (isArrayObject()) {
+ // length is always the first property of an array
+ PropertyDescriptor &lengthProperty = memberData[ArrayObject::LengthPropertyIndex];
+ lengthProperty.value = Value::fromUInt32(l);
+ }
+}
+
} // namespace VM
} // namespace QQmlJS
arrayIndex = UINT_MAX;
}
// dense arrays
- while (arrayIndex < current->arrayLength()) {
+ while (arrayIndex < current->arrayDataLen) {
p = current->arrayAt(arrayIndex);
++arrayIndex;
if (p && p->type != PropertyDescriptor::Generic && (!(flags & EnumberableOnly) || p->isEnumerable())) {