aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-05-12 15:04:53 +0200
committerLars Knoll <lars.knoll@qt.io>2017-05-19 06:23:23 +0000
commit0cdea188727e203ecc529ef8e4e8859cca0be232 (patch)
tree88866951fb97d1c7132922b60e052f496cdd4b52 /src/qml
parentcdbc4b83d59e08189d6ece9ccd88a646be155c08 (diff)
Add support for storing the Vtable in the InternalClass
Prepare for moving the vtable pointer into the internalClass. This adds the required infrastructure to InternalClass, so it can store a vtable pointer and properly handles vtable changes. Change-Id: I688fee1647268dd185d0f9636ab5b3390465daca Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp52
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h32
2 files changed, 59 insertions, 25 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index f310b6f551..e117da1a04 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -105,6 +105,7 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
InternalClass::InternalClass(ExecutionEngine *engine)
: engine(engine)
+ , vtable(0)
, m_sealed(0)
, m_frozen(0)
, size(0)
@@ -116,6 +117,7 @@ InternalClass::InternalClass(ExecutionEngine *engine)
InternalClass::InternalClass(const QV4::InternalClass &other)
: QQmlJS::Managed()
, engine(other.engine)
+ , vtable(other.vtable)
, propertyTable(other.propertyTable)
, nameMap(other.nameMap)
, propertyData(other.propertyData)
@@ -214,13 +216,13 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri
if (data == propertyData.at(idx))
return this;
- Transition temp = { identifier, 0, (int)data.flags() };
+ Transition temp = { { identifier }, nullptr, (int)data.flags() };
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup)
return t.lookup;
// create a new class and add it to the tree
- InternalClass *newClass = engine->internalClasses[EngineBase::Class_Empty];
+ InternalClass *newClass = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
for (uint i = 0; i < size; ++i) {
if (i == idx) {
newClass = newClass->addMember(nameMap.at(i), data);
@@ -234,12 +236,34 @@ InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttri
return newClass;
}
+InternalClass *InternalClass::changeVTableImpl(const VTable *vt)
+{
+ Q_ASSERT(vtable != vt);
+
+ Transition temp = { { nullptr }, nullptr, Transition::VTableChange };
+ temp.vtable = vt;
+
+ Transition &t = lookupOrInsertTransition(temp);
+ if (t.lookup)
+ return t.lookup;
+
+ // create a new class and add it to the tree
+ InternalClass *newClass;
+ newClass = engine->newClass(*this);
+ newClass->vtable = vt;
+
+ t.lookup = newClass;
+ Q_ASSERT(t.lookup);
+ Q_ASSERT(newClass->vtable);
+ return newClass;
+}
+
InternalClass *InternalClass::nonExtensible()
{
if (!extensible)
return this;
- Transition temp = { Q_NULLPTR, Q_NULLPTR, Transition::NotExtensible};
+ Transition temp = { { nullptr }, nullptr, Transition::NotExtensible};
Transition &t = lookupOrInsertTransition(temp);
if (t.lookup)
return t.lookup;
@@ -287,7 +311,7 @@ InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttribut
InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index)
{
- Transition temp = { identifier, 0, (int)data.flags() };
+ Transition temp = { { identifier }, nullptr, (int)data.flags() };
Transition &t = lookupOrInsertTransition(temp);
if (index)
@@ -323,7 +347,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
uint propIdx = oldClass->propertyTable.lookup(id);
Q_ASSERT(propIdx < oldClass->size);
- Transition temp = { id, 0, -1 };
+ Transition temp = { { id }, nullptr, -1 };
Transition &t = object->internalClass()->lookupOrInsertTransition(temp);
bool accessor = oldClass->propertyData.at(propIdx).isAccessor();
@@ -332,7 +356,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
object->setInternalClass(t.lookup);
} else {
// create a new class and add it to the tree
- InternalClass *newClass = oldClass->engine->internalClasses[EngineBase::Class_Empty];
+ InternalClass *newClass = oldClass->engine->internalClasses[EngineBase::Class_Empty]->changeVTable(oldClass->vtable);
for (uint i = 0; i < oldClass->size; ++i) {
if (i == propIdx)
continue;
@@ -351,6 +375,18 @@ void InternalClass::removeMember(Object *object, Identifier *id)
Q_ASSERT(t.lookup);
}
+uint QV4::InternalClass::find(const String *string)
+{
+ engine->identifierTable->identifier(string);
+ const Identifier *id = string->d()->identifier;
+
+ uint index = propertyTable.lookup(id);
+ if (index < size)
+ return index;
+
+ return UINT_MAX;
+}
+
uint InternalClass::find(const Identifier *id)
{
uint index = propertyTable.lookup(id);
@@ -365,7 +401,7 @@ InternalClass *InternalClass::sealed()
if (m_sealed)
return m_sealed;
- m_sealed = engine->internalClasses[EngineBase::Class_Empty];
+ m_sealed = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
@@ -394,7 +430,7 @@ InternalClass *InternalClass::frozen()
InternalClass *InternalClass::propertiesFrozen() const
{
- InternalClass *frozen = engine->internalClasses[EngineBase::Class_Empty];
+ InternalClass *frozen = engine->internalClasses[EngineBase::Class_Empty]->changeVTable(vtable);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 1d8ef4b0fb..c68a6638e7 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -54,15 +54,13 @@
#include <QHash>
#include <private/qqmljsmemorypool_p.h>
-#include <private/qv4engine_p.h>
-#include <private/qv4identifiertable_p.h>
+#include <private/qv4identifier_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
struct String;
-struct ExecutionEngine;
struct Object;
struct Identifier;
struct VTable;
@@ -222,12 +220,16 @@ private:
struct InternalClassTransition
{
- Identifier *id;
+ union {
+ Identifier *id;
+ const VTable *vtable;
+ };
InternalClass *lookup;
int flags;
enum {
// range 0-0xff is reserved for attribute changes
- NotExtensible = 0x100
+ NotExtensible = 0x100,
+ VTableChange = 0x200,
};
bool operator==(const InternalClassTransition &other) const
@@ -239,6 +241,7 @@ struct InternalClassTransition
struct InternalClass : public QQmlJS::Managed {
ExecutionEngine *engine;
+ const VTable *vtable;
PropertyHash propertyTable; // id to valueIndex
SharedInternalClassData<Identifier *> nameMap;
@@ -255,6 +258,12 @@ struct InternalClass : public QQmlJS::Managed {
bool extensible;
InternalClass *nonExtensible();
+ InternalClass *changeVTable(const VTable *vt) {
+ if (vtable == vt)
+ return this;
+ return changeVTableImpl(vt);
+ }
+
static void addMember(Object *object, String *string, PropertyAttributes data, uint *index);
InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = 0);
@@ -271,24 +280,13 @@ struct InternalClass : public QQmlJS::Managed {
void destroy();
private:
+ InternalClass *changeVTableImpl(const VTable *vt);
InternalClass *addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index);
friend struct ExecutionEngine;
InternalClass(ExecutionEngine *engine);
InternalClass(const InternalClass &other);
};
-inline uint InternalClass::find(const String *string)
-{
- engine->identifierTable->identifier(string);
- const Identifier *id = string->d()->identifier;
-
- uint index = propertyTable.lookup(id);
- if (index < size)
- return index;
-
- return UINT_MAX;
-}
-
struct InternalClassPool : public QQmlJS::MemoryPool
{
void markObjects(ExecutionEngine *engine);