From 7cc66a996e70c52bc274ae9f15f65e8a638894d9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sun, 23 Sep 2018 15:46:25 +0200 Subject: 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 --- src/qml/jsruntime/qv4argumentsobject.cpp | 3 +- src/qml/jsruntime/qv4argumentsobject_p.h | 3 +- src/qml/jsruntime/qv4engine.cpp | 60 ++++++++++++---------- src/qml/jsruntime/qv4errorobject.cpp | 6 +-- src/qml/jsruntime/qv4errorobject_p.h | 1 + src/qml/jsruntime/qv4internalclass.cpp | 46 +++++++++-------- src/qml/jsruntime/qv4internalclass_p.h | 30 +++++++++-- src/qml/jsruntime/qv4managed_p.h | 4 +- src/qml/jsruntime/qv4object.cpp | 88 +++++++++++++++----------------- src/qml/jsruntime/qv4object_p.h | 6 +-- 10 files changed, 136 insertions(+), 111 deletions(-) (limited to 'src/qml/jsruntime') 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 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(); jsObjects[DateProto] = memoryManager->allocate(); - 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(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(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(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 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 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(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 name(scope, id.asStringOrSymbol()); + auto memberIndex = o->internalClass()->find(id); if (!memberIndex.isValid()) { if (!o->isExtensible()) return false; + Scoped 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); -- cgit v1.2.3