diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-01-27 09:57:00 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-03-09 08:58:15 +0000 |
commit | 10c1e4053366085080a39ea84ebbd189c8d827ec (patch) | |
tree | 65af97d1897f113647e5463c9bdf9b3dfce94f1b /src/qml/jsruntime | |
parent | 58b882ad42f99e03ac8dca13ff9c0d39fcafbaa0 (diff) |
Unify mark handling for MemberData and ArrayData
Introduce a ValueArray class, that defines an array of
Values at the end of a Heap Object.
Change-Id: I00efbf6f5839a6687dd5bc5fc037ec8f06e0936e
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraydata.cpp | 144 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraydata_p.h | 46 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata_p.h | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 14 |
15 files changed, 143 insertions, 134 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 39b99e9876..33cda59b72 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -91,7 +91,7 @@ void ArgumentsObject::fullyCreate() if (numAccessors) { d()->mappedArguments = md->allocate(engine(), numAccessors); for (uint i = 0; i < numAccessors; ++i) { - d()->mappedArguments->data[i] = context()->callData->args[i]; + d()->mappedArguments->values[i] = context()->callData->args[i]; arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor); } } @@ -122,7 +122,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con map->copy(pd, mapAttrs); setArrayAttributes(index, Attr_Data); pd = arrayData()->getProperty(index); - pd->value = d()->mappedArguments->data[index]; + pd->value = d()->mappedArguments->values[index]; } bool strict = engine->current->strictMode; diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 47d353ffd0..ef1a7bee3c 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -129,7 +129,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt if (d->type() < Heap::ArrayData::Sparse) { offset = d->d()->offset; - toCopy = d->d()->len; + toCopy = d->d()->values.size; } else { toCopy = d->alloc(); } @@ -150,7 +150,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt Heap::SimpleArrayData *n = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size); n->init(); n->offset = 0; - n->len = d ? d->d()->len : 0; + n->values.size = d ? d->d()->values.size : 0; newData = n; } else { Heap::SparseArrayData *n = scope.engine->memoryManager->allocManaged<SparseArrayData>(size); @@ -159,7 +159,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } newData->setAlloc(alloc); newData->setType(newType); - newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->arrayData + alloc) : 0); + newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->d()->values.v + alloc) : 0); o->setArrayData(newData); if (d) { @@ -171,12 +171,12 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt newData->attrs()[i] = Attr_Data; } - if (toCopy > d->d()->alloc - offset) { - uint copyFromStart = toCopy - (d->d()->alloc - offset); - memcpy(newData->d()->arrayData + toCopy - copyFromStart, d->d()->arrayData, sizeof(Value)*copyFromStart); + if (toCopy > d->d()->values.alloc - offset) { + uint copyFromStart = toCopy - (d->d()->values.alloc - offset); + memcpy(newData->d()->values.v + toCopy - copyFromStart, d->d()->values.v, sizeof(Value)*copyFromStart); toCopy -= copyFromStart; } - memcpy(newData->d()->arrayData, d->d()->arrayData + offset, sizeof(Value)*toCopy); + memcpy(newData->d()->values.v, d->d()->values.v + offset, sizeof(Value)*toCopy); } if (newType != Heap::ArrayData::Sparse) @@ -196,22 +196,22 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt lastFree = &sparse->freeList; storeValue(lastFree, 0); for (uint i = 0; i < toCopy; ++i) { - if (!sparse->arrayData[i].isEmpty()) { + if (!sparse->values[i].isEmpty()) { SparseArrayNode *n = sparse->sparse->insert(i); n->value = i; } else { storeValue(lastFree, i); - sparse->arrayData[i].setEmpty(); - lastFree = &sparse->arrayData[i].rawValueRef(); + sparse->values[i].setEmpty(); + lastFree = &sparse->values[i].rawValueRef(); } } } - if (toCopy < sparse->alloc) { - for (uint i = toCopy; i < sparse->alloc; ++i) { + if (toCopy < sparse->values.alloc) { + for (uint i = toCopy; i < sparse->values.alloc; ++i) { storeValue(lastFree, i); - sparse->arrayData[i].setEmpty(); - lastFree = &sparse->arrayData[i].rawValueRef(); + sparse->values[i].setEmpty(); + lastFree = &sparse->values[i].rawValueRef(); } storeValue(lastFree, UINT_MAX); } @@ -237,7 +237,7 @@ void ArrayData::ensureAttributes(Object *o) ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index) { const Heap::SimpleArrayData *dd = static_cast<const Heap::SimpleArrayData *>(d); - if (index >= dd->len) + if (index >= dd->values.size) return Primitive::emptyValue().asReturnedValue(); return dd->data(index).asReturnedValue(); } @@ -245,13 +245,13 @@ ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index) bool SimpleArrayData::put(Object *o, uint index, const Value &value) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor()); + Q_ASSERT(index >= dd->values.size || !dd->attrs || !dd->attrs[index].isAccessor()); // ### honour attributes dd->data(index) = value; - if (index >= dd->len) { + if (index >= dd->values.size) { if (dd->attrs) dd->attrs[index] = Attr_Data; - dd->len = index + 1; + dd->values.size = index + 1; } return true; } @@ -259,7 +259,7 @@ bool SimpleArrayData::put(Object *o, uint index, const Value &value) bool SimpleArrayData::del(Object *o, uint index) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (index >= dd->len) + if (index >= dd->values.size) return true; if (!dd->attrs || dd->attrs[index].isConfigurable()) { @@ -282,8 +282,8 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Q_ASSERT(!dd->attrs); - if (dd->len + n > dd->alloc) { - realloc(o, Heap::ArrayData::Simple, dd->len + n, false); + if (dd->values.size + n > dd->values.alloc) { + realloc(o, Heap::ArrayData::Simple, dd->values.size + n, false); Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple); dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } @@ -291,10 +291,10 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n) dd->offset -= n; // there is enough space left in front } else { // we need to wrap around, so: - dd->offset = dd->alloc - // start at the back, but subtract: + dd->offset = dd->values.alloc - // start at the back, but subtract: (n - dd->offset); // the number of items we can put in the free space at the start of the allocated array } - dd->len += n; + dd->values.size += n; for (uint i = 0; i < n; ++i) dd->data(i) = values[i].asReturnedValue(); } @@ -303,58 +303,58 @@ ReturnedValue SimpleArrayData::pop_front(Object *o) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Q_ASSERT(!dd->attrs); - if (!dd->len) + if (!dd->values.size) return Encode::undefined(); ReturnedValue v = dd->data(0).isEmpty() ? Encode::undefined() : dd->data(0).asReturnedValue(); - dd->offset = (dd->offset + 1) % dd->alloc; - --dd->len; + dd->offset = (dd->offset + 1) % dd->values.alloc; + --dd->values.size; return v; } uint SimpleArrayData::truncate(Object *o, uint newLen) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (dd->len < newLen) + if (dd->values.size < newLen) return newLen; if (!dd->attrs) { - dd->len = newLen; + dd->values.size = newLen; return newLen; } - while (dd->len > newLen) { - if (!dd->data(dd->len - 1).isEmpty() && !dd->attrs[dd->len - 1].isConfigurable()) - return dd->len; - --dd->len; + while (dd->values.size > newLen) { + if (!dd->data(dd->values.size - 1).isEmpty() && !dd->attrs[dd->values.size - 1].isConfigurable()) + return dd->values.size; + --dd->values.size; } - return dd->len; + return dd->values.size; } uint SimpleArrayData::length(const Heap::ArrayData *d) { - return d->len; + return d->values.size; } bool SimpleArrayData::putArray(Object *o, uint index, const Value *values, uint n) { Heap::SimpleArrayData *dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (index + n > dd->alloc) { + if (index + n > dd->values.alloc) { reallocate(o, index + n + 1, false); dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } - for (uint i = dd->len; i < index; ++i) + for (uint i = dd->values.size; i < index; ++i) dd->data(i) = Primitive::emptyValue(); for (uint i = 0; i < n; ++i) dd->data(index + i) = values[i]; - dd->len = qMax(dd->len, index + n); + dd->values.size = qMax(dd->values.size, index + n); return true; } void SparseArrayData::free(Heap::ArrayData *d, uint idx) { Q_ASSERT(d && d->type == Heap::ArrayData::Sparse); - Value *v = d->arrayData + idx; + Value *v = d->values.v + idx; if (d->attrs && d->attrs[idx].isAccessor()) { // double slot, free both. Order is important, so we have a double slot for allocation again afterwards. v[1].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue()); @@ -382,32 +382,32 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) ReturnedValue *last = &dd->freeList; while (1) { if (Value::fromReturnedValue(*last).value() == UINT_MAX) { - reallocate(o, dd->alloc + 2, true); + reallocate(o, dd->values.alloc + 2, true); dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); last = &dd->freeList; Q_ASSERT(Value::fromReturnedValue(*last).value() != UINT_MAX); } - Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value()); - if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) { + Q_ASSERT(dd->values[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value()); + if (dd->values[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) { // found two slots in a row uint idx = Value::fromReturnedValue(*last).emptyValue(); Value lastV = Value::fromReturnedValue(*last); - lastV.setEmpty(dd->arrayData[lastV.emptyValue() + 1].value()); + lastV.setEmpty(dd->values[lastV.emptyValue() + 1].value()); *last = lastV.rawValue(); dd->attrs[idx] = Attr_Accessor; return idx; } - last = &dd->arrayData[Value::fromReturnedValue(*last).value()].rawValueRef(); + last = &dd->values[Value::fromReturnedValue(*last).value()].rawValueRef(); } } else { if (Value::fromReturnedValue(dd->freeList).value() == UINT_MAX) { - reallocate(o, dd->alloc + 1, false); + reallocate(o, dd->values.alloc + 1, false); dd = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } uint idx = Value::fromReturnedValue(dd->freeList).value(); Q_ASSERT(idx != UINT_MAX); - dd->freeList = dd->arrayData[idx].asReturnedValue(); + dd->freeList = dd->values[idx].asReturnedValue(); Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty()); if (dd->attrs) dd->attrs[idx] = Attr_Data; @@ -421,7 +421,7 @@ ReturnedValue SparseArrayData::get(const Heap::ArrayData *d, uint index) index = s->mappedIndex(index); if (index == UINT_MAX) return Primitive::emptyValue().asReturnedValue(); - return s->arrayData[index].asReturnedValue(); + return s->values[index].asReturnedValue(); } bool SparseArrayData::put(Object *o, uint index, const Value &value) @@ -435,7 +435,7 @@ bool SparseArrayData::put(Object *o, uint index, const Value &value) if (n->value == UINT_MAX) n->value = allocate(o); s = o->d()->arrayData.cast<Heap::SparseArrayData>(); - s->arrayData[n->value] = value; + s->values[n->value] = value; if (s->attrs) s->attrs[n->value] = Attr_Data; return true; @@ -450,7 +450,7 @@ bool SparseArrayData::del(Object *o, uint index) return true; uint pidx = n->value; - Q_ASSERT(!dd->arrayData[pidx].isEmpty()); + Q_ASSERT(!dd->values[pidx].isEmpty()); bool isAccessor = false; if (dd->attrs) { @@ -463,11 +463,11 @@ bool SparseArrayData::del(Object *o, uint index) if (isAccessor) { // free up both indices - dd->arrayData[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); - dd->arrayData[pidx].setEmpty(pidx + 1); + dd->values[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); + dd->values[pidx].setEmpty(pidx + 1); } else { Q_ASSERT(dd->type == Heap::ArrayData::Sparse); - dd->arrayData[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); + dd->values[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); } dd->freeList = Primitive::emptyValue(pidx).asReturnedValue(); @@ -496,10 +496,10 @@ void SparseArrayData::push_front(Object *o, const Value *values, uint n) { Heap::SparseArrayData *d = o->d()->arrayData.cast<Heap::SparseArrayData>(); Q_ASSERT(!d->attrs); - for (int i = n - 1; i >= 0; --i) { + for (int i = static_cast<int>(n) - 1; i >= 0; --i) { uint idx = allocate(o); d = o->d()->arrayData.cast<Heap::SparseArrayData>(); - d->arrayData[idx] = values[i]; + d->values[idx] = values[i]; d->sparse->push_front(idx); } } @@ -511,7 +511,7 @@ ReturnedValue SparseArrayData::pop_front(Object *o) uint idx = d->sparse->pop_front(); ReturnedValue v; if (idx != UINT_MAX) { - v = d->arrayData[idx].asReturnedValue(); + v = d->values[idx].asReturnedValue(); free(o->arrayData(), idx); } else { v = Encode::undefined(); @@ -589,24 +589,24 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n) ScopedValue v(scope); for (const SparseArrayNode *it = os->sparse->begin(); it != os->sparse->end(); it = it->nextNode()) { - v = otherObj->getValue(os->arrayData[it->value], other->d()->attrs[it->value]); + v = otherObj->getValue(os->values[it->value], other->d()->attrs[it->value]); obj->arraySet(oldSize + it->key(), v); } } else { for (const SparseArrayNode *it = other->d()->sparse->begin(); it != os->sparse->end(); it = it->nextNode()) - obj->arraySet(oldSize + it->key(), os->arrayData[it->value]); + obj->arraySet(oldSize + it->key(), os->values[it->value]); } } else { Heap::SimpleArrayData *os = static_cast<Heap::SimpleArrayData *>(other->d()); uint toCopy = n; uint chunk = toCopy; - if (chunk > os->alloc - os->offset) - chunk -= os->alloc - os->offset; - obj->arrayPut(oldSize, os->arrayData + os->offset, chunk); + if (chunk > os->values.alloc - os->offset) + chunk -= os->values.alloc - os->offset; + obj->arrayPut(oldSize, os->values.v + os->offset, chunk); toCopy -= chunk; if (toCopy) - obj->arrayPut(oldSize + chunk, os->arrayData, toCopy); + obj->arrayPut(oldSize + chunk, os->values.v, toCopy); } return oldSize + n; @@ -616,18 +616,18 @@ void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor) { if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) { Heap::SimpleArrayData *d = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (index < 0x1000 || index < d->len + (d->len >> 2)) { - if (index >= d->alloc) { + if (index < 0x1000 || index < d->values.size + (d->values.size >> 2)) { + if (index >= d->values.alloc) { o->arrayReserve(index + 1); d = o->d()->arrayData.cast<Heap::SimpleArrayData>(); } - if (index >= d->len) { + if (index >= d->values.size) { // mark possible hole in the array - for (uint i = d->len; i < index; ++i) + for (uint i = d->values.size; i < index; ++i) d->data(i) = Primitive::emptyValue(); - d->len = index + 1; + d->values.size = index + 1; } - d->arrayData[d->mappedIndex(index)] = *v; + d->values[d->mappedIndex(index)] = *v; return; } } @@ -638,9 +638,9 @@ void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor) if (n->value == UINT_MAX) n->value = SparseArrayData::allocate(o, isAccessor); s = o->d()->arrayData.cast<Heap::SparseArrayData>(); - s->arrayData[n->value] = *v; + s->values[n->value] = *v; if (isAccessor) - s->arrayData[n->value + Object::SetterOffset] = v[Object::SetterOffset]; + s->values[n->value + Object::SetterOffset] = v[Object::SetterOffset]; } @@ -792,7 +792,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c ++i; } } - d->len = i; + d->values.size = i; if (len > i) len = i; if (n != sparse->sparse()->end()) { @@ -808,8 +808,8 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c } } else { Heap::SimpleArrayData *d = thisObject->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (len > d->len) - len = d->len; + if (len > d->values.size) + len = d->values.size; // sort empty values to the end for (uint i = 0; i < len; i++) { @@ -830,7 +830,7 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c ArrayElementLessThan lessThan(engine, thisObject, comparefn); - Value *begin = thisObject->arrayData()->arrayData; + Value *begin = thisObject->arrayData()->values.v; sortHelper(begin, begin + len, *begin, lessThan); #ifdef CHECK_SPARSE_ARRAYS diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 919bd84762..882f8d1f8d 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -98,21 +98,15 @@ struct ArrayDataData { Custom = 3 }; - uint alloc; Type type; + uint offset; PropertyAttributes *attrs; - union { - uint len; - ReturnedValue freeList; - }; - union { - uint offset; - SparseArray *sparse; - }; - Value arrayData[1]; + ReturnedValue freeList; + SparseArray *sparse; + ValueArray values; }; static Q_CONSTEXPR quint64 ArrayData_markTable = \ - (MarkFlagsForType<decltype(ArrayDataData::arrayData)>::markFlags << (offsetof(ArrayDataData, arrayData) >> 2)) \ + (MarkFlagsForType<decltype(ArrayDataData::values)>::markFlags << (offsetof(ArrayDataData, values) >> 2)) \ << (sizeof(Base) >> 2) | QV4::Heap::Base::markTable; struct ArrayData : public Base, ArrayDataData { @@ -135,7 +129,7 @@ struct ArrayData : public Base, ArrayDataData { return get(i) == Primitive::emptyValue().asReturnedValue(); } - inline ReturnedValue length() const { + inline uint length() const { return vtable()->length(this); } @@ -143,17 +137,17 @@ struct ArrayData : public Base, ArrayDataData { V4_ASSERT_IS_TRIVIAL(ArrayData) struct SimpleArrayData : public ArrayData { - uint mappedIndex(uint index) const { return (index + offset) % alloc; } - Value data(uint index) const { return arrayData[mappedIndex(index)]; } - Value &data(uint index) { return arrayData[mappedIndex(index)]; } + uint mappedIndex(uint index) const { return (index + offset) % values.alloc; } + Value data(uint index) const { return values[mappedIndex(index)]; } + Value &data(uint index) { return values[mappedIndex(index)]; } Property *getProperty(uint index) { - if (index >= len) + if (index >= values.size) return 0; index = mappedIndex(index); - if (arrayData[index].isEmpty()) + if (values[index].isEmpty()) return 0; - return reinterpret_cast<Property *>(arrayData + index); + return reinterpret_cast<Property *>(values.v + index); } PropertyAttributes attributes(uint i) const { @@ -179,7 +173,7 @@ struct SparseArrayData : public ArrayData { SparseArrayNode *n = sparse->findNode(index); if (!n) return 0; - return reinterpret_cast<Property *>(arrayData + n->value); + return reinterpret_cast<Property *>(values.v + n->value); } PropertyAttributes attributes(uint i) const { @@ -200,15 +194,15 @@ struct Q_QML_EXPORT ArrayData : public Managed IsArrayData = true }; - uint alloc() const { return d()->alloc; } - uint &alloc() { return d()->alloc; } - void setAlloc(uint a) { d()->alloc = a; } + uint alloc() const { return d()->values.alloc; } + uint &alloc() { return d()->values.alloc; } + void setAlloc(uint a) { d()->values.alloc = a; } Type type() const { return d()->type; } void setType(Type t) { d()->type = t; } PropertyAttributes *attrs() const { return d()->attrs; } void setAttrs(PropertyAttributes *a) { d()->attrs = a; } - const Value *arrayData() const { return &d()->arrayData[0]; } - Value *arrayData() { return &d()->arrayData[0]; } + const Value *arrayData() const { return d()->values.v; } + Value *arrayData() { return d()->values.v; } const ArrayVTable *vtable() const { return d()->vtable(); } bool isSparse() const { return type() == Heap::ArrayData::Sparse; } @@ -251,8 +245,8 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData Value data(uint index) const { return d()->data(index); } Value &data(uint index) { return d()->data(index); } - uint &len() { return d()->len; } - uint len() const { return d()->len; } + uint &len() { return d()->values.size; } + uint len() const { return d()->values.size; } static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 759354f4e2..a2c19e1f2d 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -690,8 +690,8 @@ void ArrayPrototype::method_indexOf(const BuiltinFunction *, Scope &scope, CallD } else { Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex); Heap::SimpleArrayData *sa = instance->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (len > sa->len) - len = sa->len; + if (len > sa->values.size) + len = sa->values.size; uint idx = fromIndex; while (idx < len) { value = sa->data(idx); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 39b433e5f9..19298f3803 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -600,11 +600,11 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int leng size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value); Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size); d->init(); - d->alloc = length; d->type = Heap::ArrayData::Simple; d->offset = 0; - d->len = length; - memcpy(&d->arrayData, values, length*sizeof(Value)); + d->values.alloc = length; + d->values.size = length; + memcpy(&d->values.v, values, length*sizeof(Value)); a->d()->arrayData = d; a->setArrayLengthUnchecked(length); } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index ae1a403ea1..94555a6679 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -302,7 +302,7 @@ void FunctionPrototype::method_apply(const BuiltinFunction *, Scope &scope, Call cData->args[i] = Primitive::undefinedValue(); } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) { auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData()); - uint alen = sad ? sad->len : 0; + uint alen = sad ? sad->values.size : 0; if (alen > len) alen = len; for (uint i = 0; i < alen; ++i) @@ -345,7 +345,7 @@ void FunctionPrototype::method_bind(const BuiltinFunction *, Scope &scope, CallD Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0); if (callData->argc > 1) { boundArgs = MemberData::allocate(scope.engine, callData->argc - 1); - boundArgs->d()->size = callData->argc - 1; + boundArgs->d()->values.size = callData->argc - 1; memcpy(boundArgs->data(), callData->args + 1, (callData->argc - 1)*sizeof(Value)); } diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 0f4859f0fa..677f0ebea9 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -199,6 +199,7 @@ struct ScriptFunction; struct InternalClass; struct Property; struct Value; +struct ValueArray; struct Lookup; struct ArrayData; struct VTable; diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 52ed449664..f85ead1852 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -182,7 +182,7 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const Value &object, con Heap::Object *o = static_cast<Heap::Object *>(b); if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>(); - if (idx < s->len) + if (idx < s->values.size) if (!s->data(idx).isEmpty()) return s->data(idx).asReturnedValue(); } @@ -217,7 +217,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const Value &object, const Value & if (index.asArrayIndex(idx)) { if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->d()->arrayData.cast<Heap::SimpleArrayData>(); - if (idx < s->len) { + if (idx < s->values.size) { s->data(idx) = value; return; } @@ -239,7 +239,7 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const Value &object, const Value Heap::Object *o = static_cast<Heap::Object *>(b); if (o->arrayData && o->arrayData->type == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = o->arrayData.cast<Heap::SimpleArrayData>(); - if (idx < s->len) { + if (idx < s->values.size) { s->data(idx) = v; return; } diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 3a6d66a030..ce1c8b614e 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -47,15 +47,16 @@ DEFINE_MANAGED_VTABLE(MemberData); Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old) { - Q_ASSERT(!old || old->size < n); + Q_ASSERT(!old || old->values.size < n); Q_ASSERT(n); size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); Heap::MemberData *m = e->memoryManager->allocManaged<MemberData>(alloc); if (old) - memcpy(m, old, sizeof(Heap::MemberData) + (old->size - 1)* sizeof(Value)); + memcpy(m, old, sizeof(Heap::MemberData) + (old->values.size - 1) * sizeof(Value)); else m->init(); - m->size = static_cast<uint>((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); + m->values.alloc = static_cast<uint>((alloc - sizeof(Heap::MemberData) + sizeof(Value))/sizeof(Value)); + m->values.size = m->values.alloc; return m; } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index c4e797ff8d..a531d3303f 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -60,8 +60,7 @@ namespace QV4 { namespace Heap { #define MemberDataMembers(class, Member) \ - Member(class, uint, size) \ - Member(class, ValueArray, data) + Member(class, ValueArray, values) DECLARE_HEAP_OBJECT(MemberData, Base) { DECLARE_MARK_TABLE(MemberData); @@ -74,10 +73,10 @@ struct MemberData : Managed { V4_MANAGED(MemberData, Managed) - Value &operator[] (uint idx) { return d()->data[idx]; } - const Value *data() const { return d()->data; } - Value *data() { return d()->data; } - inline uint size() const { return d()->size; } + Value &operator[] (uint idx) { return d()->values[idx]; } + const Value *data() const { return d()->values.v; } + Value *data() { return d()->values.v; } + inline uint size() const { return d()->values.size; } static Heap::MemberData *allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old = 0); }; diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 095aa6b4da..7886dd24fa 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -62,7 +62,7 @@ void Object::setInternalClass(InternalClass *ic) { d()->internalClass = ic; bool hasMD = d()->memberData != nullptr; - if ((!hasMD && ic->size) || (hasMD && d()->memberData->size < ic->size)) + if ((!hasMD && ic->size) || (hasMD && d()->memberData->values.size < ic->size)) d()->memberData = MemberData::allocate(ic->engine, ic->size, d()->memberData); } @@ -582,7 +582,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint * int k = it->arrayNode->key(); uint pidx = it->arrayNode->value; Heap::SparseArrayData *sa = o->d()->arrayData.cast<Heap::SparseArrayData>(); - Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx); + Property *p = reinterpret_cast<Property *>(sa->values.v + pidx); it->arrayNode = it->arrayNode->nextNode(); PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data; if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { @@ -597,7 +597,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint * it->arrayIndex = UINT_MAX; } // dense arrays - while (it->arrayIndex < o->d()->arrayData->len) { + while (it->arrayIndex < o->d()->arrayData->values.size) { Heap::SimpleArrayData *sa = o->d()->arrayData.cast<Heap::SimpleArrayData>(); Value &val = sa->data(it->arrayIndex); PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex); @@ -1132,7 +1132,7 @@ void Object::copyArrayData(Object *other) ; } else { Q_ASSERT(!arrayData() && other->arrayData()); - ArrayData::realloc(this, other->d()->arrayData->type, other->d()->arrayData->alloc, false); + ArrayData::realloc(this, other->d()->arrayData->type, other->d()->arrayData->values.alloc, false); if (other->arrayType() == Heap::ArrayData::Sparse) { Heap::ArrayData *od = other->d()->arrayData; Heap::ArrayData *dd = d()->arrayData; @@ -1140,10 +1140,10 @@ void Object::copyArrayData(Object *other) dd->freeList = od->freeList; } else { Heap::ArrayData *dd = d()->arrayData; - dd->len = other->d()->arrayData->len; + dd->values.size = other->d()->arrayData->values.size; dd->offset = other->d()->arrayData->offset; } - memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, other->d()->arrayData->alloc*sizeof(Value)); + memcpy(d()->arrayData->values.v, other->d()->arrayData->values.v, other->d()->arrayData->values.alloc*sizeof(Value)); } setArrayLengthUnchecked(other->getLength()); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index b0eec1adfc..2affcd1af9 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -78,8 +78,8 @@ DECLARE_HEAP_OBJECT(Object, Base) { void init() { Base::init(); } void destroy() { Base::destroy(); } - const Value *propertyData(uint index) const { return memberData->data + index; } - Value *propertyData(uint index) { return memberData->data + index; } + const Value *propertyData(uint index) const { return memberData->values.v + index; } + Value *propertyData(uint index) { return memberData->values.v + index; } }; } @@ -524,7 +524,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a { // ### Clean up arrayCreate(); - if (attributes.isAccessor() || (index > 0x1000 && index > 2*d()->arrayData->alloc)) { + if (attributes.isAccessor() || (index > 0x1000 && index > 2*d()->arrayData->values.alloc)) { initSparseArray(); } else { arrayData()->vtable()->reallocate(this, index + 1, false); @@ -539,7 +539,7 @@ inline void Object::arraySet(uint index, const Property *p, PropertyAttributes a inline void Object::arraySet(uint index, const Value &value) { arrayCreate(); - if (index > 0x1000 && index > 2*d()->arrayData->alloc) { + if (index > 0x1000 && index > 2*d()->arrayData->values.alloc) { initSparseArray(); } ArrayData::insert(this, index, &value); diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index f650ffc7b1..2e72c0f13f 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -295,7 +295,7 @@ void ObjectPrototype::method_seal(const BuiltinFunction *, Scope &scope, CallDat if (o->arrayData()) { ArrayData::ensureAttributes(o); - for (uint i = 0; i < o->d()->arrayData->alloc; ++i) { + for (uint i = 0; i < o->d()->arrayData->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) o->d()->arrayData->attrs[i].setConfigurable(false); } @@ -320,7 +320,7 @@ void ObjectPrototype::method_freeze(const BuiltinFunction *, Scope &scope, CallD if (o->arrayData()) { ArrayData::ensureAttributes(o); - for (uint i = 0; i < o->arrayData()->alloc; ++i) { + for (uint i = 0; i < o->arrayData()->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) o->arrayData()->attrs[i].setConfigurable(false); if (o->arrayData()->attrs[i].isData()) @@ -371,7 +371,7 @@ void ObjectPrototype::method_isSealed(const BuiltinFunction *, Scope &scope, Cal return; } - for (uint i = 0; i < o->arrayData()->alloc; ++i) { + for (uint i = 0; i < o->arrayData()->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable()) { scope.result = Encode(false); @@ -411,7 +411,7 @@ void ObjectPrototype::method_isFrozen(const BuiltinFunction *, Scope &scope, Cal return; } - for (uint i = 0; i < o->arrayData()->alloc; ++i) { + for (uint i = 0; i < o->arrayData()->values.alloc; ++i) { if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) { scope.result = Encode(false); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 6590054bf3..4459af0e66 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -643,7 +643,7 @@ void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, co if (idx < UINT_MAX) { if (o->arrayType() == Heap::ArrayData::Simple) { Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->arrayData()); - if (s && idx < s->len && !s->data(idx).isEmpty()) { + if (s && idx < s->values.size && !s->data(idx).isEmpty()) { s->data(idx) = value; return; } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 4ff0565f9b..6d25abba9a 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -708,6 +708,20 @@ inline unsigned int Value::toUInt32() const return (unsigned int)toInt32(); } +struct ValueArray { + uint size; + uint alloc; + Value v[1]; + + inline Value &operator[] (uint index) { + Q_ASSERT(index < alloc); + return v[index]; + } + inline const Value &operator[] (uint index) const { + Q_ASSERT(index < alloc); + return v[index]; + } +}; } |