diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 100 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4internalclass_p.h | 39 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata.cpp | 5 |
3 files changed, 124 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index c890dc0550..b22d3073b9 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -137,14 +137,83 @@ void PropertyHash::detach(bool grow, int classSize) d = dd; } + +SharedInternalClassDataPrivate<PropertyKey>::SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyKey> &other) + : refcount(1), + engine(other.engine), + data(nullptr) +{ + if (other.alloc()) { + int s = other.size(); + data = MemberData::allocate(engine, other.alloc(), other.data); + setSize(s); + } +} + +SharedInternalClassDataPrivate<PropertyKey>::SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyKey> &other, + uint pos, PropertyKey value) + : refcount(1), + engine(other.engine) +{ + data = MemberData::allocate(engine, other.alloc(), nullptr); + memcpy(data, other.data, sizeof(Heap::MemberData) - sizeof(Value) + pos*sizeof(Value)); + data->values.size = pos + 1; + data->values.set(engine, pos, Value::fromReturnedValue(value.id())); +} + +void SharedInternalClassDataPrivate<PropertyKey>::grow() +{ + uint a = alloc() * 2; + int s = size(); + data = MemberData::allocate(engine, a, data); + setSize(s); + Q_ASSERT(alloc() >= a); +} + +uint SharedInternalClassDataPrivate<PropertyKey>::alloc() const +{ + return data ? data->values.alloc : 0; +} + +uint SharedInternalClassDataPrivate<PropertyKey>::size() const +{ + return data ? data->values.size : 0; +} + +void SharedInternalClassDataPrivate<PropertyKey>::setSize(uint s) +{ + Q_ASSERT(data && s <= alloc()); + data->values.size = s; +} + +PropertyKey SharedInternalClassDataPrivate<PropertyKey>::at(uint i) +{ + Q_ASSERT(data && i < size()); + return PropertyKey::fromId(data->values.values[i].rawValue()); +} + +void SharedInternalClassDataPrivate<PropertyKey>::set(uint i, PropertyKey t) +{ + Q_ASSERT(data && i < size()); + data->values.values[i].rawValueRef() = t.id(); +} + +void SharedInternalClassDataPrivate<PropertyKey>::mark(MarkStack *s) +{ + if (data) + data->mark(s); +} + + + namespace Heap { void InternalClass::init(ExecutionEngine *engine) { Base::init(); new (&propertyTable) PropertyHash(); - new (&nameMap) SharedInternalClassData<PropertyKey>(); - new (&propertyData) SharedInternalClassData<PropertyAttributes>(); + new (&nameMap) SharedInternalClassData<PropertyKey>(engine); + new (&propertyData) SharedInternalClassData<PropertyAttributes>(engine); new (&transitions) std::vector<Transition>(); this->engine = engine; @@ -204,6 +273,11 @@ void InternalClass::destroy() Base::destroy(); } +QString InternalClass::keyAt(uint index) const +{ + return nameMap.at(index).toQString(); +} + static void insertHoleIntoPropertyData(QV4::Object *object, int idx) { Heap::Object *o = object->d(); @@ -288,8 +362,8 @@ Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, Propert if (data.isAccessor() != propertyData.at(idx).isAccessor()) { // this changes the layout of the class, so we need to rebuild the data newClass->propertyTable = PropertyHash(); - newClass->nameMap = SharedInternalClassData<PropertyKey>(); - newClass->propertyData = SharedInternalClassData<PropertyAttributes>(); + newClass->nameMap = SharedInternalClassData<PropertyKey>(engine); + newClass->propertyData = SharedInternalClassData<PropertyAttributes>(engine); newClass->size = 0; for (uint i = 0; i < size; ++i) { PropertyKey identifier = nameMap.at(i); @@ -423,7 +497,9 @@ Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, Proper return t.lookup; // create a new class and add it to the tree - Heap::InternalClass *newClass = engine->newClass(this); + Scope scope(engine); + Scoped<QV4::InternalClass> ic(scope, engine->newClass(this)); + InternalClass *newClass = ic->d(); PropertyHash::Entry e = { identifier, newClass->size }; newClass->propertyTable.addEntry(e, newClass->size); @@ -504,7 +580,9 @@ Heap::InternalClass *InternalClass::sealed() return t.lookup; } - Heap::InternalClass *s = engine->newClass(this); + Scope scope(engine); + Scoped<QV4::InternalClass> ic(scope, engine->newClass(this)); + Heap::InternalClass *s = ic->d(); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); @@ -550,7 +628,9 @@ Heap::InternalClass *InternalClass::frozen() return t.lookup; } - Heap::InternalClass *f = engine->newClass(this); + Scope scope(engine); + Scoped<QV4::InternalClass> ic(scope, engine->newClass(this)); + Heap::InternalClass *f = ic->d(); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); @@ -631,11 +711,7 @@ void InternalClass::markObjects(Heap::Base *b, MarkStack *stack) if (ic->parent) ic->parent->mark(stack); - for (uint i = 0; i < ic->size; ++i) { - PropertyKey id = ic->nameMap.at(i); - if (Heap::Base *b = id.asStringOrSymbol()) - b->mark(stack); - } + ic->nameMap.mark(stack); } } diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 8bf83d87b4..cb45343d6d 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -143,7 +143,7 @@ inline uint PropertyHash::lookup(PropertyKey identifier) const template<typename T> struct SharedInternalClassDataPrivate { - SharedInternalClassDataPrivate() + SharedInternalClassDataPrivate(ExecutionEngine *) : refcount(1), m_alloc(0), m_size(0), @@ -159,7 +159,7 @@ struct SharedInternalClassDataPrivate { memcpy(data, other.data, m_size*sizeof(T)); } } - SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, int pos, T value) + SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, T value) : refcount(1), m_alloc(pos + 8), m_size(pos + 1) @@ -191,21 +191,45 @@ struct SharedInternalClassDataPrivate { T at(uint i) { Q_ASSERT(data && i < m_alloc); return data[i]; } void set(uint i, T t) { Q_ASSERT(data && i < m_alloc); data[i] = t; } - int refcount; + void mark(MarkStack *) {} + + int refcount = 1; private: uint m_alloc; uint m_size; T *data; }; +template<> +struct SharedInternalClassDataPrivate<PropertyKey> { + SharedInternalClassDataPrivate(ExecutionEngine *e) : refcount(1), engine(e), data(nullptr) {} + SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other); + SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, PropertyKey value); + ~SharedInternalClassDataPrivate() {} + + void grow(); + uint alloc() const; + uint size() const; + void setSize(uint s); + + PropertyKey at(uint i); + void set(uint i, PropertyKey t); + + void mark(MarkStack *s); + + int refcount = 1; +private: + ExecutionEngine *engine; + Heap::MemberData *data; +}; template <typename T> struct SharedInternalClassData { using Private = SharedInternalClassDataPrivate<T>; Private *d; - inline SharedInternalClassData() { - d = new Private; + inline SharedInternalClassData(ExecutionEngine *e) { + d = new Private(e); } inline SharedInternalClassData(const SharedInternalClassData &other) @@ -238,8 +262,8 @@ struct SharedInternalClassData { Q_ASSERT(pos == d->size()); if (pos == d->alloc()) d->grow(); - d->set(pos, value); d->setSize(d->size() + 1); + d->set(pos, value); } void set(uint pos, T value) { @@ -262,6 +286,8 @@ struct SharedInternalClassData { Q_ASSERT(i < d->size()); return d->at(i); } + + void mark(MarkStack *s) { d->mark(s); } }; struct InternalClassTransition @@ -318,6 +344,7 @@ struct InternalClass : Base { void init(InternalClass *other); void destroy(); + Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const; Q_REQUIRED_RESULT InternalClass *nonExtensible(); static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index); diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index da086bd47a..246f857643 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -62,8 +62,9 @@ static size_t nextPowerOfTwo(size_t s) Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old) { - Q_ASSERT(!old || old->values.size < n); - Q_ASSERT(n); + Q_ASSERT(!old || old->values.size <= n); + if (!n) + n = 4; size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); // round up to next power of two to avoid quadratic behaviour for very large objects |