From acd1918f135469f3267796627adbb7e32befc217 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 2 Feb 2013 09:52:27 +0100 Subject: [PATCH] Move the property data out of the hash table Change-Id: I814afa75706cec785ed53039f55ee407dec1ef90 Reviewed-by: Simon Hausmann --- src/v4/qv4array.cpp | 4 +-- src/v4/qv4functionobject.cpp | 6 ++--- src/v4/qv4jsonobject.cpp | 2 +- src/v4/qv4object.cpp | 60 ++++++++++++++++++++++++++++++-------------- src/v4/qv4object.h | 7 ++++++ src/v4/qv4objectiterator.cpp | 2 +- src/v4/qv4propertytable.h | 21 +++++++--------- src/v4/qv4regexpobject.cpp | 5 ++-- 8 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/v4/qv4array.cpp b/src/v4/qv4array.cpp index 5f0d838..decef65 100644 --- a/src/v4/qv4array.cpp +++ b/src/v4/qv4array.cpp @@ -586,13 +586,13 @@ void Array::setLengthUnchecked(uint l) len = l; if (arrayObject) { // length is always the first property of an array - PropertyDescriptor &lengthProperty = arrayObject->members->values[0]; + PropertyDescriptor &lengthProperty = arrayObject->memberData[ArrayObject::LengthPropertyIndex]; lengthProperty.value = Value::fromUInt32(l); } } bool Array::setLength(uint newLen) { - const PropertyDescriptor *lengthProperty = arrayObject->members->values.constData(); + const PropertyDescriptor *lengthProperty = arrayObject->memberData.constData() + ArrayObject::LengthPropertyIndex; if (lengthProperty && !lengthProperty->isWritable()) return false; uint oldLen = length(); diff --git a/src/v4/qv4functionobject.cpp b/src/v4/qv4functionobject.cpp index 41c06f0..2d96f92 100644 --- a/src/v4/qv4functionobject.cpp +++ b/src/v4/qv4functionobject.cpp @@ -361,7 +361,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, VM::Function *function) Object *proto = scope->engine->newObject(); proto->defineDefaultProperty(scope->engine->id_constructor, Value::fromObject(this)); - PropertyDescriptor *pd = members->insert(scope->engine->id_prototype); + PropertyDescriptor *pd = insertMember(scope->engine->id_prototype); pd->type = PropertyDescriptor::Data; pd->writable = PropertyDescriptor::Enabled; pd->enumberable = PropertyDescriptor::Disabled; @@ -440,8 +440,8 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObject *target, Va PropertyDescriptor pd = PropertyDescriptor::fromAccessor(thrower, thrower); pd.configurable = PropertyDescriptor::Disabled; pd.enumberable = PropertyDescriptor::Disabled; - *members->insert(scope->engine->id_arguments) = pd; - *members->insert(scope->engine->id_caller) = pd; + *insertMember(scope->engine->id_arguments) = pd; + *insertMember(scope->engine->id_caller) = pd; } Value BoundFunction::call(ExecutionContext *context, Value, Value *args, int argc) diff --git a/src/v4/qv4jsonobject.cpp b/src/v4/qv4jsonobject.cpp index 4c7ea3d..5c0027f 100644 --- a/src/v4/qv4jsonobject.cpp +++ b/src/v4/qv4jsonobject.cpp @@ -282,7 +282,7 @@ bool Parser::parseMember(Object *o) if (!parseValue(&val)) return false; - PropertyDescriptor *p = o->members->insert(context->engine->newIdentifier(key)); + PropertyDescriptor *p = o->insertMember(context->engine->newIdentifier(key)); p->value = val; END; diff --git a/src/v4/qv4object.cpp b/src/v4/qv4object.cpp index 6a5aa21..5903df4 100644 --- a/src/v4/qv4object.cpp +++ b/src/v4/qv4object.cpp @@ -129,7 +129,7 @@ void Object::defineDefaultProperty(String *name, Value value) { if (!members) members.reset(new PropertyTable()); - PropertyDescriptor *pd = members->insert(name); + PropertyDescriptor *pd = insertMember(name); pd->type = PropertyDescriptor::Data; pd->writable = PropertyDescriptor::Enabled; pd->enumberable = PropertyDescriptor::Disabled; @@ -169,7 +169,7 @@ void Object::defineReadonlyProperty(String *name, Value value) { if (!members) members.reset(new PropertyTable()); - PropertyDescriptor *pd = members->insert(name); + PropertyDescriptor *pd = insertMember(name); pd->type = PropertyDescriptor::Data; pd->writable = PropertyDescriptor::Disabled; pd->enumberable = PropertyDescriptor::Disabled; @@ -188,8 +188,8 @@ void Object::markObjects() continue; (*it)->name->mark(); } - for (int i = 0; i < (uint)members->values.size(); ++i) { - const PropertyDescriptor &pd = members->values.at(i); + for (int i = 0; i < (uint)memberData.size(); ++i) { + const PropertyDescriptor &pd = memberData.at(i); if (pd.isData()) { if (Managed *m = pd.value.asManaged()) m->mark(); @@ -204,6 +204,19 @@ void Object::markObjects() array.markObjects(); } +PropertyDescriptor *Object::insertMember(String *s) +{ + if (!members) + members.reset(new PropertyTable); + + PropertyTableEntry *e = members->insert(s); + if (e->valueIndex == UINT_MAX) { + e->valueIndex = memberData.size(); + memberData.resize(memberData.size() + 1); + } + return memberData.data() + e->valueIndex; +} + // Section 8.12.1 PropertyDescriptor *Object::__getOwnProperty__(ExecutionContext *ctx, String *name) { @@ -211,8 +224,11 @@ PropertyDescriptor *Object::__getOwnProperty__(ExecutionContext *ctx, String *na if (idx != String::InvalidArrayIndex) return __getOwnProperty__(ctx, idx); - if (members) - return members->find(name); + if (members) { + uint idx = members->find(name); + if (idx < UINT_MAX) + return memberData.data() + idx; + } return 0; } @@ -238,8 +254,9 @@ PropertyDescriptor *Object::__getPropertyDescriptor__(ExecutionContext *ctx, Str Object *o = this; while (o) { if (o->members) { - if (PropertyDescriptor *p = o->members->find(name)) - return p; + uint idx = o->members->find(name); + if (idx < UINT_MAX) + return o->memberData.data() + idx; } o = o->prototype; } @@ -281,10 +298,11 @@ Value Object::__get__(ExecutionContext *ctx, String *name, bool *hasProperty) Object *o = this; while (o) { if (o->members) { - if (PropertyDescriptor *p = o->members->find(name)) { + uint idx = o->members->find(name); + if (idx < UINT_MAX) { if (hasProperty) *hasProperty = true; - return getValue(ctx, p); + return getValue(ctx, o->memberData.data() + idx); } } o = o->prototype; @@ -398,7 +416,7 @@ void Object::__put__(ExecutionContext *ctx, String *name, Value value) } { - PropertyDescriptor *p = members->insert(name); + PropertyDescriptor *p = insertMember(name); p->type = PropertyDescriptor::Data; p->value = value; p->configurable = PropertyDescriptor::Enabled; @@ -479,7 +497,7 @@ bool Object::__hasProperty__(const ExecutionContext *ctx, String *name) const name->makeIdentifier(ctx); - if (members && members->find(name) != 0) + if (members && members->find(name) != UINT_MAX) return true; return prototype ? prototype->__hasProperty__(ctx, name) : false; @@ -505,8 +523,12 @@ bool Object::__delete__(ExecutionContext *ctx, String *name) if (members) { if (PropertyTableEntry *entry = members->findEntry(name)) { - if (members->values[entry->valueIndex].isConfigurable()) { + PropertyDescriptor &pd = memberData[entry->valueIndex]; + if (pd.isConfigurable()) { members->remove(entry); + // ### leaves a hole in memberData + pd.type = PropertyDescriptor::Generic; + pd.writable = PropertyDescriptor::Undefined; return true; } if (ctx->strictMode) @@ -538,8 +560,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr PropertyDescriptor *current; if (isArrayObject() && name->isEqualTo(ctx->engine->id_length)) { - PropertyDescriptor *lp = members->values.data(); // length is always the first property - assert(lp == members->find(ctx->engine->id_length)); + PropertyDescriptor *lp = memberData.data() + ArrayObject::LengthPropertyIndex; + assert(0 == members->find(ctx->engine->id_length)); if (desc->isEmpty() || desc->isSubset(lp)) return true; if (!lp->isWritable() || desc->type == PropertyDescriptor::Accessor || desc->isConfigurable() || desc->isEnumerable()) @@ -569,7 +591,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr if (!extensible) goto reject; // clause 4 - PropertyDescriptor *pd = members->insert(name); + PropertyDescriptor *pd = insertMember(name); *pd = *desc; pd->fullyPopulated(); return true; @@ -587,7 +609,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop PropertyDescriptor *current; // 15.4.5.1, 4b - if (isArrayObject() && index >= array.length() && !members->values.at(0).isWritable()) + if (isArrayObject() && index >= array.length() && !memberData.at(ArrayObject::LengthPropertyIndex).isWritable()) goto reject; if (isNonStrictArgumentsObject) @@ -690,14 +712,14 @@ void ArrayObject::init(ExecutionContext *context) if (!members) members.reset(new PropertyTable()); - PropertyDescriptor *pd = members->insert(context->engine->id_length); + PropertyDescriptor *pd = insertMember(context->engine->id_length); + assert(pd == memberData.constData() + LengthPropertyIndex); pd->type = PropertyDescriptor::Data; pd->writable = PropertyDescriptor::Enabled; pd->enumberable = PropertyDescriptor::Disabled; pd->configurable = PropertyDescriptor::Disabled; pd->value = Value::fromInt32(0); array.setArrayObject(this); - assert(pd = members->values.data()); } diff --git a/src/v4/qv4object.h b/src/v4/qv4object.h index 5bcc5df..dd67bee 100644 --- a/src/v4/qv4object.h +++ b/src/v4/qv4object.h @@ -103,6 +103,7 @@ struct URIErrorPrototype; struct Q_V4_EXPORT Object: Managed { Object *prototype; QScopedPointer members; + QVector memberData; Array array; Object() @@ -153,6 +154,8 @@ struct Q_V4_EXPORT Object: Managed { void defineReadonlyProperty(ExecutionEngine *engine, const QString &name, Value value); void defineReadonlyProperty(String *name, Value value); + PropertyDescriptor *insertMember(String *s); + protected: virtual void markObjects(); @@ -181,6 +184,10 @@ struct NumberObject: Object { }; struct ArrayObject: Object { + enum { + LengthPropertyIndex = 0 + }; + ArrayObject(ExecutionContext *ctx) { init(ctx); } ArrayObject(ExecutionContext *ctx, const Array &value): Object(value) { init(ctx); array.setLengthUnchecked(array.length()); } void init(ExecutionContext *context); diff --git a/src/v4/qv4objectiterator.cpp b/src/v4/qv4objectiterator.cpp index 8ce6237..62f3c30 100644 --- a/src/v4/qv4objectiterator.cpp +++ b/src/v4/qv4objectiterator.cpp @@ -129,7 +129,7 @@ PropertyDescriptor *ObjectIterator::next(String **name, uint *index) ++tableIndex; // ### check that it's not a repeated attribute if (pt) { - PropertyDescriptor *pd = current->members->values.data() + pt->valueIndex; + PropertyDescriptor *pd = current->memberData.data() + pt->valueIndex; if (!(flags & EnumberableOnly) || pd->isEnumerable()) { *name = pt->name; p = pd; diff --git a/src/v4/qv4propertytable.h b/src/v4/qv4propertytable.h index 30aa5d2..787c319 100644 --- a/src/v4/qv4propertytable.h +++ b/src/v4/qv4propertytable.h @@ -112,9 +112,6 @@ public: _properties[prop->index] = 0; prop->next = _freeList; _freeList = prop; - // ### empty space in value array - values[prop->valueIndex].type = PropertyDescriptor::Generic; - values[prop->valueIndex].writable = PropertyDescriptor::Undefined; } PropertyTableEntry *findEntry(String *name) const @@ -129,22 +126,22 @@ public: return 0; } - PropertyDescriptor *find(String *name) + uint find(String *name) { if (_properties) { for (PropertyTableEntry *prop = _buckets[name->hashValue() % _bucketCount]; prop; prop = prop->next) { if (prop && prop->name->isEqualTo(name)) - return values.data() + prop->valueIndex; + return prop->valueIndex; } } - return 0; + return UINT_MAX; } - PropertyDescriptor *insert(String *name) + PropertyTableEntry *insert(String *name) { if (PropertyTableEntry *prop = findEntry(name)) - return values.data() + prop->valueIndex; + return prop; if (_propertyCount == _allocated) { if (! _allocated) @@ -179,9 +176,10 @@ public: bucket = prop; } - prop->valueIndex = values.size(); - values.resize(values.size() + 1); - return values.data() + prop->valueIndex; + return prop; +// prop->valueIndex = values.size(); +// values.resize(values.size() + 1); +// return values.data() + prop->valueIndex; } private: @@ -227,7 +225,6 @@ private: int _bucketCount; int _primeIdx: 5; int _allocated: 27; - QVector values; }; } // namespace VM diff --git a/src/v4/qv4regexpobject.cpp b/src/v4/qv4regexpobject.cpp index 5a0faf1..69fd5bb 100644 --- a/src/v4/qv4regexpobject.cpp +++ b/src/v4/qv4regexpobject.cpp @@ -72,7 +72,7 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, PassRefPtr value, bo if (!members) members.reset(new PropertyTable()); - PropertyDescriptor *lastIndexProperty = members->insert(engine->newIdentifier(QStringLiteral("lastIndex"))); + PropertyDescriptor *lastIndexProperty = insertMember(engine->newIdentifier(QStringLiteral("lastIndex"))); lastIndexProperty->type = PropertyDescriptor::Data; lastIndexProperty->writable = PropertyDescriptor::Enabled; lastIndexProperty->enumberable = PropertyDescriptor::Disabled; @@ -88,7 +88,8 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, PassRefPtr value, bo PropertyDescriptor *RegExpObject::lastIndexProperty(ExecutionContext *ctx) { - return members->find(ctx->engine->newIdentifier(QStringLiteral("lastIndex"))); + assert(0 == members->find(ctx->engine->newIdentifier(QStringLiteral("lastIndex")))); + return &memberData[0]; } -- 2.7.4