Get rid of Members and directly store MemberData::Data pointers
authorLars Knoll <lars.knoll@theqtcompany.com>
Sat, 1 Nov 2014 20:44:57 +0000 (21:44 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Fri, 7 Nov 2014 01:00:05 +0000 (02:00 +0100)
And do the same change for ArrayData.

Change-Id: Ia1ae56bd0ff586c9b987e15af7a53f395a37054a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
14 files changed:
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4argumentsobject_p.h
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4internalclass.cpp
src/qml/jsruntime/qv4lookup.cpp
src/qml/jsruntime/qv4memberdata.cpp
src/qml/jsruntime/qv4memberdata_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4regexpobject.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4value.cpp

index e8cb788..c020e99 100644 (file)
@@ -65,10 +65,10 @@ ArgumentsObject::Data::Data(CallContext *context)
     } else {
         args->setHasAccessorProperty();
         Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
-        args->memberData()[CalleePropertyIndex] = context->d()->function->asReturnedValue();
+        args->memberData()->data()[CalleePropertyIndex] = context->d()->function->asReturnedValue();
     }
     Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
-    args->memberData()[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount);
+    args->memberData()->data()[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount);
 }
 
 void ArgumentsObject::fullyCreate()
@@ -80,9 +80,13 @@ void ArgumentsObject::fullyCreate()
     uint argCount = qMin(context()->d()->realArgumentCount, context()->d()->callData->argc);
     ArrayData::realloc(this, ArrayData::Sparse, argCount, true);
     context()->d()->engine->requireArgumentsAccessors(numAccessors);
-    mappedArguments().ensureIndex(engine(), numAccessors);
+
+    Scope scope(engine());
+    Scoped<MemberData> md(scope, d()->mappedArguments);
+    if (md)
+        d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
     for (uint i = 0; i < (uint)numAccessors; ++i) {
-        mappedArguments()[i] = context()->d()->callData->args[i];
+        mappedArguments()->data[i] = context()->d()->callData->args[i];
         arraySet(i, context()->d()->engine->argumentsAccessors[i], Attr_Accessor);
     }
     arrayPut(numAccessors, context()->d()->callData->args + numAccessors, argCount - numAccessors);
@@ -111,7 +115,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
         map.copy(*pd, mapAttrs);
         setArrayAttributes(index, Attr_Data);
         pd = arrayData()->getProperty(index);
-        pd->value = mappedArguments()[index];
+        pd->value = mappedArguments()->data[index];
     }
 
     bool strict = ctx->d()->strictMode;
@@ -227,7 +231,8 @@ void ArgumentsObject::markObjects(HeapObject *that, ExecutionEngine *e)
     ArgumentsObject::Data *o = static_cast<ArgumentsObject::Data *>(that);
     if (o->context)
         o->context->mark(e);
-    o->mappedArguments.mark(e);
+    if (o->mappedArguments)
+        o->mappedArguments->mark(e);
 
     Object::markObjects(that, e);
 }
index 73c6bb2..d961d08 100644 (file)
@@ -82,14 +82,14 @@ struct ArgumentsObject: Object {
         Data(CallContext *context);
         CallContext *context;
         bool fullyCreated;
-        MembermappedArguments;
+        MemberData::Data *mappedArguments;
     };
     V4_OBJECT(Object)
     Q_MANAGED_TYPE(ArgumentsObject)
 
     CallContext *context() const { return d()->context; }
     bool fullyCreated() const { return d()->fullyCreated; }
-    Members &mappedArguments() { return d()->mappedArguments; }
+    MemberData::Data *mappedArguments() { return d()->mappedArguments; }
 
     static bool isNonStrictArgumentsObject(Managed *m) {
         return m->internalClass()->vtable->type == Type_ArgumentsObject &&
index 1da54b1..ff9d2cc 100644 (file)
@@ -77,7 +77,6 @@ struct SyntaxErrorObject;
 struct ArgumentsObject;
 struct ExecutionContext;
 struct ExecutionEngine;
-struct Members;
 class MemoryManager;
 class ExecutableAllocator;
 
index deb9e62..7c93cab 100644 (file)
@@ -96,8 +96,10 @@ FunctionObject::Data::Data(InternalClass *ic)
     : Object::Data(ic)
     , scope(ic->engine->rootContext)
 {
-    memberData.ensureIndex(ic->engine, Index_Prototype);
-    memberData[Index_Prototype] = Encode::undefined();
+    Scope scope(ic->engine);
+    ScopedObject o(scope, this);
+    o->ensureMemberIndex(ic->engine, Index_Prototype);
+    memberData->data[Index_Prototype] = Encode::undefined();
 }
 
 
@@ -115,13 +117,14 @@ void FunctionObject::init(String *n, bool createProto)
     d()->needsActivation = true;
     d()->strictMode = false;
 
-    memberData().ensureIndex(s.engine, Index_Prototype);
+    ensureMemberIndex(s.engine, Index_Prototype);
     if (createProto) {
         Scoped<Object> proto(s, scope()->d()->engine->newObject(scope()->d()->engine->protoClass));
-        proto->memberData()[Index_ProtoConstructor] = this->asReturnedValue();
-        memberData()[Index_Prototype] = proto.asReturnedValue();
+        proto->ensureMemberIndex(s.engine, Index_ProtoConstructor);
+        proto->memberData()->data()[Index_ProtoConstructor] = this->asReturnedValue();
+        memberData()->data()[Index_Prototype] = proto.asReturnedValue();
     } else {
-        memberData()[Index_Prototype] = Encode::undefined();
+        memberData()->data()[Index_Prototype] = Encode::undefined();
     }
 
     ScopedValue v(s, n);
@@ -333,14 +336,12 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
         return ctx->engine()->throwTypeError();
 
     ScopedValue boundThis(scope, ctx->argument(0));
-    Members boundArgs;
-    boundArgs.reset();
+    Scoped<MemberData> boundArgs(scope);
     if (ctx->d()->callData->argc > 1) {
-        boundArgs.ensureIndex(scope.engine, ctx->d()->callData->argc - 1);
-        boundArgs.d()->d()->size = ctx->d()->callData->argc - 1;
-        memcpy(boundArgs.data(), ctx->d()->callData->args + 1, (ctx->d()->callData->argc - 1)*sizeof(Value));
+        boundArgs = MemberData::reallocate(scope.engine, 0, ctx->d()->callData->argc - 1);
+        boundArgs->d()->size = ctx->d()->callData->argc - 1;
+        memcpy(boundArgs->data(), ctx->d()->callData->args + 1, (ctx->d()->callData->argc - 1)*sizeof(Value));
     }
-    ScopedValue protectBoundArgs(scope, boundArgs.d());
 
     return BoundFunction::create(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
 }
@@ -584,10 +585,10 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
 
 DEFINE_OBJECT_VTABLE(BoundFunction);
 
-BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
+BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, MemberData *boundArgs)
     : FunctionObject::Data(scope, QStringLiteral("__bound function__"))
     , target(target)
-    , boundArgs(boundArgs)
+    , boundArgs(boundArgs ? boundArgs->d() : 0)
 {
     this->boundThis = boundThis;
     setVTable(staticVTable());
@@ -598,7 +599,8 @@ BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const
 
     ScopedValue l(s, target->get(s.engine->id_length));
     int len = l->toUInt32();
-    len -= boundArgs.size();
+    if (boundArgs)
+        len -= boundArgs->size();
     if (len < 0)
         len = 0;
     f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
@@ -617,10 +619,15 @@ ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
     if (scope.hasException())
         return Encode::undefined();
 
-    ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
+    Scoped<MemberData> boundArgs(scope, f->boundArgs());
+    ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
     callData->thisObject = f->boundThis();
-    memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
-    memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
+    Value *argp = callData->args;
+    if (boundArgs) {
+        memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
+        argp += boundArgs->size();
+    }
+    memcpy(argp, dd->args, dd->argc*sizeof(Value));
     return f->target()->call(callData);
 }
 
@@ -631,9 +638,14 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
     if (scope.hasException())
         return Encode::undefined();
 
-    ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
-    memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
-    memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
+    Scoped<MemberData> boundArgs(scope, f->boundArgs());
+    ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
+    Value *argp = callData->args;
+    if (boundArgs) {
+        memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
+        argp += boundArgs->size();
+    }
+    memcpy(argp, dd->args, dd->argc*sizeof(Value));
     return f->target()->construct(callData);
 }
 
@@ -642,6 +654,7 @@ void BoundFunction::markObjects(HeapObject *that, ExecutionEngine *e)
     BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
     o->target->mark(e);
     o->boundThis.mark(e);
-    o->boundArgs.mark(e);
+    if (o->boundArgs)
+        o->boundArgs->mark(e);
     FunctionObject::markObjects(that, e);
 }
index 1ff8124..07a8c45 100644 (file)
@@ -96,7 +96,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
 
     static Returned<FunctionObject> *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
 
-    ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); }
+    ReturnedValue protoProperty() { return memberData()->data()[Index_Prototype].asReturnedValue(); }
 
     bool needsActivation() const { return d()->needsActivation; }
     bool strictMode() const { return d()->strictMode; }
@@ -202,21 +202,22 @@ struct ScriptFunction: SimpleScriptFunction {
 
 struct BoundFunction: FunctionObject {
     struct Data : FunctionObject::Data {
-        Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs);
+        Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, MemberData *boundArgs);
         FunctionObject *target;
         Value boundThis;
-        MemberboundArgs;
+        MemberData::Data *boundArgs;
     };
     V4_OBJECT(FunctionObject)
 
-    static Returned<BoundFunction> *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs)
+    static Returned<BoundFunction> *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, QV4::MemberData *boundArgs)
     {
         return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
     }
 
     FunctionObject *target() { return d()->target; }
     Value boundThis() const { return d()->boundThis; }
-    Members boundArgs() const { return d()->boundArgs; }
+    // ### GC
+    MemberData::Data *boundArgs() const { return d()->boundArgs; }
 
     static ReturnedValue construct(Managed *, CallData *d);
     static ReturnedValue call(Managed *that, CallData *dd);
index a59c389..0f8eb2b 100644 (file)
@@ -153,10 +153,10 @@ void InternalClass::changeMember(Object *object, String *string, PropertyAttribu
 
     if (newClass->size > object->internalClass()->size) {
         Q_ASSERT(newClass->size == object->internalClass()->size + 1);
-        memmove(object->memberData().data() + idx + 2, object->memberData().data() + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
+        memmove(object->memberData()->data() + idx + 2, object->memberData()->data() + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
     } else if (newClass->size < object->internalClass()->size) {
         Q_ASSERT(newClass->size == object->internalClass()->size - 1);
-        memmove(object->memberData().data() + idx + 1, object->memberData().data() + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
+        memmove(object->memberData()->data() + idx + 1, object->memberData()->data() + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
     }
     object->setInternalClass(newClass);
 }
@@ -351,7 +351,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
     }
 
     // remove the entry in memberdata
-    memmove(object->memberData().data() + propIdx, object->memberData().data() + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
+    memmove(object->memberData()->data() + propIdx, object->memberData()->data() + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
 
     oldClass->transitions.insert(t, object->internalClass());
 }
index f7ebb62..9d4649b 100644 (file)
@@ -49,7 +49,7 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute
         if (index != UINT_MAX) {
             level = i;
             *attrs = obj->internalClass()->propertyData.at(index);
-            return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+            return !attrs->isAccessor() ? obj->memberData()->data()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
         }
 
         obj = obj->prototype();
@@ -61,7 +61,7 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute
         index = obj->internalClass()->find(name);
         if (index != UINT_MAX) {
             *attrs = obj->internalClass()->propertyData.at(index);
-            return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+            return !attrs->isAccessor() ? obj->memberData()->data()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
         }
 
         obj = obj->prototype();
@@ -80,7 +80,7 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
         if (index != UINT_MAX) {
             level = i;
             *attrs = obj->internalClass()->propertyData.at(index);
-            return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+            return !attrs->isAccessor() ? obj->memberData()->data()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
         }
 
         obj = obj->prototype();
@@ -92,7 +92,7 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
         index = obj->internalClass()->find(name);
         if (index != UINT_MAX) {
             *attrs = obj->internalClass()->propertyData.at(index);
-            return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+            return !attrs->isAccessor() ? obj->memberData()->data()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
         }
 
         obj = obj->prototype();
@@ -334,7 +334,7 @@ ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object)
         // the internal class won't match
         Object *o = object->objectValue();
         if (l->classList[0] == o->internalClass())
-            return o->memberData()[l->index].asReturnedValue();
+            return o->memberData()->data()[l->index].asReturnedValue();
     }
     return getterTwoClasses(l, object);
 }
@@ -347,7 +347,7 @@ ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object)
         Object *o = object->objectValue();
         if (l->classList[0] == o->internalClass() &&
             l->classList[1] == o->prototype()->internalClass())
-            return o->prototype()->memberData()[l->index].asReturnedValue();
+            return o->prototype()->memberData()->data()[l->index].asReturnedValue();
     }
     return getterTwoClasses(l, object);
 }
@@ -363,7 +363,7 @@ ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object)
             if (l->classList[1] == o->internalClass()) {
                 o = o->prototype();
                 if (l->classList[2] == o->internalClass())
-                    return o->memberData()[l->index].asReturnedValue();
+                    return o->memberData()->data()[l->index].asReturnedValue();
             }
         }
     }
@@ -378,9 +378,9 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, const ValueRef object)
         // the internal class won't match
         Object *o = object->objectValue();
         if (l->classList[0] == o->internalClass())
-            return o->memberData()[l->index].asReturnedValue();
+            return o->memberData()->data()[l->index].asReturnedValue();
         if (l->classList[2] == o->internalClass())
-            return o->memberData()[l->index2].asReturnedValue();
+            return o->memberData()->data()[l->index2].asReturnedValue();
     }
     l->getter = getterFallback;
     return getterFallback(l, object);
@@ -393,10 +393,10 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, const ValueRef object)
         // the internal class won't match
         Object *o = object->objectValue();
         if (l->classList[0] == o->internalClass())
-            return o->memberData()[l->index].asReturnedValue();
+            return o->memberData()->data()[l->index].asReturnedValue();
         if (l->classList[2] == o->internalClass() &&
             l->classList[3] == o->prototype()->internalClass())
-            return o->prototype()->memberData()[l->index2].asReturnedValue();
+            return o->prototype()->memberData()->data()[l->index2].asReturnedValue();
     }
     l->getter = getterFallback;
     return getterFallback(l, object);
@@ -410,10 +410,10 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, const ValueRef object)
         Object *o = object->objectValue();
         if (l->classList[0] == o->internalClass() &&
             l->classList[1] == o->prototype()->internalClass())
-            return o->prototype()->memberData()[l->index].asReturnedValue();
+            return o->prototype()->memberData()->data()[l->index].asReturnedValue();
         if (l->classList[2] == o->internalClass() &&
             l->classList[3] == o->prototype()->internalClass())
-            return o->prototype()->memberData()[l->index2].asReturnedValue();
+            return o->prototype()->memberData()->data()[l->index2].asReturnedValue();
         return getterFallback(l, object);
     }
     l->getter = getterFallback;
@@ -496,7 +496,7 @@ ReturnedValue Lookup::primitiveGetter0(Lookup *l, const ValueRef object)
     if (object->type() == l->type) {
         Object *o = l->proto;
         if (l->classList[0] == o->internalClass())
-            return o->memberData()[l->index].asReturnedValue();
+            return o->memberData()->data()[l->index].asReturnedValue();
     }
     l->getter = getterGeneric;
     return getterGeneric(l, object);
@@ -508,7 +508,7 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, const ValueRef object)
         Object *o = l->proto;
         if (l->classList[0] == o->internalClass() &&
             l->classList[1] == o->prototype()->internalClass())
-            return o->prototype()->memberData()[l->index].asReturnedValue();
+            return o->prototype()->memberData()->data()[l->index].asReturnedValue();
     }
     l->getter = getterGeneric;
     return getterGeneric(l, object);
@@ -565,7 +565,7 @@ ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object)
 ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object)
 {
     if (ArrayObject *a = object->asArrayObject())
-        return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
+        return a->memberData()->data()[ArrayObject::LengthPropertyIndex].asReturnedValue();
 
     l->getter = getterGeneric;
     return getterGeneric(l, object);
@@ -605,7 +605,7 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx)
 {
     Object *o = ctx->d()->engine->globalObject;
     if (l->classList[0] == o->internalClass())
-        return o->memberData()[l->index].asReturnedValue();
+        return o->memberData()->data()[l->index].asReturnedValue();
 
     l->globalGetter = globalGetterGeneric;
     return globalGetterGeneric(l, ctx);
@@ -616,7 +616,7 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx)
     Object *o = ctx->d()->engine->globalObject;
     if (l->classList[0] == o->internalClass() &&
         l->classList[1] == o->prototype()->internalClass())
-        return o->prototype()->memberData()[l->index].asReturnedValue();
+        return o->prototype()->memberData()->data()[l->index].asReturnedValue();
 
     l->globalGetter = globalGetterGeneric;
     return globalGetterGeneric(l, ctx);
@@ -630,7 +630,7 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx)
         if (l->classList[1] == o->internalClass()) {
             o = o->prototype();
             if (l->classList[2] == o->internalClass()) {
-                return o->prototype()->memberData()[l->index].asReturnedValue();
+                return o->prototype()->memberData()->data()[l->index].asReturnedValue();
             }
         }
     }
@@ -744,7 +744,7 @@ void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value)
 {
     Object *o = static_cast<Object *>(object->asManaged());
     if (o && o->internalClass() == l->classList[0]) {
-        o->memberData()[l->index] = *value;
+        o->memberData()->data()[l->index] = *value;
         return;
     }
 
@@ -756,9 +756,9 @@ void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef valu
     Object *o = static_cast<Object *>(object->asManaged());
     if (o && o->internalClass() == l->classList[0]) {
         if (!o->prototype()) {
-            if (l->index >= o->memberData().size())
+            if (!o->memberData() || l->index >= o->memberData()->size())
                 o->ensureMemberIndex(l->index);
-            o->memberData()[l->index] = *value;
+            o->memberData()->data()[l->index] = *value;
             o->setInternalClass(l->classList[3]);
             return;
         }
@@ -774,9 +774,9 @@ void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef valu
     if (o && o->internalClass() == l->classList[0]) {
         Object *p = o->prototype();
         if (p && p->internalClass() == l->classList[1]) {
-            if (l->index >= o->memberData().size())
+            if (!o->memberData() || l->index >= o->memberData()->size())
                 o->ensureMemberIndex(l->index);
-            o->memberData()[l->index] = *value;
+            o->memberData()->data()[l->index] = *value;
             o->setInternalClass(l->classList[3]);
             return;
         }
@@ -794,9 +794,9 @@ void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef valu
         if (p && p->internalClass() == l->classList[1]) {
             p = p->prototype();
             if (p && p->internalClass() == l->classList[2]) {
-                if (l->index >= o->memberData().size())
+                if (!o->memberData() || l->index >= o->memberData()->size())
                     o->ensureMemberIndex(l->index);
-                o->memberData()[l->index] = *value;
+                o->memberData()->data()[l->index] = *value;
                 o->setInternalClass(l->classList[3]);
                 return;
             }
@@ -812,11 +812,11 @@ void Lookup::setter0setter0(Lookup *l, const ValueRef object, const ValueRef val
     Object *o = static_cast<Object *>(object->asManaged());
     if (o) {
         if (o->internalClass() == l->classList[0]) {
-            o->memberData()[l->index] = *value;
+            o->memberData()->data()[l->index] = *value;
             return;
         }
         if (o->internalClass() == l->classList[1]) {
-            o->memberData()[l->index2] = *value;
+            o->memberData()->data()[l->index2] = *value;
             return;
         }
     }
index de22630..bf07a74 100644 (file)
@@ -45,18 +45,19 @@ void MemberData::markObjects(HeapObject *that, ExecutionEngine *e)
         m->data[i].mark(e);
 }
 
-void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx)
+MemberData::Data *MemberData::reallocate(ExecutionEngine *e, Data *old, uint idx)
 {
-    uint s = size();
-    if (idx >= s) {
-        int newAlloc = qMax((uint)4, 2*idx);
-        uint alloc = sizeof(MemberData::Data) + (newAlloc)*sizeof(Value);
-        MemberData *newMemberData = static_cast<MemberData *>(e->memoryManager->allocManaged(alloc));
-        if (d())
-            memcpy(newMemberData, d(), sizeof(MemberData::Data) + s*sizeof(Value));
-        else
-            new (newMemberData) MemberData(e->memberDataClass);
-        newMemberData->d()->size = newAlloc;
-        m = &newMemberData->data;
-    }
+    uint s = old ? old->size : 0;
+    if (idx < s)
+        return old;
+
+    int newAlloc = qMax((uint)4, 2*idx);
+    uint alloc = sizeof(Data) + (newAlloc)*sizeof(Value);
+    MemberData *newMemberData = static_cast<MemberData *>(e->memoryManager->allocManaged(alloc));
+    if (old)
+        memcpy(newMemberData, old, sizeof(MemberData::Data) + s*sizeof(Value));
+    else
+        new (newMemberData) MemberData(e->memberDataClass);
+    newMemberData->d()->size = newAlloc;
+    return newMemberData->d();
 }
index cc7b10f..0177601 100644 (file)
@@ -53,24 +53,13 @@ struct MemberData : Managed
 
     MemberData(QV4::InternalClass *ic) : Managed(ic) {}
     Value &operator[] (uint idx) { return d()->data[idx]; }
+    const Value *data() const { return d()->data; }
+    Value *data() { return d()->data; }
+    inline uint size() const { return d()->size; }
 
-    static void markObjects(HeapObject *that, ExecutionEngine *e);
-};
+    static MemberData::Data *reallocate(QV4::ExecutionEngine *e, MemberData::Data *old, uint idx);
 
-struct Members : Value
-{
-    void reset() { m = 0; }
-    void ensureIndex(QV4::ExecutionEngine *e, uint idx);
-    Value &operator[] (uint idx) const { return static_cast<MemberData *>(managed())->d()->data[idx]; }
-    inline uint size() const { return d() ? d()->d()->size : 0; }
-    inline MemberData *d() const { return static_cast<MemberData *>(managed()); }
-    Value *data() const { return static_cast<MemberData *>(managed())->d()->data; }
-
-    void mark(ExecutionEngine *e) const {
-        MemberData *m = d();
-        if (m)
-            m->mark(e);
-    }
+    static void markObjects(HeapObject *that, ExecutionEngine *e);
 };
 
 }
index 576537d..f8b0c9f 100644 (file)
@@ -55,7 +55,7 @@ Object::Data::Data(InternalClass *internalClass)
     if (internalClass->size) {
         Scope scope(internalClass->engine);
         ScopedObject o(scope, this);
-        o->memberData().ensureIndex(internalClass->engine, internalClass->size);
+        o->ensureMemberIndex(internalClass->engine, internalClass->size);
     }
 }
 
@@ -182,14 +182,15 @@ void Object::markObjects(HeapObject *that, ExecutionEngine *e)
 {
     Object::Data *o = static_cast<Object::Data *>(that);
 
-    o->memberData.mark(e);
+    if (o->memberData)
+        o->memberData->mark(e);
     if (o->arrayData)
         o->arrayData->mark(e);
 }
 
 void Object::ensureMemberIndex(uint idx)
 {
-    memberData().ensureIndex(engine(), idx);
+    d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
 }
 
 void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes)
@@ -206,7 +207,7 @@ void Object::insertMember(String *s, const Property &p, PropertyAttributes attri
         pp->value = p.value;
         pp->set = p.set;
     } else {
-        memberData()[idx] = p.value;
+        d()->memberData->data[idx] = p.value;
     }
 }
 
@@ -262,7 +263,7 @@ Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *at
         if (idx < UINT_MAX) {
             if (attrs)
                 *attrs = o->internalClass()->propertyData[idx];
-            return o->propertyAt(idx);
+            return const_cast<Property *>(o->propertyAt(idx));
         }
 
         o = o->prototype();
@@ -465,7 +466,7 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
             l->classList[0] = o->internalClass();
             l->index = idx;
             l->setter = Lookup::setter0;
-            o->memberData()[idx] = *value;
+            o->memberData()->data()[idx] = *value;
             return;
         }
 
@@ -1153,7 +1154,7 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
         // special case, as the property is on the object itself
         l->getter = Lookup::arrayLengthGetter;
         ArrayObject *a = static_cast<ArrayObject *>(m);
-        return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
+        return a->memberData()->data()[ArrayObject::LengthPropertyIndex].asReturnedValue();
     }
     return Object::getLookup(m, l);
 }
@@ -1161,9 +1162,9 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
 uint ArrayObject::getLength(const Managed *m)
 {
     const ArrayObject *a = static_cast<const ArrayObject *>(m);
-    if (a->memberData()[ArrayObject::LengthPropertyIndex].isInteger())
-        return a->memberData()[ArrayObject::LengthPropertyIndex].integerValue();
-    return Primitive::toUInt32(a->memberData()[ArrayObject::LengthPropertyIndex].doubleValue());
+    if (a->memberData()->data()[ArrayObject::LengthPropertyIndex].isInteger())
+        return a->memberData()->data()[ArrayObject::LengthPropertyIndex].integerValue();
+    return Primitive::toUInt32(a->memberData()->data()[ArrayObject::LengthPropertyIndex].doubleValue());
 }
 
 QStringList ArrayObject::toQStringList() const
index f11220f..7347232 100644 (file)
@@ -49,8 +49,8 @@ struct Q_QML_EXPORT Object: Managed {
         }
         Data(InternalClass *internal = 0);
 
-        MembermemberData;
-        ArrayData *arrayData;
+        MemberData::Data *memberData;
+        ArrayData::Data *arrayData;
     };
     V4_OBJECT(Object)
     Q_MANAGED_TYPE(Object)
@@ -59,12 +59,14 @@ struct Q_QML_EXPORT Object: Managed {
         IsObject = true
     };
 
-    Members &memberData() { return d()->memberData; }
-    const Members &memberData() const { return d()->memberData; }
-    ArrayData *arrayData() const { return d()->arrayData; }
-    void setArrayData(ArrayData *a) { d()->arrayData = a; }
+    // ### GC
+    MemberData *memberData() { return reinterpret_cast<MemberData *>(d()->memberData); }
+    const MemberData *memberData() const { return reinterpret_cast<const MemberData *>(d()->memberData); }
+    ArrayData *arrayData() const { return reinterpret_cast<ArrayData *>(d()->arrayData); }
+    void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
 
-    Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData().data() + index); }
+    const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData()->data() + index); }
+    Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData()->data() + index); }
 
     const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass()->vtable); }
     Object *prototype() const { return internalClass()->prototype; }
@@ -115,6 +117,10 @@ struct Q_QML_EXPORT Object: Managed {
     void defineReadonlyProperty(const QString &name, ValueRef value);
     void defineReadonlyProperty(String *name, ValueRef value);
 
+    void ensureMemberIndex(QV4::ExecutionEngine *e, uint idx) {
+        d()->memberData = MemberData::reallocate(e, d()->memberData, idx);
+    }
+
     void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
         Property p(*v);
         insertMember(s, p, attributes);
@@ -300,7 +306,7 @@ struct ArrayObject: Object {
         Data(ExecutionEngine *engine, const QStringList &list);
         Data(InternalClass *ic) : Object::Data(ic) { init(); }
         void init()
-        { memberData[LengthPropertyIndex] = Primitive::fromInt32(0); }
+        { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); }
     };
 
     V4_OBJECT(Object)
@@ -321,7 +327,7 @@ struct ArrayObject: Object {
 inline void Object::setArrayLengthUnchecked(uint l)
 {
     if (isArrayObject())
-        memberData()[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+        memberData()->data()[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
 }
 
 inline void Object::push_back(const ValueRef v)
index 23b46c8..2fd91a0 100644 (file)
@@ -390,8 +390,8 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
         array->arrayPut(i, v);
     }
     array->setArrayLengthUnchecked(len);
-    array->memberData()[Index_ArrayIndex] = Primitive::fromInt32(result);
-    array->memberData()[Index_ArrayInput] = arg.asReturnedValue();
+    array->memberData()->data()[Index_ArrayIndex] = Primitive::fromInt32(result);
+    array->memberData()->data()[Index_ArrayInput] = arg.asReturnedValue();
 
     RegExpCtor::Data *dd = regExpCtor->d();
     dd->lastMatch = array;
index b817bc5..fe9d07e 100644 (file)
@@ -1172,7 +1172,7 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu
     }
 
     for (uint i = 0; i < klass->size; ++i)
-        o->memberData()[i] = *args++;
+        o->memberData()->data()[i] = *args++;
 
     if (arrayValueCount > 0) {
         ScopedValue entry(scope);
index a80cc40..e4f84b2 100644 (file)
@@ -91,6 +91,8 @@ double Value::toNumberImpl() const
             ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
             Scope scope(ctx);
             ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), NUMBER_HINT));
+            if (scope.engine->hasException)
+                return 0;
             return prim->toNumber();
         }
 #endif