aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4internalclass.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2014-03-06 10:13:26 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-07 21:15:58 +0100
commit19cd5c46693a287c08025c01ded8eaf140e21317 (patch)
treec24bb7cc6cb0a3bfcd957e1c654c45b1a67f73ab /src/qml/jsruntime/qv4internalclass.cpp
parent6a0d0c8f7eff456b7ad6ad7609275410cb8d8f1c (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.cpp127
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)