aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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);