diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 17 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 57 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 56 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata.cpp | 27 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 24 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value.cpp | 2 |
14 files changed, 135 insertions, 118 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index e8cb788b74..c020e99cbb 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -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); } diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 73c6bb26f3..d961d0881f 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -82,14 +82,14 @@ struct ArgumentsObject: Object { Data(CallContext *context); CallContext *context; bool fullyCreated; - Members mappedArguments; + 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 && diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 1da54b1129..ff9d2cc181 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -77,7 +77,6 @@ struct SyntaxErrorObject; struct ArgumentsObject; struct ExecutionContext; struct ExecutionEngine; -struct Members; class MemoryManager; class ExecutableAllocator; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index deb9e62591..7c93cab0ca 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -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); } diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 1ff8124e6a..07a8c45aed 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -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; - Members boundArgs; + 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); diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index a59c3892a1..0f8eb2bfff 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -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()); } diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index f7ebb62b8d..9d4649b287 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -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; } } diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index de226305f1..bf07a74b96 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -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(); } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index cc7b10ff81..0177601b9f 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -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); }; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 576537dcef..f8b0c9f0a0 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -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 diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index f11220f55c..7347232857 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -49,8 +49,8 @@ struct Q_QML_EXPORT Object: Managed { } Data(InternalClass *internal = 0); - Members memberData; - 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) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 23b46c8492..2fd91a0675 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -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; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b817bc594b..fe9d07e772 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -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); diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index a80cc40add..e4f84b22fb 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -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 |