6#include <private/qv4mm_p.h>
19 Heap::ArrayData::Simple,
35 Heap::ArrayData::Sparse,
54 a->values.
mark(stack);
68 bool hasAttrs =
d->attrs();
69 enforceAttributes |= hasAttrs;
71 if (requested <= d->
alloc() && newType ==
d->type() && hasAttrs == enforceAttributes)
73 if (alloc < d->
alloc())
76 if (
d->type() < Heap::ArrayData::Sparse) {
78 toCopy =
d->d()->values.size;
82 if (
d->type() > newType)
86 while (
alloc < requested)
89 if (enforceAttributes)
93 if (newType < Heap::ArrayData::Sparse) {
97 n->values.size =
d ?
d->d()->values.size : 0;
104 newData->setAlloc(
alloc);
105 newData->setType(newType);
106 newData->setAttrs(enforceAttributes ?
reinterpret_cast<PropertyAttributes *
>(newData->d()->values.values +
alloc) :
nullptr);
107 o->setArrayData(newData);
110 if (enforceAttributes) {
114 for (
uint i = 0;
i < toCopy; ++
i)
118 if (toCopy >
d->d()->values.alloc -
offset) {
119 uint copyFromStart = toCopy - (
d->d()->values.alloc -
offset);
121 memcpy(newData->d()->values.values + toCopy - copyFromStart,
d->d()->values.values,
sizeof(
Value)*copyFromStart);
122 toCopy -= copyFromStart;
125 memcpy(newData->d()->values.values,
d->d()->values.values +
offset,
sizeof(
Value)*toCopy);
128 if (newType != Heap::ArrayData::Sparse)
134 if (
d &&
d->type() == Heap::ArrayData::Sparse) {
136 sparse->sparse = old->sparse;
137 old->sparse =
nullptr;
138 lastFree = &sparse->sparse->freeList;
141 lastFree = &sparse->sparse->freeList;
143 for (
uint i = 0;
i < toCopy; ++
i) {
150 lastFree = &sparse->values.values[
i];
155 if (toCopy < sparse->
values.alloc) {
159 lastFree = &sparse->values.values[
i];
170 realloc(
o, Heap::ArrayData::Simple,
n, enforceAttributes);
171 return o->arrayData();
176 if (
o->arrayData() &&
o->arrayData()->attrs)
185 if (
index >= dd->values.size)
196 if (
index >= dd->values.size) {
199 dd->values.size =
index + 1;
207 if (
index >= dd->values.size)
230 if (dd->values.size +
n > dd->values.
alloc) {
231 realloc(
o, Heap::ArrayData::Simple, dd->values.size +
n,
false);
232 Q_ASSERT(
o->d()->arrayData->type == Heap::ArrayData::Simple);
239 dd->offset = dd->values.
alloc -
242 dd->values.size +=
n;
251 if (!dd->values.size)
255 dd->offset = (dd->offset + 1) % dd->values.
alloc;
263 if (dd->values.size < newLen)
267 dd->values.size = newLen;
271 while (dd->values.size > newLen) {
273 return dd->values.size;
276 return dd->values.size;
281 return d->values.size;
296 dd->values.size =
qMax(dd->values.size,
index +
n);
302 Q_ASSERT(
d &&
d->type == Heap::ArrayData::Sparse);
303 Value *
v =
d->values.values + idx;
304 if (
d->attrs &&
d->attrs[idx].isAccessor()) {
306 v[1] =
d->sparse->freeList;
309 *
v =
d->sparse->freeList;
311 d->sparse->freeList =
Encode(idx);
313 d->attrs[idx].clear();
318 realloc(
o, Heap::ArrayData::Sparse,
n, enforceAttributes);
319 return o->arrayData();
325 Q_ASSERT(
o->d()->arrayData->type == Heap::ArrayData::Sparse);
328 Value *last = &dd->sparse->freeList;
330 if (last->
int_32() == -1) {
333 last = &dd->sparse->freeList;
345 last = &dd->values.values[last->
int_32()];
348 if (dd->sparse->freeList.
int_32() == -1) {
354 dd->sparse->freeList = dd->values[idx];
366 if (
index == UINT_MAX)
368 return s->values[
index].asReturnedValue();
378 Q_ASSERT(
n->value == UINT_MAX || !
s->attrs || !
s->attrs[
n->value].isAccessor());
379 if (
n->value == UINT_MAX)
399 bool isAccessor =
false;
410 dd->values.values[pidx + 1] = dd->sparse->freeList;
411 dd->values.values[pidx] =
Encode(pidx + 1);
414 dd->values.values[pidx] = dd->sparse->freeList;
417 dd->sparse->freeList =
Encode(pidx);
418 dd->sparse->erase(
n);
426 if (
n->value == UINT_MAX) {
432 free(
o->arrayData(),
n->value);
443 for (
int i =
static_cast<int>(
n) - 1;
i >= 0; --
i) {
446 d->setArrayData(
o->engine(), idx,
values[
i]);
447 d->sparse->push_front(idx);
455 uint idx =
d->sparse->pop_front();
457 if (idx != UINT_MAX) {
458 v =
d->values[idx].asReturnedValue();
459 free(
o->arrayData(), idx);
470 if (
begin !=
d->sparse->end()) {
474 if (!
d->attrs[
it->value].isConfigurable()) {
475 newLen =
it->key() + 1;
479 free(
o->arrayData(),
it->value);
482 d->sparse->erase(
it);
497 n =
n->previousNode();
498 return n ?
n->key() + 1 : 0;
514 return obj->getLength();
520 obj->initSparseArray();
524 uint oldSize =
obj->getLength();
529 obj->arraySet(oldSize +
i, (
v = otherObj->
get(
i)));
530 }
else if (
other->isSparse()) {
532 if (
other->hasAttributes()) {
535 it != os->sparse->end();
it =
it->nextNode()) {
537 obj->arraySet(oldSize +
it->key(),
v);
541 it != os->sparse->end();
it =
it->nextNode())
542 obj->arraySet(oldSize +
it->key(), os->values[
it->value]);
548 if (chunk > os->values.
alloc - os->offset)
549 chunk = os->values.
alloc - os->offset;
550 obj->arrayPut(oldSize, os->values.
data() + os->offset, chunk);
553 obj->arrayPut(oldSize + chunk, os->values.
data(), toCopy);
561 if (!isAccessor &&
o->d()->arrayData->type != Heap::ArrayData::Sparse) {
563 if (
index < 0x1000 || index < d->
values.size + (
d->values.size >> 2)) {
564 if (
index >=
d->values.alloc) {
565 o->arrayReserve(
index + 1);
568 if (
index >=
d->values.size) {
572 d->values.size =
index + 1;
579 o->initSparseArray();
582 if (
n->value == UINT_MAX)
592 Scope scope(m_engine);
594 if (
v1.isUndefined() ||
v1.isEmpty())
596 if (
v2.isUndefined() ||
v2.isEmpty())
609 return result->toNumber() < 0;
619 return p1s->toQString() < p2s->toQString();
646 if (!sparse->sparse()->nEntries())
650 ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ?
true :
false);
655 if (sparse->attrs()) {
656 while (
n != sparse->sparse()->end()) {
668 while (
n != sparse->sparse()->end()) {
671 d->setData(
engine,
i, sparse->arrayData()[
n->value]);
679 if (
n != sparse->sparse()->end()) {
682 while (
n != sparse->sparse()->end()) {
684 thisObject->
arraySet(
n->value,
reinterpret_cast<const Property *
>(sparse->arrayData() +
n->value),
a);
692 if (
len >
d->values.size)
693 len =
d->values.size;
697 if (
d->data(
i).isEmpty()) {
699 if (!
d->data(
len).isEmpty())
717#ifdef CHECK_SPARSE_ARRAYS
bool operator()(Value v1, Value v2) const
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
QSet< QString >::iterator it
\qmltype Particle \inqmlmodule QtQuick.Particles
void sortHelper(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
#define Q_STATIC_ASSERT(Condition)
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMax(const T &a, const T &b)
GLint GLfloat GLfloat GLfloat v2
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLintptr offset
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static bool lessThan(const QChar *a, int l, const char *c)
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable)
#define DEFINE_MANAGED_VTABLE(classname)
static bool isNonStrictArgumentsObject(Managed *m)
static void insert(Object *o, uint index, const Value *v, bool isAccessor=false)
static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen)
bool isEmpty(uint i) const
static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes)
PropertyAttributes * attrs() const
const Value * arrayData() const
void setArrayData(EngineBase *e, uint index, Value newVal)
static uint append(Object *obj, ArrayObject *otherObj, uint n)
static void ensureAttributes(Object *o)
static constexpr ReturnedValue undefined()
MemoryManager * memoryManager
ReturnedValue throwTypeError()
void setData(EngineBase *e, uint index, Value newVal)
const Value & data(uint index) const
uint mappedIndex(uint index) const
void mark(MarkStack *markStack)
ExecutionEngine * engine() const
void arraySet(uint index, const Property *p, PropertyAttributes attributes=Attr_Data)
static ReturnedValue getValue(const Value *thisObject, const Value &v, PropertyAttributes attrs)
void setArrayData(ArrayData *a)
Heap::ArrayData * arrayData() const
ReturnedValue get(StringOrSymbol *name, bool *hasProperty=nullptr, const Value *receiver=nullptr) const
bool isConfigurable() const
bool hasException() const
static uint length(const Heap::ArrayData *d)
static Heap::ArrayData * reallocate(Object *o, uint n, bool enforceAttributes)
static ReturnedValue get(const Heap::ArrayData *d, uint index)
static uint truncate(Object *o, uint newLen)
static bool del(Object *o, uint index)
static void push_front(Object *o, const Value *values, uint n)
static void setAttribute(Object *o, uint index, PropertyAttributes attrs)
static bool put(Object *o, uint index, const Value &value)
static bool putArray(Object *o, uint index, const Value *values, uint n)
static ReturnedValue pop_front(Object *o)
static bool putArray(Object *o, uint index, const Value *values, uint n)
static ReturnedValue pop_front(Object *o)
static uint length(const Heap::ArrayData *d)
static uint truncate(Object *o, uint newLen)
static Heap::ArrayData * reallocate(Object *o, uint n, bool enforceAttributes)
static uint allocate(Object *o, bool doubleSlot=false)
static bool put(Object *o, uint index, const Value &value)
static void push_front(Object *o, const Value *values, uint n)
static bool del(Object *o, uint index)
static ReturnedValue get(const Heap::ArrayData *d, uint index)
static void setAttribute(Object *o, uint index, PropertyAttributes attrs)
static void free(Heap::ArrayData *d, uint idx)
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
QV4_NEARLY_ALWAYS_INLINE constexpr void setEmpty()
bool isFunctionObject() const
static constexpr Value fromReturnedValue(ReturnedValue val)
static constexpr Value emptyValue()