aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-23 15:46:25 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-27 08:33:59 +0000
commit7cc66a996e70c52bc274ae9f15f65e8a638894d9 (patch)
tree6b493e26e775db2c6ef5b3c22a031e8dbaad01d0 /src/qml
parentf63d48d474db7e9eff7583f1b8478228b13d3c82 (diff)
Get rid of remaining assumptions about setter being next to getters
The only place where we now assume that getters and setters are next to each other in the MemberData is in the internal class. Change-Id: I3285f3abb1cbfe051853e808339cd360eb602262 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h3
-rw-r--r--src/qml/jsruntime/qv4engine.cpp60
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp6
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h1
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp46
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h30
-rw-r--r--src/qml/jsruntime/qv4managed_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp88
-rw-r--r--src/qml/jsruntime/qv4object_p.h6
10 files changed, 136 insertions, 111 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 43aa2e931e..c9281ee194 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -59,10 +59,11 @@ void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame)
Object::init();
Q_ASSERT(internalClass->verifyIndex(v4->id_callee()->propertyKey(), CalleePropertyIndex));
+ Q_ASSERT(internalClass->findValueOrSetter(v4->id_callee()->propertyKey()).index == CalleeSetterPropertyIndex);
Q_ASSERT(internalClass->verifyIndex(v4->symbol_iterator()->propertyKey(), SymbolIteratorPropertyIndex));
setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
setProperty(v4, CalleePropertyIndex, *v4->thrower());
- setProperty(v4, CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower());
+ setProperty(v4, CalleeSetterPropertyIndex, *v4->thrower());
Scope scope(v4);
Scoped<QV4::StrictArgumentsObject> args(scope, this);
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index e1aeae6034..f668fb3208 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -82,7 +82,8 @@ DECLARE_HEAP_OBJECT(StrictArgumentsObject, Object) {
enum {
LengthPropertyIndex = 0,
SymbolIteratorPropertyIndex = 1,
- CalleePropertyIndex = 2
+ CalleePropertyIndex = 2,
+ CalleeSetterPropertyIndex = 3
};
void init(CppStackFrame *frame);
};
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index dc5f80df7b..4c1e660429 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -341,15 +341,20 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
jsObjects[BooleanProto] = memoryManager->allocate<BooleanPrototype>();
jsObjects[DateProto] = memoryManager->allocate<DatePrototype>();
- uint index;
+#ifdef QT_NO_DEBUG
+ InternalClassEntry *index = nullptr;
+#else
+ InternalClassEntry _index;
+ auto *index = &_index;
+#endif
ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic->d());
ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
classes[Class_FunctionObject] = ic->d();
- ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, &index);
- Q_ASSERT(index == Heap::ArrowFunction::Index_Name);
- ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, &index);
- Q_ASSERT(index == Heap::ArrowFunction::Index_Length);
+ ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, index);
+ Q_ASSERT(index->index == Heap::ArrowFunction::Index_Name);
+ ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, index);
+ Q_ASSERT(index->index == Heap::ArrowFunction::Index_Length);
classes[Class_ArrowFunction] = ic->changeVTable(ArrowFunction::staticVTable());
ic = ic->changeVTable(ScriptFunction::staticVTable());
classes[Class_ScriptFunction] = ic->d();
@@ -363,8 +368,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
classes[Class_GeneratorFunction] = ic->d();
ic = ic->changeVTable(MemberGeneratorFunction::staticVTable());
classes[Class_MemberGeneratorFunction] = ic->d();
- classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor()->propertyKey(), Attr_NotEnumerable, &index);
- Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
+ classes[Class_ObjectProto] = classes[Class_Object]->addMember(id_constructor()->propertyKey(), Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == Heap::FunctionObject::Index_ProtoConstructor);
jsObjects[GeneratorProto] = memoryManager->allocObject<GeneratorPrototype>(classes[Class_Object]);
classes[Class_GeneratorObject] = newInternalClass(QV4::GeneratorObject::staticVTable(), generatorPrototype());
@@ -372,33 +377,34 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
ScopedString str(scope);
classes[Class_RegExp] = classes[Class_Empty]->changeVTable(QV4::RegExp::staticVTable());
ic = newInternalClass(QV4::RegExpObject::staticVTable(), objectPrototype());
- ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
- Q_ASSERT(index == RegExpObject::Index_LastIndex);
+ ic = ic->addMember(id_lastIndex()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, index);
+ Q_ASSERT(index->index == RegExpObject::Index_LastIndex);
jsObjects[RegExpProto] = memoryManager->allocObject<RegExpPrototype>(classes[Class_Object]);
classes[Class_RegExpObject] = ic->changePrototype(regExpPrototype()->d());
- ic = classes[Class_ArrayObject]->addMember(id_index()->propertyKey(), Attr_Data, &index);
- Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
- classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, &index);
- Q_ASSERT(index == RegExpObject::Index_ArrayInput);
+ ic = classes[Class_ArrayObject]->addMember(id_index()->propertyKey(), Attr_Data, index);
+ Q_ASSERT(index->index == RegExpObject::Index_ArrayIndex);
+ classes[Class_RegExpExecArray] = ic->addMember(id_input()->propertyKey(), Attr_Data, index);
+ Q_ASSERT(index->index == RegExpObject::Index_ArrayInput);
ic = newInternalClass(ErrorObject::staticVTable(), nullptr);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorObject::Index_Stack);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorObject::Index_FileName);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("stack")))->propertyKey(), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorObject::Index_Stack);
+ Q_ASSERT(index->setterIndex == ErrorObject::Index_StackSetter);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("fileName")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorObject::Index_FileName);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("lineNumber")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
classes[Class_ErrorObject] = ic->d();
- Q_ASSERT(index == ErrorObject::Index_LineNumber);
- classes[Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorObject::Index_Message);
+ Q_ASSERT(index->index == ErrorObject::Index_LineNumber);
+ classes[Class_ErrorObjectWithMessage] = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorObject::Index_Message);
ic = newInternalClass(Object::staticVTable(), objectPrototype());
- ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorPrototype::Index_Constructor);
- ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorPrototype::Index_Message);
- classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, &index);
- Q_ASSERT(index == ErrorPrototype::Index_Name);
+ ic = ic->addMember(id_constructor()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorPrototype::Index_Constructor);
+ ic = ic->addMember((str = newIdentifier(QStringLiteral("message")))->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorPrototype::Index_Message);
+ classes[Class_ErrorProto] = ic->addMember(id_name()->propertyKey(), Attr_Data|Attr_NotEnumerable, index);
+ Q_ASSERT(index->index == ErrorPrototype::Index_Name);
classes[Class_ProxyObject] = classes[Class_Empty]->changeVTable(ProxyObject::staticVTable());
classes[Class_ProxyFunctionObject] = classes[Class_Empty]->changeVTable(ProxyFunctionObject::staticVTable());
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index eb246478c5..c6d6c77d11 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -74,7 +74,7 @@ void Heap::ErrorObject::init()
return;
setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
- setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Value::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_StackSetter, Value::undefinedValue());
setProperty(scope.engine, QV4::ErrorObject::Index_FileName, Value::undefinedValue());
setProperty(scope.engine, QV4::ErrorObject::Index_LineNumber, Value::undefinedValue());
}
@@ -88,7 +88,7 @@ void Heap::ErrorObject::init(const Value &message, ErrorType t)
Scoped<QV4::ErrorObject> e(scope, this);
setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
- setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Value::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_StackSetter, Value::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
if (!e->d()->stackTrace->isEmpty()) {
@@ -110,7 +110,7 @@ void Heap::ErrorObject::init(const Value &message, const QString &fileName, int
Scoped<QV4::ErrorObject> e(scope, this);
setProperty(scope.engine, QV4::ErrorObject::Index_Stack, scope.engine->getStackFunction()->d());
- setProperty(scope.engine, QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset, Value::undefinedValue());
+ setProperty(scope.engine, QV4::ErrorObject::Index_StackSetter, Value::undefinedValue());
e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
StackFrame frame;
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index bce7e4abad..139bcc9754 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -153,6 +153,7 @@ struct ErrorObject: Object {
enum {
Index_Stack = 0, // Accessor Property
+ Index_StackSetter = 1, // Accessor Property
Index_FileName = 2,
Index_LineNumber = 3,
Index_Message = 4
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index bd037ef8a6..7096c1b591 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -299,24 +299,24 @@ static void removeFromPropertyData(QV4::Object *object, int idx, bool accessor =
o->setProperty(v4, size + 1, Value::undefinedValue());
}
-void InternalClass::changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index)
+void InternalClass::changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
{
Q_ASSERT(id.isStringOrSymbol());
- uint idx;
+ InternalClassEntry idx;
Heap::InternalClass *oldClass = object->internalClass();
Heap::InternalClass *newClass = oldClass->changeMember(id, data, &idx);
- if (index)
- *index = idx;
+ if (entry)
+ *entry = idx;
uint oldSize = oldClass->size;
object->setInternalClass(newClass);
// don't use oldClass anymore, it could be GC'ed
if (newClass->size > oldSize) {
Q_ASSERT(newClass->size == oldSize + 1);
- insertHoleIntoPropertyData(object, idx);
+ insertHoleIntoPropertyData(object, idx.setterIndex - 1);
} else if (newClass->size < oldSize) {
Q_ASSERT(newClass->size == oldSize - 1);
- removeFromPropertyData(object, idx + 1);
+ removeFromPropertyData(object, idx.index + 1);
}
}
@@ -340,15 +340,18 @@ static void addDummyEntry(InternalClass *newClass, PropertyHash::Entry e)
++newClass->size;
}
-Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, PropertyAttributes data, uint *index)
+Heap::InternalClass *InternalClass::changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
{
data.resolve();
PropertyHash::Entry *e = findEntry(identifier);
Q_ASSERT(e && e->index != UINT_MAX);
uint idx = e->index;
- if (index)
- *index = idx;
+ if (entry) {
+ entry->index = idx;
+ entry->setterIndex = data.isAccessor() ? idx + 1 : UINT_MAX;
+ entry->attributes = data;
+ }
if (data == propertyData.at(idx))
return static_cast<Heap::InternalClass *>(this);
@@ -458,43 +461,42 @@ Heap::InternalClass *InternalClass::nonExtensible()
return newClass;
}
-void InternalClass::addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index)
+void InternalClass::addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
{
Q_ASSERT(id.isStringOrSymbol());
data.resolve();
PropertyHash::Entry *e = object->internalClass()->propertyTable.lookup(id);
if (e && e->index < object->internalClass()->size) {
- changeMember(object, id, data, index);
+ changeMember(object, id, data, entry);
return;
}
- uint idx;
- Heap::InternalClass *newClass = object->internalClass()->addMemberImpl(id, data, &idx);
- if (index)
- *index = idx;
-
+ Heap::InternalClass *newClass = object->internalClass()->addMemberImpl(id, data, entry);
object->setInternalClass(newClass);
}
-Heap::InternalClass *InternalClass::addMember(PropertyKey identifier, PropertyAttributes data, uint *index)
+Heap::InternalClass *InternalClass::addMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
{
Q_ASSERT(identifier.isStringOrSymbol());
data.resolve();
PropertyHash::Entry *e = propertyTable.lookup(identifier);
if (e && e->index < size)
- return changeMember(identifier, data, index);
+ return changeMember(identifier, data, entry);
- return addMemberImpl(identifier, data, index);
+ return addMemberImpl(identifier, data, entry);
}
-Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, PropertyAttributes data, uint *index)
+Heap::InternalClass *InternalClass::addMemberImpl(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry)
{
Transition temp = { { identifier }, nullptr, (int)data.flags() };
Transition &t = lookupOrInsertTransition(temp);
- if (index)
- *index = size;
+ if (entry) {
+ entry->index = size;
+ entry->setterIndex = data.isAccessor() ? size + 1 : UINT_MAX;
+ entry->attributes = data;
+ }
if (t.lookup)
return t.lookup;
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index cced746568..febc1561f9 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -63,6 +63,13 @@ namespace QV4 {
struct VTable;
struct MarkStack;
+struct InternalClassEntry {
+ uint index;
+ uint setterIndex;
+ PropertyAttributes attributes;
+ bool isValid() const { return !attributes.isEmpty(); }
+};
+
struct PropertyHashData;
struct PropertyHash
{
@@ -347,10 +354,10 @@ struct InternalClass : Base {
Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const;
Q_REQUIRED_RESULT InternalClass *nonExtensible();
- static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index);
- Q_REQUIRED_RESULT InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, uint *index = nullptr);
- Q_REQUIRED_RESULT InternalClass *changeMember(PropertyKey identifier, PropertyAttributes data, uint *index = nullptr);
- static void changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, uint *index = nullptr);
+ static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry);
+ Q_REQUIRED_RESULT InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry = nullptr);
+ Q_REQUIRED_RESULT InternalClass *changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry = nullptr);
+ static void changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry = nullptr);
static void removeMember(QV4::Object *object, PropertyKey identifier);
PropertyHash::Entry *findEntry(const PropertyKey id)
{
@@ -363,6 +370,19 @@ struct InternalClass : Base {
return nullptr;
}
+ InternalClassEntry find(const PropertyKey id)
+ {
+ Q_ASSERT(id.isStringOrSymbol());
+
+ PropertyHash::Entry *e = propertyTable.lookup(id);
+ if (e && e->index < size) {
+ PropertyAttributes a = propertyData.at(e->index);
+ return { e->index, (a.isAccessor() ? e->index + 1 : UINT_MAX), a };
+ }
+
+ return { UINT_MAX, UINT_MAX, Attr_Invalid };
+ }
+
struct IndexAndAttribute {
uint index;
PropertyAttributes attrs;
@@ -439,7 +459,7 @@ struct InternalClass : Base {
private:
Q_QML_EXPORT InternalClass *changeVTableImpl(const VTable *vt);
Q_QML_EXPORT InternalClass *changePrototypeImpl(Heap::Object *proto);
- InternalClass *addMemberImpl(PropertyKey identifier, PropertyAttributes data, uint *index);
+ InternalClass *addMemberImpl(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry);
void removeChildEntry(InternalClass *child);
friend struct ExecutionEngine;
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index cacb262ba7..0ca921b98a 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -229,8 +229,8 @@ struct InternalClass : Managed
Q_REQUIRED_RESULT Heap::InternalClass *changePrototype(Heap::Object *proto) {
return d()->changePrototype(proto);
}
- Q_REQUIRED_RESULT Heap::InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, uint *index = 0) {
- return d()->addMember(identifier, data, index);
+ Q_REQUIRED_RESULT Heap::InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry = nullptr) {
+ return d()->addMember(identifier, data, entry);
}
void operator =(Heap::InternalClass *ic) {
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 855bebff88..b6446d39d1 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -74,19 +74,18 @@ void Object::setInternalClass(Heap::InternalClass *ic)
d()->memberData.set(ic->engine, MemberData::allocate(ic->engine, requiredSize, d()->memberData));
}
-void Object::getProperty(uint index, Property *p, PropertyAttributes *attrs) const
+void Object::getProperty(const InternalClassEntry &entry, Property *p) const
{
- p->value = *propertyData(index);
- *attrs = internalClass()->propertyData.at(index);
- if (attrs->isAccessor())
- p->set = *propertyData(index + SetterOffset);
+ p->value = *propertyData(entry.index);
+ if (entry.attributes.isAccessor())
+ p->set = *propertyData(entry.setterIndex);
}
-void Object::setProperty(uint index, const Property *p)
+void Object::setProperty(const InternalClassEntry &entry, const Property *p)
{
- setProperty(index, p->value);
- if (internalClass()->propertyData.at(index).isAccessor())
- setProperty(index + SetterOffset, p->set);
+ setProperty(entry.index, p->value);
+ if (entry.attributes.isAccessor())
+ setProperty(entry.setterIndex, p->set);
}
void Heap::Object::setUsedAsProto()
@@ -249,16 +248,13 @@ void Heap::Object::markObjects(Heap::Base *b, MarkStack *stack)
void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttributes attributes)
{
- uint idx;
+ InternalClassEntry idx;
PropertyKey key = s->toPropertyKey();
Heap::InternalClass::addMember(this, key, attributes, &idx);
- if (attributes.isAccessor()) {
- setProperty(idx, p->value);
- setProperty(idx + SetterOffset, p->set);
- } else {
- setProperty(idx, p->value);
- }
+ setProperty(idx.index, p->value);
+ if (attributes.isAccessor())
+ setProperty(idx.setterIndex, p->set);
}
void Object::setPrototypeUnchecked(const Object *p)
@@ -367,30 +363,26 @@ PropertyKey ObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, Pr
while (true) {
while (memberIndex < o->internalClass()->size) {
PropertyKey n = o->internalClass()->nameMap.at(memberIndex);
+ ++memberIndex;
if (!n.isStringOrSymbol()) {
// accessor properties have a dummy entry with n == 0
- ++memberIndex;
continue;
}
if (!iterateOverSymbols && n.isSymbol()) {
- ++memberIndex;
continue;
}
if (iterateOverSymbols && !n.isSymbol()) {
- ++memberIndex;
continue;
}
- uint index = memberIndex;
- PropertyAttributes a = o->internalClass()->propertyData[memberIndex];
- ++memberIndex;
+ InternalClassEntry e = o->internalClass()->find(n);
if (pd) {
- pd->value = *o->propertyData(index);
- if (a.isAccessor())
- pd->set = *o->propertyData(index + Object::SetterOffset);
+ pd->value = *o->propertyData(e.index);
+ if (e.attributes.isAccessor())
+ pd->set = *o->propertyData(e.setterIndex);
}
if (attrs)
- *attrs = a;
+ *attrs = e.attributes;
return n;
}
if (iterateOverSymbols)
@@ -598,7 +590,7 @@ bool Object::internalDeleteProperty(PropertyKey id)
return true;
}
-bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs)
+bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, const InternalClassEntry *memberEntry, const Property *p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
@@ -607,9 +599,9 @@ bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, Stri
Scope scope(engine);
ScopedProperty current(scope);
PropertyAttributes cattrs;
- if (member) {
- getProperty(index, current, &cattrs);
- cattrs = internalClass()->propertyData[index];
+ if (memberEntry) {
+ getProperty(*memberEntry, current);
+ cattrs = memberEntry->attributes;
} else if (arrayData()) {
arrayData()->getProperty(index, current, &cattrs);
cattrs = arrayData()->attributes(index);
@@ -640,7 +632,7 @@ bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, Stri
// 9b
cattrs.setType(PropertyAttributes::Accessor);
cattrs.clearWritable();
- if (!member) {
+ if (!memberEntry) {
// need to convert the array and the slot
initSparseArray();
Q_ASSERT(arrayData());
@@ -652,7 +644,7 @@ bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, Stri
// 9c
cattrs.setType(PropertyAttributes::Data);
cattrs.setWritable(false);
- if (!member) {
+ if (!memberEntry) {
// need to convert the array and the slot
setArrayAttributes(index, cattrs);
}
@@ -676,9 +668,11 @@ bool Object::internalDefineOwnProperty(ExecutionEngine *engine, uint index, Stri
accept:
current->merge(cattrs, p, attrs);
- if (member) {
- Heap::InternalClass::changeMember(this, member->propertyKey(), cattrs);
- setProperty(index, current);
+ if (memberEntry) {
+ PropertyKey key = internalClass()->nameMap.at(memberEntry->index);
+ InternalClassEntry e;
+ Heap::InternalClass::changeMember(this, key, cattrs, &e);
+ setProperty(e, current);
} else {
setArrayAttributes(index, cattrs);
arrayData()->setProperty(scope.engine, index, current);
@@ -802,13 +796,13 @@ PropertyAttributes Object::virtualGetOwnProperty(const Managed *m, PropertyKey i
} else {
Q_ASSERT(id.asStringOrSymbol());
- auto member = o->internalClass()->findValueOrGetter(id);
+ auto member = o->internalClass()->find(id);
if (member.isValid()) {
- attrs = member.attrs;
+ attrs = member.attributes;
if (p) {
p->value = *o->propertyData(member.index);
if (attrs.isAccessor())
- p->set = *o->propertyData(member.index + SetterOffset);
+ p->set = *o->propertyData(member.setterIndex);
}
return attrs;
}
@@ -852,13 +846,13 @@ bool Object::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property
return o->internalDefineOwnProperty(scope.engine, index, nullptr, p, attrs);
}
- auto memberIndex = o->internalClass()->findValueOrGetter(id);
- Scoped<StringOrSymbol> name(scope, id.asStringOrSymbol());
+ auto memberIndex = o->internalClass()->find(id);
if (!memberIndex.isValid()) {
if (!o->isExtensible())
return false;
+ Scoped<StringOrSymbol> name(scope, id.asStringOrSymbol());
ScopedProperty pd(scope);
pd->copy(p, attrs);
pd->fullyPopulated(&attrs);
@@ -866,7 +860,7 @@ bool Object::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property
return true;
}
- return o->internalDefineOwnProperty(scope.engine, memberIndex.index, name, p, attrs);
+ return o->internalDefineOwnProperty(scope.engine, UINT_MAX, &memberIndex, p, attrs);
}
bool Object::virtualIsExtensible(const Managed *m)
@@ -1057,11 +1051,11 @@ bool ArrayObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro
Scope scope(engine);
Q_ASSERT(a->internalClass()->verifyIndex(engine->id_length()->propertyKey(), Heap::ArrayObject::LengthPropertyIndex));
ScopedProperty lp(scope);
- PropertyAttributes cattrs;
- a->getProperty(Heap::ArrayObject::LengthPropertyIndex, lp, &cattrs);
- if (attrs.isEmpty() || p->isSubset(attrs, lp, cattrs))
+ InternalClassEntry e = a->internalClass()->find(scope.engine->id_length()->propertyKey());
+ a->getProperty(e, lp);
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, e.attributes))
return true;
- if (!cattrs.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
+ if (!e.attributes.isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
return false;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
@@ -1075,8 +1069,8 @@ bool ArrayObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro
succeeded = a->setArrayLength(l);
}
if (attrs.hasWritable() && !attrs.isWritable()) {
- cattrs.setWritable(false);
- Heap::InternalClass::changeMember(a, engine->id_length()->propertyKey(), cattrs);
+ e.attributes.setWritable(false);
+ Heap::InternalClass::changeMember(a, engine->id_length()->propertyKey(), e.attributes);
}
if (!succeeded)
return false;
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index a32f8a4dac..7ac9888a88 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -159,8 +159,8 @@ struct Q_QML_EXPORT Object: Managed {
Heap::ArrayData *arrayData() const { return d()->arrayData; }
void setArrayData(ArrayData *a) { d()->arrayData.set(engine(), a->d()); }
- void getProperty(uint index, Property *p, PropertyAttributes *attrs) const;
- void setProperty(uint index, const Property *p);
+ void getProperty(const InternalClassEntry &entry, Property *p) const;
+ void setProperty(const InternalClassEntry &entry, const Property *p);
void setProperty(uint index, Value v) const { d()->setProperty(engine(), index, v); }
void setProperty(uint index, Heap::Base *b) const { d()->setProperty(engine(), index, b); }
void setProperty(ExecutionEngine *engine, uint index, Value v) const { d()->setProperty(engine, index, v); }
@@ -384,7 +384,7 @@ protected:
static ReturnedValue virtualInstanceOf(const Object *typeObject, const Value &var);
private:
- bool internalDefineOwnProperty(ExecutionEngine *engine, uint index, StringOrSymbol *member, const Property *p, PropertyAttributes attrs);
+ bool internalDefineOwnProperty(ExecutionEngine *engine, uint index, const InternalClassEntry *memberEntry, const Property *p, PropertyAttributes attrs);
ReturnedValue internalGet(PropertyKey id, const Value *receiver, bool *hasProperty) const;
bool internalPut(PropertyKey id, const Value &value, Value *receiver);
bool internalDeleteProperty(PropertyKey id);