diff options
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 60 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4errorobject.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4errorobject_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 46 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4internalclass_p.h | 30 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 88 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 6 |
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); |