aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4internalclass.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-05-15 09:56:05 +0200
committerLars Knoll <lars.knoll@qt.io>2017-05-19 06:23:29 +0000
commitafbb57ae84ecbee5fab9eb6e58356b19d7995ea5 (patch)
tree33418ab6f9507c238998c61fdd818cb8823db71a /src/qml/jsruntime/qv4internalclass.cpp
parentcae7975a036352ca4bbcf1381a445362f8e01367 (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.cpp53
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