diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-05-15 09:56:05 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-05-19 06:23:29 +0000 |
commit | afbb57ae84ecbee5fab9eb6e58356b19d7995ea5 (patch) | |
tree | 33418ab6f9507c238998c61fdd818cb8823db71a /src/qml/jsruntime/qv4internalclass.cpp | |
parent | cae7975a036352ca4bbcf1381a445362f8e01367 (diff) |
Move the prototype into the internal class
This saves another pointer on all Objects.
Currently introduces a slight performance regression
on some of the v8 benchmarks, that needs addressing.
Change-Id: I87de8e1d198d2683f4e903c467ce2a60ba542243
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4internalclass.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 9a4087485f..600198567a 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -106,6 +106,7 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize) InternalClass::InternalClass(ExecutionEngine *engine) : engine(engine) , vtable(0) + , prototype(0) , m_sealed(0) , m_frozen(0) , size(0) @@ -118,6 +119,7 @@ InternalClass::InternalClass(const QV4::InternalClass &other) : QQmlJS::Managed() , engine(other.engine) , vtable(other.vtable) + , prototype(other.prototype) , propertyTable(other.propertyTable) , nameMap(other.nameMap) , propertyData(other.propertyData) @@ -223,6 +225,7 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri // create a new class and add it to the tree InternalClass *newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); + newClass = newClass->changePrototype(prototype); for (uint i = 0; i < size; ++i) { if (i == idx) { newClass = newClass->addMember(nameMap.at(i), data); @@ -236,6 +239,35 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri return newClass; } +InternalClass *InternalClass::changePrototypeImpl(Heap::Object *proto) +{ + Q_ASSERT(prototype != proto); + + Transition temp = { { nullptr }, 0, Transition::PrototypeChange }; + temp.prototype = proto; + + Transition &t = lookupOrInsertTransition(temp); + if (t.lookup) + return t.lookup; + + // create a new class and add it to the tree + InternalClass *newClass; + if (!size && !prototype) { + newClass = engine->newClass(*this); + newClass->prototype = proto; + } else { + newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); + newClass = newClass->changePrototype(proto); + for (uint i = 0; i < size; ++i) { + if (!propertyData.at(i).isEmpty()) + newClass = newClass->addMember(nameMap.at(i), propertyData.at(i)); + } + } + + t.lookup = newClass; + return newClass; +} + InternalClass *InternalClass::changeVTableImpl(const VTable *vt) { Q_ASSERT(vtable != vt); @@ -366,6 +398,7 @@ void InternalClass::removeMember(Object *object, Identifier *id) } else { // create a new class and add it to the tree InternalClass *newClass = oldClass->engine->internalClasses[EngineBase::Class_Empty]->changeVTable(oldClass->vtable); + newClass = newClass->changePrototype(oldClass->prototype); for (uint i = 0; i < oldClass->size; ++i) { if (i == propIdx) continue; @@ -411,6 +444,7 @@ InternalClass *InternalClass::sealed() return m_sealed; m_sealed = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); + m_sealed = m_sealed->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (attrs.isEmpty()) @@ -440,6 +474,7 @@ InternalClass *InternalClass::frozen() InternalClass *InternalClass::propertiesFrozen() const { InternalClass *frozen = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable); + frozen = frozen->changePrototype(prototype); for (uint i = 0; i < size; ++i) { PropertyAttributes attrs = propertyData.at(i); if (attrs.isEmpty()) @@ -480,9 +515,25 @@ void InternalClass::destroy() } } +void InternalClass::mark(ExecutionEngine *e) +{ + if (m_sealed) + m_sealed->mark(e); + if (m_frozen) + m_frozen->mark(e); + + for (size_t i = 0; i < transitions.size(); ++i) { + Q_ASSERT(transitions.at(i).lookup); + transitions.at(i).lookup->mark(e); + } + if (prototype) + prototype->mark(engine); +} + void InternalClassPool::markObjects(ExecutionEngine *engine) { - Q_UNUSED(engine); + InternalClass *ic = engine->internalClasses[EngineBase::Class_Empty]; + ic->mark(engine); } QT_END_NAMESPACE |