Move the property data out of the hash table
authorLars Knoll <lars.knoll@digia.com>
Sat, 2 Feb 2013 08:52:27 +0000 (09:52 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 4 Feb 2013 14:05:54 +0000 (15:05 +0100)
Change-Id: I814afa75706cec785ed53039f55ee407dec1ef90
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/v4/qv4array.cpp
src/v4/qv4functionobject.cpp
src/v4/qv4jsonobject.cpp
src/v4/qv4object.cpp
src/v4/qv4object.h
src/v4/qv4objectiterator.cpp
src/v4/qv4propertytable.h
src/v4/qv4regexpobject.cpp

index 5f0d838..decef65 100644 (file)
@@ -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();
index 41c06f0..2d96f92 100644 (file)
@@ -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)
index 4c7ea3d..5c0027f 100644 (file)
@@ -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;
index 6a5aa21..5903df4 100644 (file)
@@ -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());
 }
 
 
index 5bcc5df..dd67bee 100644 (file)
@@ -103,6 +103,7 @@ struct URIErrorPrototype;
 struct Q_V4_EXPORT Object: Managed {
     Object *prototype;
     QScopedPointer<PropertyTable> members;
+    QVector<PropertyDescriptor> 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);
index 8ce6237..62f3c30 100644 (file)
@@ -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;
index 30aa5d2..787c319 100644 (file)
@@ -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<PropertyDescriptor> values;
 };
 
 } // namespace VM
index 5a0faf1..69fd5bb 100644 (file)
@@ -72,7 +72,7 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, PassRefPtr<RegExp> 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<RegExp> 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];
 }