From f63d48d474db7e9eff7583f1b8478228b13d3c82 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sun, 23 Sep 2018 12:10:12 +0200 Subject: Differentiate between finding for get and set in InternalClass This is required, so we can get rid of the requirement that getter and setter live next to each other in the member data. Change-Id: I2ed57a171628af4dfecd1836d00e958c6bed9d4f Reviewed-by: Erik Verbruggen --- src/qml/jsruntime/qv4argumentsobject.cpp | 2 +- src/qml/jsruntime/qv4context.cpp | 6 +++--- src/qml/jsruntime/qv4internalclass_p.h | 15 ++++++++++++++- src/qml/jsruntime/qv4lookup.cpp | 11 ++++++----- src/qml/jsruntime/qv4object.cpp | 24 +++++++++++------------- src/qml/jsruntime/qv4object_p.h | 2 +- src/qml/jsruntime/qv4qmlcontext.cpp | 4 ++-- 7 files changed, 38 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 9cebe6f043..43aa2e931e 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -61,7 +61,7 @@ void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame) Q_ASSERT(internalClass->verifyIndex(v4->id_callee()->propertyKey(), CalleePropertyIndex)); Q_ASSERT(internalClass->verifyIndex(v4->symbol_iterator()->propertyKey(), SymbolIteratorPropertyIndex)); setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues()); - setProperty(v4, CalleePropertyIndex + QV4::Object::GetterOffset, *v4->thrower()); + setProperty(v4, CalleePropertyIndex, *v4->thrower()); setProperty(v4, CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower()); Scope scope(v4); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 38e233965f..94b1a9fb73 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -295,11 +295,11 @@ ExecutionContext::Error ExecutionContext::setProperty(String *name, const Value Q_FALLTHROUGH(); case Heap::ExecutionContext::Type_GlobalContext: if (ctx->activation) { - uint member = ctx->activation->internalClass->indexOfValueOrGetter(id); - if (member < UINT_MAX) { + auto member = ctx->activation->internalClass->findValueOrSetter(id); + if (member.index < UINT_MAX) { Scope scope(engine); ScopedObject a(scope, ctx->activation); - if (!a->putValue(member, value)) + if (!a->putValue(member.index, member.attrs, value)) return TypeError; return NoError; } diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index 82ace19d30..cced746568 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -369,7 +369,7 @@ struct InternalClass : Base { bool isValid() const { return index != UINT_MAX; } }; - IndexAndAttribute find(const PropertyKey id) + IndexAndAttribute findValueOrGetter(const PropertyKey id) { Q_ASSERT(id.isStringOrSymbol()); @@ -380,6 +380,19 @@ struct InternalClass : Base { return { UINT_MAX, Attr_Invalid }; } + IndexAndAttribute findValueOrSetter(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 { a.isAccessor() ? e->index + 1 : e->index, a }; + } + + return { UINT_MAX, Attr_Invalid }; + } + uint indexOfValueOrGetter(const PropertyKey id) { Q_ASSERT(id.isStringOrSymbol()); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 141d9b5afb..994daa864b 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -50,7 +50,7 @@ using namespace QV4; void Lookup::resolveProtoGetter(PropertyKey name, const Heap::Object *proto) { while (proto) { - auto index = proto->internalClass->find(name); + auto index = proto->internalClass->findValueOrGetter(name); if (index.isValid()) { PropertyAttributes attrs = index.attrs; protoLookup.data = proto->propertyData(index.index); @@ -77,7 +77,7 @@ ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *objec return getter(this, engine, *object); } - auto index = obj->internalClass->find(name); + auto index = obj->internalClass->findValueOrGetter(name); if (index.isValid()) { PropertyAttributes attrs = index.attrs; uint nInline = obj->vtable()->nInlineProperties; @@ -478,9 +478,10 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value Heap::InternalClass *c = object->internalClass(); PropertyKey key = name->toPropertyKey(); - auto idx = c->find(key); + auto idx = c->findValueOrSetter(key); if (idx.isValid()) { if (object->isArrayObject() && idx.index == Heap::ArrayObject::LengthPropertyIndex) { + Q_ASSERT(!idx.attrs.isAccessor()); setter = arrayLengthSetter; return setter(this, engine, *object, value); } else if (idx.attrs.isData() && idx.attrs.isWritable()) { @@ -506,8 +507,8 @@ bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value setter = setterFallback; return true; } - idx = object->internalClass()->find(key); - if (!idx.isValid()) { // ### can this even happen? + idx = object->internalClass()->findValueOrSetter(key); + if (!idx.isValid() || idx.attrs.isAccessor()) { // ### can this even happen? setter = setterFallback; return false; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 476ecf7f2a..855bebff88 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -108,16 +108,14 @@ ReturnedValue Object::getValueAccessor(const Value &thisObject, const Value &v, return f->call(jsCallData); } -bool Object::putValue(uint memberIndex, const Value &value) +bool Object::putValue(uint memberIndex, PropertyAttributes attrs, const Value &value) { Heap::InternalClass *ic = internalClass(); if (ic->engine->hasException) return false; - PropertyAttributes attrs = ic->propertyData[memberIndex]; - if (attrs.isAccessor()) { - const FunctionObject *set = propertyData(memberIndex + SetterOffset)->as(); + const FunctionObject *set = propertyData(memberIndex)->as(); if (set) { Scope scope(ic->engine); ScopedFunctionObject setter(scope, set); @@ -256,7 +254,7 @@ void Object::insertMember(StringOrSymbol *s, const Property *p, PropertyAttribut Heap::InternalClass::addMember(this, key, attributes, &idx); if (attributes.isAccessor()) { - setProperty(idx + GetterOffset, p->value); + setProperty(idx, p->value); setProperty(idx + SetterOffset, p->set); } else { setProperty(idx, p->value); @@ -295,10 +293,10 @@ PropertyIndex Object::getValueOrSetter(PropertyKey id, PropertyAttributes *attrs } else { Heap::Object *o = d(); while (o) { - auto idx = o->internalClass->find(id); + auto idx = o->internalClass->findValueOrSetter(id); if (idx.isValid()) { *attrs = idx.attrs; - return o->writablePropertyData(attrs->isAccessor() ? idx.index + SetterOffset : idx.index ); + return o->writablePropertyData(idx.index); } o = o->prototype(); @@ -443,7 +441,7 @@ ReturnedValue Object::internalGet(PropertyKey id, const Value *receiver, bool *h Q_ASSERT(!id.isArrayIndex()); while (1) { - auto idx = o->internalClass->find(id); + auto idx = o->internalClass->findValueOrGetter(id); if (idx.isValid()) { if (hasProperty) *hasProperty = true; @@ -488,10 +486,10 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver) if (arrayData()) propertyIndex = arrayData()->getValueOrSetter(index, &attrs); } else { - auto member = internalClass()->find(id); + auto member = internalClass()->findValueOrSetter(id); if (member.isValid()) { attrs = member.attrs; - propertyIndex = d()->writablePropertyData(member.attrs.isAccessor() ? member.index + SetterOffset : member.index); + propertyIndex = d()->writablePropertyData(member.index); } } @@ -588,7 +586,7 @@ bool Object::internalDeleteProperty(PropertyKey id) return false; } - auto memberIdx = internalClass()->find(id); + auto memberIdx = internalClass()->findValueOrGetter(id); if (memberIdx.isValid()) { if (memberIdx.attrs.isConfigurable()) { Heap::InternalClass::removeMember(this, id); @@ -804,7 +802,7 @@ PropertyAttributes Object::virtualGetOwnProperty(const Managed *m, PropertyKey i } else { Q_ASSERT(id.asStringOrSymbol()); - auto member = o->internalClass()->find(id); + auto member = o->internalClass()->findValueOrGetter(id); if (member.isValid()) { attrs = member.attrs; if (p) { @@ -854,7 +852,7 @@ bool Object::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property return o->internalDefineOwnProperty(scope.engine, index, nullptr, p, attrs); } - auto memberIndex = o->internalClass()->find(id); + auto memberIndex = o->internalClass()->findValueOrGetter(id); Scoped name(scope, id.asStringOrSymbol()); if (!memberIndex.isValid()) { diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index c9b0ff7e1f..a32f8a4dac 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -197,7 +197,7 @@ struct Q_QML_EXPORT Object: Managed { } static ReturnedValue getValueAccessor(const Value &thisObject, const Value &v, PropertyAttributes attrs); - bool putValue(uint memberIndex, const Value &value); + bool putValue(uint memberIndex, PropertyAttributes attrs, const Value &value); /* The spec default: Writable: true, Enumerable: false, Configurable: true */ void defineDefaultProperty(StringOrSymbol *name, const Value &value, PropertyAttributes attributes = Attr_Data|Attr_NotEnumerable) { diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index b10065d308..cc0b0feeee 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -265,9 +265,9 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val return false; QV4::Scoped wrapper(scope, resource); - auto member = wrapper->internalClass()->find(id); + auto member = wrapper->internalClass()->findValueOrSetter(id); if (member.index < UINT_MAX) - return wrapper->putValue(member.index, value); + return wrapper->putValue(member.index, member.attrs, value); // It's possible we could delay the calculation of the "actual" context (in the case // of sub contexts) until it is definitely needed. -- cgit v1.2.3