diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-03-06 10:13:26 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-07 21:15:58 +0100 |
commit | 19cd5c46693a287c08025c01ded8eaf140e21317 (patch) | |
tree | c24bb7cc6cb0a3bfcd957e1c654c45b1a67f73ab /src/qml/jsruntime/qv4internalclass.cpp | |
parent | 6a0d0c8f7eff456b7ad6ad7609275410cb8d8f1c (diff) |
Reserve a double slot for accessor properties
Reserve two slots in the internal class for accessor
properties. This opens up reducing the default storage
required per data property to one Value. In practice
this implies cutting the required memory in half.
Change-Id: Ifed897852bbdfd810018f0d6b049fca6690ead2c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime/qv4internalclass.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 127 |
1 files changed, 95 insertions, 32 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 761a180722..7c4a8de284 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -151,33 +151,53 @@ InternalClass::InternalClass(const QV4::InternalClass &other) { } -// ### Should we build this up from the empty class to avoid duplication? +void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) +{ + uint idx; + InternalClass *newClass = object->internalClass->changeMember(string, data, &idx); + if (index) + *index = idx; + + if (newClass->size > object->internalClass->size) { + Q_ASSERT(newClass->size == object->internalClass->size + 1); + memmove(object->memberData + idx + 2, object->memberData + idx + 1, (object->internalClass->size - idx - 1)*sizeof(Property)); + } else if (newClass->size < object->internalClass->size) { + Q_ASSERT(newClass->size == object->internalClass->size - 1); + memmove(object->memberData + idx + 1, object->memberData + idx + 2, (object->internalClass->size - idx - 2)*sizeof(Property)); + } + object->internalClass = newClass; +} + InternalClass *InternalClass::changeMember(String *string, PropertyAttributes data, uint *index) { -// qDebug() << "InternalClass::changeMember()" << string->toQString() << hex << (uint)data.m_all; data.resolve(); uint idx = find(string); + Q_ASSERT(idx != UINT_MAX); + if (index) *index = idx; - Q_ASSERT(idx != UINT_MAX); - if (data == propertyData.at(idx)) return this; - Transition t = { { string->identifier }, (int)data.flags() }; QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t); if (tit != transitions.constEnd()) return tit.value(); // create a new class and add it to the tree - InternalClass *newClass = engine->newClass(*this); - newClass->propertyData.set(idx, data); + InternalClass *newClass = engine->emptyClass->changeVTable(vtable); + newClass = newClass->changePrototype(prototype); + for (uint i = 0; i < size; ++i) { + if (i == idx) { + newClass = newClass->addMember(nameMap.at(i), data); + } else if (!propertyData.at(i).isEmpty()) { + newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + } + } transitions.insert(t, newClass); return newClass; - } InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto) @@ -209,8 +229,10 @@ InternalClass *InternalClass::changePrototype(Object *proto) } else { newClass = engine->emptyClass->changeVTable(vtable); newClass = newClass->changePrototype(proto); - for (uint i = 0; i < size; ++i) - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + for (uint i = 0; i < size; ++i) { + if (!propertyData.at(i).isEmpty()) + newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + } } transitions.insert(t, newClass); @@ -238,14 +260,39 @@ InternalClass *InternalClass::changeVTable(const ManagedVTable *vt) } else { newClass = engine->emptyClass->changeVTable(vt); newClass = newClass->changePrototype(prototype); - for (uint i = 0; i < size; ++i) - newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + for (uint i = 0; i < size; ++i) { + if (!propertyData.at(i).isEmpty()) + newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + } } transitions.insert(t, newClass); return newClass; } +void InternalClass::addMember(Object *object, StringRef string, PropertyAttributes data, uint *index) +{ + return addMember(object, string.getPointer(), data, index); +} + +void InternalClass::addMember(Object *object, String *string, PropertyAttributes data, uint *index) +{ + data.resolve(); + object->internalClass->engine->identifierTable->identifier(string); + if (object->internalClass->propertyTable.lookup(string->identifier) < object->internalClass->size) { + changeMember(object, string, data, index); + return; + } + + uint idx; + InternalClass *newClass = object->internalClass->addMemberImpl(string, data, &idx); + if (index) + *index = idx; + + object->internalClass = newClass; +} + + InternalClass *InternalClass::addMember(StringRef string, PropertyAttributes data, uint *index) { return addMember(string.getPointer(), data, index); @@ -253,13 +300,17 @@ InternalClass *InternalClass::addMember(StringRef string, PropertyAttributes dat InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index) { -// qDebug() << "InternalClass::addMember()" << string->toQString() << size << hex << (uint)data.m_all << data.type(); data.resolve(); engine->identifierTable->identifier(string); if (propertyTable.lookup(string->identifier) < size) return changeMember(string, data, index); + return addMemberImpl(string, data, index); +} + +InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes data, uint *index) +{ Transition t = { { string->identifier }, (int)data.flags() }; QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t); @@ -270,44 +321,56 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, // create a new class and add it to the tree InternalClass *newClass = engine->newClass(*this); - PropertyHash::Entry e = { string->identifier, size }; - newClass->propertyTable.addEntry(e, size); + PropertyHash::Entry e = { string->identifier, newClass->size }; + newClass->propertyTable.addEntry(e, newClass->size); // The incoming string can come from anywhere, so make sure to // store a string in the nameMap that's guaranteed to get // marked properly during GC. String *name = engine->newIdentifier(string->toQString()); - newClass->nameMap.add(size, name); - - newClass->propertyData.add(size, data); + newClass->nameMap.add(newClass->size, name); + newClass->propertyData.add(newClass->size, data); ++newClass->size; + if (data.isAccessor()) { + // add a dummy entry, since we need two entries for accessors + newClass->propertyTable.addEntry(e, newClass->size); + newClass->nameMap.add(newClass->size, 0); + newClass->propertyData.add(newClass->size, PropertyAttributes()); + ++newClass->size; + } + transitions.insert(t, newClass); return newClass; } void InternalClass::removeMember(Object *object, Identifier *id) { - uint propIdx = propertyTable.lookup(id); - Q_ASSERT(propIdx < size); + InternalClass *oldClass = object->internalClass; + uint propIdx = oldClass->propertyTable.lookup(id); + Q_ASSERT(propIdx < oldClass->size); Transition t = { { id } , -1 }; - QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t); + QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass->transitions.constFind(t); - if (tit != transitions.constEnd()) { + if (tit != object->internalClass->transitions.constEnd()) { object->internalClass = tit.value(); - return; + } else { + // create a new class and add it to the tree + InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable); + newClass = newClass->changePrototype(oldClass->prototype); + for (uint i = 0; i < oldClass->size; ++i) { + if (i == propIdx) + continue; + if (!oldClass->propertyData.at(i).isEmpty()) + newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i)); + } + object->internalClass = newClass; } - // create a new class and add it to the tree - object->internalClass = engine->emptyClass->changeVTable(vtable); - object->internalClass = object->internalClass->changePrototype(prototype); - for (uint i = 0; i < size; ++i) { - if (i == propIdx) - continue; - object->internalClass = object->internalClass->addMember(nameMap.at(i), propertyData.at(i)); - } + // remove the entry in memberdata + memmove(object->memberData + propIdx, object->memberData + propIdx + 1, (object->internalClass->size - propIdx)*sizeof(Property)); - transitions.insert(t, object->internalClass); + oldClass->transitions.insert(t, object->internalClass); } uint InternalClass::find(const StringRef string) |