diff options
Diffstat (limited to 'src/qml/jsruntime')
78 files changed, 3748 insertions, 3546 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 72010d3fa8..c27aaa90d8 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -105,13 +105,6 @@ SOURCES += \ $$PWD/qv4string.cpp \ $$PWD/qv4value.cpp -# Use SSE2 floating point math on 32 bit instead of the default -# 387 to make test results pass on 32 and on 64 bit builds. -linux-g++*:isEqual(QT_ARCH,i386) { - QMAKE_CFLAGS += -march=pentium4 -msse2 -mfpmath=sse - QMAKE_CXXFLAGS += -march=pentium4 -msse2 -mfpmath=sse -} - valgrind { DEFINES += V4_USE_VALGRIND } diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 987b228209..71563b7b0d 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -46,63 +46,58 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArgumentsObject); -ArgumentsObject::ArgumentsObject(CallContext *context) - : Object(context->strictMode ? context->engine->strictArgumentsObjectClass : context->engine->argumentsObjectClass) +ArgumentsObject::Data::Data(CallContext *context) + : Object::Data(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass) , context(context) , fullyCreated(false) { - ExecutionEngine *v4 = context->engine; + Q_ASSERT(internalClass->vtable == staticVTable()); + + ExecutionEngine *v4 = context->d()->engine; Scope scope(v4); - ScopedObject protectThis(scope, this); + Scoped<ArgumentsObject> args(scope, this); - setArrayType(ArrayData::Complex); + args->setArrayType(ArrayData::Complex); - if (context->strictMode) { - Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee)); - Q_ASSERT(CallerPropertyIndex == internalClass->find(context->engine->id_caller)); - propertyAt(CalleePropertyIndex)->value = v4->thrower; - propertyAt(CalleePropertyIndex)->set = v4->thrower; - propertyAt(CallerPropertyIndex)->value = v4->thrower; - propertyAt(CallerPropertyIndex)->set = v4->thrower; + if (context->d()->strictMode) { + Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee)); + Q_ASSERT(CallerPropertyIndex == args->internalClass()->find(context->d()->engine->id_caller)); + args->propertyAt(CalleePropertyIndex)->value = v4->thrower; + args->propertyAt(CalleePropertyIndex)->set = v4->thrower; + args->propertyAt(CallerPropertyIndex)->value = v4->thrower; + args->propertyAt(CallerPropertyIndex)->set = v4->thrower; - arrayReserve(context->callData->argc); - arrayPut(0, context->callData->args, context->callData->argc); - fullyCreated = true; + args->arrayReserve(context->d()->callData->argc); + args->arrayPut(0, context->d()->callData->args, context->d()->callData->argc); + args->d()->fullyCreated = true; } else { - hasAccessorProperty = 1; - Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee)); - memberData[CalleePropertyIndex] = context->function->asReturnedValue(); + args->setHasAccessorProperty(); + Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee)); + args->memberData()[CalleePropertyIndex] = context->d()->function->asReturnedValue(); } - Q_ASSERT(LengthPropertyIndex == internalClass->find(context->engine->id_length)); - memberData[LengthPropertyIndex] = Primitive::fromInt32(context->realArgumentCount); - - Q_ASSERT(internalClass->vtable == staticVTable()); -} - -void ArgumentsObject::destroy(Managed *that) -{ - static_cast<ArgumentsObject *>(that)->~ArgumentsObject(); + Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length)); + args->memberData()[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount); } void ArgumentsObject::fullyCreate() { - if (fullyCreated) + if (fullyCreated()) return; - uint numAccessors = qMin((int)context->function->formalParameterCount(), context->realArgumentCount); - uint argCount = qMin(context->realArgumentCount, context->callData->argc); + uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount); + uint argCount = qMin(context()->d()->realArgumentCount, context()->d()->callData->argc); ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true); - context->engine->requireArgumentsAccessors(numAccessors); - mappedArguments.ensureIndex(engine(), numAccessors); + context()->d()->engine->requireArgumentsAccessors(numAccessors); + mappedArguments().ensureIndex(engine(), numAccessors); for (uint i = 0; i < (uint)numAccessors; ++i) { - mappedArguments[i] = context->callData->args[i]; - arraySet(i, context->engine->argumentsAccessors[i], Attr_Accessor); + mappedArguments()[i] = context()->d()->callData->args[i]; + arraySet(i, context()->d()->engine->argumentsAccessors[i], Attr_Accessor); } - arrayPut(numAccessors, context->callData->args + numAccessors, argCount - numAccessors); + arrayPut(numAccessors, context()->d()->callData->args + numAccessors, argCount - numAccessors); for (uint i = numAccessors; i < argCount; ++i) setArrayAttributes(i, Attr_Data); - fullyCreated = true; + d()->fullyCreated = true; } bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs) @@ -110,26 +105,26 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const fullyCreate(); Scope scope(ctx); - Property *pd = arrayData->getProperty(index); + Property *pd = arrayData()->getProperty(index); Property map; PropertyAttributes mapAttrs; bool isMapped = false; - uint numAccessors = qMin((int)context->function->formalParameterCount(), context->realArgumentCount); + uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount); if (pd && index < (uint)numAccessors) - isMapped = arrayData->attributes(index).isAccessor() && pd->getter() == context->engine->argumentsAccessors[index].getter(); + isMapped = arrayData()->attributes(index).isAccessor() && pd->getter() == context()->d()->engine->argumentsAccessors[index].getter(); if (isMapped) { - mapAttrs = arrayData->attributes(index); + mapAttrs = arrayData()->attributes(index); map.copy(*pd, mapAttrs); setArrayAttributes(index, Attr_Data); - pd = arrayData->getProperty(index); - pd->value = mappedArguments[index]; + pd = arrayData()->getProperty(index); + pd->value = mappedArguments()[index]; } - bool strict = ctx->strictMode; - ctx->strictMode = false; + bool strict = ctx->d()->strictMode; + ctx->d()->strictMode = false; bool result = Object::defineOwnProperty2(ctx, index, desc, attrs); - ctx->strictMode = strict; + ctx->d()->strictMode = strict; if (isMapped && attrs.isData()) { ScopedCallData callData(scope, 1); @@ -139,12 +134,12 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const if (attrs.isWritable()) { setArrayAttributes(index, mapAttrs); - pd = arrayData->getProperty(index); + pd = arrayData()->getProperty(index); pd->copy(map, mapAttrs); } } - if (ctx->strictMode && !result) + if (ctx->d()->strictMode && !result) return ctx->throwTypeError(); return result; } @@ -152,13 +147,13 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty) { ArgumentsObject *args = static_cast<ArgumentsObject *>(m); - if (args->fullyCreated) + if (args->fullyCreated()) return Object::getIndexed(m, index, hasProperty); - if (index < static_cast<uint>(args->context->callData->argc)) { + if (index < static_cast<uint>(args->context()->d()->callData->argc)) { if (hasProperty) *hasProperty = true; - return args->context->callData->args[index].asReturnedValue(); + return args->context()->d()->callData->args[index].asReturnedValue(); } if (hasProperty) *hasProperty = false; @@ -168,21 +163,21 @@ ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasPrope void ArgumentsObject::putIndexed(Managed *m, uint index, const ValueRef value) { ArgumentsObject *args = static_cast<ArgumentsObject *>(m); - if (!args->fullyCreated && index >= static_cast<uint>(args->context->callData->argc)) + if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->d()->callData->argc)) args->fullyCreate(); - if (args->fullyCreated) { + if (args->fullyCreated()) { Object::putIndexed(m, index, value); return; } - args->context->callData->args[index] = value; + args->context()->d()->callData->args[index] = value; } bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index) { ArgumentsObject *args = static_cast<ArgumentsObject *>(m); - if (!args->fullyCreated) + if (!args->fullyCreated()) args->fullyCreate(); return Object::deleteIndexedProperty(m, index); } @@ -190,11 +185,11 @@ bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index) PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index) { const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m); - if (args->fullyCreated) + if (args->fullyCreated()) return Object::queryIndexed(m, index); - uint numAccessors = qMin((int)args->context->function->formalParameterCount(), args->context->realArgumentCount); - uint argCount = qMin(args->context->realArgumentCount, args->context->callData->argc); + uint numAccessors = qMin((int)args->context()->d()->function->formalParameterCount(), args->context()->d()->realArgumentCount); + uint argCount = qMin(args->context()->d()->realArgumentCount, args->context()->d()->callData->argc); if (index >= argCount) return PropertyAttributes(); if (index >= numAccessors) @@ -213,8 +208,8 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData) if (!o) return v4->currentContext()->throwTypeError(); - Q_ASSERT(g->index < static_cast<unsigned>(o->context->callData->argc)); - return o->context->argument(g->index); + Q_ASSERT(g->index() < static_cast<unsigned>(o->context()->d()->callData->argc)); + return o->context()->argument(g->index()); } DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction); @@ -228,17 +223,17 @@ ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData) if (!o) return v4->currentContext()->throwTypeError(); - Q_ASSERT(s->index < static_cast<unsigned>(o->context->callData->argc)); - o->context->callData->args[s->index] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined(); + Q_ASSERT(s->index() < static_cast<unsigned>(o->context()->d()->callData->argc)); + o->context()->d()->callData->args[s->index()] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined(); return Encode::undefined(); } void ArgumentsObject::markObjects(Managed *that, ExecutionEngine *e) { ArgumentsObject *o = static_cast<ArgumentsObject *>(that); - if (o->context) - o->context->mark(e); - o->mappedArguments.mark(e); + if (o->context()) + o->context()->mark(e); + 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 80c2a70501..59ab9f020e 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -50,43 +50,58 @@ namespace QV4 { struct ArgumentsGetterFunction: FunctionObject { - V4_OBJECT - uint index; + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, uint index) + : FunctionObject::Data(scope) + , index(index) + { + setVTable(staticVTable()); + } + uint index; + }; + V4_OBJECT(FunctionObject) - ArgumentsGetterFunction(ExecutionContext *scope, uint index) - : FunctionObject(scope), index(index) { - setVTable(staticVTable()); - } + uint index() const { return d()->index; } static ReturnedValue call(Managed *that, CallData *d); }; struct ArgumentsSetterFunction: FunctionObject { - V4_OBJECT - uint index; + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, uint index) + : FunctionObject::Data(scope) + , index(index) + { + setVTable(staticVTable()); + } + uint index; + }; + V4_OBJECT(FunctionObject) - ArgumentsSetterFunction(ExecutionContext *scope, uint index) - : FunctionObject(scope), index(index) { - setVTable(staticVTable()); - } + uint index() const { return d()->index; } static ReturnedValue call(Managed *that, CallData *callData); }; struct ArgumentsObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(CallContext *context); + CallContext *context; + bool fullyCreated; + Members mappedArguments; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(ArgumentsObject) - CallContext *context; - bool fullyCreated; - Members mappedArguments; - ArgumentsObject(CallContext *context); - ~ArgumentsObject() {} + + CallContext *context() const { return d()->context; } + bool fullyCreated() const { return d()->fullyCreated; } + Members &mappedArguments() { return d()->mappedArguments; } static bool isNonStrictArgumentsObject(Managed *m) { - return m->internalClass->vtable->type == Type_ArgumentsObject && - !static_cast<ArgumentsObject *>(m)->context->strictMode; + return m->internalClass()->vtable->type == Type_ArgumentsObject && + !static_cast<ArgumentsObject *>(m)->context()->d()->strictMode; } enum { @@ -100,7 +115,6 @@ struct ArgumentsObject: Object { static bool deleteIndexedProperty(Managed *m, uint index); static PropertyAttributes queryIndexed(const Managed *m, uint index); static void markObjects(Managed *that, ExecutionEngine *e); - static void destroy(Managed *); void fullyCreate(); }; diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index ed2122fb89..f56c31b177 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -45,9 +45,25 @@ using namespace QV4; +const QV4::ManagedVTable QV4::ArrayData::static_vtbl = { + 0, + QV4::ArrayData::IsExecutionContext, + QV4::ArrayData::IsString, + QV4::ArrayData::IsObject, + QV4::ArrayData::IsFunctionObject, + QV4::ArrayData::IsErrorObject, + QV4::ArrayData::IsArrayData, + 0, + QV4::ArrayData::MyType, + "ArrayData", + Q_VTABLE_FUNCTION(QV4::ArrayData, destroy), + 0, + isEqualTo +}; + const ArrayVTable SimpleArrayData::static_vtbl = { - DEFINE_MANAGED_VTABLE_INT(SimpleArrayData), + DEFINE_MANAGED_VTABLE_INT(SimpleArrayData, 0), SimpleArrayData::Simple, SimpleArrayData::reallocate, SimpleArrayData::get, @@ -64,7 +80,7 @@ const ArrayVTable SimpleArrayData::static_vtbl = const ArrayVTable SparseArrayData::static_vtbl = { - DEFINE_MANAGED_VTABLE_INT(SparseArrayData), + DEFINE_MANAGED_VTABLE_INT(SparseArrayData, 0), ArrayData::Sparse, SparseArrayData::reallocate, SparseArrayData::get, @@ -82,7 +98,7 @@ const ArrayVTable SparseArrayData::static_vtbl = void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes) { - ArrayData *d = o->arrayData; + ArrayData *d = o->arrayData(); uint oldAlloc = 0; uint toCopy = 0; @@ -90,19 +106,19 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e alloc = 8; if (d) { - bool hasAttrs = d->attrs; + bool hasAttrs = d->attrs(); enforceAttributes |= hasAttrs; - if (!offset && alloc <= d->alloc && newType == d->type && hasAttrs == enforceAttributes) + if (!offset && alloc <= d->alloc() && newType == d->type() && hasAttrs == enforceAttributes) return; - oldAlloc = d->alloc; - if (d->type < Sparse) { - offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset); - toCopy = static_cast<SimpleArrayData *>(d)->len; + oldAlloc = d->alloc(); + if (d->type() < Sparse) { + offset = qMax(offset, static_cast<SimpleArrayData *>(d)->offset()); + toCopy = static_cast<SimpleArrayData *>(d)->len(); } else { Q_ASSERT(!offset); - toCopy = d->alloc; + toCopy = d->alloc(); newType = Sparse; } } @@ -115,69 +131,69 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e size += alloc*sizeof(PropertyAttributes); if (newType < Sparse) { - size += sizeof(SimpleArrayData); + size += sizeof(SimpleArrayData::Data); SimpleArrayData *newData = static_cast<SimpleArrayData *>(o->engine()->memoryManager->allocManaged(size)); - new (newData) SimpleArrayData(o->engine()); - newData->alloc = alloc - offset; - newData->type = newType; - newData->data = reinterpret_cast<Value *>(newData + 1) + offset; - newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) + offset : 0; - newData->offset = offset; - newData->len = d ? static_cast<SimpleArrayData *>(d)->len : 0; - o->arrayData = newData; + new (newData->d()) SimpleArrayData::Data(o->engine()); + newData->setAlloc(alloc - offset); + newData->setType(newType); + newData->setArrayData(reinterpret_cast<Value *>(newData->d() + 1) + offset); + newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->arrayData() + alloc) + offset : 0); + newData->offset() = offset; + newData->len() = d ? static_cast<SimpleArrayData *>(d)->len() : 0; + o->setArrayData(newData); } else { - size += sizeof(SparseArrayData); + size += sizeof(SparseArrayData::Data); SparseArrayData *newData = static_cast<SparseArrayData *>(o->engine()->memoryManager->allocManaged(size)); - new (newData) SparseArrayData(o->engine()); - newData->alloc = alloc; - newData->type = newType; - newData->data = reinterpret_cast<Value *>(newData + 1); - newData->attrs = enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->data + alloc) : 0; - o->arrayData = newData; + new (newData->d()) SparseArrayData::Data(o->engine()); + newData->setAlloc(alloc); + newData->setType(newType); + newData->setArrayData(reinterpret_cast<Value *>(newData->d() + 1)); + newData->setAttrs(enforceAttributes ? reinterpret_cast<PropertyAttributes *>(newData->arrayData() + alloc) : 0); + o->setArrayData(newData); } if (d) { - memcpy(o->arrayData->data, d->data, sizeof(Value)*toCopy); + memcpy(o->arrayData()->arrayData(), d->arrayData(), sizeof(Value)*toCopy); if (enforceAttributes) { - if (d->attrs) - memcpy(o->arrayData->attrs, d->attrs, sizeof(PropertyAttributes)*toCopy); + if (d->attrs()) + memcpy(o->arrayData()->attrs(), d->attrs(), sizeof(PropertyAttributes)*toCopy); else for (uint i = 0; i < toCopy; ++i) - o->arrayData->attrs[i] = Attr_Data; + o->arrayData()->attrs()[i] = Attr_Data; } } if (newType != Sparse) return; - SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData); - if (d && d->type == Sparse) { + SparseArrayData *newData = static_cast<SparseArrayData *>(o->arrayData()); + if (d && d->type() == Sparse) { SparseArrayData *old = static_cast<SparseArrayData *>(d); - newData->sparse = old->sparse; - old->sparse = 0; - newData->freeList = old->freeList; + newData->setSparse(old->sparse()); + old->setSparse(0); + newData->freeList() = old->freeList(); } else { - newData->sparse = new SparseArray; - uint *lastFree = &newData->freeList; + newData->setSparse(new SparseArray); + uint *lastFree = &newData->freeList(); for (uint i = 0; i < toCopy; ++i) { - if (!newData->data[i].isEmpty()) { - SparseArrayNode *n = newData->sparse->insert(i); + if (!newData->arrayData()[i].isEmpty()) { + SparseArrayNode *n = newData->sparse()->insert(i); n->value = i; } else { *lastFree = i; - newData->data[i].tag = Value::Empty_Type; - lastFree = &newData->data[i].uint_32; + newData->arrayData()[i].tag = Value::Empty_Type; + lastFree = &newData->arrayData()[i].uint_32; } } } - uint *lastFree = &newData->freeList; - for (uint i = toCopy; i < newData->alloc; ++i) { + uint *lastFree = &newData->freeList(); + for (uint i = toCopy; i < newData->alloc(); ++i) { *lastFree = i; - newData->data[i].tag = Value::Empty_Type; - lastFree = &newData->data[i].uint_32; + newData->arrayData()[i].tag = Value::Empty_Type; + lastFree = &newData->arrayData()[i].uint_32; } - *lastFree = newData->alloc; + *lastFree = newData->alloc(); // ### Could explicitly free the old data } @@ -185,248 +201,244 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e void SimpleArrayData::getHeadRoom(Object *o) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); Q_ASSERT(dd); - Q_ASSERT(!dd->offset); - uint offset = qMax(dd->len >> 2, (uint)16); + Q_ASSERT(!dd->offset()); + uint offset = qMax(dd->len() >> 2, (uint)16); realloc(o, Simple, offset, 0, false); } ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes) { realloc(o, Simple, 0, n, enforceAttributes); - return o->arrayData; + return o->arrayData(); } void ArrayData::ensureAttributes(Object *o) { - if (o->arrayData && o->arrayData->attrs) + if (o->arrayData() && o->arrayData()->attrs()) return; ArrayData::realloc(o, Simple, 0, 0, true); } -void SimpleArrayData::destroy(Managed *) -{ -} - void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e) { SimpleArrayData *dd = static_cast<SimpleArrayData *>(d); - uint l = dd->len; + uint l = dd->len(); for (uint i = 0; i < l; ++i) - dd->data[i].mark(e); + dd->arrayData()[i].mark(e); } ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index) { const SimpleArrayData *dd = static_cast<const SimpleArrayData *>(d); - if (index >= dd->len) + if (index >= dd->len()) return Primitive::emptyValue().asReturnedValue(); - return dd->data[index].asReturnedValue(); + return dd->arrayData()[index].asReturnedValue(); } bool SimpleArrayData::put(Object *o, uint index, ValueRef value) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor()); + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + Q_ASSERT(index >= dd->len() || !dd->attrs() || !dd->attrs()[index].isAccessor()); // ### honour attributes - dd->data[index] = value; - if (index >= dd->len) { - if (dd->attrs) - dd->attrs[index] = Attr_Data; - dd->len = index + 1; + dd->arrayData()[index] = value; + if (index >= dd->len()) { + if (dd->attrs()) + dd->attrs()[index] = Attr_Data; + dd->len() = index + 1; } return true; } bool SimpleArrayData::del(Object *o, uint index) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - if (index >= dd->len) + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + if (index >= dd->len()) return true; - if (!dd->attrs || dd->attrs[index].isConfigurable()) { - dd->data[index] = Primitive::emptyValue(); - if (dd->attrs) - dd->attrs[index] = Attr_Data; + if (!dd->attrs() || dd->attrs()[index].isConfigurable()) { + dd->arrayData()[index] = Primitive::emptyValue(); + if (dd->attrs()) + dd->attrs()[index] = Attr_Data; return true; } - if (dd->data[index].isEmpty()) + if (dd->arrayData()[index].isEmpty()) return true; return false; } void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs) { - o->arrayData->attrs[index] = attrs; + o->arrayData()->attrs()[index] = attrs; } PropertyAttributes SimpleArrayData::attribute(const ArrayData *d, uint index) { - return d->attrs[index]; + return d->attrs()[index]; } void SimpleArrayData::push_front(Object *o, Value *values, uint n) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - Q_ASSERT(!dd->attrs); + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + Q_ASSERT(!dd->attrs()); for (int i = n - 1; i >= 0; --i) { - if (!dd->offset) { + if (!dd->offset()) { getHeadRoom(o); - dd = static_cast<SimpleArrayData *>(o->arrayData); + dd = static_cast<SimpleArrayData *>(o->arrayData()); } - --dd->offset; - --dd->data; - ++dd->len; - ++dd->alloc; - *dd->data = values[i].asReturnedValue(); + --dd->offset(); + --dd->arrayData(); + ++dd->len(); + ++dd->alloc(); + *dd->arrayData() = values[i].asReturnedValue(); } } ReturnedValue SimpleArrayData::pop_front(Object *o) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - Q_ASSERT(!dd->attrs); - if (!dd->len) + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + Q_ASSERT(!dd->attrs()); + if (!dd->len()) return Encode::undefined(); - ReturnedValue v = dd->data[0].isEmpty() ? Encode::undefined() : dd->data[0].asReturnedValue(); - ++dd->offset; - ++dd->data; - --dd->len; - --dd->alloc; + ReturnedValue v = dd->arrayData()[0].isEmpty() ? Encode::undefined() : dd->arrayData()[0].asReturnedValue(); + ++dd->offset(); + ++dd->arrayData(); + --dd->len(); + --dd->alloc(); return v; } uint SimpleArrayData::truncate(Object *o, uint newLen) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - if (dd->len < newLen) + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + if (dd->len() < newLen) return newLen; - if (dd->attrs) { - Value *it = dd->data + dd->len; - const Value *begin = dd->data + newLen; + if (dd->attrs()) { + Value *it = dd->arrayData() + dd->len(); + const Value *begin = dd->arrayData() + newLen; while (--it >= begin) { - if (!it->isEmpty() && !dd->attrs[it - dd->data].isConfigurable()) { - newLen = it - dd->data + 1; + if (!it->isEmpty() && !dd->attrs()[it - dd->arrayData()].isConfigurable()) { + newLen = it - dd->arrayData() + 1; break; } *it = Primitive::emptyValue(); } } - dd->len = newLen; + dd->len() = newLen; return newLen; } uint SimpleArrayData::length(const ArrayData *d) { - return static_cast<const SimpleArrayData *>(d)->len; + return static_cast<const SimpleArrayData *>(d)->len(); } bool SimpleArrayData::putArray(Object *o, uint index, Value *values, uint n) { - SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData); - if (index + n > dd->alloc) { + SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData()); + if (index + n > dd->alloc()) { reallocate(o, index + n + 1, false); - dd = static_cast<SimpleArrayData *>(o->arrayData); + dd = static_cast<SimpleArrayData *>(o->arrayData()); } - for (uint i = dd->len; i < index; ++i) - dd->data[i] = Primitive::emptyValue(); + for (uint i = dd->len(); i < index; ++i) + dd->arrayData()[i] = Primitive::emptyValue(); for (uint i = 0; i < n; ++i) - dd->data[index + i] = values[i]; - dd->len = qMax(dd->len, index + n); + dd->arrayData()[index + i] = values[i]; + dd->len() = qMax(dd->len(), index + n); return true; } void SparseArrayData::free(ArrayData *d, uint idx) { - Q_ASSERT(d && d->type == ArrayData::Sparse); + Q_ASSERT(d && d->type() == ArrayData::Sparse); SparseArrayData *dd = static_cast<SparseArrayData *>(d); - Value *v = dd->data + idx; - if (dd->attrs && dd->attrs[idx].isAccessor()) { + Value *v = dd->arrayData() + idx; + if (dd->attrs() && dd->attrs()[idx].isAccessor()) { // double slot, free both. Order is important, so we have a double slot for allocation again afterwards. v[1].tag = Value::Empty_Type; - v[1].uint_32 = dd->freeList; + v[1].uint_32 = dd->freeList(); v[0].tag = Value::Empty_Type; v[0].uint_32 = idx + 1; } else { v->tag = Value::Empty_Type; - v->uint_32 = dd->freeList; + v->uint_32 = dd->freeList(); } - dd->freeList = idx; - if (dd->attrs) - dd->attrs[idx].clear(); + dd->freeList() = idx; + if (dd->attrs()) + dd->attrs()[idx].clear(); } void SparseArrayData::destroy(Managed *d) { SparseArrayData *dd = static_cast<SparseArrayData *>(d); - delete dd->sparse; + delete dd->sparse(); } void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e) { SparseArrayData *dd = static_cast<SparseArrayData *>(d); - uint l = dd->alloc; + uint l = dd->alloc(); for (uint i = 0; i < l; ++i) - dd->data[i].mark(e); + dd->arrayData()[i].mark(e); } ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes) { realloc(o, Sparse, 0, n, enforceAttributes); - return o->arrayData; + return o->arrayData(); } // double slots are required for accessor properties uint SparseArrayData::allocate(Object *o, bool doubleSlot) { - Q_ASSERT(o->arrayData->type == ArrayData::Sparse); - SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData); + Q_ASSERT(o->arrayData()->type() == ArrayData::Sparse); + SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData()); if (doubleSlot) { - uint *last = &dd->freeList; + uint *last = &dd->freeList(); while (1) { - if (*last + 1 >= dd->alloc) { - reallocate(o, o->arrayData->alloc + 2, true); - dd = static_cast<SparseArrayData *>(o->arrayData); - last = &dd->freeList; + if (*last + 1 >= dd->alloc()) { + reallocate(o, o->arrayData()->alloc() + 2, true); + dd = static_cast<SparseArrayData *>(o->arrayData()); + last = &dd->freeList(); } - if (dd->data[*last].uint_32 == (*last + 1)) { + if (dd->arrayData()[*last].uint_32 == (*last + 1)) { // found two slots in a row uint idx = *last; - *last = dd->data[*last + 1].uint_32; - o->arrayData->attrs[idx] = Attr_Accessor; + *last = dd->arrayData()[*last + 1].uint_32; + o->arrayData()->attrs()[idx] = Attr_Accessor; return idx; } - last = &dd->data[*last].uint_32; + last = &dd->arrayData()[*last].uint_32; } } else { - if (dd->alloc == dd->freeList) { - reallocate(o, o->arrayData->alloc + 2, false); - dd = static_cast<SparseArrayData *>(o->arrayData); + if (dd->alloc() == dd->freeList()) { + reallocate(o, o->arrayData()->alloc() + 2, false); + dd = static_cast<SparseArrayData *>(o->arrayData()); } - uint idx = dd->freeList; - dd->freeList = dd->data[idx].uint_32; - if (dd->attrs) - dd->attrs[idx] = Attr_Data; + uint idx = dd->freeList(); + dd->freeList() = dd->arrayData()[idx].uint_32; + if (dd->attrs()) + dd->attrs()[idx] = Attr_Data; return idx; } } ReturnedValue SparseArrayData::get(const ArrayData *d, uint index) { - SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->findNode(index); + SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse()->findNode(index); if (!n) return Primitive::emptyValue().asReturnedValue(); - return d->data[n->value].asReturnedValue(); + return d->arrayData()[n->value].asReturnedValue(); } bool SparseArrayData::put(Object *o, uint index, ValueRef value) @@ -434,93 +446,93 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) if (value->isEmpty()) return true; - SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index); - Q_ASSERT(n->value == UINT_MAX || !o->arrayData->attrs || !o->arrayData->attrs[n->value].isAccessor()); + SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData())->sparse()->insert(index); + Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor()); if (n->value == UINT_MAX) n->value = allocate(o); - o->arrayData->data[n->value] = value; - if (o->arrayData->attrs) - o->arrayData->attrs[n->value] = Attr_Data; + o->arrayData()->arrayData()[n->value] = value; + if (o->arrayData()->attrs()) + o->arrayData()->attrs()[n->value] = Attr_Data; return true; } bool SparseArrayData::del(Object *o, uint index) { - SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData); - SparseArrayNode *n = dd->sparse->findNode(index); + SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData()); + SparseArrayNode *n = dd->sparse()->findNode(index); if (!n) return true; uint pidx = n->value; - Q_ASSERT(!dd->data[pidx].isEmpty()); + Q_ASSERT(!dd->arrayData()[pidx].isEmpty()); bool isAccessor = false; - if (dd->attrs) { - if (!dd->attrs[pidx].isConfigurable()) + if (dd->attrs()) { + if (!dd->attrs()[pidx].isConfigurable()) return false; - isAccessor = dd->attrs[pidx].isAccessor(); - dd->attrs[pidx] = Attr_Data; + isAccessor = dd->attrs()[pidx].isAccessor(); + dd->attrs()[pidx] = Attr_Data; } if (isAccessor) { // free up both indices - dd->data[pidx + 1].tag = Value::Undefined_Type; - dd->data[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList; - dd->data[pidx].tag = Value::Undefined_Type; - dd->data[pidx].uint_32 = pidx + 1; + dd->arrayData()[pidx + 1].tag = Value::Undefined_Type; + dd->arrayData()[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList(); + dd->arrayData()[pidx].tag = Value::Undefined_Type; + dd->arrayData()[pidx].uint_32 = pidx + 1; } else { - dd->data[pidx].tag = Value::Undefined_Type; - dd->data[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList; + dd->arrayData()[pidx].tag = Value::Undefined_Type; + dd->arrayData()[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList(); } - dd->freeList = pidx; - dd->sparse->erase(n); + dd->freeList() = pidx; + dd->sparse()->erase(n); return true; } void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs) { - SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData); - SparseArrayNode *n = d->sparse->insert(index); + SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData()); + SparseArrayNode *n = d->sparse()->insert(index); if (n->value == UINT_MAX) { n->value = allocate(o, attrs.isAccessor()); - d = static_cast<SparseArrayData *>(o->arrayData); + d = static_cast<SparseArrayData *>(o->arrayData()); } - else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) { + else if (attrs.isAccessor() != d->attrs()[n->value].isAccessor()) { // need to convert the slot free(d, n->value); n->value = allocate(o, attrs.isAccessor()); } - o->arrayData->attrs[n->value] = attrs; + o->arrayData()->attrs()[n->value] = attrs; } PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index) { - SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse->insert(index); + SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse()->insert(index); if (!n) return PropertyAttributes(); - return d->attrs[n->value]; + return d->attrs()[n->value]; } void SparseArrayData::push_front(Object *o, Value *values, uint n) { - Q_ASSERT(!o->arrayData->attrs); + Q_ASSERT(!o->arrayData()->attrs()); for (int i = n - 1; i >= 0; --i) { uint idx = allocate(o); - o->arrayData->data[idx] = values[i]; - static_cast<SparseArrayData *>(o->arrayData)->sparse->push_front(idx); + o->arrayData()->arrayData()[idx] = values[i]; + static_cast<SparseArrayData *>(o->arrayData())->sparse()->push_front(idx); } } ReturnedValue SparseArrayData::pop_front(Object *o) { - Q_ASSERT(!o->arrayData->attrs); - uint idx = static_cast<SparseArrayData *>(o->arrayData)->sparse->pop_front(); + Q_ASSERT(!o->arrayData()->attrs()); + uint idx = static_cast<SparseArrayData *>(o->arrayData())->sparse()->pop_front(); ReturnedValue v; if (idx != UINT_MAX) { - v = o->arrayData->data[idx].asReturnedValue(); - free(o->arrayData, idx); + v = o->arrayData()->arrayData()[idx].asReturnedValue(); + free(o->arrayData(), idx); } else { v = Encode::undefined(); } @@ -529,13 +541,13 @@ ReturnedValue SparseArrayData::pop_front(Object *o) uint SparseArrayData::truncate(Object *o, uint newLen) { - SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData); - SparseArrayNode *begin = d->sparse->lowerBound(newLen); - if (begin != d->sparse->end()) { - SparseArrayNode *it = d->sparse->end()->previousNode(); + SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData()); + SparseArrayNode *begin = d->sparse()->lowerBound(newLen); + if (begin != d->sparse()->end()) { + SparseArrayNode *it = d->sparse()->end()->previousNode(); while (1) { - if (d->attrs) { - if (!d->attrs[it->value].isConfigurable()) { + if (d->attrs()) { + if (!d->attrs()[it->value].isConfigurable()) { newLen = it->key() + 1; break; } @@ -543,7 +555,7 @@ uint SparseArrayData::truncate(Object *o, uint newLen) free(d, it->value); bool brk = (it == begin); SparseArrayNode *prev = it->previousNode(); - static_cast<SparseArrayData *>(d)->sparse->erase(it); + static_cast<SparseArrayData *>(d)->sparse()->erase(it); if (brk) break; it = prev; @@ -555,9 +567,9 @@ uint SparseArrayData::truncate(Object *o, uint newLen) uint SparseArrayData::length(const ArrayData *d) { const SparseArrayData *dd = static_cast<const SparseArrayData *>(d); - if (!dd->sparse) + if (!dd->sparse()) return 0; - SparseArrayNode *n = dd->sparse->end(); + SparseArrayNode *n = dd->sparse()->end(); n = n->previousNode(); return n ? n->key() + 1 : 0; } @@ -572,12 +584,12 @@ bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n) uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) { - Q_ASSERT(!obj->arrayData->hasAttributes()); + Q_ASSERT(!obj->arrayData()->hasAttributes()); if (!n) return obj->getLength(); - const ArrayData *other = otherObj->arrayData; + const ArrayData *other = otherObj->arrayData(); if (other->isSparse()) obj->initSparseArray(); @@ -587,21 +599,21 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) uint oldSize = obj->getLength(); if (other->isSparse()) { - if (otherObj->hasAccessorProperty && other->hasAttributes()) { + if (otherObj->hasAccessorProperty() && other->hasAttributes()) { Scope scope(obj->engine()); ScopedValue v(scope); - for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin(); - it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode()) { - v = otherObj->getValue(reinterpret_cast<Property *>(other->data + it->value), other->attrs[it->value]); + for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse()->begin(); + it != static_cast<const SparseArrayData *>(other)->sparse()->end(); it = it->nextNode()) { + v = otherObj->getValue(reinterpret_cast<Property *>(other->arrayData() + it->value), other->attrs()[it->value]); obj->arraySet(oldSize + it->key(), v); } } else { - for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse->begin(); - it != static_cast<const SparseArrayData *>(other)->sparse->end(); it = it->nextNode()) - obj->arraySet(oldSize + it->key(), ValueRef(other->data[it->value])); + for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse()->begin(); + it != static_cast<const SparseArrayData *>(other)->sparse()->end(); it = it->nextNode()) + obj->arraySet(oldSize + it->key(), ValueRef(other->arrayData()[it->value])); } } else { - obj->arrayPut(oldSize, other->data, n); + obj->arrayPut(oldSize, other->arrayData(), n); } return oldSize + n; @@ -609,42 +621,42 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) Property *ArrayData::insert(Object *o, uint index, bool isAccessor) { - if (!isAccessor && o->arrayData->type != ArrayData::Sparse) { - SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData); - if (index < 0x1000 || index < d->len + (d->len >> 2)) { - if (index >= o->arrayData->alloc) { + if (!isAccessor && o->arrayData()->type() != ArrayData::Sparse) { + SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData()); + if (index < 0x1000 || index < d->len() + (d->len() >> 2)) { + if (index >= o->arrayData()->alloc()) { o->arrayReserve(index + 1); - d = static_cast<SimpleArrayData *>(o->arrayData); + d = static_cast<SimpleArrayData *>(o->arrayData()); } - if (index >= d->len) { + if (index >= d->len()) { // mark possible hole in the array - for (uint i = d->len; i < index; ++i) - d->data[i] = Primitive::emptyValue(); - d->len = index + 1; + for (uint i = d->len(); i < index; ++i) + d->arrayData()[i] = Primitive::emptyValue(); + d->len() = index + 1; } - return reinterpret_cast<Property *>(o->arrayData->data + index); + return reinterpret_cast<Property *>(o->arrayData()->arrayData() + index); } } o->initSparseArray(); - SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData)->sparse->insert(index); + SparseArrayNode *n = static_cast<SparseArrayData *>(o->arrayData())->sparse()->insert(index); if (n->value == UINT_MAX) n->value = SparseArrayData::allocate(o, isAccessor); - return reinterpret_cast<Property *>(o->arrayData->data + n->value); + return reinterpret_cast<Property *>(o->arrayData()->arrayData() + n->value); } class ArrayElementLessThan { public: - inline ArrayElementLessThan(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn) + inline ArrayElementLessThan(ExecutionContext *context, Object *thisObject, const ValueRef comparefn) : m_context(context), thisObject(thisObject), m_comparefn(comparefn) {} bool operator()(const Value &v1, const Value &v2) const; private: ExecutionContext *m_context; - ObjectRef thisObject; + Object *thisObject; const ValueRef m_comparefn; }; @@ -674,12 +686,12 @@ bool ArrayElementLessThan::operator()(const Value &v1, const Value &v2) const return p1s->toQString() < p2s->toQString(); } -void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint len) +void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint len) { if (!len) return; - if (!thisObject->arrayData->length()) + if (!thisObject->arrayData()->length()) return; if (!(comparefn->isUndefined() || comparefn->asObject())) { @@ -690,50 +702,50 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu // The spec says the sorting goes through a series of get,put and delete operations. // this implies that the attributes don't get sorted around. - if (thisObject->arrayData->type == ArrayData::Sparse) { + if (thisObject->arrayData()->type() == ArrayData::Sparse) { // since we sort anyway, we can simply iterate over the entries in the sparse // array and append them one by one to a regular one. - SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData); + SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData()); - if (!sparse->sparse->nEntries()) + if (!sparse->sparse()->nEntries()) return; - thisObject->arrayData = 0; - ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse->nEntries(), sparse->attrs ? true : false); - SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData); + thisObject->setArrayData(0); + ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse()->nEntries(), sparse->attrs() ? true : false); + SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData()); - SparseArrayNode *n = sparse->sparse->begin(); + SparseArrayNode *n = sparse->sparse()->begin(); uint i = 0; - if (sparse->attrs) { - while (n != sparse->sparse->end()) { + if (sparse->attrs()) { + while (n != sparse->sparse()->end()) { if (n->value >= len) break; - PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data; - d->data[i] = thisObject->getValue(reinterpret_cast<Property *>(sparse->data + n->value), a); - d->attrs[i] = a.isAccessor() ? Attr_Data : a; + PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data; + d->arrayData()[i] = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a); + d->attrs()[i] = a.isAccessor() ? Attr_Data : a; n = n->nextNode(); ++i; } } else { - while (n != sparse->sparse->end()) { + while (n != sparse->sparse()->end()) { if (n->value >= len) break; - d->data[i] = sparse->data[n->value]; + d->arrayData()[i] = sparse->arrayData()[n->value]; n = n->nextNode(); ++i; } } - d->len = i; + d->len() = i; if (len > i) len = i; - if (n != sparse->sparse->end()) { + if (n != sparse->sparse()->end()) { // have some entries outside the sort range that we need to ignore when sorting thisObject->initSparseArray(); - while (n != sparse->sparse->end()) { - PropertyAttributes a = sparse->attrs ? sparse->attrs[n->value] : Attr_Data; - thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->data + n->value), a); + while (n != sparse->sparse()->end()) { + PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data; + thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->arrayData() + n->value), a); n = n->nextNode(); } @@ -741,19 +753,19 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu } // ### explicitly delete sparse } else { - SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData); - if (len > d->len) - len = d->len; + SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData()); + if (len > d->len()) + len = d->len(); // sort empty values to the end for (uint i = 0; i < len; i++) { - if (thisObject->arrayData->data[i].isEmpty()) { + if (thisObject->arrayData()->arrayData()[i].isEmpty()) { while (--len > i) - if (!thisObject->arrayData->data[len].isEmpty()) + if (!thisObject->arrayData()->arrayData()[len].isEmpty()) break; - Q_ASSERT(!thisObject->arrayData->attrs || !thisObject->arrayData->attrs[len].isAccessor()); - thisObject->arrayData->data[i] = thisObject->arrayData->data[len]; - thisObject->arrayData->data[len] = Primitive::emptyValue(); + Q_ASSERT(!thisObject->arrayData()->attrs() || !thisObject->arrayData()->attrs()[len].isAccessor()); + thisObject->arrayData()->arrayData()[i] = thisObject->arrayData()->arrayData()[len]; + thisObject->arrayData()->arrayData()[len] = Primitive::emptyValue(); } } @@ -764,7 +776,7 @@ void ArrayData::sort(ExecutionContext *context, ObjectRef thisObject, const Valu ArrayElementLessThan lessThan(context, thisObject, comparefn); - Value *begin = thisObject->arrayData->data; + Value *begin = thisObject->arrayData()->arrayData(); std::sort(begin, begin + len, lessThan); #ifdef CHECK_SPARSE_ARRAYS diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 50b7b8a947..aab9157ced 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -57,6 +57,10 @@ namespace QV4 { static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \ template <typename T> \ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \ + V4_MANAGED_SIZE_TEST \ + const Data *d() const { return &static_cast<const Data &>(Managed::data); } \ + Data *d() { return &static_cast<Data &>(Managed::data); } + struct ArrayData; @@ -80,11 +84,6 @@ struct ArrayVTable struct Q_QML_EXPORT ArrayData : public Managed { - ArrayData(InternalClass *ic) - : Managed(ic) - { - } - enum Type { Simple = 0, Complex = 1, @@ -92,13 +91,30 @@ struct Q_QML_EXPORT ArrayData : public Managed Custom = 3 }; - uint alloc; - Type type; - PropertyAttributes *attrs; - Value *data; - - const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); } - bool isSparse() const { return this && type == Sparse; } + struct Data : public Managed::Data { + Data(InternalClass *ic) + : Managed::Data(ic) + {} + uint alloc; + Type type; + PropertyAttributes *attrs; + Value *arrayData; + }; + V4_MANAGED(Managed) + + uint alloc() const { return d()->alloc; } + uint &alloc() { return d()->alloc; } + void setAlloc(uint a) { d()->alloc = a; } + Type type() const { return d()->type; } + void setType(Type t) { d()->type = t; } + PropertyAttributes *attrs() const { return d()->attrs; } + void setAttrs(PropertyAttributes *a) { d()->attrs = a; } + Value *arrayData() const { return d()->arrayData; } + Value *&arrayData() { return d()->arrayData; } + void setArrayData(Value *v) { d()->arrayData = v; } + + const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass()->vtable); } + bool isSparse() const { return this && type() == Sparse; } uint length() const { if (!this) @@ -107,11 +123,11 @@ struct Q_QML_EXPORT ArrayData : public Managed } bool hasAttributes() const { - return this && attrs; + return this && attrs(); } PropertyAttributes attributes(int i) const { Q_ASSERT(this); - return attrs ? vtable()->attribute(this, i) : Attr_Data; + return attrs() ? vtable()->attribute(this, i) : Attr_Data; } bool isEmpty(uint i) const { @@ -130,26 +146,31 @@ struct Q_QML_EXPORT ArrayData : public Managed static void ensureAttributes(Object *o); static void realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes); - static void sort(ExecutionContext *context, ObjectRef thisObject, const ValueRef comparefn, uint dataLen); + static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen); static uint append(Object *obj, const ArrayObject *otherObj, uint n); static Property *insert(Object *o, uint index, bool isAccessor = false); }; struct Q_QML_EXPORT SimpleArrayData : public ArrayData { - V4_ARRAYDATA - SimpleArrayData(ExecutionEngine *engine) - : ArrayData(engine->simpleArrayDataClass) - {} + struct Data : public ArrayData::Data { + Data(ExecutionEngine *engine) + : ArrayData::Data(engine->simpleArrayDataClass) + {} + uint len; + uint offset; + }; + V4_ARRAYDATA - uint len; - uint offset; + uint &len() { return d()->len; } + uint len() const { return d()->len; } + uint &offset() { return d()->offset; } + uint offset() const { return d()->offset; } static void getHeadRoom(Object *o); static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes); - static void destroy(Managed *d); static void markObjects(Managed *d, ExecutionEngine *e); static ReturnedValue get(const ArrayData *d, uint index); @@ -166,14 +187,20 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData struct Q_QML_EXPORT SparseArrayData : public ArrayData { - V4_ARRAYDATA + struct Data : public ArrayData::Data { + Data(ExecutionEngine *engine) + : ArrayData::Data(engine->emptyClass) + { setVTable(staticVTable()); } - SparseArrayData(ExecutionEngine *engine) - : ArrayData(engine->emptyClass) - { setVTable(staticVTable()); } + uint freeList; + SparseArray *sparse; + }; + V4_ARRAYDATA - uint freeList; - SparseArray *sparse; + uint &freeList() { return d()->freeList; } + uint freeList() const { return d()->freeList; } + SparseArray *sparse() const { return d()->sparse; } + void setSparse(SparseArray *s) { d()->sparse = s; } static uint allocate(Object *o, bool doubleSlot = false); static void free(ArrayData *d, uint idx); @@ -199,16 +226,16 @@ inline Property *ArrayData::getProperty(uint index) const { if (!this) return 0; - if (type != Sparse) { + if (type() != Sparse) { const SimpleArrayData *that = static_cast<const SimpleArrayData *>(this); - if (index >= that->len || data[index].isEmpty()) + if (index >= that->len() || arrayData()[index].isEmpty()) return 0; - return reinterpret_cast<Property *>(data + index); + return reinterpret_cast<Property *>(arrayData() + index); } else { - SparseArrayNode *n = static_cast<const SparseArrayData *>(this)->sparse->findNode(index); + SparseArrayNode *n = static_cast<const SparseArrayData *>(this)->sparse()->findNode(index); if (!n) return 0; - return reinterpret_cast<Property *>(data + n->value); + return reinterpret_cast<Property *>(arrayData() + n->value); } } diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index fbd757a829..abe8a44065 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -48,8 +48,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayCtor); -ArrayCtor::ArrayCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Array")) +ArrayCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Array")) { setVTable(staticVTable()); } @@ -84,12 +84,7 @@ ReturnedValue ArrayCtor::call(Managed *that, CallData *callData) return construct(that, callData); } -ArrayPrototype::ArrayPrototype(InternalClass *ic) - : ArrayObject(ic) -{ -} - -void ArrayPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void ArrayPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -122,21 +117,21 @@ void ArrayPrototype::init(ExecutionEngine *engine, ObjectRef ctor) ReturnedValue ArrayPrototype::method_isArray(CallContext *ctx) { - bool isArray = ctx->callData->argc && ctx->callData->args[0].asArrayObject(); + bool isArray = ctx->d()->callData->argc && ctx->d()->callData->args[0].asArrayObject(); return Encode(isArray); } ReturnedValue ArrayPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - ScopedObject o(scope, ctx->callData->thisObject, ScopedObject::Convert); - if (ctx->engine->hasException) + ScopedObject o(scope, ctx->d()->callData->thisObject, ScopedObject::Convert); + if (ctx->d()->engine->hasException) return Encode::undefined(); - ScopedString s(scope, ctx->engine->newString(QStringLiteral("join"))); - ScopedFunctionObject f(scope, o->get(s)); + ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("join"))); + ScopedFunctionObject f(scope, o->get(s.getPointer())); if (!!f) { ScopedCallData d(scope, 0); - d->thisObject = ctx->callData->thisObject; + d->thisObject = ctx->d()->callData->thisObject; return f->call(d); } return ObjectPrototype::method_toString(ctx); @@ -150,9 +145,9 @@ ReturnedValue ArrayPrototype::method_toLocaleString(CallContext *ctx) ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) { Scope scope(ctx); - ScopedObject result(scope, ctx->engine->newArrayObject()); + ScopedObject result(scope, ctx->d()->engine->newArrayObject()); - ScopedObject thisObject(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject thisObject(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!thisObject) return Encode::undefined(); ScopedArrayObject instance(scope, thisObject); @@ -165,9 +160,9 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) ScopedArrayObject elt(scope); ScopedObject eltAsObj(scope); ScopedValue entry(scope); - for (int i = 0; i < ctx->callData->argc; ++i) { - eltAsObj = ctx->callData->args[i]; - elt = ctx->callData->args[i]; + for (int i = 0; i < ctx->d()->callData->argc; ++i) { + eltAsObj = ctx->d()->callData->args[i]; + elt = ctx->d()->callData->args[i]; if (elt) { uint n = elt->getLength(); uint newLen = ArrayData::append(result.getPointer(), elt.getPointer(), n); @@ -179,7 +174,7 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx) result->putIndexed(startIndex + i, entry); } } else { - result->arraySet(result->getLength(), ValueRef(ctx->callData->args[i])); + result->arraySet(result->getLength(), ValueRef(ctx->d()->callData->args[i])); } } @@ -197,12 +192,12 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) else r4 = arg->toQString(); - ScopedObject self(scope, ctx->callData->thisObject); - ScopedValue length(scope, self->get(ctx->engine->id_length)); + ScopedObject self(scope, ctx->d()->callData->thisObject); + ScopedValue length(scope, self->get(ctx->d()->engine->id_length)); const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); if (!r2) - return ctx->engine->newString(QString())->asReturnedValue(); + return ctx->d()->engine->newString(QString())->asReturnedValue(); QString R; @@ -223,8 +218,8 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) // // crazy! // - ScopedString name(scope, ctx->engine->newString(QStringLiteral("0"))); - ScopedValue r6(scope, self->get(name)); + ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0"))); + ScopedValue r6(scope, self->get(name.getPointer())); if (!r6->isNullOrUndefined()) R = r6->toString(ctx)->toQString(); @@ -233,7 +228,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) R += r4; name = Primitive::fromDouble(k).toString(ctx); - r12 = self->get(name); + r12 = self->get(name.getPointer()); if (scope.hasException()) return Encode::undefined(); @@ -242,20 +237,20 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) } } - return ctx->engine->newString(R)->asReturnedValue(); + return ctx->d()->engine->newString(R)->asReturnedValue(); } ReturnedValue ArrayPrototype::method_pop(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); uint len = instance->getLength(); if (!len) { if (!instance->isArrayObject()) - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0))); return Encode::undefined(); } @@ -269,14 +264,14 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx) if (instance->isArrayObject()) instance->setArrayLength(len - 1); else - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1))); return result.asReturnedValue(); } ReturnedValue ArrayPrototype::method_push(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -284,38 +279,38 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx) uint len = instance->getLength(); - if (len + ctx->callData->argc < len) { + if (len + ctx->d()->callData->argc < len) { // ughh... double l = len; ScopedString s(scope); - for (int i = 0; i < ctx->callData->argc; ++i) { + for (int i = 0; i < ctx->d()->callData->argc; ++i) { s = Primitive::fromDouble(l + i).toString(ctx); - instance->put(s, ctx->callData->args[i]); + instance->put(s.getPointer(), ctx->d()->callData->args[i]); } - double newLen = l + ctx->callData->argc; + double newLen = l + ctx->d()->callData->argc; if (!instance->isArrayObject()) - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen))); else { - ScopedString str(scope, ctx->engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); + ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow"))); return ctx->throwRangeError(str); } return Encode(newLen); } - if (!ctx->callData->argc) { + if (!ctx->d()->callData->argc) { ; - } else if (!instance->protoHasArray() && instance->arrayData->length() <= len && instance->arrayType() == ArrayData::Simple) { - instance->arrayData->vtable()->putArray(instance.getPointer(), len, ctx->callData->args, ctx->callData->argc); - len = instance->arrayData->length(); + } else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayType() == ArrayData::Simple) { + instance->arrayData()->vtable()->putArray(instance.getPointer(), len, ctx->d()->callData->args, ctx->d()->callData->argc); + len = instance->arrayData()->length(); } else { - for (int i = 0; i < ctx->callData->argc; ++i) - instance->putIndexed(len + i, ctx->callData->args[i]); - len += ctx->callData->argc; + for (int i = 0; i < ctx->d()->callData->argc; ++i) + instance->putIndexed(len + i, ctx->d()->callData->args[i]); + len += ctx->d()->callData->argc; } if (instance->isArrayObject()) instance->setArrayLengthUnchecked(len); else - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len))); return Encode(len); } @@ -323,7 +318,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx) ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); uint length = instance->getLength(); @@ -355,7 +350,7 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx) ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -365,14 +360,14 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) if (!len) { if (!instance->isArrayObject()) - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromInt32(0))); return Encode::undefined(); } ScopedValue result(scope); - if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len && instance->arrayData->type != ArrayData::Custom) { - result = instance->arrayData->vtable()->pop_front(instance.getPointer()); + if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) { + result = instance->arrayData()->vtable()->pop_front(instance.getPointer()); } else { result = instance->getIndexed(0); if (scope.hasException()) @@ -399,18 +394,18 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) if (instance->isArrayObject()) instance->setArrayLengthUnchecked(len - 1); else - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - 1))); return result.asReturnedValue(); } ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) { Scope scope(ctx); - ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!o) return Encode::undefined(); - Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> result(scope, ctx->d()->engine->newArrayObject()); uint len = o->getLength(); double s = ScopedValue(scope, ctx->argument(0))->toInteger(); uint start; @@ -421,8 +416,8 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) else start = (uint) s; uint end = len; - if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) { - double e = ctx->callData->args[1].toInteger(); + if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isUndefined()) { + double e = ctx->d()->callData->args[1].toInteger(); if (e < 0) end = (uint)qMax(len + e, 0.); else if (e > len) @@ -448,7 +443,7 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx) ReturnedValue ArrayPrototype::method_sort(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -456,18 +451,18 @@ ReturnedValue ArrayPrototype::method_sort(CallContext *ctx) ScopedValue comparefn(scope, ctx->argument(0)); ArrayData::sort(ctx, instance, comparefn, len); - return ctx->callData->thisObject.asReturnedValue(); + return ctx->d()->callData->thisObject.asReturnedValue(); } ReturnedValue ArrayPrototype::method_splice(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); uint len = instance->getLength(); - Scoped<ArrayObject> newArray(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> newArray(scope, ctx->d()->engine->newArrayObject()); double rs = ScopedValue(scope, ctx->argument(0))->toInteger(); uint start; @@ -490,7 +485,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx) } newArray->setArrayLengthUnchecked(deleteCount); - uint itemCount = ctx->callData->argc < 2 ? 0 : ctx->callData->argc - 2; + uint itemCount = ctx->d()->callData->argc < 2 ? 0 : ctx->d()->callData->argc - 2; if (itemCount < deleteCount) { for (uint k = start; k < len - deleteCount; ++k) { @@ -528,13 +523,13 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx) } for (uint i = 0; i < itemCount; ++i) { - instance->putIndexed(start + i, ctx->callData->args[i + 2]); + instance->putIndexed(start + i, ctx->d()->callData->args[i + 2]); if (scope.hasException()) return Encode::undefined(); } - ctx->strictMode = true; - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))); + ctx->d()->strictMode = true; + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(len - deleteCount + itemCount))); return newArray.asReturnedValue(); } @@ -542,7 +537,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx) ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -550,27 +545,27 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) uint len = instance->getLength(); - if (!instance->protoHasArray() && !instance->arrayData->hasAttributes() && instance->arrayData->length() <= len && instance->arrayData->type != ArrayData::Custom) { - instance->arrayData->vtable()->push_front(instance.getPointer(), ctx->callData->args, ctx->callData->argc); + if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) { + instance->arrayData()->vtable()->push_front(instance.getPointer(), ctx->d()->callData->args, ctx->d()->callData->argc); } else { ScopedValue v(scope); for (uint k = len; k > 0; --k) { bool exists; v = instance->getIndexed(k - 1, &exists); if (exists) - instance->putIndexed(k + ctx->callData->argc - 1, v); + instance->putIndexed(k + ctx->d()->callData->argc - 1, v); else - instance->deleteIndexedProperty(k + ctx->callData->argc - 1); + instance->deleteIndexedProperty(k + ctx->d()->callData->argc - 1); } - for (int i = 0; i < ctx->callData->argc; ++i) - instance->putIndexed(i, ctx->callData->args[i]); + for (int i = 0; i < ctx->d()->callData->argc; ++i) + instance->putIndexed(i, ctx->d()->callData->args[i]); } - uint newLen = len + ctx->callData->argc; + uint newLen = len + ctx->d()->callData->argc; if (instance->isArrayObject()) instance->setArrayLengthUnchecked(newLen); else - instance->put(ctx->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen))); + instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen))); return Encode(newLen); } @@ -579,18 +574,18 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); uint len = instance->getLength(); if (!len) return Encode(-1); - ScopedValue searchValue(scope, ctx->callData->argument(0)); + ScopedValue searchValue(scope, ctx->d()->callData->argument(0)); uint fromIndex = 0; - if (ctx->callData->argc >= 2) { - double f = ctx->callData->args[1].toInteger(); + if (ctx->d()->callData->argc >= 2) { + double f = ctx->d()->callData->args[1].toInteger(); if (scope.hasException()) return Encode::undefined(); if (f >= len) @@ -613,7 +608,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) ScopedValue value(scope); - if (instance->hasAccessorProperty || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) { + if (instance->hasAccessorProperty() || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) { // lets be safe and slow for (uint i = fromIndex; i < len; ++i) { bool exists; @@ -623,13 +618,13 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) if (exists && RuntimeHelpers::strictEqual(value, searchValue)) return Encode(i); } - } else if (!instance->arrayData) { + } else if (!instance->arrayData()) { return Encode(-1); } else { Q_ASSERT(instance->arrayType() == ArrayData::Simple || instance->arrayType() == ArrayData::Complex); - if (len > instance->arrayData->length()) - len = instance->arrayData->length(); - Value *val = instance->arrayData->data; + if (len > instance->arrayData()->length()) + len = instance->arrayData()->length(); + Value *val = instance->arrayData()->arrayData(); Value *end = val + len; val += fromIndex; while (val < end) { @@ -638,7 +633,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) if (scope.hasException()) return Encode::undefined(); if (RuntimeHelpers::strictEqual(value, searchValue)) - return Encode((uint)(val - instance->arrayData->data)); + return Encode((uint)(val - instance->arrayData()->arrayData())); } ++val; } @@ -650,7 +645,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx) { Scope scope(ctx); - ScopedObject instance(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); uint len = instance->getLength(); @@ -660,13 +655,13 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx) ScopedValue searchValue(scope); uint fromIndex = len; - if (ctx->callData->argc >= 1) + if (ctx->d()->callData->argc >= 1) searchValue = ctx->argument(0); else searchValue = Primitive::undefinedValue(); - if (ctx->callData->argc >= 2) { - double f = ctx->callData->args[1].toInteger(); + if (ctx->d()->callData->argc >= 2) { + double f = ctx->d()->callData->args[1].toInteger(); if (scope.hasException()) return Encode::undefined(); if (f > 0) @@ -695,7 +690,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx) ReturnedValue ArrayPrototype::method_every(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -729,7 +724,7 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx) ReturnedValue ArrayPrototype::method_some(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -763,7 +758,7 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx) ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -794,7 +789,7 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx) ReturnedValue ArrayPrototype::method_map(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -804,7 +799,7 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx) if (!callback) return ctx->throwTypeError(); - Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject()); a->arrayReserve(len); a->setArrayLengthUnchecked(len); @@ -831,7 +826,7 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx) ReturnedValue ArrayPrototype::method_filter(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -841,7 +836,7 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx) if (!callback) return ctx->throwTypeError(); - Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject()); a->arrayReserve(len); ScopedValue selected(scope); @@ -872,7 +867,7 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx) ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -886,7 +881,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx) ScopedValue acc(scope); ScopedValue v(scope); - if (ctx->callData->argc > 1) { + if (ctx->d()->callData->argc > 1) { acc = ctx->argument(1); } else { bool kPresent = false; @@ -922,7 +917,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx) ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> instance(scope, ctx->callData->thisObject.toObject(ctx)); + Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!instance) return Encode::undefined(); @@ -933,7 +928,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx) return ctx->throwTypeError(); if (len == 0) { - if (ctx->callData->argc == 1) + if (ctx->d()->callData->argc == 1) return ctx->throwTypeError(); return ctx->argument(1); } @@ -941,7 +936,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx) uint k = len; ScopedValue acc(scope); ScopedValue v(scope); - if (ctx->callData->argc > 1) { + if (ctx->d()->callData->argc > 1) { acc = ctx->argument(1); } else { bool kPresent = false; diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index e7f8ba711f..dccda2896e 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -51,8 +51,11 @@ namespace QV4 { struct ArrayCtor: FunctionObject { - V4_OBJECT - ArrayCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *m, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -60,9 +63,7 @@ struct ArrayCtor: FunctionObject struct ArrayPrototype: ArrayObject { - ArrayPrototype(InternalClass *ic); - - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_isArray(CallContext *ctx); static ReturnedValue method_toString(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 662ec64efb..38a0f7f549 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -46,8 +46,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(BooleanCtor); DEFINE_OBJECT_VTABLE(BooleanObject); -BooleanCtor::BooleanCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Boolean")) +BooleanCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Boolean")) { setVTable(staticVTable()); } @@ -66,7 +66,7 @@ ReturnedValue BooleanCtor::call(Managed *, CallData *callData) return Encode(value); } -void BooleanPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void BooleanPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -80,28 +80,28 @@ void BooleanPrototype::init(ExecutionEngine *engine, ObjectRef ctor) ReturnedValue BooleanPrototype::method_toString(CallContext *ctx) { bool result; - if (ctx->callData->thisObject.isBoolean()) { - result = ctx->callData->thisObject.booleanValue(); + if (ctx->d()->callData->thisObject.isBoolean()) { + result = ctx->d()->callData->thisObject.booleanValue(); } else { Scope scope(ctx); - Scoped<BooleanObject> thisObject(scope, ctx->callData->thisObject); + Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject); if (!thisObject) return ctx->throwTypeError(); - result = thisObject->value.booleanValue(); + result = thisObject->value().booleanValue(); } - return Encode(ctx->engine->newString(QLatin1String(result ? "true" : "false"))); + return Encode(ctx->d()->engine->newString(QLatin1String(result ? "true" : "false"))); } ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx) { - if (ctx->callData->thisObject.isBoolean()) - return ctx->callData->thisObject.asReturnedValue(); + if (ctx->d()->callData->thisObject.isBoolean()) + return ctx->d()->callData->thisObject.asReturnedValue(); Scope scope(ctx); - Scoped<BooleanObject> thisObject(scope, ctx->callData->thisObject); + Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject); if (!thisObject) return ctx->throwTypeError(); - return thisObject->value.asReturnedValue(); + return thisObject->value().asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 617f7f6b01..35cfd5729e 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -51,8 +51,11 @@ namespace QV4 { struct BooleanCtor: FunctionObject { - V4_OBJECT - BooleanCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -60,8 +63,7 @@ struct BooleanCtor: FunctionObject struct BooleanPrototype: BooleanObject { - BooleanPrototype(InternalClass *ic): BooleanObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_valueOf(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index b43b4893a3..62d5859e87 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -52,27 +52,30 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(ExecutionContext); +DEFINE_MANAGED_VTABLE(CallContext); +DEFINE_MANAGED_VTABLE(WithContext); +DEFINE_MANAGED_VTABLE(GlobalContext); -CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) +HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) { - Q_ASSERT(function->function); + Q_ASSERT(function->function()); - CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc))); - new (c) CallContext(engine, Type_CallContext); + CallContext::Data *c = reinterpret_cast<CallContext::Data *>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc))); + new (c) CallContext::Data(d()->engine, Type_CallContext); c->function = function; c->realArgumentCount = callData->argc; - c->strictMode = function->strictMode; - c->outer = function->scope; + c->strictMode = function->strictMode(); + c->outer = function->scope(); c->activation = 0; - c->compilationUnit = function->function->compilationUnit; + c->compilationUnit = function->function()->compilationUnit; c->lookups = c->compilationUnit->runtimeLookups; c->locals = (Value *)((quintptr(c + 1) + 7) & ~7); - const CompiledData::Function *compiledFunction = function->function->compiledFunction; + const CompiledData::Function *compiledFunction = function->function()->compiledFunction; int nLocals = compiledFunction->nLocals; if (nLocals) std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue()); @@ -86,43 +89,41 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData return c; } -WithContext *ExecutionContext::newWithContext(ObjectRef with) +WithContext *ExecutionContext::newWithContext(Object *with) { - WithContext *w = new (engine->memoryManager) WithContext(engine, with); - return w; + return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with); } -CatchContext *ExecutionContext::newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue) +CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue) { - CatchContext *c = new (engine->memoryManager) CatchContext(engine, exceptionVarName, exceptionValue); - return c; + return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue); } -CallContext *ExecutionContext::newQmlContext(FunctionObject *f, ObjectRef qml) +CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml) { - CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))); - new (c) CallContext(engine, qml, f); + CallContext *c = reinterpret_cast<CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))); + new (c->d()) CallContext::Data(d()->engine, qml, f); return c; } -void ExecutionContext::createMutableBinding(const StringRef name, bool deletable) +void ExecutionContext::createMutableBinding(String *name, bool deletable) { Scope scope(this); // find the right context to create the binding on - ScopedObject activation(scope, engine->globalObject); + ScopedObject activation(scope, d()->engine->globalObject); ExecutionContext *ctx = this; while (ctx) { - if (ctx->type >= Type_CallContext) { + if (ctx->d()->type >= Type_CallContext) { CallContext *c = static_cast<CallContext *>(ctx); - if (!c->activation) - c->activation = engine->newObject()->getPointer(); - activation = c->activation; + if (!c->d()->activation) + c->d()->activation = d()->engine->newObject()->getPointer(); + activation = c->d()->activation; break; } - ctx = ctx->outer; + ctx = ctx->d()->outer; } if (activation->hasProperty(name)) @@ -134,38 +135,38 @@ void ExecutionContext::createMutableBinding(const StringRef name, bool deletable } -GlobalContext::GlobalContext(ExecutionEngine *eng) - : ExecutionContext(eng, Type_GlobalContext) +GlobalContext::Data::Data(ExecutionEngine *eng) + : ExecutionContext::Data(eng, Type_GlobalContext) { global = eng->globalObject; } -WithContext::WithContext(ExecutionEngine *engine, ObjectRef with) - : ExecutionContext(engine, Type_WithContext) +WithContext::Data::Data(ExecutionEngine *engine, Object *with) + : ExecutionContext::Data(engine, Type_WithContext) { - callData = parent->callData; + callData = parent->d()->callData; outer = parent; - lookups = parent->lookups; - compilationUnit = parent->compilationUnit; + lookups = parent->d()->lookups; + compilationUnit = parent->d()->compilationUnit; - withObject = with.getPointer(); + withObject = with; } -CatchContext::CatchContext(ExecutionEngine *engine, const StringRef exceptionVarName, const ValueRef exceptionValue) - : ExecutionContext(engine, Type_CatchContext) +CatchContext::Data::Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue) + : ExecutionContext::Data(engine, Type_CatchContext) { - strictMode = parent->strictMode; - callData = parent->callData; + strictMode = parent->d()->strictMode; + callData = parent->d()->callData; outer = parent; - lookups = parent->lookups; - compilationUnit = parent->compilationUnit; + lookups = parent->d()->lookups; + compilationUnit = parent->d()->compilationUnit; this->exceptionVarName = exceptionVarName; this->exceptionValue = exceptionValue; } -CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject *function) - : ExecutionContext(engine, Type_QmlContext) +CallContext::Data::Data(ExecutionEngine *engine, Object *qml, FunctionObject *function) + : ExecutionContext::Data(engine, Type_QmlContext) { this->function = function; callData = reinterpret_cast<CallData *>(this + 1); @@ -174,12 +175,12 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject callData->thisObject = Primitive::undefinedValue(); strictMode = true; - outer = function->scope; + outer = function->scope(); - activation = qml.getPointer(); + activation = qml; - if (function->function) { - compilationUnit = function->function->compilationUnit; + if (function->function()) { + compilationUnit = function->function()->compilationUnit; lookups = compilationUnit->runtimeLookups; } @@ -190,170 +191,170 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject String * const *CallContext::formals() const { - return (function && function->function) ? function->function->internalClass->nameMap.constData() : 0; + return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() : 0; } unsigned int CallContext::formalCount() const { - return function ? function->formalParameterCount() : 0; + return d()->function ? d()->function->formalParameterCount() : 0; } String * const *CallContext::variables() const { - return (function && function->function) ? function->function->internalClass->nameMap.constData() + function->function->compiledFunction->nFormals : 0; + return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() + d()->function->function()->compiledFunction->nFormals : 0; } unsigned int CallContext::variableCount() const { - return function ? function->varCount() : 0; + return d()->function ? d()->function->varCount() : 0; } -bool ExecutionContext::deleteProperty(const StringRef name) +bool ExecutionContext::deleteProperty(String *name) { Scope scope(this); bool hasWith = false; - for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) { - if (ctx->type == Type_WithContext) { + for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) { + if (ctx->d()->type == Type_WithContext) { hasWith = true; WithContext *w = static_cast<WithContext *>(ctx); - if (w->withObject->hasProperty(name)) - return w->withObject->deleteProperty(name); - } else if (ctx->type == Type_CatchContext) { + if (w->d()->withObject->hasProperty(name)) + return w->d()->withObject->deleteProperty(name); + } else if (ctx->d()->type == Type_CatchContext) { CatchContext *c = static_cast<CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name)) + if (c->d()->exceptionVarName->isEqualTo(name)) return false; - } else if (ctx->type >= Type_CallContext) { + } else if (ctx->d()->type >= Type_CallContext) { CallContext *c = static_cast<CallContext *>(ctx); - FunctionObject *f = c->function; - if (f->needsActivation || hasWith) { - uint index = f->function->internalClass->find(name); + FunctionObject *f = c->d()->function; + if (f->needsActivation() || hasWith) { + uint index = f->function()->internalClass->find(name); if (index < UINT_MAX) // ### throw in strict mode? return false; } - if (c->activation && c->activation->hasProperty(name)) - return c->activation->deleteProperty(name); - } else if (ctx->type == Type_GlobalContext) { + if (c->d()->activation && c->d()->activation->hasProperty(name)) + return c->d()->activation->deleteProperty(name); + } else if (ctx->d()->type == Type_GlobalContext) { GlobalContext *g = static_cast<GlobalContext *>(ctx); - if (g->global->hasProperty(name)) - return g->global->deleteProperty(name); + if (g->d()->global->hasProperty(name)) + return g->d()->global->deleteProperty(name); } } - if (strictMode) + if (d()->strictMode) throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString())); return true; } bool CallContext::needsOwnArguments() const { - return function->needsActivation || callData->argc < static_cast<int>(function->formalParameterCount()); + return d()->function->needsActivation() || d()->callData->argc < static_cast<int>(d()->function->formalParameterCount()); } void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine) { ExecutionContext *ctx = static_cast<ExecutionContext *>(m); - if (ctx->outer) - ctx->outer->mark(engine); + if (ctx->d()->outer) + ctx->d()->outer->mark(engine); // ### shouldn't need these 3 lines - ctx->callData->thisObject.mark(engine); - for (int arg = 0; arg < ctx->callData->argc; ++arg) - ctx->callData->args[arg].mark(engine); + ctx->d()->callData->thisObject.mark(engine); + for (int arg = 0; arg < ctx->d()->callData->argc; ++arg) + ctx->d()->callData->args[arg].mark(engine); - if (ctx->type >= Type_CallContext) { + if (ctx->d()->type >= Type_CallContext) { QV4::CallContext *c = static_cast<CallContext *>(ctx); - for (unsigned local = 0, lastLocal = c->function->varCount(); local < lastLocal; ++local) - c->locals[local].mark(engine); - if (c->activation) - c->activation->mark(engine); - c->function->mark(engine); - } else if (ctx->type == Type_WithContext) { + for (unsigned local = 0, lastLocal = c->d()->function->varCount(); local < lastLocal; ++local) + c->d()->locals[local].mark(engine); + if (c->d()->activation) + c->d()->activation->mark(engine); + c->d()->function->mark(engine); + } else if (ctx->d()->type == Type_WithContext) { WithContext *w = static_cast<WithContext *>(ctx); - w->withObject->mark(engine); - } else if (ctx->type == Type_CatchContext) { + w->d()->withObject->mark(engine); + } else if (ctx->d()->type == Type_CatchContext) { CatchContext *c = static_cast<CatchContext *>(ctx); - c->exceptionVarName->mark(engine); - c->exceptionValue.mark(engine); - } else if (ctx->type == Type_GlobalContext) { + c->d()->exceptionVarName->mark(engine); + c->d()->exceptionValue.mark(engine); + } else if (ctx->d()->type == Type_GlobalContext) { GlobalContext *g = static_cast<GlobalContext *>(ctx); - g->global->mark(engine); + g->d()->global->mark(engine); } } -void ExecutionContext::setProperty(const StringRef name, const ValueRef value) +void ExecutionContext::setProperty(String *name, const ValueRef value) { Scope scope(this); - for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) { - if (ctx->type == Type_WithContext) { - ScopedObject w(scope, static_cast<WithContext *>(ctx)->withObject); + for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) { + if (ctx->d()->type == Type_WithContext) { + ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject); if (w->hasProperty(name)) { w->put(name, value); return; } - } else if (ctx->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->exceptionVarName->isEqualTo(name)) { - static_cast<CatchContext *>(ctx)->exceptionValue = *value; + } else if (ctx->d()->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->d()->exceptionVarName->isEqualTo(name)) { + static_cast<CatchContext *>(ctx)->d()->exceptionValue = *value; return; } else { ScopedObject activation(scope, (Object *)0); - if (ctx->type >= Type_CallContext) { + if (ctx->d()->type >= Type_CallContext) { CallContext *c = static_cast<CallContext *>(ctx); - if (c->function->function) { - uint index = c->function->function->internalClass->find(name); + if (c->d()->function->function()) { + uint index = c->d()->function->function()->internalClass->find(name); if (index < UINT_MAX) { - if (index < c->function->formalParameterCount()) { - c->callData->args[c->function->formalParameterCount() - index - 1] = *value; + if (index < c->d()->function->formalParameterCount()) { + c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1] = *value; } else { - index -= c->function->formalParameterCount(); - c->locals[index] = *value; + index -= c->d()->function->formalParameterCount(); + c->d()->locals[index] = *value; } return; } } - activation = c->activation; - } else if (ctx->type == Type_GlobalContext) { - activation = static_cast<GlobalContext *>(ctx)->global; + activation = c->d()->activation; + } else if (ctx->d()->type == Type_GlobalContext) { + activation = static_cast<GlobalContext *>(ctx)->d()->global; } if (activation) { - if (ctx->type == Type_QmlContext) { + if (ctx->d()->type == Type_QmlContext) { activation->put(name, value); return; } else { - uint member = activation->internalClass->find(name); + uint member = activation->internalClass()->find(name); if (member < UINT_MAX) { - activation->putValue(activation->propertyAt(member), activation->internalClass->propertyData[member], value); + activation->putValue(activation->propertyAt(member), activation->internalClass()->propertyData[member], value); return; } } } } } - if (strictMode || name->equals(engine->id_this)) { - ScopedValue n(scope, name.asReturnedValue()); + if (d()->strictMode || name->equals(d()->engine->id_this.getPointer())) { + ScopedValue n(scope, name->asReturnedValue()); throwReferenceError(n); return; } - engine->globalObject->put(name, value); + d()->engine->globalObject->put(name, value); } -ReturnedValue ExecutionContext::getProperty(const StringRef name) +ReturnedValue ExecutionContext::getProperty(String *name) { Scope scope(this); ScopedValue v(scope); name->makeIdentifier(); - if (name->equals(engine->id_this)) - return callData->thisObject.asReturnedValue(); + if (name->equals(d()->engine->id_this.getPointer())) + return d()->callData->thisObject.asReturnedValue(); bool hasWith = false; bool hasCatchScope = false; - for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) { - if (ctx->type == Type_WithContext) { - ScopedObject w(scope, static_cast<WithContext *>(ctx)->withObject); + for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) { + if (ctx->d()->type == Type_WithContext) { + ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject); hasWith = true; bool hasProperty = false; v = w->get(name, &hasProperty); @@ -363,62 +364,62 @@ ReturnedValue ExecutionContext::getProperty(const StringRef name) continue; } - else if (ctx->type == Type_CatchContext) { + else if (ctx->d()->type == Type_CatchContext) { hasCatchScope = true; CatchContext *c = static_cast<CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name)) - return c->exceptionValue.asReturnedValue(); + if (c->d()->exceptionVarName->isEqualTo(name)) + return c->d()->exceptionValue.asReturnedValue(); } - else if (ctx->type >= Type_CallContext) { + else if (ctx->d()->type >= Type_CallContext) { QV4::CallContext *c = static_cast<CallContext *>(ctx); - ScopedFunctionObject f(scope, c->function); - if (f->function && (f->needsActivation || hasWith || hasCatchScope)) { - uint index = f->function->internalClass->find(name); + ScopedFunctionObject f(scope, c->d()->function); + if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) { + uint index = f->function()->internalClass->find(name); if (index < UINT_MAX) { - if (index < c->function->formalParameterCount()) - return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue(); - return c->locals[index - c->function->formalParameterCount()].asReturnedValue(); + if (index < c->d()->function->formalParameterCount()) + return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue(); + return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue(); } } - if (c->activation) { + if (c->d()->activation) { bool hasProperty = false; - v = c->activation->get(name, &hasProperty); + v = c->d()->activation->get(name, &hasProperty); if (hasProperty) return v.asReturnedValue(); } - if (f->function && f->function->isNamedExpression() - && name->equals(f->function->name())) + if (f->function() && f->function()->isNamedExpression() + && name->equals(f->function()->name())) return f.asReturnedValue(); } - else if (ctx->type == Type_GlobalContext) { + else if (ctx->d()->type == Type_GlobalContext) { GlobalContext *g = static_cast<GlobalContext *>(ctx); bool hasProperty = false; - v = g->global->get(name, &hasProperty); + v = g->d()->global->get(name, &hasProperty); if (hasProperty) return v.asReturnedValue(); } } - ScopedValue n(scope, name.asReturnedValue()); + ScopedValue n(scope, name); return throwReferenceError(n); } -ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectRef base) +ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base) { Scope scope(this); ScopedValue v(scope); base = (Object *)0; name->makeIdentifier(); - if (name->equals(engine->id_this)) - return callData->thisObject.asReturnedValue(); + if (name->equals(d()->engine->id_this.getPointer())) + return d()->callData->thisObject.asReturnedValue(); bool hasWith = false; bool hasCatchScope = false; - for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) { - if (ctx->type == Type_WithContext) { - Object *w = static_cast<WithContext *>(ctx)->withObject; + for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) { + if (ctx->d()->type == Type_WithContext) { + Object *w = static_cast<WithContext *>(ctx)->d()->withObject; hasWith = true; bool hasProperty = false; v = w->get(name, &hasProperty); @@ -429,103 +430,103 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR continue; } - else if (ctx->type == Type_CatchContext) { + else if (ctx->d()->type == Type_CatchContext) { hasCatchScope = true; CatchContext *c = static_cast<CatchContext *>(ctx); - if (c->exceptionVarName->isEqualTo(name)) - return c->exceptionValue.asReturnedValue(); + if (c->d()->exceptionVarName->isEqualTo(name)) + return c->d()->exceptionValue.asReturnedValue(); } - else if (ctx->type >= Type_CallContext) { + else if (ctx->d()->type >= Type_CallContext) { QV4::CallContext *c = static_cast<CallContext *>(ctx); - FunctionObject *f = c->function; - if (f->function && (f->needsActivation || hasWith || hasCatchScope)) { - uint index = f->function->internalClass->find(name); + FunctionObject *f = c->d()->function; + if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) { + uint index = f->function()->internalClass->find(name); if (index < UINT_MAX) { - if (index < c->function->formalParameterCount()) - return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue(); - return c->locals[index - c->function->formalParameterCount()].asReturnedValue(); + if (index < c->d()->function->formalParameterCount()) + return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue(); + return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue(); } } - if (c->activation) { + if (c->d()->activation) { bool hasProperty = false; - v = c->activation->get(name, &hasProperty); + v = c->d()->activation->get(name, &hasProperty); if (hasProperty) { - if (ctx->type == Type_QmlContext) - base = c->activation; + if (ctx->d()->type == Type_QmlContext) + base = c->d()->activation; return v.asReturnedValue(); } } - if (f->function && f->function->isNamedExpression() - && name->equals(f->function->name())) - return c->function->asReturnedValue(); + if (f->function() && f->function()->isNamedExpression() + && name->equals(f->function()->name())) + return c->d()->function->asReturnedValue(); } - else if (ctx->type == Type_GlobalContext) { + else if (ctx->d()->type == Type_GlobalContext) { GlobalContext *g = static_cast<GlobalContext *>(ctx); bool hasProperty = false; - v = g->global->get(name, &hasProperty); + v = g->d()->global->get(name, &hasProperty); if (hasProperty) return v.asReturnedValue(); } } - ScopedValue n(scope, name.asReturnedValue()); + ScopedValue n(scope, name); return throwReferenceError(n); } ReturnedValue ExecutionContext::throwError(const ValueRef value) { - return engine->throwException(value); + return d()->engine->throwException(value); } ReturnedValue ExecutionContext::throwError(const QString &message) { Scope scope(this); - ScopedValue v(scope, engine->newString(message)); - v = engine->newErrorObject(v); + ScopedValue v(scope, d()->engine->newString(message)); + v = d()->engine->newErrorObject(v); return throwError(v); } ReturnedValue ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column) { Scope scope(this); - Scoped<Object> error(scope, engine->newSyntaxErrorObject(message, fileName, line, column)); + Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message, fileName, line, column)); return throwError(error); } ReturnedValue ExecutionContext::throwSyntaxError(const QString &message) { Scope scope(this); - Scoped<Object> error(scope, engine->newSyntaxErrorObject(message)); + Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message)); return throwError(error); } ReturnedValue ExecutionContext::throwTypeError() { Scope scope(this); - Scoped<Object> error(scope, engine->newTypeErrorObject(QStringLiteral("Type error"))); + Scoped<Object> error(scope, d()->engine->newTypeErrorObject(QStringLiteral("Type error"))); return throwError(error); } ReturnedValue ExecutionContext::throwTypeError(const QString &message) { Scope scope(this); - Scoped<Object> error(scope, engine->newTypeErrorObject(message)); + Scoped<Object> error(scope, d()->engine->newTypeErrorObject(message)); return throwError(error); } ReturnedValue ExecutionContext::throwUnimplemented(const QString &message) { Scope scope(this); - ScopedValue v(scope, engine->newString(QStringLiteral("Unimplemented ") + message)); - v = engine->newErrorObject(v); + ScopedValue v(scope, d()->engine->newString(QStringLiteral("Unimplemented ") + message)); + v = d()->engine->newErrorObject(v); return throwError(v); } ReturnedValue ExecutionContext::catchException(StackTrace *trace) { - return engine->catchException(this, trace); + return d()->engine->catchException(this, trace); } ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value) @@ -533,7 +534,7 @@ ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value) Scope scope(this); Scoped<String> s(scope, value->toString(this)); QString msg = s->toQString() + QStringLiteral(" is not defined"); - Scoped<Object> error(scope, engine->newReferenceErrorObject(msg)); + Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg)); return throwError(error); } @@ -541,7 +542,7 @@ ReturnedValue ExecutionContext::throwReferenceError(const QString &message, cons { Scope scope(this); QString msg = message; - Scoped<Object> error(scope, engine->newReferenceErrorObject(msg, fileName, line, column)); + Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg, fileName, line, column)); return throwError(error); } @@ -550,20 +551,20 @@ ReturnedValue ExecutionContext::throwRangeError(const ValueRef value) Scope scope(this); ScopedString s(scope, value->toString(this)); QString msg = s->toQString() + QStringLiteral(" out of range"); - ScopedObject error(scope, engine->newRangeErrorObject(msg)); + ScopedObject error(scope, d()->engine->newRangeErrorObject(msg)); return throwError(error); } ReturnedValue ExecutionContext::throwRangeError(const QString &message) { Scope scope(this); - ScopedObject error(scope, engine->newRangeErrorObject(message)); + ScopedObject error(scope, d()->engine->newRangeErrorObject(message)); return throwError(error); } ReturnedValue ExecutionContext::throwURIError(const ValueRef msg) { Scope scope(this); - ScopedObject error(scope, engine->newURIErrorObject(msg)); + ScopedObject error(scope, d()->engine->newURIErrorObject(msg)); return throwError(error); } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index a07cbf2da5..7e67028364 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -69,8 +69,6 @@ struct WithContext; struct Q_QML_EXPORT ExecutionContext : public Managed { - V4_MANAGED - Q_MANAGED_TYPE(ExecutionContext) enum { IsExecutionContext = true }; @@ -83,48 +81,66 @@ struct Q_QML_EXPORT ExecutionContext : public Managed Type_CallContext = 0x5, Type_QmlContext = 0x6 }; - - ExecutionContext(ExecutionEngine *engine, ContextType t) - : Managed(engine->executionContextClass) - { - this->type = t; - strictMode = false; - this->engine = engine; - this->parent = engine->currentContext(); - outer = 0; - lookups = 0; - compilationUnit = 0; - currentEvalCode = 0; - lineNumber = -1; - engine->current = this; - } - - ContextType type; - bool strictMode; - - CallData *callData; - - ExecutionEngine *engine; - ExecutionContext *parent; - ExecutionContext *outer; - Lookup *lookups; - CompiledData::CompilationUnit *compilationUnit; - struct EvalCode { Function *function; EvalCode *next; }; - EvalCode *currentEvalCode; - int lineNumber; + struct Data : Managed::Data { + Data(ExecutionEngine *engine, ContextType t) + : Managed::Data(engine->executionContextClass) + , type(t) + , strictMode(false) + , engine(engine) + , parent(engine->currentContext()) + , outer(0) + , lookups(0) + , compilationUnit(0) + , currentEvalCode(0) + , lineNumber(-1) + { + engine->current = reinterpret_cast<ExecutionContext *>(this); + } + ContextType type; + bool strictMode; + + CallData *callData; + + ExecutionEngine *engine; + ExecutionContext *parent; + ExecutionContext *outer; + Lookup *lookups; + CompiledData::CompilationUnit *compilationUnit; + EvalCode *currentEvalCode; + + int lineNumber; - CallContext *newCallContext(FunctionObject *f, CallData *callData); - WithContext *newWithContext(ObjectRef with); - CatchContext *newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue); - CallContext *newQmlContext(FunctionObject *f, ObjectRef qml); + }; + V4_MANAGED(Managed) + Q_MANAGED_TYPE(ExecutionContext) - void createMutableBinding(const StringRef name, bool deletable); + ExecutionContext(ExecutionEngine *engine, ContextType t) + : Managed(engine->executionContextClass) + { + d()->type = t; + d()->strictMode = false; + d()->engine = engine; + d()->parent = engine->currentContext(); + d()->outer = 0; + d()->lookups = 0; + d()->compilationUnit = 0; + d()->currentEvalCode = 0; + d()->lineNumber = -1; + engine->current = this; + } + + HeapObject *newCallContext(FunctionObject *f, CallData *callData); + WithContext *newWithContext(Object *with); + CatchContext *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue); + CallContext *newQmlContext(FunctionObject *f, Object *qml); + + void createMutableBinding(String *name, bool deletable); ReturnedValue throwError(const QV4::ValueRef value); ReturnedValue throwError(const QString &message); @@ -139,10 +155,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed ReturnedValue throwURIError(const ValueRef msg); ReturnedValue throwUnimplemented(const QString &message); - void setProperty(const StringRef name, const ValueRef value); - ReturnedValue getProperty(const StringRef name); - ReturnedValue getPropertyAndBase(const StringRef name, ObjectRef base); - bool deleteProperty(const StringRef name); + void setProperty(String *name, const ValueRef value); + ReturnedValue getProperty(String *name); + ReturnedValue getPropertyAndBase(String *name, Object *&base); + bool deleteProperty(String *name); // Can only be called from within catch(...), rethrows if no JS exception. ReturnedValue catchException(StackTrace *trace = 0); @@ -155,19 +171,22 @@ struct Q_QML_EXPORT ExecutionContext : public Managed struct CallContext : public ExecutionContext { - CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) - : ExecutionContext(engine, t) - { - function = 0; - locals = 0; - activation = 0; - } - CallContext(ExecutionEngine *engine, ObjectRef qml, QV4::FunctionObject *function); - - FunctionObject *function; - int realArgumentCount; - Value *locals; - Object *activation; + struct Data : ExecutionContext::Data { + Data(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) + : ExecutionContext::Data(engine, t) + { + function = 0; + locals = 0; + activation = 0; + } + Data(ExecutionEngine *engine, Object *qml, QV4::FunctionObject *function); + + FunctionObject *function; + int realArgumentCount; + Value *locals; + Object *activation; + }; + V4_MANAGED(ExecutionContext) // formals are in reverse order String * const *formals() const; @@ -180,52 +199,60 @@ struct CallContext : public ExecutionContext }; inline ReturnedValue CallContext::argument(int i) { - return i < callData->argc ? callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue(); + return i < d()->callData->argc ? d()->callData->args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue(); } struct GlobalContext : public ExecutionContext { - GlobalContext(ExecutionEngine *engine); + struct Data : ExecutionContext::Data { + Data(ExecutionEngine *engine); + Object *global; + }; + V4_MANAGED(ExecutionContext) - Object *global; }; struct CatchContext : public ExecutionContext { - CatchContext(ExecutionEngine *engine, const StringRef exceptionVarName, const ValueRef exceptionValue); - - StringValue exceptionVarName; - Value exceptionValue; + struct Data : ExecutionContext::Data { + Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue); + StringValue exceptionVarName; + Value exceptionValue; + }; + V4_MANAGED(ExecutionContext) }; struct WithContext : public ExecutionContext { - WithContext(ExecutionEngine *engine, ObjectRef with); - Object *withObject; + struct Data : ExecutionContext::Data { + Data(ExecutionEngine *engine, Object *with); + Object *withObject; + }; + V4_MANAGED(ExecutionContext) }; inline CallContext *ExecutionContext::asCallContext() { - return type >= Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0; + return d()->type >= Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0; } inline const CallContext *ExecutionContext::asCallContext() const { - return type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0; + return d()->type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0; } inline void ExecutionEngine::pushContext(CallContext *context) { - context->parent = current; + context->d()->parent = current; current = context; - current->currentEvalCode = 0; + current->d()->currentEvalCode = 0; } inline ExecutionContext *ExecutionEngine::popContext() { - Q_ASSERT(current->parent); - current = current->parent; + Q_ASSERT(current->d()->parent); + current = current->d()->parent; return current; } @@ -235,7 +262,7 @@ struct ExecutionContextSaver ExecutionContext *savedContext; ExecutionContextSaver(ExecutionContext *context) - : engine(context->engine) + : engine(context->d()->engine) , savedContext(context) { } @@ -246,7 +273,7 @@ struct ExecutionContextSaver }; inline Scope::Scope(ExecutionContext *ctx) - : engine(ctx->engine) + : engine(ctx->d()->engine) #ifndef QT_NO_DEBUG , size(0) #endif @@ -256,7 +283,7 @@ inline Scope::Scope(ExecutionContext *ctx) /* Function *f, int argc */ #define requiredMemoryForExecutionContect(f, argc) \ - ((sizeof(CallContext) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData) + ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData) } // namespace QV4 diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index ceef88455b..b7fac9432f 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -643,8 +643,8 @@ static double getLocalTZA() DEFINE_OBJECT_VTABLE(DateObject); -DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date) - : Object(engine->dateClass) +DateObject::Data::Data(ExecutionEngine *engine, const QDateTime &date) + : Object::Data(engine->dateClass) { setVTable(staticVTable()); value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN()); @@ -652,13 +652,13 @@ DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date) QDateTime DateObject::toQDateTime() const { - return ToDateTime(value.asDouble(), Qt::LocalTime); + return ToDateTime(date().asDouble(), Qt::LocalTime); } DEFINE_OBJECT_VTABLE(DateCtor); -DateCtor::DateCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Date")) +DateCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Date")) { setVTable(staticVTable()); } @@ -674,7 +674,7 @@ ReturnedValue DateCtor::construct(Managed *m, CallData *callData) Scope scope(m->engine()); ScopedValue arg(scope, callData->args[0]); if (DateObject *d = arg->asDateObject()) - arg = d->value; + arg = d->date(); else arg = RuntimeHelpers::toPrimitive(arg, PREFERREDTYPE_HINT); @@ -707,7 +707,7 @@ ReturnedValue DateCtor::call(Managed *m, CallData *) return m->engine()->newString(ToString(t))->asReturnedValue(); } -void DatePrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void DatePrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -770,8 +770,8 @@ void DatePrototype::init(ExecutionEngine *engine, ObjectRef ctor) double DatePrototype::getThisDate(ExecutionContext *ctx) { - if (DateObject *thisObject = ctx->callData->thisObject.asDateObject()) - return thisObject->value.asDouble(); + if (DateObject *thisObject = ctx->d()->callData->thisObject.asDateObject()) + return thisObject->date().asDouble(); else { ctx->throwTypeError(); return 0; @@ -780,22 +780,22 @@ double DatePrototype::getThisDate(ExecutionContext *ctx) ReturnedValue DatePrototype::method_parse(CallContext *ctx) { - if (!ctx->callData->argc) + if (!ctx->d()->callData->argc) return Encode(qSNaN()); - return Encode(ParseString(ctx->callData->args[0].toString(ctx)->toQString())); + return Encode(ParseString(ctx->d()->callData->args[0].toString(ctx)->toQString())); } ReturnedValue DatePrototype::method_UTC(CallContext *ctx) { - const int numArgs = ctx->callData->argc; + const int numArgs = ctx->d()->callData->argc; if (numArgs >= 2) { - double year = ctx->callData->args[0].toNumber(); - double month = ctx->callData->args[1].toNumber(); - double day = numArgs >= 3 ? ctx->callData->args[2].toNumber() : 1; - double hours = numArgs >= 4 ? ctx->callData->args[3].toNumber() : 0; - double mins = numArgs >= 5 ? ctx->callData->args[4].toNumber() : 0; - double secs = numArgs >= 6 ? ctx->callData->args[5].toNumber() : 0; - double ms = numArgs >= 7 ? ctx->callData->args[6].toNumber() : 0; + double year = ctx->d()->callData->args[0].toNumber(); + double month = ctx->d()->callData->args[1].toNumber(); + double day = numArgs >= 3 ? ctx->d()->callData->args[2].toNumber() : 1; + double hours = numArgs >= 4 ? ctx->d()->callData->args[3].toNumber() : 0; + double mins = numArgs >= 5 ? ctx->d()->callData->args[4].toNumber() : 0; + double secs = numArgs >= 6 ? ctx->d()->callData->args[5].toNumber() : 0; + double ms = numArgs >= 7 ? ctx->d()->callData->args[6].toNumber() : 0; if (year >= 0 && year <= 99) year += 1900; double t = MakeDate(MakeDay(year, month, day), @@ -815,37 +815,37 @@ ReturnedValue DatePrototype::method_now(CallContext *ctx) ReturnedValue DatePrototype::method_toString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_toDateString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToDateString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToDateString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_toTimeString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToTimeString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToTimeString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_toLocaleString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToLocaleString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToLocaleString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_toLocaleDateString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToLocaleDateString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToLocaleDateString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_toLocaleTimeString(CallContext *ctx) { double t = getThisDate(ctx); - return ctx->engine->newString(ToLocaleTimeString(t))->asReturnedValue(); + return ctx->d()->engine->newString(ToLocaleTimeString(t))->asReturnedValue(); } ReturnedValue DatePrototype::method_valueOf(CallContext *ctx) @@ -1007,196 +1007,196 @@ ReturnedValue DatePrototype::method_getTimezoneOffset(CallContext *ctx) ReturnedValue DatePrototype::method_setTime(CallContext *ctx) { Scope scope(ctx); - Scoped<DateObject> self(scope, ctx->callData->thisObject); + Scoped<DateObject> self(scope, ctx->d()->callData->thisObject); if (!self) return ctx->throwTypeError(); - double t = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - self->value.setDouble(TimeClip(t)); - return self->value.asReturnedValue(); + double t = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + self->date().setDouble(TimeClip(t)); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx) { Scope scope(ctx); - Scoped<DateObject> self(scope, ctx->callData->thisObject); + Scoped<DateObject> self(scope, ctx->d()->callData->thisObject); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); - return self->value.asReturnedValue(); + double t = LocalTime(self->date().asDouble()); + double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double ms = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); - return self->value.asReturnedValue(); + double t = self->date().asDouble(); + double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double ms = (ctx->callData->argc < 2) ? msFromTime(t) : ctx->callData->args[1].toNumber(); + double t = LocalTime(self->date().asDouble()); + double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double ms = (ctx->d()->callData->argc < 2) ? msFromTime(t) : ctx->d()->callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double sec = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double ms = (ctx->callData->argc < 2) ? msFromTime(t) : ctx->callData->args[1].toNumber(); + double t = self->date().asDouble(); + double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double ms = (ctx->d()->callData->argc < 2) ? msFromTime(t) : ctx->d()->callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double sec = (ctx->callData->argc < 2) ? SecFromTime(t) : ctx->callData->args[1].toNumber(); - double ms = (ctx->callData->argc < 3) ? msFromTime(t) : ctx->callData->args[2].toNumber(); + double t = LocalTime(self->date().asDouble()); + double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double sec = (ctx->d()->callData->argc < 2) ? SecFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double ms = (ctx->d()->callData->argc < 3) ? msFromTime(t) : ctx->d()->callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double min = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double sec = (ctx->callData->argc < 2) ? SecFromTime(t) : ctx->callData->args[1].toNumber(); - double ms = (ctx->callData->argc < 3) ? msFromTime(t) : ctx->callData->args[2].toNumber(); + double t = self->date().asDouble(); + double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double sec = (ctx->d()->callData->argc < 2) ? SecFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double ms = (ctx->d()->callData->argc < 3) ? msFromTime(t) : ctx->d()->callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setHours(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double min = (ctx->callData->argc < 2) ? MinFromTime(t) : ctx->callData->args[1].toNumber(); - double sec = (ctx->callData->argc < 3) ? SecFromTime(t) : ctx->callData->args[2].toNumber(); - double ms = (ctx->callData->argc < 4) ? msFromTime(t) : ctx->callData->args[3].toNumber(); + double t = LocalTime(self->date().asDouble()); + double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double min = (ctx->d()->callData->argc < 2) ? MinFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double sec = (ctx->d()->callData->argc < 3) ? SecFromTime(t) : ctx->d()->callData->args[2].toNumber(); + double ms = (ctx->d()->callData->argc < 4) ? msFromTime(t) : ctx->d()->callData->args[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double hour = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double min = (ctx->callData->argc < 2) ? MinFromTime(t) : ctx->callData->args[1].toNumber(); - double sec = (ctx->callData->argc < 3) ? SecFromTime(t) : ctx->callData->args[2].toNumber(); - double ms = (ctx->callData->argc < 4) ? msFromTime(t) : ctx->callData->args[3].toNumber(); + double t = self->date().asDouble(); + double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double min = (ctx->d()->callData->argc < 2) ? MinFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double sec = (ctx->d()->callData->argc < 3) ? SecFromTime(t) : ctx->d()->callData->args[2].toNumber(); + double ms = (ctx->d()->callData->argc < 4) ? msFromTime(t) : ctx->d()->callData->args[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setDate(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); + double t = LocalTime(self->date().asDouble()); + double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double date = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); + double t = self->date().asDouble(); + double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setMonth(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); - double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double date = (ctx->callData->argc < 2) ? DateFromTime(t) : ctx->callData->args[1].toNumber(); + double t = LocalTime(self->date().asDouble()); + double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double date = (ctx->d()->callData->argc < 2) ? DateFromTime(t) : ctx->d()->callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double month = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double date = (ctx->callData->argc < 2) ? DateFromTime(t) : ctx->callData->args[1].toNumber(); + double t = self->date().asDouble(); + double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double date = (ctx->d()->callData->argc < 2) ? DateFromTime(t) : ctx->d()->callData->args[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setYear(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); + double t = self->date().asDouble(); if (std::isnan(t)) t = 0; else t = LocalTime(t); - double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); + double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); double r; if (std::isnan(year)) { r = qSNaN(); @@ -1207,50 +1207,50 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx) r = UTC(MakeDate(r, TimeWithinDay(t))); r = TimeClip(r); } - self->value.setDouble(r); - return self->value.asReturnedValue(); + self->date().setDouble(r); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double month = (ctx->callData->argc < 2) ? MonthFromTime(t) : ctx->callData->args[1].toNumber(); - double date = (ctx->callData->argc < 3) ? DateFromTime(t) : ctx->callData->args[2].toNumber(); + double t = self->date().asDouble(); + double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double month = (ctx->d()->callData->argc < 2) ? MonthFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double date = (ctx->d()->callData->argc < 3) ? DateFromTime(t) : ctx->d()->callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = LocalTime(self->value.asDouble()); + double t = LocalTime(self->date().asDouble()); if (std::isnan(t)) t = 0; - double year = ctx->callData->argc ? ctx->callData->args[0].toNumber() : qSNaN(); - double month = (ctx->callData->argc < 2) ? MonthFromTime(t) : ctx->callData->args[1].toNumber(); - double date = (ctx->callData->argc < 3) ? DateFromTime(t) : ctx->callData->args[2].toNumber(); + double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN(); + double month = (ctx->d()->callData->argc < 2) ? MonthFromTime(t) : ctx->d()->callData->args[1].toNumber(); + double date = (ctx->d()->callData->argc < 3) ? DateFromTime(t) : ctx->d()->callData->args[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); - self->value.setDouble(t); - return self->value.asReturnedValue(); + self->date().setDouble(t); + return self->date().asReturnedValue(); } ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); - return ctx->engine->newString(ToUTCString(t))->asReturnedValue(); + double t = self->date().asDouble(); + return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue(); } static void addZeroPrefixedInt(QString &str, int num, int nDigits) @@ -1268,19 +1268,19 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits) ReturnedValue DatePrototype::method_toISOString(CallContext *ctx) { - DateObject *self = ctx->callData->thisObject.asDateObject(); + DateObject *self = ctx->d()->callData->thisObject.asDateObject(); if (!self) return ctx->throwTypeError(); - double t = self->value.asDouble(); + double t = self->date().asDouble(); if (!std::isfinite(t)) - return ctx->throwRangeError(ctx->callData->thisObject); + return ctx->throwRangeError(ctx->d()->callData->thisObject); QString result; int year = (int)YearFromTime(t); if (year < 0 || year > 9999) { if (qAbs(year) >= 1000000) - return ctx->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue(); + return ctx->d()->engine->newString(QStringLiteral("Invalid Date"))->asReturnedValue(); result += year < 0 ? QLatin1Char('-') : QLatin1Char('+'); year = qAbs(year); addZeroPrefixedInt(result, year, 6); @@ -1301,27 +1301,27 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx) addZeroPrefixedInt(result, msFromTime(t), 3); result += QLatin1Char('Z'); - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } ReturnedValue DatePrototype::method_toJSON(CallContext *ctx) { Scope scope(ctx); - ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->callData->thisObject))); + ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject))); ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT)); if (tv->isNumber() && !std::isfinite(tv->toNumber())) return Encode::null(); - ScopedString s(scope, ctx->engine->newString(QStringLiteral("toISOString"))); - ScopedValue v(scope, O->objectValue()->get(s)); + ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString"))); + ScopedValue v(scope, O->objectValue()->get(s.getPointer())); FunctionObject *toIso = v->asFunctionObject(); if (!toIso) return ctx->throwTypeError(); ScopedCallData callData(scope, 0); - callData->thisObject = ctx->callData->thisObject; + callData->thisObject = ctx->d()->callData->thisObject; return toIso->call(callData); } diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index c52e8c3ee1..6df4da45c9 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -52,27 +52,38 @@ class QDateTime; namespace QV4 { struct DateObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, const ValueRef date) + : Object::Data(engine->dateClass) + { + value = date; + } + Data(ExecutionEngine *engine, const QDateTime &date); + Data(InternalClass *ic) + : Object::Data(ic) + { + Q_ASSERT(internalClass->vtable == staticVTable()); + value = Primitive::fromDouble(qSNaN()); + } + Value value; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(DateObject) - Value value; - DateObject(ExecutionEngine *engine, const ValueRef date): Object(engine->dateClass) { - value = date; - } - DateObject(ExecutionEngine *engine, const QDateTime &value); - QDateTime toQDateTime() const; -protected: - DateObject(InternalClass *ic): Object(ic) { - Q_ASSERT(internalClass->vtable == staticVTable()); - value = Primitive::fromDouble(qSNaN()); - } + Value date() const { return d()->value; } + Value &date() { return d()->value; } + void setDate(const ValueRef date) { d()->value = date; } + + QDateTime toQDateTime() const; }; struct DateCtor: FunctionObject { - V4_OBJECT - DateCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *); @@ -80,8 +91,7 @@ struct DateCtor: FunctionObject struct DatePrototype: DateObject { - DatePrototype(InternalClass *ic): DateObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static double getThisDate(ExecutionContext *ctx); diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 06c6dbb4d9..04422b9f5e 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -210,7 +210,7 @@ Debugger::ExecutionState Debugger::currentExecutionState() const { ExecutionState state; state.fileName = getFunction()->sourceFile(); - state.lineNumber = engine()->currentContext()->lineNumber; + state.lineNumber = engine()->currentContext()->d()->lineNumber; return state; } @@ -224,12 +224,12 @@ static inline CallContext *findContext(ExecutionContext *ctxt, int frame) { while (ctxt) { CallContext *cCtxt = ctxt->asCallContext(); - if (cCtxt && cCtxt->function) { + if (cCtxt && cCtxt->d()->function) { if (frame < 1) return cCtxt; --frame; } - ctxt = ctxt->parent; + ctxt = ctxt->d()->parent; } return 0; @@ -238,7 +238,7 @@ static inline CallContext *findContext(ExecutionContext *ctxt, int frame) static inline CallContext *findScope(ExecutionContext *ctxt, int scope) { for (; scope > 0 && ctxt; --scope) - ctxt = ctxt->outer; + ctxt = ctxt->d()->outer; return ctxt ? ctxt->asCallContext() : 0; } @@ -327,7 +327,7 @@ void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int sco QString qName; if (String *name = ctxt->variables()[i]) qName = name->toQString(); - v = ctxt->locals[i]; + v = ctxt->d()->locals[i]; collector->collect(qName, v); } } @@ -367,16 +367,16 @@ bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame) ExecutionContext *ctxt = findContext(engine->currentContext(), frameNr); while (ctxt) { if (CallContext *cCtxt = ctxt->asCallContext()) - if (cCtxt->activation) + if (cCtxt->d()->activation) break; - ctxt = ctxt->outer; + ctxt = ctxt->d()->outer; } if (!ctxt) return false; Scope scope(engine); - ScopedObject o(scope, ctxt->asCallContext()->activation); + ScopedObject o(scope, ctxt->asCallContext()->d()->activation); collector->collect(o); return true; } @@ -434,12 +434,12 @@ QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const return types; CallContext *sctxt = findContext(m_engine->currentContext(), frame); - if (!sctxt || sctxt->type < ExecutionContext::Type_SimpleCallContext) + if (!sctxt || sctxt->d()->type < ExecutionContext::Type_SimpleCallContext) return types; CallContext *ctxt = static_cast<CallContext *>(sctxt); - for (ExecutionContext *it = ctxt; it; it = it->outer) - types.append(it->type); + for (ExecutionContext *it = ctxt; it; it = it->d()->outer) + types.append(it->d()->type); return types; } @@ -450,7 +450,7 @@ void Debugger::maybeBreakAtInstruction() return; QMutexLocker locker(&m_lock); - int lineNumber = engine()->currentContext()->lineNumber; + int lineNumber = engine()->currentContext()->d()->lineNumber; if (m_gatherSources) { m_gatherSources->run(); @@ -495,7 +495,7 @@ void Debugger::leavingFunction(const ReturnedValue &retVal) QMutexLocker locker(&m_lock); if (m_stepping != NotStepping && m_currentContext == m_engine->currentContext()) { - m_currentContext = m_engine->currentContext()->parent; + m_currentContext = m_engine->currentContext()->d()->parent; m_stepping = StepOver; m_returnedValue = retVal; } @@ -517,10 +517,10 @@ Function *Debugger::getFunction() const { ExecutionContext *context = m_engine->currentContext(); if (CallContext *callCtx = context->asCallContext()) - return callCtx->function->function; + return callCtx->d()->function->function(); else { - Q_ASSERT(context->type == QV4::ExecutionContext::Type_GlobalContext); - return context->engine->globalCode; + Q_ASSERT(context->d()->type == QV4::ExecutionContext::Type_GlobalContext); + return context->d()->engine->globalCode; } } @@ -726,7 +726,7 @@ void Debugger::Collector::collect(const QString &name, const ScopedValue &value) } } -void Debugger::Collector::collect(const ObjectRef object) +void Debugger::Collector::collect(Object *object) { bool property = true; qSwap(property, m_isProperty); diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h index 47a7d77b28..f834b8d15f 100644 --- a/src/qml/jsruntime/qv4debugging_p.h +++ b/src/qml/jsruntime/qv4debugging_p.h @@ -105,7 +105,7 @@ public: virtual ~Collector(); void collect(const QString &name, const ScopedValue &value); - void collect(const ObjectRef object); + void collect(Object *object); protected: virtual void addUndefined(const QString &name) = 0; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 72be889e72..7be518916d 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -71,6 +71,7 @@ #include "qv4memberdata_p.h" #include <QtCore/QTextStream> +#include <QDateTime> #ifdef V4_ENABLE_JIT #include "qv4isel_masm_p.h" @@ -258,13 +259,13 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) memberDataClass = InternalClass::create(this, MemberData::staticVTable(), 0); - ObjectPrototype *objectPrototype = new (memoryManager) ObjectPrototype(InternalClass::create(this, ObjectPrototype::staticVTable(), 0)); + ScopedObject objectPrototype(scope, memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable(), 0))); objectClass = InternalClass::create(this, Object::staticVTable(), objectPrototype); Q_ASSERT(objectClass->vtable == Object::staticVTable()); arrayClass = InternalClass::create(this, ArrayObject::staticVTable(), objectPrototype); arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable); - ArrayPrototype *arrayPrototype = new (memoryManager) ArrayPrototype(arrayClass); + ScopedObject arrayPrototype(scope, memoryManager->alloc<ArrayPrototype>(arrayClass)); arrayClass = arrayClass->changePrototype(arrayPrototype); simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable(), 0); @@ -279,100 +280,100 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) initRootContext(); - StringPrototype *stringPrototype = new (memoryManager) StringPrototype(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype)); + ScopedObject stringPrototype(scope, memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype))); stringObjectClass = InternalClass::create(this, String::staticVTable(), stringPrototype); - NumberPrototype *numberPrototype = new (memoryManager) NumberPrototype(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype)); + ScopedObject numberPrototype(scope, memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype))); numberClass = InternalClass::create(this, NumberObject::staticVTable(), numberPrototype); - BooleanPrototype *booleanPrototype = new (memoryManager) BooleanPrototype(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype)); + ScopedObject booleanPrototype(scope, memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype))); booleanClass = InternalClass::create(this, BooleanObject::staticVTable(), booleanPrototype); - DatePrototype *datePrototype = new (memoryManager) DatePrototype(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype)); + ScopedObject datePrototype(scope, memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype))); dateClass = InternalClass::create(this, DateObject::staticVTable(), datePrototype); InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable(), objectPrototype); uint index; functionProtoClass = functionProtoClass->addMember(id_prototype, Attr_NotEnumerable, &index); Q_ASSERT(index == FunctionObject::Index_Prototype); - FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(functionProtoClass); + ScopedObject functionPrototype(scope, memoryManager->alloc<FunctionPrototype>(functionProtoClass)); functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype); functionClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == FunctionObject::Index_Prototype); protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == FunctionObject::Index_ProtoConstructor); - RegExpPrototype *regExpPrototype = new (memoryManager) RegExpPrototype(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype)); - regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype); + Scoped<RegExpPrototype> regExpPrototype(scope, memoryManager->alloc<RegExpPrototype>(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype))); + regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype.getPointer()); regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayIndex); regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index); Q_ASSERT(index == RegExpObject::Index_ArrayInput); - ErrorPrototype *errorPrototype = new (memoryManager) ErrorPrototype(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype)); + ScopedObject errorPrototype(scope, memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype))); errorClass = InternalClass::create(this, ErrorObject::staticVTable(), errorPrototype); - EvalErrorPrototype *evalErrorPrototype = new (memoryManager) EvalErrorPrototype(errorClass); + ScopedObject evalErrorPrototype(scope, memoryManager->alloc<EvalErrorPrototype>(errorClass)); evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable(), evalErrorPrototype); - RangeErrorPrototype *rangeErrorPrototype = new (memoryManager) RangeErrorPrototype(errorClass); + ScopedObject rangeErrorPrototype(scope, memoryManager->alloc<RangeErrorPrototype>(errorClass)); rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable(), rangeErrorPrototype); - ReferenceErrorPrototype *referenceErrorPrototype = new (memoryManager) ReferenceErrorPrototype(errorClass); + ScopedObject referenceErrorPrototype(scope, memoryManager->alloc<ReferenceErrorPrototype>(errorClass)); referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable(), referenceErrorPrototype); - SyntaxErrorPrototype *syntaxErrorPrototype = new (memoryManager) SyntaxErrorPrototype(errorClass); + ScopedObject syntaxErrorPrototype(scope, memoryManager->alloc<SyntaxErrorPrototype>(errorClass)); syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable(), syntaxErrorPrototype); - TypeErrorPrototype *typeErrorPrototype = new (memoryManager) TypeErrorPrototype(errorClass); + ScopedObject typeErrorPrototype(scope, memoryManager->alloc<TypeErrorPrototype>(errorClass)); typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable(), typeErrorPrototype); - URIErrorPrototype *uRIErrorPrototype = new (memoryManager) URIErrorPrototype(errorClass); + ScopedObject uRIErrorPrototype(scope, memoryManager->alloc<URIErrorPrototype>(errorClass)); uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable(), uRIErrorPrototype); - VariantPrototype *variantPrototype = new (memoryManager) VariantPrototype(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype)); + ScopedObject variantPrototype(scope, memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype))); variantClass = InternalClass::create(this, VariantObject::staticVTable(), variantPrototype); Q_ASSERT(variantClass->prototype == variantPrototype); - Q_ASSERT(variantPrototype->internalClass->prototype == objectPrototype); - - sequencePrototype = new (memoryManager) SequencePrototype(arrayClass); - - objectCtor = new (memoryManager) ObjectCtor(rootContext); - stringCtor = new (memoryManager) StringCtor(rootContext); - numberCtor = new (memoryManager) NumberCtor(rootContext); - booleanCtor = new (memoryManager) BooleanCtor(rootContext); - arrayCtor = new (memoryManager) ArrayCtor(rootContext); - functionCtor = new (memoryManager) FunctionCtor(rootContext); - dateCtor = new (memoryManager) DateCtor(rootContext); - regExpCtor = new (memoryManager) RegExpCtor(rootContext); - errorCtor = new (memoryManager) ErrorCtor(rootContext); - evalErrorCtor = new (memoryManager) EvalErrorCtor(rootContext); - rangeErrorCtor = new (memoryManager) RangeErrorCtor(rootContext); - referenceErrorCtor = new (memoryManager) ReferenceErrorCtor(rootContext); - syntaxErrorCtor = new (memoryManager) SyntaxErrorCtor(rootContext); - typeErrorCtor = new (memoryManager) TypeErrorCtor(rootContext); - uRIErrorCtor = new (memoryManager) URIErrorCtor(rootContext); - - objectPrototype->init(this, objectCtor); - stringPrototype->init(this, stringCtor); - numberPrototype->init(this, numberCtor); - booleanPrototype->init(this, booleanCtor); - arrayPrototype->init(this, arrayCtor); - datePrototype->init(this, dateCtor); - functionPrototype->init(this, functionCtor); - regExpPrototype->init(this, regExpCtor); - errorPrototype->init(this, errorCtor); - evalErrorPrototype->init(this, evalErrorCtor); - rangeErrorPrototype->init(this, rangeErrorCtor); - referenceErrorPrototype->init(this, referenceErrorCtor); - syntaxErrorPrototype->init(this, syntaxErrorCtor); - typeErrorPrototype->init(this, typeErrorCtor); - uRIErrorPrototype->init(this, uRIErrorCtor); - - variantPrototype->init(); + Q_ASSERT(variantPrototype->internalClass()->prototype == objectPrototype); + + sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass)); + + objectCtor = memoryManager->alloc<ObjectCtor>(rootContext); + stringCtor = memoryManager->alloc<StringCtor>(rootContext); + numberCtor = memoryManager->alloc<NumberCtor>(rootContext); + booleanCtor = memoryManager->alloc<BooleanCtor>(rootContext); + arrayCtor = memoryManager->alloc<ArrayCtor>(rootContext); + functionCtor = memoryManager->alloc<FunctionCtor>(rootContext); + dateCtor = memoryManager->alloc<DateCtor>(rootContext); + regExpCtor = memoryManager->alloc<RegExpCtor>(rootContext); + errorCtor = memoryManager->alloc<ErrorCtor>(rootContext); + evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(rootContext); + rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(rootContext); + referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(rootContext); + syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(rootContext); + typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(rootContext); + uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(rootContext); + + static_cast<ObjectPrototype *>(objectPrototype.getPointer())->init(this, objectCtor.asObject()); + static_cast<StringPrototype *>(stringPrototype.getPointer())->init(this, stringCtor.asObject()); + static_cast<NumberPrototype *>(numberPrototype.getPointer())->init(this, numberCtor.asObject()); + static_cast<BooleanPrototype *>(booleanPrototype.getPointer())->init(this, booleanCtor.asObject()); + static_cast<ArrayPrototype *>(arrayPrototype.getPointer())->init(this, arrayCtor.asObject()); + static_cast<DatePrototype *>(datePrototype.getPointer())->init(this, dateCtor.asObject()); + static_cast<FunctionPrototype *>(functionPrototype.getPointer())->init(this, functionCtor.asObject()); + static_cast<RegExpPrototype *>(regExpPrototype.getPointer())->init(this, regExpCtor.asObject()); + static_cast<ErrorPrototype *>(errorPrototype.getPointer())->init(this, errorCtor.asObject()); + static_cast<EvalErrorPrototype *>(evalErrorPrototype.getPointer())->init(this, evalErrorCtor.asObject()); + static_cast<RangeErrorPrototype *>(rangeErrorPrototype.getPointer())->init(this, rangeErrorCtor.asObject()); + static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.getPointer())->init(this, referenceErrorCtor.asObject()); + static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.getPointer())->init(this, syntaxErrorCtor.asObject()); + static_cast<TypeErrorPrototype *>(typeErrorPrototype.getPointer())->init(this, typeErrorCtor.asObject()); + static_cast<URIErrorPrototype *>(uRIErrorPrototype.getPointer())->init(this, uRIErrorCtor.asObject()); + + static_cast<VariantPrototype *>(variantPrototype.getPointer())->init(); static_cast<SequencePrototype *>(sequencePrototype.managed())->init(); // // set up the global object // globalObject = newObject()->getPointer(); - rootContext->global = globalObject; - rootContext->callData->thisObject = globalObject; - Q_ASSERT(globalObject->internalClass->vtable); + rootContext->d()->global = globalObject; + rootContext->d()->callData->thisObject = globalObject; + Q_ASSERT(globalObject->internalClass()->vtable); globalObject->defineDefaultProperty(QStringLiteral("Object"), objectCtor); globalObject->defineDefaultProperty(QStringLiteral("String"), stringCtor); @@ -390,14 +391,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) globalObject->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor); globalObject->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor); ScopedObject o(scope); - globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = new (memoryManager) MathObject(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype)))); - globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = new (memoryManager) JsonObject(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype)))); + globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype)))); + globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype)))); globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue()); globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN())); globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY)); - evalFunction = new (memoryManager) EvalFunction(rootContext); + + evalFunction = Scoped<EvalFunction>(scope, memoryManager->alloc<EvalFunction>(rootContext)); globalObject->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction)); globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2); @@ -412,13 +414,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1); Scoped<String> name(scope, newString(QStringLiteral("thrower"))); - thrower = newBuiltinFunction(rootContext, name, throwTypeError)->getPointer(); + thrower = ScopedFunctionObject(scope, BuiltinFunction::create(rootContext, name.getPointer(), throwTypeError)).getPointer(); } ExecutionEngine::~ExecutionEngine() { delete debugger; + debugger = 0; delete profiler; + profiler = 0; delete m_multiplyWrappedQObjects; m_multiplyWrappedQObjects = 0; delete identifierTable; @@ -451,18 +455,20 @@ void ExecutionEngine::enableDebugger() void ExecutionEngine::enableProfiler() { Q_ASSERT(!profiler); - profiler = new QV4::Profiling::Profiler(); + profiler = new QV4::Profiling::Profiler(this); } void ExecutionEngine::initRootContext() { - rootContext = static_cast<GlobalContext *>(memoryManager->allocManaged(sizeof(GlobalContext) + sizeof(CallData))); - new (rootContext) GlobalContext(this); - rootContext->callData = reinterpret_cast<CallData *>(rootContext + 1); - rootContext->callData->tag = QV4::Value::_Integer_Type; - rootContext->callData->argc = 0; - rootContext->callData->thisObject = globalObject; - rootContext->callData->args[0] = Encode::undefined(); + GlobalContext *r = static_cast<GlobalContext*>(memoryManager->allocManaged(sizeof(GlobalContext::Data) + sizeof(CallData))); + new (r->d()) GlobalContext::Data(this); + r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1); + r->d()->callData->tag = QV4::Value::_Integer_Type; + r->d()->callData->argc = 0; + r->d()->callData->thisObject = globalObject; + r->d()->callData->args[0] = Encode::undefined(); + + rootContext = r; } InternalClass *ExecutionEngine::newClass(const InternalClass &other) @@ -472,43 +478,32 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other) ExecutionContext *ExecutionEngine::pushGlobalContext() { - GlobalContext *g = new (memoryManager) GlobalContext(this); - g->callData = rootContext->callData; + GlobalContext *g = memoryManager->alloc<GlobalContext>(this); + g->d()->callData = rootContext->d()->callData; Q_ASSERT(currentContext() == g); return g; } -Returned<FunctionObject> *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *)) -{ - BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code); - return f->asReturned<FunctionObject>(); -} - -Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs) -{ - Q_ASSERT(target); - - BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs); - return f->asReturned<BoundFunction>(); -} - Returned<Object> *ExecutionEngine::newObject() { - Object *object = new (memoryManager) Object(this); + Scope scope(this); + ScopedObject object(scope, memoryManager->alloc<Object>(this)); return object->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newObject(InternalClass *internalClass) { - Object *object = new (memoryManager) Object(internalClass); + Scope scope(this); + ScopedObject object(scope, memoryManager->alloc<Object>(internalClass)); return object->asReturned<Object>(); } Returned<String> *ExecutionEngine::newString(const QString &s) { - return (new (memoryManager) String(this, s))->asReturned<String>(); + Scope scope(this); + return ScopedString(scope, memoryManager->alloc<String>(this, s))->asReturned<String>(); } String *ExecutionEngine::newIdentifier(const QString &text) @@ -518,29 +513,31 @@ String *ExecutionEngine::newIdentifier(const QString &text) Returned<Object> *ExecutionEngine::newStringObject(const ValueRef value) { - StringObject *object = new (memoryManager) StringObject(this, value); + Scope scope(this); + Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value)); return object->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newNumberObject(const ValueRef value) { - NumberObject *object = new (memoryManager) NumberObject(this, value); + Scope scope(this); + Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value)); return object->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newBooleanObject(const ValueRef value) { - Object *object = new (memoryManager) BooleanObject(this, value); + Scope scope(this); + ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, value)); return object->asReturned<Object>(); } Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count) { - ArrayObject *object = new (memoryManager) ArrayObject(this); + Scope scope(this); + ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this)); if (count) { - Scope scope(this); - ScopedValue protectArray(scope, object); if (count < 0x1000) object->arrayReserve(count); object->setArrayLengthUnchecked(count); @@ -550,26 +547,30 @@ Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count) Returned<ArrayObject> *ExecutionEngine::newArrayObject(const QStringList &list) { - ArrayObject *object = new (memoryManager) ArrayObject(this, list); + Scope scope(this); + ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list)); return object->asReturned<ArrayObject>(); } Returned<ArrayObject> *ExecutionEngine::newArrayObject(InternalClass *ic) { - ArrayObject *object = new (memoryManager) ArrayObject(ic); + Scope scope(this); + ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic)); return object->asReturned<ArrayObject>(); } Returned<DateObject> *ExecutionEngine::newDateObject(const ValueRef value) { - DateObject *object = new (memoryManager) DateObject(this, value); + Scope scope(this); + Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value)); return object->asReturned<DateObject>(); } Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt) { - DateObject *object = new (memoryManager) DateObject(this, dt); + Scope scope(this); + Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt)); return object->asReturned<DateObject>(); } @@ -588,21 +589,24 @@ Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, return newRegExpObject(re, global); } -Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExpRef re, bool global) +Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExp *re, bool global) { - RegExpObject *object = new (memoryManager) RegExpObject(this, re, global); + Scope scope(this); + Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global)); return object->asReturned<RegExpObject>(); } Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re) { - RegExpObject *object = new (memoryManager) RegExpObject(this, re); + Scope scope(this); + Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re)); return object->asReturned<RegExpObject>(); } Returned<Object> *ExecutionEngine::newErrorObject(const ValueRef value) { - ErrorObject *object = new (memoryManager) ErrorObject(errorClass, value); + Scope scope(this); + ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, value)); return object->asReturned<Object>(); } @@ -610,57 +614,65 @@ Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message) { Scope scope(this); ScopedString s(scope, newString(message)); - Object *error = new (memoryManager) SyntaxErrorObject(this, s); + ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s)); return error->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column) { - Object *error = new (memoryManager) SyntaxErrorObject(this, message, fileName, line, column); + Scope scope(this); + ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column)); return error->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message) { - Object *o = new (memoryManager) ReferenceErrorObject(this, message); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message)); return o->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber) { - Object *o = new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber, columnNumber); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber)); return o->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newTypeErrorObject(const QString &message) { - Object *o = new (memoryManager) TypeErrorObject(this, message); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message)); return o->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newRangeErrorObject(const QString &message) { - Object *o = new (memoryManager) RangeErrorObject(this, message); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message)); return o->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newURIErrorObject(const ValueRef message) { - Object *o = new (memoryManager) URIErrorObject(this, message); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message)); return o->asReturned<Object>(); } Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v) { - Object *o = new (memoryManager) VariantObject(this, v); + Scope scope(this); + ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v)); return o->asReturned<Object>(); } -Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o) +Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o) { - Object *obj = new (memoryManager) ForEachIteratorObject(ctx, o); + Scope scope(this); + ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(ctx, o)); return obj->asReturned<Object>(); } @@ -668,20 +680,20 @@ Returned<Object> *ExecutionEngine::qmlContextObject() const { ExecutionContext *ctx = currentContext(); - if (ctx->type == QV4::ExecutionContext::Type_SimpleCallContext && !ctx->outer) - ctx = ctx->parent; + if (ctx->d()->type == QV4::ExecutionContext::Type_SimpleCallContext && !ctx->d()->outer) + ctx = ctx->d()->parent; - if (!ctx->outer) + if (!ctx->d()->outer) return 0; - while (ctx->outer && ctx->outer->type != ExecutionContext::Type_GlobalContext) - ctx = ctx->outer; + while (ctx->d()->outer && ctx->d()->outer->d()->type != ExecutionContext::Type_GlobalContext) + ctx = ctx->d()->outer; Q_ASSERT(ctx); - if (ctx->type != ExecutionContext::Type_QmlContext) + if (ctx->d()->type != ExecutionContext::Type_QmlContext) return 0; - return static_cast<CallContext *>(ctx)->activation->asReturned<Object>(); + return static_cast<CallContext *>(ctx)->d()->activation->asReturned<Object>(); } QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const @@ -693,30 +705,30 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const QV4::ExecutionContext *c = currentContext(); while (c && frameLimit) { CallContext *callCtx = c->asCallContext(); - if (callCtx && callCtx->function) { + if (callCtx && callCtx->d()->function) { StackFrame frame; - if (callCtx->function->function) - frame.source = callCtx->function->function->sourceFile(); - name = callCtx->function->name(); + if (callCtx->d()->function->function()) + frame.source = callCtx->d()->function->function()->sourceFile(); + name = callCtx->d()->function->name(); frame.function = name->toQString(); frame.line = -1; frame.column = -1; - if (callCtx->function->function) + if (callCtx->d()->function->function()) // line numbers can be negative for places where you can't set a real breakpoint - frame.line = qAbs(callCtx->lineNumber); + frame.line = qAbs(callCtx->d()->lineNumber); stack.append(frame); --frameLimit; } - c = c->parent; + c = c->d()->parent; } if (frameLimit && globalCode) { StackFrame frame; frame.source = globalCode->sourceFile(); frame.function = globalCode->name()->toQString(); - frame.line = rootContext->lineNumber; + frame.line = rootContext->d()->lineNumber; frame.column = -1; @@ -750,8 +762,8 @@ static inline char *v4StackTrace(const ExecutionContext *context) QString result; QTextStream str(&result); str << "stack=["; - if (context && context->engine) { - const QVector<StackFrame> stackTrace = context->engine->stackTrace(20); + if (context && context->d()->engine) { + const QVector<StackFrame> stackTrace = context->d()->engine->stackTrace(20); for (int i = 0; i < stackTrace.size(); ++i) { if (i) str << ','; @@ -781,12 +793,12 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file) QV4::ExecutionContext *c = currentContext(); while (c) { CallContext *callCtx = c->asCallContext(); - if (callCtx && callCtx->function) { - if (callCtx->function->function) - base.setUrl(callCtx->function->function->sourceFile()); + if (callCtx && callCtx->d()->function) { + if (callCtx->d()->function->function()) + base.setUrl(callCtx->d()->function->function()->sourceFile()); break; } - c = c->parent; + c = c->d()->parent; } if (base.isEmpty() && globalCode) @@ -817,8 +829,8 @@ void ExecutionEngine::requireArgumentsAccessors(int n) delete [] oldAccessors; } for (int i = oldSize; i < nArgumentsAccessors; ++i) { - argumentsAccessors[i].value = Value::fromManaged(new (memoryManager) ArgumentsGetterFunction(rootContext, i)); - argumentsAccessors[i].set = Value::fromManaged(new (memoryManager) ArgumentsSetterFunction(rootContext, i)); + argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(rootContext, i)); + argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(rootContext, i)); } } } @@ -839,12 +851,12 @@ void ExecutionEngine::markObjects() ExecutionContext *c = currentContext(); while (c) { - Q_ASSERT(c->inUse); - if (!c->markBit) { - c->markBit = 1; + Q_ASSERT(c->inUse()); + if (!c->markBit()) { + c->d()->markBit = 1; c->markObjects(c, this); } - c = c->parent; + c = c->d()->parent; } id_empty->mark(this); @@ -932,7 +944,7 @@ ReturnedValue ExecutionEngine::throwException(const ValueRef value) QV4::Scope scope(this); QV4::Scoped<ErrorObject> error(scope, value); if (!!error) - exceptionStackTrace = error->stackTrace; + exceptionStackTrace = error->d()->stackTrace; else exceptionStackTrace = stackTrace(); @@ -971,7 +983,7 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError(ExecutionContext *context) QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception); if (!!errorObj && errorObj->asSyntaxError()) { QV4::ScopedString m(scope, errorObj->engine()->newString(QStringLiteral("message"))); - QV4::ScopedValue v(scope, errorObj->get(m)); + QV4::ScopedValue v(scope, errorObj->get(m.getPointer())); error.setDescription(v->toQStringNoThrow()); } else error.setDescription(exception->toQStringNoThrow()); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index d678d6595e..a3f83de338 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -86,6 +86,7 @@ struct SyntaxErrorObject; struct ArgumentsObject; struct ExecutionContext; struct ExecutionEngine; +struct Members; class MemoryManager; class ExecutableAllocator; @@ -111,7 +112,7 @@ struct IdentifierTable; struct InternalClass; struct InternalClassPool; class MultiplyWrappedQObjectMap; -class RegExp; +struct RegExp; class RegExpCache; struct QmlExtensions; struct Exception; @@ -169,7 +170,6 @@ public: return jsStackTop->managed(); } - IdentifierTable *identifierTable; QV4::Debugging::Debugger *debugger; @@ -285,7 +285,7 @@ public: // calling preserve() on the object which removes it from this scarceResource list. class ScarceResourceData { public: - ScarceResourceData(const QVariant &data) : data(data) {} + ScarceResourceData(const QVariant &data = QVariant()) : data(data) {} QVariant data; QIntrusiveListNode node; }; @@ -306,9 +306,6 @@ public: void pushContext(CallContext *context); ExecutionContext *popContext(); - Returned<FunctionObject> *newBuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *)); - Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs); - Returned<Object> *newObject(); Returned<Object> *newObject(InternalClass *internalClass); @@ -327,7 +324,7 @@ public: Returned<DateObject> *newDateObject(const QDateTime &dt); Returned<RegExpObject> *newRegExpObject(const QString &pattern, int flags); - Returned<RegExpObject> *newRegExpObject(RegExpRef re, bool global); + Returned<RegExpObject> *newRegExpObject(RegExp *re, bool global); Returned<RegExpObject> *newRegExpObject(const QRegExp &re); Returned<Object> *newErrorObject(const ValueRef value); @@ -341,7 +338,7 @@ public: Returned<Object> *newVariantObject(const QVariant &v); - Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o); + Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, Object *o); Returned<Object> *qmlContextObject() const; @@ -378,10 +375,10 @@ private: inline void Managed::mark(QV4::ExecutionEngine *engine) { - Q_ASSERT(inUse); - if (markBit) + Q_ASSERT(inUse()); + if (markBit()) return; - markBit = 1; + d()->markBit = 1; engine->pushForGC(this); } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 9d6403e7dd..b99a82a1f5 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -71,104 +71,100 @@ using namespace QV4; -ErrorObject::ErrorObject(InternalClass *ic) - : Object(ic) - , stack(0) +ErrorObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { - Scope scope(engine()); - ScopedValue protectThis(scope, this); + Scope scope(ic->engine); + Scoped<ErrorObject> e(scope, this); - ScopedString s(scope, ic->engine->newString(QStringLiteral("Error"))); - defineDefaultProperty(QStringLiteral("name"), s); + ScopedString s(scope, scope.engine->newString(QStringLiteral("Error"))); + e->defineDefaultProperty(QStringLiteral("name"), s); } -ErrorObject::ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t) - : Object(ic) - , stack(0) +ErrorObject::Data::Data(InternalClass *ic, const ValueRef message, ErrorType t) + : Object::Data(ic) { subtype = t; - Scope scope(engine()); - ScopedValue protectThis(scope, this); + Scope scope(ic->engine); + Scoped<ErrorObject> e(scope, this); - defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); + e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); if (!message->isUndefined()) - defineDefaultProperty(QStringLiteral("message"), message); + e->defineDefaultProperty(QStringLiteral("message"), message); ScopedString s(scope); - defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className()))); + e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className()))); - stackTrace = ic->engine->stackTrace(); - if (!stackTrace.isEmpty()) { - defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source))); - defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line)); + e->d()->stackTrace = scope.engine->stackTrace(); + if (!e->d()->stackTrace.isEmpty()) { + e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source))); + e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line)); } } -ErrorObject::ErrorObject(InternalClass *ic, const QString &message, ErrorObject::ErrorType t) - : Object(ic) - , stack(0) +ErrorObject::Data::Data(InternalClass *ic, const QString &message, ErrorObject::ErrorType t) + : Object::Data(ic) { subtype = t; - Scope scope(engine()); - ScopedValue protectThis(scope, this); + Scope scope(ic->engine); + Scoped<ErrorObject> e(scope, this); ScopedString s(scope); - defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); + e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); - ScopedValue v(scope, ic->engine->newString(message)); - defineDefaultProperty(QStringLiteral("message"), v); - defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className()))); + ScopedValue v(scope, scope.engine->newString(message)); + e->defineDefaultProperty(QStringLiteral("message"), v); + e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className()))); - stackTrace = ic->engine->stackTrace(); - if (!stackTrace.isEmpty()) { - defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source))); - defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line)); + e->d()->stackTrace = scope.engine->stackTrace(); + if (!e->d()->stackTrace.isEmpty()) { + e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source))); + e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line)); } } -ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) - : Object(ic) - , stack(0) +ErrorObject::Data::Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) + : Object::Data(ic) { subtype = t; - Scope scope(engine()); - ScopedValue protectThis(scope, this); + Scope scope(ic->engine); + Scoped<ErrorObject> e(scope, this); ScopedString s(scope); - defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); - defineDefaultProperty(QStringLiteral("name"), (s = ic->engine->newString(className()))); + e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0); + e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className()))); - stackTrace = ic->engine->stackTrace(); + e->d()->stackTrace = scope.engine->stackTrace(); StackFrame frame; frame.source = fileName; frame.line = line; frame.column = column; - stackTrace.prepend(frame); + e->d()->stackTrace.prepend(frame); - if (!stackTrace.isEmpty()) { - defineDefaultProperty(QStringLiteral("fileName"), (s = ic->engine->newString(stackTrace.at(0).source))); - defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(stackTrace.at(0).line)); + if (!e->d()->stackTrace.isEmpty()) { + e->defineDefaultProperty(QStringLiteral("fileName"), (s = scope.engine->newString(e->d()->stackTrace.at(0).source))); + e->defineDefaultProperty(QStringLiteral("lineNumber"), Primitive::fromInt32(e->d()->stackTrace.at(0).line)); } - ScopedValue v(scope, ic->engine->newString(message)); - defineDefaultProperty(QStringLiteral("message"), v); + ScopedValue v(scope, scope.engine->newString(message)); + e->defineDefaultProperty(QStringLiteral("message"), v); } ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) { Scope scope(ctx); - Scoped<ErrorObject> This(scope, ctx->callData->thisObject); + Scoped<ErrorObject> This(scope, ctx->d()->callData->thisObject); if (!This) return ctx->throwTypeError(); - if (!This->stack) { + if (!This->d()->stack) { QString trace; - for (int i = 0; i < This->stackTrace.count(); ++i) { + for (int i = 0; i < This->d()->stackTrace.count(); ++i) { if (i > 0) trace += QLatin1Char('\n'); - const StackFrame &frame = This->stackTrace[i]; + const StackFrame &frame = This->d()->stackTrace[i]; trace += frame.function; trace += QLatin1Char('@'); trace += frame.source; @@ -177,16 +173,16 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) trace += QString::number(frame.line); } } - This->stack = ctx->engine->newString(trace)->getPointer(); + This->d()->stack = ctx->d()->engine->newString(trace)->getPointer(); } - return This->stack->asReturnedValue(); + return This->d()->stack->asReturnedValue(); } void ErrorObject::markObjects(Managed *that, ExecutionEngine *e) { ErrorObject *This = that->asErrorObject(); - if (This->stack) - This->stack->mark(e); + if (This->d()->stack) + This->d()->stack->mark(e); Object::markObjects(that, e); } @@ -194,58 +190,58 @@ DEFINE_OBJECT_VTABLE(ErrorObject); DEFINE_OBJECT_VTABLE(SyntaxErrorObject); -SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg) - : ErrorObject(engine->syntaxErrorClass, msg, SyntaxError) +SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef msg) + : ErrorObject::Data(engine->syntaxErrorClass, msg, SyntaxError) { } -SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : ErrorObject(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError) +SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) + : ErrorObject::Data(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError) { } -EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const ValueRef message) - : ErrorObject(engine->evalErrorClass, message, EvalError) +EvalErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message) + : ErrorObject::Data(engine->evalErrorClass, message, EvalError) { } -RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const ValueRef message) - : ErrorObject(engine->rangeErrorClass, message, RangeError) +RangeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message) + : ErrorObject::Data(engine->rangeErrorClass, message, RangeError) { } -RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message) - : ErrorObject(engine->rangeErrorClass, message, RangeError) +RangeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message) + : ErrorObject::Data(engine->rangeErrorClass, message, RangeError) { } -ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message) - : ErrorObject(engine->referenceErrorClass, message, ReferenceError) +ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message) + : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError) { } -ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message) - : ErrorObject(engine->referenceErrorClass, message, ReferenceError) +ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &message) + : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError) { } -ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) - : ErrorObject(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError) +ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber) + : ErrorObject::Data(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError) { } -TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const ValueRef message) - : ErrorObject(engine->typeErrorClass, message, TypeError) +TypeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message) + : ErrorObject::Data(engine->typeErrorClass, message, TypeError) { } -TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message) - : ErrorObject(engine->typeErrorClass, message, TypeError) +TypeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message) + : ErrorObject::Data(engine->typeErrorClass, message, TypeError) { } -URIErrorObject::URIErrorObject(ExecutionEngine *engine, const ValueRef message) - : ErrorObject(engine->uriErrorClass, message, URIError) +URIErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message) + : ErrorObject::Data(engine->uriErrorClass, message, URIError) { } @@ -257,14 +253,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor); DEFINE_OBJECT_VTABLE(TypeErrorCtor); DEFINE_OBJECT_VTABLE(URIErrorCtor); -ErrorCtor::ErrorCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Error")) +ErrorCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Error")) { setVTable(staticVTable()); } -ErrorCtor::ErrorCtor(ExecutionContext *scope, const QString &name) - : FunctionObject(scope, name) +ErrorCtor::Data::Data(ExecutionContext *scope, const QString &name) + : FunctionObject::Data(scope, name) { setVTable(staticVTable()); } @@ -281,8 +277,8 @@ ReturnedValue ErrorCtor::call(Managed *that, CallData *callData) return static_cast<Object *>(that)->construct(callData); } -EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("EvalError")) +EvalErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("EvalError")) { setVTable(staticVTable()); } @@ -291,11 +287,11 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) EvalErrorObject(m->engine(), v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<EvalErrorObject>(m->engine(), v))->asReturnedValue(); } -RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("RangeError")) +RangeErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("RangeError")) { setVTable(staticVTable()); } @@ -304,11 +300,11 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) RangeErrorObject(scope.engine, v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue(); } -ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("ReferenceError")) +ReferenceErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("ReferenceError")) { setVTable(staticVTable()); } @@ -317,11 +313,11 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) ReferenceErrorObject(scope.engine, v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue(); } -SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("SyntaxError")) +SyntaxErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("SyntaxError")) { setVTable(staticVTable()); } @@ -330,11 +326,11 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) SyntaxErrorObject(scope.engine, v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue(); } -TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("TypeError")) +TypeErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("TypeError")) { setVTable(staticVTable()); } @@ -343,11 +339,11 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) TypeErrorObject(scope.engine, v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue(); } -URIErrorCtor::URIErrorCtor(ExecutionContext *scope) - : ErrorCtor(scope, QStringLiteral("URIError")) +URIErrorCtor::Data::Data(ExecutionContext *scope) + : ErrorCtor::Data(scope, QStringLiteral("URIError")) { setVTable(staticVTable()); } @@ -356,10 +352,10 @@ ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData) { Scope scope(m->engine()); ScopedValue v(scope, callData->argument(0)); - return (new (m->engine()->memoryManager) URIErrorObject(scope.engine, v))->asReturnedValue(); + return (m->engine()->memoryManager->alloc<URIErrorObject>(scope.engine, v))->asReturnedValue(); } -void ErrorPrototype::init(ExecutionEngine *engine, ObjectRef ctor, Object *obj) +void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj) { Scope scope(engine); ScopedString s(scope); @@ -375,19 +371,19 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - Object *o = ctx->callData->thisObject.asObject(); + Object *o = ctx->d()->callData->thisObject.asObject(); if (!o) return ctx->throwTypeError(); - ScopedValue name(scope, o->get(ctx->engine->id_name)); + ScopedValue name(scope, o->get(ctx->d()->engine->id_name)); QString qname; if (name->isUndefined()) qname = QString::fromLatin1("Error"); else qname = name->toQString(); - ScopedString s(scope, ctx->engine->newString(QString::fromLatin1("message"))); - ScopedValue message(scope, o->get(s)); + ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message"))); + ScopedValue message(scope, o->get(s.getPointer())); QString qmessage; if (!message->isUndefined()) qmessage = message->toQString(); @@ -401,5 +397,5 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx) str = qname + QLatin1String(": ") + qmessage; } - return ctx->engine->newString(str)->asReturnedValue(); + return ctx->d()->engine->newString(str)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index c44cc5cdb2..ddf30d2059 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -51,8 +51,6 @@ namespace QV4 { struct SyntaxErrorObject; struct ErrorObject: Object { - V4_OBJECT - Q_MANAGED_TYPE(ErrorObject) enum { IsErrorObject = true }; @@ -66,17 +64,19 @@ struct ErrorObject: Object { TypeError, URIError }; - - ErrorObject(InternalClass *ic); - ErrorObject(InternalClass *ic, const ValueRef message, ErrorType t = Error); - ErrorObject(InternalClass *ic, const QString &message, ErrorType t = Error); - ErrorObject(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error); + struct Data : Object::Data { + Data(InternalClass *ic); + Data(InternalClass *ic, const ValueRef message, ErrorType t = Error); + Data(InternalClass *ic, const QString &message, ErrorType t = Error); + Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error); + StackTrace stackTrace; + String *stack; + }; + V4_OBJECT(Object) + Q_MANAGED_TYPE(ErrorObject) SyntaxErrorObject *asSyntaxError(); - StackTrace stackTrace; - String *stack; - static ReturnedValue method_get_stack(CallContext *ctx); static void markObjects(Managed *that, ExecutionEngine *e); static void destroy(Managed *that) { static_cast<ErrorObject *>(that)->~ErrorObject(); } @@ -88,40 +88,55 @@ inline ErrorObject *value_cast(const Value &v) { } struct EvalErrorObject: ErrorObject { - EvalErrorObject(ExecutionEngine *engine, const ValueRef message); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + }; }; struct RangeErrorObject: ErrorObject { - RangeErrorObject(ExecutionEngine *engine, const ValueRef message); - RangeErrorObject(ExecutionEngine *engine, const QString &msg); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + Data(ExecutionEngine *engine, const QString &msg); + }; }; struct ReferenceErrorObject: ErrorObject { - ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message); - ReferenceErrorObject(ExecutionEngine *engine, const QString &msg); - ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + Data(ExecutionEngine *engine, const QString &msg); + Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber); + }; }; struct SyntaxErrorObject: ErrorObject { - V4_OBJECT - SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg); - SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber); + }; + V4_OBJECT(ErrorObject) }; struct TypeErrorObject: ErrorObject { - TypeErrorObject(ExecutionEngine *engine, const ValueRef message); - TypeErrorObject(ExecutionEngine *engine, const QString &msg); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + Data(ExecutionEngine *engine, const QString &msg); + }; }; struct URIErrorObject: ErrorObject { - URIErrorObject(ExecutionEngine *engine, const ValueRef message); + struct Data : ErrorObject::Data { + Data(ExecutionEngine *engine, const ValueRef message); + }; }; struct ErrorCtor: FunctionObject { - V4_OBJECT - ErrorCtor(ExecutionContext *scope); - ErrorCtor(ExecutionContext *scope, const QString &name); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + Data(ExecutionContext *scope, const QString &name); + }; + + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -129,103 +144,107 @@ struct ErrorCtor: FunctionObject struct EvalErrorCtor: ErrorCtor { - V4_OBJECT - EvalErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; struct RangeErrorCtor: ErrorCtor { - V4_OBJECT - RangeErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; struct ReferenceErrorCtor: ErrorCtor { - V4_OBJECT - ReferenceErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; struct SyntaxErrorCtor: ErrorCtor { - V4_OBJECT - SyntaxErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; struct TypeErrorCtor: ErrorCtor { - V4_OBJECT - TypeErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; struct URIErrorCtor: ErrorCtor { - V4_OBJECT - URIErrorCtor(ExecutionContext *scope); + struct Data : ErrorCtor::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(ErrorCtor) static ReturnedValue construct(Managed *m, CallData *callData); }; -struct ErrorPrototype: ErrorObject +struct ErrorPrototype : ErrorObject { - // ### shouldn't be undefined - ErrorPrototype(InternalClass *ic): ErrorObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor) { init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this); } - static void init(ExecutionEngine *engine, ObjectRef ctor, Object *obj); + static void init(ExecutionEngine *engine, Object *ctor, Object *obj); static ReturnedValue method_toString(CallContext *ctx); }; -struct EvalErrorPrototype: ErrorObject +struct EvalErrorPrototype : ErrorObject { - EvalErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; -struct RangeErrorPrototype: ErrorObject +struct RangeErrorPrototype : ErrorObject { - RangeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; -struct ReferenceErrorPrototype: ErrorObject +struct ReferenceErrorPrototype : ErrorObject { - ReferenceErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; -struct SyntaxErrorPrototype: ErrorObject +struct SyntaxErrorPrototype : ErrorObject { - SyntaxErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; -struct TypeErrorPrototype: ErrorObject +struct TypeErrorPrototype : ErrorObject { - TypeErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; -struct URIErrorPrototype: ErrorObject +struct URIErrorPrototype : ErrorObject { - URIErrorPrototype(InternalClass *ic): ErrorObject(ic) { setVTable(staticVTable()); } - void init(ExecutionEngine *engine, ObjectRef ctor) { ErrorPrototype::init(engine, ctor, this); } + void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this); } }; inline SyntaxErrorObject *ErrorObject::asSyntaxError() { - return subtype == SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0; + return subtype() == SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0; } } diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 6fdf61f2c3..bf77b4434c 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -45,6 +45,7 @@ #include "qv4value_inl_p.h" #include "qv4engine_p.h" #include "qv4lookup_p.h" +#include "qv4mm_p.h" QT_BEGIN_NAMESPACE @@ -62,6 +63,8 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, internalClass = engine->emptyClass; const quint32 *formalsIndices = compiledFunction->formalsTable(); // iterate backwards, so we get the right ordering for duplicate names + Scope scope(engine); + ScopedString s(scope); for (int i = static_cast<int>(compiledFunction->nFormals - 1); i >= 0; --i) { String *arg = compilationUnit->runtimeStrings[formalsIndices[i]].asString(); while (1) { @@ -71,7 +74,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, break; } // duplicate arguments, need some trick to store them - arg = new (engine->memoryManager) String(engine, arg, engine->newString(QString(0xfffe))->getPointer()); + arg = (s = engine->memoryManager->alloc<String>(engine, arg, engine->newString(QString(0xfffe))->getPointer())).getPointer(); } } diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index e6385d861c..482f247319 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -94,8 +94,8 @@ struct Q_QML_EXPORT Function { ReturnedValue (*codePtr)(ExecutionContext *, const uchar *)); ~Function(); - inline StringRef name() { - return compilationUnit->runtimeStrings[compiledFunction->nameIndex]; + inline String *name() { + return compilationUnit->runtimeStrings[compiledFunction->nameIndex].getPointer(); } inline QString sourceFile() const { return compilationUnit->fileName(); } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 39a123c4d2..10974780f3 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -74,88 +74,88 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); -FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto) - : Object(scope->engine->functionClass) +FunctionObject::Data::Data(ExecutionContext *scope, String *name, bool createProto) + : Object::Data(scope->d()->engine->functionClass) , scope(scope) - , function(0) { - init(name, createProto); + Scope s(scope); + ScopedFunctionObject f(s, this); + f->init(name, createProto); } -FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : Object(scope->engine->functionClass) + +FunctionObject::Data::Data(ExecutionContext *scope, const QString &name, bool createProto) + : Object::Data(scope->d()->engine->functionClass) , scope(scope) - , function(0) { Scope s(scope); - ScopedValue protectThis(s, this); + ScopedFunctionObject f(s, this); ScopedString n(s, s.engine->newString(name)); - init(n, createProto); + f->init(n.getPointer(), createProto); } -FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) - : Object(scope->engine->functionClass) +FunctionObject::Data::Data(ExecutionContext *scope, const ReturnedValue name) + : Object::Data(scope->d()->engine->functionClass) , scope(scope) - , function(0) { Scope s(scope); - ScopedValue protectThis(s, this); + ScopedFunctionObject f(s, this); ScopedString n(s, name); - init(n, false); + f->init(n.getPointer(), false); } -FunctionObject::FunctionObject(InternalClass *ic) - : Object(ic) +FunctionObject::Data::Data(InternalClass *ic) + : Object::Data(ic) , scope(ic->engine->rootContext) - , function(0) { - needsActivation = false; - strictMode = false; + memberData.ensureIndex(ic->engine, Index_Prototype); memberData[Index_Prototype] = Encode::undefined(); } -FunctionObject::~FunctionObject() + +FunctionObject::Data::~Data() { if (function) function->compilationUnit->deref(); } -void FunctionObject::init(const StringRef n, bool createProto) +void FunctionObject::init(String *n, bool createProto) { - Scope s(internalClass->engine); + Scope s(internalClass()->engine); ScopedValue protectThis(s, this); - needsActivation = true; - strictMode = false; + d()->needsActivation = true; + d()->strictMode = false; + memberData().ensureIndex(s.engine, Index_Prototype); if (createProto) { - Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass)); - proto->memberData[Index_ProtoConstructor] = this->asReturnedValue(); - memberData[Index_Prototype] = proto.asReturnedValue(); + Scoped<Object> proto(s, scope()->d()->engine->newObject(scope()->d()->engine->protoClass)); + proto->memberData()[Index_ProtoConstructor] = this->asReturnedValue(); + memberData()[Index_Prototype] = proto.asReturnedValue(); } else { - memberData[Index_Prototype] = Encode::undefined(); + memberData()[Index_Prototype] = Encode::undefined(); } - ScopedValue v(s, n.asReturnedValue()); - defineReadonlyProperty(scope->engine->id_name, v); + ScopedValue v(s, n); + defineReadonlyProperty(s.engine->id_name, v); } ReturnedValue FunctionObject::name() { - return get(scope->engine->id_name); + return get(scope()->d()->engine->id_name); } ReturnedValue FunctionObject::newInstance() { - Scope scope(internalClass->engine); + Scope scope(internalClass()->engine); ScopedCallData callData(scope, 0); return construct(callData); } ReturnedValue FunctionObject::construct(Managed *that, CallData *) { - that->internalClass->engine->currentContext()->throwTypeError(); + that->internalClass()->engine->currentContext()->throwTypeError(); return Encode::undefined(); } @@ -167,8 +167,8 @@ ReturnedValue FunctionObject::call(Managed *, CallData *) void FunctionObject::markObjects(Managed *that, ExecutionEngine *e) { FunctionObject *o = static_cast<FunctionObject *>(that); - if (o->scope) - o->scope->mark(e); + if (o->scope()) + o->scope()->mark(e); Object::markObjects(that, e); } @@ -179,14 +179,14 @@ FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Fu function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith || function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount || function->isNamedExpression()) - return new (scope->engine->memoryManager) ScriptFunction(scope, function); - return new (scope->engine->memoryManager) SimpleScriptFunction(scope, function, createProto); + return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function); + return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto); } DEFINE_OBJECT_VTABLE(FunctionCtor); -FunctionCtor::FunctionCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Function")) +FunctionCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Function")) { setVTable(staticVTable()); } @@ -195,7 +195,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope) ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) { FunctionCtor *f = static_cast<FunctionCtor *>(that); - ExecutionEngine *v4 = f->internalClass->engine; + ExecutionEngine *v4 = f->internalClass()->engine; ExecutionContext *ctx = v4->currentContext(); QString arguments; QString body; @@ -207,7 +207,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) } body = callData->args[callData->argc - 1].toString(ctx)->toQString(); } - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}"); @@ -229,7 +229,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) IR::Module module(v4->debugger != 0); - QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode); + QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode()); cg.generateFromFunctionExpression(QString(), function, fe, &module); QV4::Compiler::JSUnitGenerator jsGenerator(&module); @@ -246,12 +246,14 @@ ReturnedValue FunctionCtor::call(Managed *that, CallData *callData) return construct(that, callData); } -FunctionPrototype::FunctionPrototype(InternalClass *ic) - : FunctionObject(ic) +DEFINE_OBJECT_VTABLE(FunctionPrototype); + +FunctionPrototype::Data::Data(InternalClass *ic) + : FunctionObject::Data(ic) { } -void FunctionPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -270,17 +272,17 @@ void FunctionPrototype::init(ExecutionEngine *engine, ObjectRef ctor) ReturnedValue FunctionPrototype::method_toString(CallContext *ctx) { - FunctionObject *fun = ctx->callData->thisObject.asFunctionObject(); + FunctionObject *fun = ctx->d()->callData->thisObject.asFunctionObject(); if (!fun) return ctx->throwTypeError(); - return ctx->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue(); + return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue(); } ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) { Scope scope(ctx); - FunctionObject *o = ctx->callData->thisObject.asFunctionObject(); + FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject(); if (!o) return ctx->throwTypeError(); @@ -300,13 +302,13 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) ScopedCallData callData(scope, len); if (len) { - if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty) { + if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty()) { for (quint32 i = 0; i < len; ++i) callData->args[i] = arr->getIndexed(i); } else { - int alen = qMin(len, arr->arrayData->length()); + int alen = qMin(len, arr->arrayData()->length()); if (alen) - memcpy(callData->args, arr->arrayData->data, alen*sizeof(Value)); + memcpy(callData->args, arr->arrayData()->arrayData(), alen*sizeof(Value)); for (quint32 i = alen; i < len; ++i) callData->args[i] = Primitive::undefinedValue(); } @@ -320,14 +322,14 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx) { Scope scope(ctx); - FunctionObject *o = ctx->callData->thisObject.asFunctionObject(); + FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject(); if (!o) return ctx->throwTypeError(); - ScopedCallData callData(scope, ctx->callData->argc ? ctx->callData->argc - 1 : 0); - if (ctx->callData->argc) { - for (int i = 1; i < ctx->callData->argc; ++i) - callData->args[i - 1] = ctx->callData->args[i]; + ScopedCallData callData(scope, ctx->d()->callData->argc ? ctx->d()->callData->argc - 1 : 0); + if (ctx->d()->callData->argc) { + for (int i = 1; i < ctx->d()->callData->argc; ++i) + callData->args[i - 1] = ctx->d()->callData->args[i]; } callData->thisObject = ctx->argument(0); return o->call(callData); @@ -336,49 +338,34 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx) ReturnedValue FunctionPrototype::method_bind(CallContext *ctx) { Scope scope(ctx); - Scoped<FunctionObject> target(scope, ctx->callData->thisObject); + Scoped<FunctionObject> target(scope, ctx->d()->callData->thisObject); if (!target) return ctx->throwTypeError(); ScopedValue boundThis(scope, ctx->argument(0)); - QVector<Value> boundArgs; - for (int i = 1; i < ctx->callData->argc; ++i) - boundArgs += ctx->callData->args[i]; + Members boundArgs; + boundArgs.reset(); + 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)); + } + ScopedValue protectBoundArgs(scope, boundArgs.d()); - return ctx->engine->newBoundFunction(ctx->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue(); + return BoundFunction::create(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue(); } DEFINE_OBJECT_VTABLE(ScriptFunction); -ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) - : SimpleScriptFunction(scope, function, true) +ScriptFunction::Data::Data(ExecutionContext *scope, Function *function) + : SimpleScriptFunction::Data(scope, function, true) { setVTable(staticVTable()); - - Scope s(scope); - ScopedValue protectThis(s, this); - - // global function - if (!scope) - return; - - ExecutionEngine *v4 = scope->engine; - - needsActivation = function->needsActivation(); - strictMode = function->isStrict(); - - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount())); - - if (scope->strictMode) { - Property pd(v4->thrower, v4->thrower); - insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - } } ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) { - ExecutionEngine *v4 = that->internalClass->engine; + ExecutionEngine *v4 = that->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -391,13 +378,13 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); callData->thisObject = obj.asReturnedValue(); - ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData); + ExecutionContext *ctx = reinterpret_cast<ExecutionContext *>(context->newCallContext(f.getPointer(), callData)); ExecutionContextSaver ctxSaver(context); - ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function)); + ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function())); - if (f->function->compiledFunction->hasQmlDependencies()) - QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction); + if (f->function()->compiledFunction->hasQmlDependencies()) + QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction); if (result->isObject()) return result.asReturnedValue(); @@ -407,7 +394,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) { ScriptFunction *f = static_cast<ScriptFunction *>(that); - ExecutionEngine *v4 = f->internalClass->engine; + ExecutionEngine *v4 = f->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -415,53 +402,51 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); Scope scope(context); - CallContext *ctx = context->newCallContext(f, callData); + CallContext *ctx = reinterpret_cast<CallContext *>(context->newCallContext(f, callData)); ExecutionContextSaver ctxSaver(context); - ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function)); + ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function())); - if (f->function->compiledFunction->hasQmlDependencies()) - QmlContextWrapper::registerQmlDependencies(ctx->engine, f->function->compiledFunction); + if (f->function()->compiledFunction->hasQmlDependencies()) + QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction); return result.asReturnedValue(); } DEFINE_OBJECT_VTABLE(SimpleScriptFunction); -SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto) - : FunctionObject(scope, function->name(), createProto) +SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bool createProto) + : FunctionObject::Data(scope, function->name(), createProto) { setVTable(staticVTable()); - Scope s(scope); - ScopedValue protectThis(s, this); - this->function = function; - this->function->compilationUnit->ref(); + function->compilationUnit->ref(); Q_ASSERT(function); Q_ASSERT(function->code); + needsActivation = function->needsActivation(); + strictMode = function->isStrict(); + // global function if (!scope) return; - ExecutionEngine *v4 = scope->engine; - - needsActivation = function->needsActivation(); - strictMode = function->isStrict(); + Scope s(scope); + ScopedFunctionObject f(s, this); - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount())); + f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount())); - if (scope->strictMode) { - Property pd(v4->thrower, v4->thrower); - insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + if (scope->d()->strictMode) { + Property pd(s.engine->thrower, s.engine->thrower); + f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } } ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) { - ExecutionEngine *v4 = that->internalClass->engine; + ExecutionEngine *v4 = that->engine(); if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -475,24 +460,24 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); ExecutionContextSaver ctxSaver(context); - CallContext ctx(v4); - ctx.strictMode = f->strictMode; + CallContext::Data ctx(v4); + ctx.strictMode = f->strictMode(); ctx.callData = callData; ctx.function = f.getPointer(); - ctx.compilationUnit = f->function->compilationUnit; + ctx.compilationUnit = f->function()->compilationUnit; ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.outer = f->scope; + ctx.outer = f->scope(); ctx.locals = v4->stackPush(f->varCount()); while (callData->argc < (int)f->formalParameterCount()) { callData->args[callData->argc] = Encode::undefined(); ++callData->argc; } - Q_ASSERT(v4->currentContext() == &ctx); + Q_ASSERT(v4->currentContext()->d() == &ctx); - Scoped<Object> result(scope, Q_V4_PROFILE(v4, &ctx, f->function)); + Scoped<Object> result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function())); - if (f->function->compiledFunction->hasQmlDependencies()) - QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction); + if (f->function()->compiledFunction->hasQmlDependencies()) + QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction); if (!result) return callData->thisObject.asReturnedValue(); @@ -501,7 +486,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) { - ExecutionEngine *v4 = that->internalClass->engine; + ExecutionEngine *v4 = that->internalClass()->engine; if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -512,24 +497,24 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); ExecutionContextSaver ctxSaver(context); - CallContext ctx(v4); - ctx.strictMode = f->strictMode; + CallContext::Data ctx(v4); + ctx.strictMode = f->strictMode(); ctx.callData = callData; ctx.function = f; - ctx.compilationUnit = f->function->compilationUnit; + ctx.compilationUnit = f->function()->compilationUnit; ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.outer = f->scope; + ctx.outer = f->scope(); ctx.locals = v4->stackPush(f->varCount()); while (callData->argc < (int)f->formalParameterCount()) { callData->args[callData->argc] = Encode::undefined(); ++callData->argc; } - Q_ASSERT(v4->currentContext() == &ctx); + Q_ASSERT(v4->currentContext()->d() == &ctx); - ScopedValue result(scope, Q_V4_PROFILE(v4, &ctx, f->function)); + ScopedValue result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function())); - if (f->function->compiledFunction->hasQmlDependencies()) - QmlContextWrapper::registerQmlDependencies(v4, f->function->compiledFunction); + if (f->function()->compiledFunction->hasQmlDependencies()) + QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction); return result.asReturnedValue(); } @@ -538,10 +523,10 @@ InternalClass *SimpleScriptFunction::internalClassForConstructor() { ReturnedValue proto = protoProperty(); InternalClass *classForConstructor; - Scope scope(internalClass->engine); + Scope scope(internalClass()->engine); ScopedObject p(scope, proto); if (p) - classForConstructor = internalClass->engine->constructClass->changePrototype(p.getPointer()); + classForConstructor = internalClass()->engine->constructClass->changePrototype(p.getPointer()); else classForConstructor = scope.engine->objectClass; @@ -552,8 +537,8 @@ InternalClass *SimpleScriptFunction::internalClassForConstructor() DEFINE_OBJECT_VTABLE(BuiltinFunction); -BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *)) - : FunctionObject(scope, name) +BuiltinFunction::Data::Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) + : FunctionObject::Data(scope, name) , code(code) { setVTable(staticVTable()); @@ -561,13 +546,13 @@ BuiltinFunction::BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue BuiltinFunction::construct(Managed *f, CallData *) { - return f->internalClass->engine->currentContext()->throwTypeError(); + return f->internalClass()->engine->currentContext()->throwTypeError(); } ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) { BuiltinFunction *f = static_cast<BuiltinFunction *>(that); - ExecutionEngine *v4 = f->internalClass->engine; + ExecutionEngine *v4 = f->internalClass()->engine; if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -575,18 +560,18 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); ExecutionContextSaver ctxSaver(context); - CallContext ctx(v4); - ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? + CallContext::Data ctx(v4); + ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context? ctx.callData = callData; - Q_ASSERT(v4->currentContext() == &ctx); + Q_ASSERT(v4->currentContext()->d() == &ctx); - return f->code(&ctx); + return f->d()->code(reinterpret_cast<CallContext *>(&ctx)); } ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData) { IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that); - ExecutionEngine *v4 = f->internalClass->engine; + ExecutionEngine *v4 = f->internalClass()->engine; if (v4->hasException) return Encode::undefined(); CHECK_STACK_LIMITS(v4); @@ -594,82 +579,76 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData) ExecutionContext *context = v4->currentContext(); ExecutionContextSaver ctxSaver(context); - CallContext ctx(v4); - ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? + CallContext::Data ctx(v4); + ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context? ctx.callData = callData; - Q_ASSERT(v4->currentContext() == &ctx); + Q_ASSERT(v4->currentContext()->d() == &ctx); - return f->code(&ctx, f->index); + return f->d()->code(reinterpret_cast<CallContext *>(&ctx), f->d()->index); } DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); DEFINE_OBJECT_VTABLE(BoundFunction); -BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs) - : FunctionObject(scope, QStringLiteral("__bound function__")) +BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs) + : FunctionObject::Data(scope, QStringLiteral("__bound function__")) , target(target) , boundArgs(boundArgs) { + this->boundThis = boundThis; setVTable(staticVTable()); subtype = FunctionObject::BoundFunction; - this->boundThis = boundThis; Scope s(scope); - ScopedValue protectThis(s, this); + ScopedObject f(s, this); - ScopedValue l(s, target->get(scope->engine->id_length)); + ScopedValue l(s, target->get(s.engine->id_length)); int len = l->toUInt32(); len -= boundArgs.size(); if (len < 0) len = 0; - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(len)); + f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len)); - ExecutionEngine *v4 = scope->engine; + ExecutionEngine *v4 = s.engine; Property pd(v4->thrower, v4->thrower); - insertMember(scope->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); - insertMember(scope->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); -} - -void BoundFunction::destroy(Managed *that) -{ - static_cast<BoundFunction *>(that)->~BoundFunction(); + f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); } ReturnedValue BoundFunction::call(Managed *that, CallData *dd) { BoundFunction *f = static_cast<BoundFunction *>(that); - Scope scope(f->scope->engine); + Scope scope(f->scope()->d()->engine); if (scope.hasException()) return Encode::undefined(); - ScopedCallData callData(scope, f->boundArgs.size() + dd->argc); - callData->thisObject = f->boundThis; - memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); - memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value)); - return f->target->call(callData); + ScopedCallData callData(scope, f->boundArgs().size() + 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)); + return f->target()->call(callData); } ReturnedValue BoundFunction::construct(Managed *that, CallData *dd) { BoundFunction *f = static_cast<BoundFunction *>(that); - Scope scope(f->scope->engine); + Scope scope(f->scope()->d()->engine); if (scope.hasException()) return Encode::undefined(); - ScopedCallData callData(scope, f->boundArgs.size() + dd->argc); - memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); - memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value)); - return f->target->construct(callData); + 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)); + return f->target()->construct(callData); } void BoundFunction::markObjects(Managed *that, ExecutionEngine *e) { BoundFunction *o = static_cast<BoundFunction *>(that); - o->target->mark(e); - o->boundThis.mark(e); - for (int i = 0; i < o->boundArgs.size(); ++i) - o->boundArgs.at(i).mark(e); + o->target()->mark(e); + o->boundThis().mark(e); + 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 5b832d0595..907b660911 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -51,6 +51,7 @@ #include "qv4property_p.h" #include "qv4function_p.h" #include "qv4objectiterator_p.h" +#include "qv4mm_p.h" #include <QtCore/QString> #include <QtCore/QHash> @@ -94,7 +95,17 @@ struct InternalClass; struct Lookup; struct Q_QML_EXPORT FunctionObject: Object { - V4_OBJECT + struct Q_QML_PRIVATE_EXPORT Data : Object::Data { + Data(ExecutionContext *scope, String *name, bool createProto = false); + Data(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); + Data(ExecutionContext *scope, const ReturnedValue name); + Data(InternalClass *ic); + ~Data(); + + ExecutionContext *scope; + Function *function; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(FunctionObject) enum { IsFunctionObject = true @@ -111,18 +122,15 @@ struct Q_QML_EXPORT FunctionObject: Object { Index_ProtoConstructor = 0 }; - ExecutionContext *scope; - ReturnedValue name(); - unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; } - unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } - Function *function; - FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false); - FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); - FunctionObject(ExecutionContext *scope, const ReturnedValue name); - ~FunctionObject(); + ExecutionContext *scope() { return d()->scope; } + Function *function() { return d()->function; } + + ReturnedValue name(); + unsigned int formalParameterCount() { return function() ? function()->compiledFunction->nFormals : 0; } + unsigned int varCount() { return function() ? function()->compiledFunction->nLocals : 0; } - void init(const StringRef name, bool createProto); + void init(String *name, bool createProto); ReturnedValue newInstance(); @@ -130,6 +138,9 @@ struct Q_QML_EXPORT FunctionObject: Object { using Object::call; static ReturnedValue construct(Managed *that, CallData *); static ReturnedValue call(Managed *that, CallData *d); + static void destroy(Managed *m) { + static_cast<FunctionObject *>(m)->d()->~Data(); + } static FunctionObject *cast(const Value &v) { return v.asFunctionObject(); @@ -137,14 +148,13 @@ struct Q_QML_EXPORT FunctionObject: Object { static FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); - ReturnedValue protoProperty() { return memberData[Index_Prototype].asReturnedValue(); } + ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); } -protected: - FunctionObject(InternalClass *ic); + bool needsActivation() const { return d()->needsActivation; } + bool strictMode() const { return d()->strictMode; } + bool bindingKeyFlag() const { return d()->bindingKeyFlag; } static void markObjects(Managed *that, ExecutionEngine *e); - static void destroy(Managed *that) - { static_cast<FunctionObject*>(that)->~FunctionObject(); } }; template<> @@ -152,12 +162,13 @@ inline FunctionObject *value_cast(const Value &v) { return v.asFunctionObject(); } -DEFINE_REF(FunctionObject, Object); - struct FunctionCtor: FunctionObject { - V4_OBJECT - FunctionCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *that, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -165,8 +176,12 @@ struct FunctionCtor: FunctionObject struct FunctionPrototype: FunctionObject { - FunctionPrototype(InternalClass *ic); - void init(ExecutionEngine *engine, ObjectRef ctor); + struct Data : FunctionObject::Data { + Data(InternalClass *ic); + }; + V4_OBJECT(FunctionObject) + + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_apply(CallContext *ctx); @@ -174,11 +189,17 @@ struct FunctionPrototype: FunctionObject static ReturnedValue method_bind(CallContext *ctx); }; -struct BuiltinFunction: FunctionObject { - V4_OBJECT - ReturnedValue (*code)(CallContext *); +struct Q_QML_EXPORT BuiltinFunction: FunctionObject { + struct Q_QML_EXPORT Data : FunctionObject::Data { + Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)); + ReturnedValue (*code)(CallContext *); + }; + V4_OBJECT(FunctionObject) - BuiltinFunction(ExecutionContext *scope, const StringRef name, ReturnedValue (*code)(CallContext *)); + static BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) + { + return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code); + } static ReturnedValue construct(Managed *, CallData *); static ReturnedValue call(Managed *that, CallData *callData); @@ -186,18 +207,18 @@ struct BuiltinFunction: FunctionObject { struct IndexedBuiltinFunction: FunctionObject { - V4_OBJECT - - ReturnedValue (*code)(CallContext *ctx, uint index); - uint index; - - IndexedBuiltinFunction(ExecutionContext *scope, uint index, ReturnedValue (*code)(CallContext *ctx, uint index)) - : FunctionObject(scope) - , code(code) - , index(index) - { - setVTable(staticVTable()); - } + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, uint index, ReturnedValue (*code)(CallContext *ctx, uint index)) + : FunctionObject::Data(scope), + code(code) + , index(index) + { + setVTable(staticVTable()); + } + ReturnedValue (*code)(CallContext *, uint index); + uint index; + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *m, CallData *) { @@ -209,8 +230,10 @@ struct IndexedBuiltinFunction: FunctionObject struct SimpleScriptFunction: FunctionObject { - V4_OBJECT - SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, Function *function, bool createProto); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -219,8 +242,10 @@ struct SimpleScriptFunction: FunctionObject { }; struct ScriptFunction: SimpleScriptFunction { - V4_OBJECT - ScriptFunction(ExecutionContext *scope, Function *function); + struct Data : SimpleScriptFunction::Data { + Data(ExecutionContext *scope, Function *function); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -228,19 +253,26 @@ struct ScriptFunction: SimpleScriptFunction { struct BoundFunction: FunctionObject { - V4_OBJECT - FunctionObject *target; - Value boundThis; - QVector<Value> boundArgs; + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs); + FunctionObject *target; + Value boundThis; + Members boundArgs; + }; + V4_OBJECT(FunctionObject) - BoundFunction(ExecutionContext *scope, FunctionObjectRef target, const ValueRef boundThis, const QVector<Value> &boundArgs); - ~BoundFunction() {} + static BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &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; } static ReturnedValue construct(Managed *, CallData *d); static ReturnedValue call(Managed *that, CallData *dd); - static void destroy(Managed *); static void markObjects(Managed *that, ExecutionEngine *e); }; diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index a00231c3a1..039f5c1e78 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -74,15 +74,19 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); } // Decide whether to enable or disable the JIT // White list architectures +// +// NOTE: This should match the logic in qv4targetplatform_p.h! -#if defined(Q_PROCESSOR_X86) +#if defined(Q_PROCESSOR_X86) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD)) #define V4_ENABLE_JIT -#elif defined(Q_PROCESSOR_X86_64) +#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)) #define V4_ENABLE_JIT #elif defined(Q_PROCESSOR_ARM_32) #if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4) #define V4_ENABLE_JIT +#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA. +#define V4_ENABLE_JIT #endif #endif @@ -161,12 +165,6 @@ template<typename T> struct Returned; typedef Returned<String> ReturnedString; typedef Returned<Object> ReturnedObject; typedef Returned<FunctionObject> ReturnedFunctionObject; -struct ManagedRef; -struct StringRef; -struct ObjectRef; -struct ArrayObjectRef; -struct FunctionObjectRef; -struct RegExpRef; struct PersistentValuePrivate; class PersistentValue; diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index eb0994c1e6..fc4a097915 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -346,11 +346,13 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok) DEFINE_OBJECT_VTABLE(EvalFunction); -EvalFunction::EvalFunction(ExecutionContext *scope) - : FunctionObject(scope, scope->engine->id_eval) +EvalFunction::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, scope->d()->engine->id_eval) { setVTable(staticVTable()); - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1)); + Scope s(scope); + ScopedFunctionObject f(s, this); + f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1)); } ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) @@ -363,16 +365,16 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) ContextStateSaver(ExecutionContext *context) : savedContext(context) - , strictMode(context->strictMode) - , evalCode(context->currentEvalCode) - , compilationUnit(context->compilationUnit) + , strictMode(context->d()->strictMode) + , evalCode(context->d()->currentEvalCode) + , compilationUnit(context->d()->compilationUnit) {} ~ContextStateSaver() { - savedContext->strictMode = strictMode; - savedContext->currentEvalCode = evalCode; - savedContext->compilationUnit = compilationUnit; + savedContext->d()->strictMode = strictMode; + savedContext->d()->currentEvalCode = evalCode; + savedContext->d()->compilationUnit = compilationUnit; } }; @@ -396,10 +398,10 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) return callData->args[0].asReturnedValue(); const QString code = callData->args[0].stringValue()->toQString(); - bool inheritContext = !ctx->strictMode; + bool inheritContext = !ctx->d()->strictMode; Script script(ctx, code, QStringLiteral("eval code")); - script.strictMode = (directCall && parentContext->strictMode); + script.strictMode = (directCall && parentContext->d()->strictMode); script.inheritContext = inheritContext; script.parse(); if (scope.engine->hasException) @@ -409,14 +411,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) if (!function) return Encode::undefined(); - strictMode = function->isStrict() || (ctx->strictMode); + d()->strictMode = function->isStrict() || (ctx->d()->strictMode); - needsActivation = function->needsActivation(); + d()->needsActivation = function->needsActivation(); - if (strictMode) { + if (strictMode()) { ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function)); ScopedCallData callData(scope, 0); - callData->thisObject = ctx->callData->thisObject; + callData->thisObject = ctx->d()->callData->thisObject; return e->call(callData); } @@ -424,12 +426,12 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) ExecutionContext::EvalCode evalCode; evalCode.function = function; - evalCode.next = ctx->currentEvalCode; - ctx->currentEvalCode = &evalCode; + evalCode.next = ctx->d()->currentEvalCode; + ctx->d()->currentEvalCode = &evalCode; // set the correct strict mode flag on the context - ctx->strictMode = strictMode; - ctx->compilationUnit = function->compilationUnit; + ctx->d()->strictMode = strictMode(); + ctx->d()->compilationUnit = function->compilationUnit; return function->code(ctx, function->codeData); } @@ -470,7 +472,7 @@ ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx) String *inputString = string->toString(ctx); // 1 QString trimmed = inputString->toQString().trimmed(); // 2 - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); const QChar *pos = trimmed.constData(); @@ -574,117 +576,117 @@ ReturnedValue GlobalFunctions::method_parseFloat(CallContext *ctx) /// isNaN [15.1.2.4] ReturnedValue GlobalFunctions::method_isNaN(CallContext *ctx) { - if (!ctx->callData->argc) + if (!ctx->d()->callData->argc) // undefined gets converted to NaN return Encode(true); - if (ctx->callData->args[0].integerCompatible()) + if (ctx->d()->callData->args[0].integerCompatible()) return Encode(false); - double d = ctx->callData->args[0].toNumber(); + double d = ctx->d()->callData->args[0].toNumber(); return Encode((bool)std::isnan(d)); } /// isFinite [15.1.2.5] ReturnedValue GlobalFunctions::method_isFinite(CallContext *ctx) { - if (!ctx->callData->argc) + if (!ctx->d()->callData->argc) // undefined gets converted to NaN return Encode(false); - if (ctx->callData->args[0].integerCompatible()) + if (ctx->d()->callData->args[0].integerCompatible()) return Encode(true); - double d = ctx->callData->args[0].toNumber(); + double d = ctx->d()->callData->args[0].toNumber(); return Encode((bool)std::isfinite(d)); } /// decodeURI [15.1.3.1] ReturnedValue GlobalFunctions::method_decodeURI(CallContext *context) { - if (context->callData->argc == 0) + if (context->d()->callData->argc == 0) return Encode::undefined(); - QString uriString = context->callData->args[0].toString(context)->toQString(); + QString uriString = context->d()->callData->args[0].toString(context)->toQString(); bool ok; QString out = decode(uriString, DecodeNonReserved, &ok); if (!ok) { Scope scope(context); - ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); + ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); return context->throwURIError(s); } - return context->engine->newString(out)->asReturnedValue(); + return context->d()->engine->newString(out)->asReturnedValue(); } /// decodeURIComponent [15.1.3.2] ReturnedValue GlobalFunctions::method_decodeURIComponent(CallContext *context) { - if (context->callData->argc == 0) + if (context->d()->callData->argc == 0) return Encode::undefined(); - QString uriString = context->callData->args[0].toString(context)->toQString(); + QString uriString = context->d()->callData->args[0].toString(context)->toQString(); bool ok; QString out = decode(uriString, DecodeAll, &ok); if (!ok) { Scope scope(context); - ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); + ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); return context->throwURIError(s); } - return context->engine->newString(out)->asReturnedValue(); + return context->d()->engine->newString(out)->asReturnedValue(); } /// encodeURI [15.1.3.3] ReturnedValue GlobalFunctions::method_encodeURI(CallContext *context) { - if (context->callData->argc == 0) + if (context->d()->callData->argc == 0) return Encode::undefined(); - QString uriString = context->callData->args[0].toString(context)->toQString(); + QString uriString = context->d()->callData->args[0].toString(context)->toQString(); bool ok; QString out = encode(uriString, uriUnescapedReserved, &ok); if (!ok) { Scope scope(context); - ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); + ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); return context->throwURIError(s); } - return context->engine->newString(out)->asReturnedValue(); + return context->d()->engine->newString(out)->asReturnedValue(); } /// encodeURIComponent [15.1.3.4] ReturnedValue GlobalFunctions::method_encodeURIComponent(CallContext *context) { - if (context->callData->argc == 0) + if (context->d()->callData->argc == 0) return Encode::undefined(); - QString uriString = context->callData->args[0].toString(context)->toQString(); + QString uriString = context->d()->callData->args[0].toString(context)->toQString(); bool ok; QString out = encode(uriString, uriUnescaped, &ok); if (!ok) { Scope scope(context); - ScopedString s(scope, context->engine->newString(QStringLiteral("malformed URI sequence"))); + ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence"))); return context->throwURIError(s); } - return context->engine->newString(out)->asReturnedValue(); + return context->d()->engine->newString(out)->asReturnedValue(); } ReturnedValue GlobalFunctions::method_escape(CallContext *context) { - if (!context->callData->argc) - return context->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); + if (!context->d()->callData->argc) + return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); - QString str = context->callData->args[0].toString(context)->toQString(); - return context->engine->newString(escape(str))->asReturnedValue(); + QString str = context->d()->callData->args[0].toString(context)->toQString(); + return context->d()->engine->newString(escape(str))->asReturnedValue(); } ReturnedValue GlobalFunctions::method_unescape(CallContext *context) { - if (!context->callData->argc) - return context->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); + if (!context->d()->callData->argc) + return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue(); - QString str = context->callData->args[0].toString(context)->toQString(); - return context->engine->newString(unescape(str))->asReturnedValue(); + QString str = context->d()->callData->args[0].toString(context)->toQString(); + return context->d()->engine->newString(unescape(str))->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 63823acc19..b3fcb0c89b 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -50,8 +50,11 @@ namespace QV4 { struct Q_QML_EXPORT EvalFunction : FunctionObject { - V4_OBJECT - EvalFunction(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + + V4_OBJECT(FunctionObject) ReturnedValue evalCall(CallData *callData, bool directCall); diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp index 87fbd6f8e4..bbb756bab3 100644 --- a/src/qml/jsruntime/qv4identifier.cpp +++ b/src/qml/jsruntime/qv4identifier.cpp @@ -149,8 +149,8 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(String *str) const { if (!d) return 0; - if (str->identifier) - return lookup(str->identifier); + if (str->d()->identifier) + return lookup(str->d()->identifier); return lookup(str->toQString()); } diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp index e300a4811e..8627438fe1 100644 --- a/src/qml/jsruntime/qv4identifiertable.cpp +++ b/src/qml/jsruntime/qv4identifiertable.cpp @@ -69,7 +69,7 @@ IdentifierTable::~IdentifierTable() { for (int i = 0; i < alloc; ++i) if (entries[i]) - delete entries[i]->identifier; + delete entries[i]->d()->identifier; free(entries); } @@ -77,12 +77,12 @@ void IdentifierTable::addEntry(String *str) { uint hash = str->hashValue(); - if (str->subtype == String::StringType_ArrayIndex) + if (str->subtype() == String::StringType_ArrayIndex) return; - str->identifier = new Identifier; - str->identifier->string = str->toQString(); - str->identifier->hashValue = hash; + str->d()->identifier = new Identifier; + str->d()->identifier->string = str->toQString(); + str->d()->identifier->hashValue = hash; bool grow = (alloc <= size*2); @@ -95,7 +95,7 @@ void IdentifierTable::addEntry(String *str) String *e = entries[i]; if (!e) continue; - uint idx = e->stringHash % newAlloc; + uint idx = e->d()->stringHash % newAlloc; while (newEntries[idx]) { ++idx; idx %= newAlloc; @@ -123,7 +123,7 @@ String *IdentifierTable::insertString(const QString &s) uint hash = String::createHashValue(s.constData(), s.length()); uint idx = hash % alloc; while (String *e = entries[idx]) { - if (e->stringHash == hash && e->toQString() == s) + if (e->d()->stringHash == hash && e->toQString() == s) return e; ++idx; idx %= alloc; @@ -137,29 +137,29 @@ String *IdentifierTable::insertString(const QString &s) Identifier *IdentifierTable::identifierImpl(const String *str) { - if (str->identifier) - return str->identifier; + if (str->d()->identifier) + return str->d()->identifier; uint hash = str->hashValue(); - if (str->subtype == String::StringType_ArrayIndex) + if (str->subtype() == String::StringType_ArrayIndex) return 0; uint idx = hash % alloc; while (String *e = entries[idx]) { - if (e->stringHash == hash && e->isEqualTo(str)) { - str->identifier = e->identifier; - return e->identifier; + if (e->d()->stringHash == hash && e->isEqualTo(str)) { + str->d()->identifier = e->d()->identifier; + return e->d()->identifier; } ++idx; idx %= alloc; } addEntry(const_cast<QV4::String *>(str)); - return str->identifier; + return str->d()->identifier; } Identifier *IdentifierTable::identifier(const QString &s) { - return insertString(s)->identifier; + return insertString(s)->d()->identifier; } Identifier *IdentifierTable::identifier(const char *s, int len) @@ -171,15 +171,15 @@ Identifier *IdentifierTable::identifier(const char *s, int len) QLatin1String latin(s, len); uint idx = hash % alloc; while (String *e = entries[idx]) { - if (e->stringHash == hash && e->toQString() == latin) - return e->identifier; + if (e->d()->stringHash == hash && e->toQString() == latin) + return e->d()->identifier; ++idx; idx %= alloc; } String *str = engine->newString(QString::fromLatin1(s, len))->getPointer(); addEntry(str); - return str->identifier; + return str->d()->identifier; } } diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h index 09956fc342..7675d1642e 100644 --- a/src/qml/jsruntime/qv4identifiertable_p.h +++ b/src/qml/jsruntime/qv4identifiertable_p.h @@ -69,8 +69,8 @@ public: String *insertString(const QString &s); Identifier *identifier(const String *str) { - if (str->identifier) - return str->identifier; + if (str->d()->identifier) + return str->d()->identifier; return identifierImpl(str); } @@ -82,11 +82,11 @@ public: void mark(ExecutionEngine *e) { for (int i = 0; i < alloc; ++i) { String *entry = entries[i]; - if (!entry || entry->markBit) + if (!entry || entry->markBit()) continue; - entry->markBit = 1; - Q_ASSERT(entry->internalClass->vtable->markObjects); - entry->internalClass->vtable->markObjects(entry, e); + entry->d()->markBit = 1; + Q_ASSERT(entry->internalClass()->vtable->markObjects); + entry->internalClass()->vtable->markObjects(entry, e); } } }; diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index d5bae0e35e..b9576e1bee 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -89,11 +89,11 @@ QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status stat QV4::ScopedObject o(scope, v4->newObject()); QV4::ScopedString s(scope); QV4::ScopedValue v(scope); - o->put((s = v4->newString(QStringLiteral("OK"))), (v = QV4::Primitive::fromInt32(Ok))); - o->put((s = v4->newString(QStringLiteral("LOADING"))), (v = QV4::Primitive::fromInt32(Loading))); - o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))), (v = QV4::Primitive::fromInt32(NetworkError))); - o->put((s = v4->newString(QStringLiteral("EXCEPTION"))), (v = QV4::Primitive::fromInt32(Exception))); - o->put((s = v4->newString(QStringLiteral("status"))), (v = QV4::Primitive::fromInt32(status))); + o->put((s = v4->newString(QStringLiteral("OK"))).getPointer(), (v = QV4::Primitive::fromInt32(Ok))); + o->put((s = v4->newString(QStringLiteral("LOADING"))).getPointer(), (v = QV4::Primitive::fromInt32(Loading))); + o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))).getPointer(), (v = QV4::Primitive::fromInt32(NetworkError))); + o->put((s = v4->newString(QStringLiteral("EXCEPTION"))).getPointer(), (v = QV4::Primitive::fromInt32(Exception))); + o->put((s = v4->newString(QStringLiteral("status"))).getPointer(), (v = QV4::Primitive::fromInt32(status))); return o.asReturnedValue(); } @@ -160,13 +160,13 @@ void QV4Include::finished() script.run(); if (scope.engine->hasException) { QV4::ScopedValue ex(scope, ctx->catchException()); - resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception))); - resultObj->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("exception"))), ex); + resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception))); + resultObj->put(v4->newString(QStringLiteral("exception"))->getPointer(), ex); } else { - resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok))); + resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok))); } } else { - resultObj->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("status"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); + resultObj->put(v4->newString(QStringLiteral("status"))->getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); } QV4::ScopedValue cb(scope, m_callbackFunction.value()); @@ -181,27 +181,26 @@ void QV4Include::finished() */ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) { - if (!ctx->callData->argc) + if (!ctx->d()->callData->argc) return QV4::Encode::undefined(); - QV4::ExecutionEngine *v4 = ctx->engine; - QV4::Scope scope(v4); - QV8Engine *engine = v4->v8Engine; - QQmlContextData *context = QV4::QmlContextWrapper::callingContext(v4); + QV4::Scope scope(ctx->engine()); + QV8Engine *engine = scope.engine->v8Engine; + QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine); if (!context || !context->isJSContext) V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); - QUrl url(ctx->engine->resolvedUrl(ctx->callData->args[0].toQStringNoThrow())); + QUrl url(scope.engine->resolvedUrl(ctx->d()->callData->args[0].toQStringNoThrow())); QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); - if (ctx->callData->argc >= 2 && ctx->callData->args[1].asFunctionObject()) - callbackFunction = ctx->callData->args[1]; + if (ctx->d()->callData->argc >= 2 && ctx->d()->callData->args[1].asFunctionObject()) + callbackFunction = ctx->d()->callData->args[1]; QString localFile = QQmlFile::urlToLocalFileOrQrc(url); QV4::ScopedValue result(scope); - QV4::ScopedObject qmlcontextobject(scope, v4->qmlContextObject()); + QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject()); if (localFile.isEmpty()) { QV4Include *i = new QV4Include(url, engine, context, @@ -218,21 +217,21 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) QString code = QString::fromUtf8(data); QmlIR::Document::removeScriptPragmas(code); - QV4::Script script(v4, qmlcontextobject, code, url.toString()); + QV4::Script script(scope.engine, qmlcontextobject, code, url.toString()); - QV4::ExecutionContext *ctx = v4->currentContext(); + QV4::ExecutionContext *ctx = scope.engine->currentContext(); script.parse(); - if (!v4->hasException) + if (!scope.engine->hasException) script.run(); - if (v4->hasException) { + if (scope.engine->hasException) { QV4::ScopedValue ex(scope, ctx->catchException()); - result = resultValue(v4, Exception); - result->asObject()->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("exception"))), ex); + result = resultValue(scope.engine, Exception); + result->asObject()->put(scope.engine->newString(QStringLiteral("exception"))->getPointer(), ex); } else { - result = resultValue(v4, Ok); + result = resultValue(scope.engine, Ok); } } else { - result = resultValue(v4, NetworkError); + result = resultValue(scope.engine, NetworkError); } callback(callbackFunction, result); diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 3dc20b8e76..2edaf6fe96 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -155,18 +155,18 @@ InternalClass::InternalClass(const QV4::InternalClass &other) void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) { uint idx; - InternalClass *newClass = object->internalClass->changeMember(string, data, &idx); + InternalClass *newClass = object->internalClass()->changeMember(string, data, &idx); if (index) *index = idx; - 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)); - } 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)); + 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)); + } 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)); } - object->internalClass = newClass; + object->setInternalClass(newClass); } InternalClass *InternalClass::changeMember(String *string, PropertyAttributes data, uint *index) @@ -181,7 +181,7 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da if (data == propertyData.at(idx)) return this; - Transition t = { { string->identifier }, (int)data.flags() }; + Transition t = { { string->d()->identifier }, (int)data.flags() }; QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t); if (tit != transitions.constEnd()) return tit.value(); @@ -271,40 +271,30 @@ InternalClass *InternalClass::changeVTable(const ManagedVTable *vt) return newClass; } -void InternalClass::addMember(Object *object, StringRef string, PropertyAttributes data, uint *index) -{ - return addMember(object, string.getPointer(), data, index); -} - void InternalClass::addMember(Object *object, String *string, PropertyAttributes data, uint *index) { data.resolve(); - object->internalClass->engine->identifierTable->identifier(string); - if (object->internalClass->propertyTable.lookup(string->identifier) < object->internalClass->size) { + object->internalClass()->engine->identifierTable->identifier(string); + if (object->internalClass()->propertyTable.lookup(string->d()->identifier) < object->internalClass()->size) { changeMember(object, string, data, index); return; } uint idx; - InternalClass *newClass = object->internalClass->addMemberImpl(string, data, &idx); + InternalClass *newClass = object->internalClass()->addMemberImpl(string, data, &idx); if (index) *index = idx; - object->internalClass = newClass; + object->setInternalClass(newClass); } -InternalClass *InternalClass::addMember(StringRef string, PropertyAttributes data, uint *index) -{ - return addMember(string.getPointer(), data, index); -} - InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index) { data.resolve(); engine->identifierTable->identifier(string); - if (propertyTable.lookup(string->identifier) < size) + if (propertyTable.lookup(string->d()->identifier) < size) return changeMember(string, data, index); return addMemberImpl(string, data, index); @@ -312,7 +302,7 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes data, uint *index) { - Transition t = { { string->identifier }, (int)data.flags() }; + Transition t = { { string->d()->identifier }, (int)data.flags() }; QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t); if (index) @@ -322,7 +312,7 @@ InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes d // create a new class and add it to the tree InternalClass *newClass = engine->newClass(*this); - PropertyHash::Entry e = { string->identifier, newClass->size }; + PropertyHash::Entry e = { string->d()->identifier, newClass->size }; newClass->propertyTable.addEntry(e, newClass->size); // The incoming string can come from anywhere, so make sure to @@ -346,15 +336,15 @@ InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes d void InternalClass::removeMember(Object *object, Identifier *id) { - InternalClass *oldClass = object->internalClass; + InternalClass *oldClass = object->internalClass(); uint propIdx = oldClass->propertyTable.lookup(id); Q_ASSERT(propIdx < oldClass->size); Transition t = { { id } , -1 }; - QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass->transitions.constFind(t); + QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass()->transitions.constFind(t); - if (tit != object->internalClass->transitions.constEnd()) { - object->internalClass = tit.value(); + if (tit != object->internalClass()->transitions.constEnd()) { + object->setInternalClass(tit.value()); } else { // create a new class and add it to the tree InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable); @@ -365,24 +355,19 @@ void InternalClass::removeMember(Object *object, Identifier *id) if (!oldClass->propertyData.at(i).isEmpty()) newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i)); } - object->internalClass = newClass; + object->setInternalClass(newClass); } // remove the entry in memberdata - memmove(object->memberData.data() + propIdx, object->memberData.data() + propIdx + 1, (object->internalClass->size - propIdx)*sizeof(Value)); - - oldClass->transitions.insert(t, object->internalClass); -} + memmove(object->memberData().data() + propIdx, object->memberData().data() + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value)); -uint InternalClass::find(const StringRef string) -{ - return find(string.getPointer()); + oldClass->transitions.insert(t, object->internalClass()); } uint InternalClass::find(const String *string) { engine->identifierTable->identifier(string); - const Identifier *id = string->identifier; + const Identifier *id = string->d()->identifier; uint index = propertyTable.lookup(id); if (index < size) diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h index bd1828a146..830d5f792f 100644 --- a/src/qml/jsruntime/qv4internalclass_p.h +++ b/src/qml/jsruntime/qv4internalclass_p.h @@ -234,14 +234,11 @@ struct InternalClass : public QQmlJS::Managed { static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto); InternalClass *changePrototype(Object *proto); InternalClass *changeVTable(const ManagedVTable *vt); - static void addMember(Object *object, StringRef string, PropertyAttributes data, uint *index); static void addMember(Object *object, String *string, PropertyAttributes data, uint *index); - InternalClass *addMember(StringRef string, PropertyAttributes data, uint *index = 0); InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0); InternalClass *changeMember(String *string, PropertyAttributes data, uint *index = 0); static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = 0); static void removeMember(Object *object, Identifier *id); - uint find(const StringRef string); uint find(const String *s); InternalClass *sealed(); diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index ca82af1b30..2cbb72e15f 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -81,7 +81,7 @@ private: ReturnedValue parseObject(); ReturnedValue parseArray(); - bool parseMember(ObjectRef o); + bool parseMember(Object *o); bool parseString(QString *string); bool parseValue(ValueRef val); bool parseNumber(ValueRef val); @@ -237,7 +237,7 @@ ReturnedValue JsonParser::parseObject() BEGIN << "parseObject pos=" << json; Scope scope(context); - ScopedObject o(scope, context->engine->newObject()); + ScopedObject o(scope, context->d()->engine->newObject()); QChar token = nextToken(); while (token == Quote) { @@ -268,7 +268,7 @@ ReturnedValue JsonParser::parseObject() /* member = string name-separator value */ -bool JsonParser::parseMember(ObjectRef o) +bool JsonParser::parseMember(Object *o) { BEGIN << "parseMember"; Scope scope(context); @@ -285,12 +285,12 @@ bool JsonParser::parseMember(ObjectRef o) if (!parseValue(val)) return false; - ScopedString s(scope, context->engine->newIdentifier(key)); + ScopedString s(scope, context->d()->engine->newIdentifier(key)); uint idx = s->asArrayIndex(); if (idx < UINT_MAX) { o->putIndexed(idx, val); } else { - o->insertMember(s, val); + o->insertMember(s.getPointer(), val); } END; @@ -304,7 +304,7 @@ ReturnedValue JsonParser::parseArray() { Scope scope(context); BEGIN << "parseArray"; - Scoped<ArrayObject> array(scope, context->engine->newArrayObject()); + Scoped<ArrayObject> array(scope, context->d()->engine->newArrayObject()); if (++nestingLevel > nestingLimit) { lastError = QJsonParseError::DeepNesting; @@ -407,7 +407,7 @@ bool JsonParser::parseValue(ValueRef val) return false; DEBUG << "value: string"; END; - val = context->engine->newString(value); + val = context->d()->engine->newString(value); return true; } case BeginArray: { @@ -656,8 +656,8 @@ struct Stringify Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {} QString Str(const QString &key, ValueRef v); - QString JA(ArrayObjectRef a); - QString JO(ObjectRef o); + QString JA(ArrayObject *a); + QString JO(Object *o); QString makeMember(const QString &key, ValueRef v); }; @@ -710,21 +710,21 @@ QString Stringify::Str(const QString &key, ValueRef v) ScopedValue value(scope, *v); ScopedObject o(scope, value); if (o) { - ScopedString s(scope, ctx->engine->newString(QStringLiteral("toJSON"))); - Scoped<FunctionObject> toJSON(scope, o->get(s)); + ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON"))); + Scoped<FunctionObject> toJSON(scope, o->get(s.getPointer())); if (!!toJSON) { ScopedCallData callData(scope, 1); callData->thisObject = value; - callData->args[0] = ctx->engine->newString(key); + callData->args[0] = ctx->d()->engine->newString(key); value = toJSON->call(callData); } } if (replacerFunction) { - ScopedObject holder(scope, ctx->engine->newObject()); + ScopedObject holder(scope, ctx->d()->engine->newObject()); holder->put(ctx, QString(), value); ScopedCallData callData(scope, 2); - callData->args[0] = ctx->engine->newString(key); + callData->args[0] = ctx->d()->engine->newString(key); callData->args[1] = value; callData->thisObject = holder; value = replacerFunction->call(callData); @@ -733,11 +733,11 @@ QString Stringify::Str(const QString &key, ValueRef v) o = value.asReturnedValue(); if (o) { if (NumberObject *n = o->asNumberObject()) - value = n->value; + value = n->value(); else if (StringObject *so = o->asStringObject()) - value = so->value; + value = so->d()->value; else if (BooleanObject *b =o->asBooleanObject()) - value = b->value; + value = b->value(); } if (value->isNull()) @@ -780,9 +780,9 @@ QString Stringify::makeMember(const QString &key, ValueRef v) return QString(); } -QString Stringify::JO(ObjectRef o) +QString Stringify::JO(Object *o) { - if (stack.contains(o.getPointer())) { + if (stack.contains(o)) { ctx->throwTypeError(); return QString(); } @@ -790,7 +790,7 @@ QString Stringify::JO(ObjectRef o) Scope scope(ctx); QString result; - stack.push(o.getPointer()); + stack.push(o); QString stepback = indent; indent += gap; @@ -814,7 +814,7 @@ QString Stringify::JO(ObjectRef o) for (int i = 0; i < propertyList.size(); ++i) { bool exists; s = propertyList.at(i); - ScopedValue v(scope, o->get(s, &exists)); + ScopedValue v(scope, o->get(s.getPointer(), &exists)); if (!exists) continue; QString member = makeMember(s->toQString(), v); @@ -837,9 +837,9 @@ QString Stringify::JO(ObjectRef o) return result; } -QString Stringify::JA(ArrayObjectRef a) +QString Stringify::JA(ArrayObject *a) { - if (stack.contains(a.getPointer())) { + if (stack.contains(a)) { ctx->throwTypeError(); return QString(); } @@ -847,7 +847,7 @@ QString Stringify::JA(ArrayObjectRef a) Scope scope(a->engine()); QString result; - stack.push(a.getPointer()); + stack.push(a); QString stepback = indent; indent += gap; @@ -883,14 +883,14 @@ QString Stringify::JA(ArrayObjectRef a) } -JsonObject::JsonObject(InternalClass *ic) - : Object(ic) +JsonObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { Scope scope(ic->engine); - ScopedObject protectThis(scope, this); + ScopedObject o(scope, this); - defineDefaultProperty(QStringLiteral("parse"), method_parse, 2); - defineDefaultProperty(QStringLiteral("stringify"), method_stringify, 3); + o->defineDefaultProperty(QStringLiteral("parse"), method_parse, 2); + o->defineDefaultProperty(QStringLiteral("stringify"), method_stringify, 3); } @@ -939,9 +939,9 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) ScopedValue s(scope, ctx->argument(2)); if (NumberObject *n = s->asNumberObject()) - s = n->value; + s = n->value(); else if (StringObject *so = s->asStringObject()) - s = so->value; + s = so->d()->value; if (s->isNumber()) { stringify.gap = QString(qMin(10, (int)s->toInteger()), ' '); @@ -954,7 +954,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) QString result = stringify.Str(QString(), arg0); if (result.isEmpty() || scope.engine->hasException) return Encode::undefined(); - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } @@ -962,7 +962,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx) ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value) { if (value.isString()) - return engine->currentContext()->engine->newString(value.toString())->asReturnedValue(); + return engine->currentContext()->d()->engine->newString(value.toString())->asReturnedValue(); else if (value.isDouble()) return Encode(value.toDouble()); else if (value.isBool()) @@ -1008,12 +1008,12 @@ QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJs ScopedValue v(scope); for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it) { v = fromJsonValue(engine, it.value()); - o->put((s = engine->newString(it.key())), v); + o->put((s = engine->newString(it.key())).getPointer(), v); } return o.asReturnedValue(); } -QJsonObject JsonObject::toJsonObject(ObjectRef o, V4ObjectSet &visitedObjects) +QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects) { QJsonObject result; if (!o || o->asFunctionObject()) @@ -1061,7 +1061,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso return a.asReturnedValue(); } -QJsonArray JsonObject::toJsonArray(ArrayObjectRef a, V4ObjectSet &visitedObjects) +QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects) { QJsonArray result; if (!a) diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index 34a4f4dd4b..03d5ad29c8 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct JsonObject : Object { + struct Data : Object::Data { + Data(InternalClass *ic); + }; Q_MANAGED_TYPE(JsonObject) - V4_OBJECT + V4_OBJECT(Object) private: typedef QSet<QV4::Object *> V4ObjectSet; public: - JsonObject(InternalClass *ic); static ReturnedValue method_parse(CallContext *ctx); static ReturnedValue method_stringify(CallContext *ctx); @@ -67,15 +69,15 @@ public: static inline QJsonValue toJsonValue(const QV4::ValueRef value) { V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); } - static inline QJsonObject toJsonObject(QV4::ObjectRef o) + static inline QJsonObject toJsonObject(QV4::Object *o) { V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); } - static inline QJsonArray toJsonArray(QV4::ArrayObjectRef a) + static inline QJsonArray toJsonArray(QV4::ArrayObject *a) { V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); } private: static QJsonValue toJsonValue(const QV4::ValueRef value, V4ObjectSet &visitedObjects); - static QJsonObject toJsonObject(QV4::ObjectRef o, V4ObjectSet &visitedObjects); - static QJsonArray toJsonArray(QV4::ArrayObjectRef a, V4ObjectSet &visitedObjects); + static QJsonObject toJsonObject(Object *o, V4ObjectSet &visitedObjects); + static QJsonArray toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects); }; diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 1155bbf9e9..57154c4779 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -51,13 +51,13 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute { int i = 0; while (i < Size && obj) { - classList[i] = obj->internalClass; + classList[i] = obj->internalClass(); - index = obj->internalClass->find(name); + index = obj->internalClass()->find(name); 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); + *attrs = obj->internalClass()->propertyData.at(index); + return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs); } obj = obj->prototype(); @@ -66,10 +66,10 @@ ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttribute level = Size; while (obj) { - index = obj->internalClass->find(name); + 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); + *attrs = obj->internalClass()->propertyData.at(index); + return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs); } obj = obj->prototype(); @@ -82,13 +82,13 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs) Object *thisObject = obj; int i = 0; while (i < Size && obj) { - classList[i] = obj->internalClass; + classList[i] = obj->internalClass(); - index = obj->internalClass->find(name); + index = obj->internalClass()->find(name); 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); + *attrs = obj->internalClass()->propertyData.at(index); + return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs); } obj = obj->prototype(); @@ -97,10 +97,10 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs) level = Size; while (obj) { - index = obj->internalClass->find(name); + 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); + *attrs = obj->internalClass()->propertyData.at(index); + return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs); } obj = obj->prototype(); @@ -147,8 +147,8 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co } if (idx < UINT_MAX) { - if (!o->arrayData->hasAttributes()) { - ScopedValue v(scope, o->arrayData->get(idx)); + if (!o->arrayData()->hasAttributes()) { + ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); } @@ -159,7 +159,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co ScopedString name(scope, index->toString(ctx)); if (scope.hasException()) return Encode::undefined(); - return o->get(name); + return o->get(name.getPointer()); } @@ -171,10 +171,10 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, c return indexedGetterGeneric(l, object, index); Object *o = object->objectValue(); - if (o->arrayData && o->arrayData->type == ArrayData::Simple) { - if (idx < static_cast<SimpleArrayData *>(o->arrayData)->len) - if (!o->arrayData->data[idx].isEmpty()) - return o->arrayData->data[idx].asReturnedValue(); + if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { + if (idx < static_cast<SimpleArrayData *>(o->arrayData())->len()) + if (!o->arrayData()->arrayData()[idx].isEmpty()) + return o->arrayData()->arrayData()[idx].asReturnedValue(); } return indexedGetterFallback(l, object, index); @@ -184,7 +184,7 @@ void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueR { if (object->isObject()) { Object *o = object->objectValue(); - if (o->arrayData && o->arrayData->type == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) { + if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) { l->indexedSetter = indexedSetterObjectInt; indexedSetterObjectInt(l, object, index, v); return; @@ -203,10 +203,10 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value uint idx = index->asArrayIndex(); if (idx < UINT_MAX) { - if (o->arrayData && o->arrayData->type == ArrayData::Simple) { - SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData); - if (s && idx < s->len && !s->data[idx].isEmpty()) { - s->data[idx] = value; + if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { + SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData()); + if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) { + s->arrayData()[idx] = value; return; } } @@ -215,7 +215,7 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value } ScopedString name(scope, index->toString(ctx)); - o->put(name, value); + o->put(name.getPointer(), value); } void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v) @@ -227,10 +227,10 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const Valu } Object *o = object->objectValue(); - if (o->arrayData && o->arrayData->type == ArrayData::Simple) { - SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData); - if (idx < s->len && !s->data[idx].isEmpty()) { - s->data[idx] = v; + if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { + SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData()); + if (idx < s->len() && !s->arrayData()[idx].isEmpty()) { + s->arrayData()[idx] = v; return; } } @@ -254,7 +254,7 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object) case Value::Managed_Type: Q_ASSERT(object->isString()); proto = engine->stringObjectClass->prototype; - if (l->name->equals(engine->id_length)) { + if (l->name->equals(engine->id_length.getPointer())) { // special case, as the property is on the object itself l->getter = stringLengthGetter; return stringLengthGetter(l, object); @@ -331,7 +331,7 @@ ReturnedValue Lookup::getterFallback(Lookup *l, const ValueRef object) if (!o) return Encode::undefined(); QV4::ScopedString s(scope, l->name); - return o->get(s); + return o->get(s.getPointer()); } ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object) @@ -340,8 +340,8 @@ ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) - return o->memberData[l->index].asReturnedValue(); + if (l->classList[0] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); } return getterTwoClasses(l, object); } @@ -352,9 +352,9 @@ ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index].asReturnedValue(); + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) + return o->prototype()->memberData()[l->index].asReturnedValue(); } return getterTwoClasses(l, object); } @@ -365,12 +365,12 @@ ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) { + if (l->classList[0] == o->internalClass()) { o = o->prototype(); - if (l->classList[1] == o->internalClass) { + if (l->classList[1] == o->internalClass()) { o = o->prototype(); - if (l->classList[2] == o->internalClass) - return o->memberData[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); } } } @@ -384,10 +384,10 @@ ReturnedValue Lookup::getter0getter0(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) - return o->memberData[l->index].asReturnedValue(); - if (l->classList[2] == o->internalClass) - return o->memberData[l->index2].asReturnedValue(); + if (l->classList[0] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass()) + return o->memberData()[l->index2].asReturnedValue(); } l->getter = getterFallback; return getterFallback(l, object); @@ -399,11 +399,11 @@ ReturnedValue Lookup::getter0getter1(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) - return o->memberData[l->index].asReturnedValue(); - if (l->classList[2] == o->internalClass && - l->classList[3] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index2].asReturnedValue(); + if (l->classList[0] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass() && + l->classList[3] == o->prototype()->internalClass()) + return o->prototype()->memberData()[l->index2].asReturnedValue(); } l->getter = getterFallback; return getterFallback(l, object); @@ -415,12 +415,12 @@ ReturnedValue Lookup::getter1getter1(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index].asReturnedValue(); - if (l->classList[2] == o->internalClass && - l->classList[3] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index2].asReturnedValue(); + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) + return o->prototype()->memberData()[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass() && + l->classList[3] == o->prototype()->internalClass()) + return o->prototype()->memberData()[l->index2].asReturnedValue(); return getterFallback(l, object); } l->getter = getterFallback; @@ -434,7 +434,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) { + if (l->classList[0] == o->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->propertyAt(l->index)->getter(); if (!getter) @@ -455,8 +455,8 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) { + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter(); if (!getter) @@ -477,11 +477,11 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object) // we can safely cast to a QV4::Object here. If object is actually a string, // the internal class won't match Object *o = object->objectValue(); - if (l->classList[0] == o->internalClass) { + if (l->classList[0] == o->internalClass()) { o = o->prototype(); - if (l->classList[1] == o->internalClass) { + if (l->classList[1] == o->internalClass()) { o = o->prototype(); - if (l->classList[2] == o->internalClass) { + if (l->classList[2] == o->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->propertyAt(l->index)->getter(); if (!getter) @@ -502,8 +502,8 @@ 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(); + if (l->classList[0] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); } l->getter = getterGeneric; return getterGeneric(l, object); @@ -513,9 +513,9 @@ ReturnedValue Lookup::primitiveGetter1(Lookup *l, const ValueRef object) { if (object->type() == l->type) { Object *o = l->proto; - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index].asReturnedValue(); + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) + return o->prototype()->memberData()[l->index].asReturnedValue(); } l->getter = getterGeneric; return getterGeneric(l, object); @@ -525,7 +525,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, const ValueRef object) { if (object->type() == l->type) { Object *o = l->proto; - if (l->classList[0] == o->internalClass) { + if (l->classList[0] == o->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->propertyAt(l->index)->getter(); if (!getter) @@ -544,8 +544,8 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object) { if (object->type() == l->type) { Object *o = l->proto; - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) { + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter(); if (!getter) @@ -563,7 +563,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object) ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object) { if (String *s = object->asString()) - return Encode(s->length()); + return Encode(s->d()->length()); l->getter = getterGeneric; return getterGeneric(l, object); @@ -572,7 +572,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()[ArrayObject::LengthPropertyIndex].asReturnedValue(); l->getter = getterGeneric; return getterGeneric(l, object); @@ -581,7 +581,7 @@ ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object) ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; + Object *o = ctx->d()->engine->globalObject; PropertyAttributes attrs; ReturnedValue v = l->lookup(o, &attrs); if (v != Primitive::emptyValue().asReturnedValue()) { @@ -610,9 +610,9 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass) - return o->memberData[l->index].asReturnedValue(); + Object *o = ctx->d()->engine->globalObject; + if (l->classList[0] == o->internalClass()) + return o->memberData()[l->index].asReturnedValue(); l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, ctx); @@ -620,10 +620,10 @@ ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) - return o->prototype()->memberData[l->index].asReturnedValue(); + 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(); l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, ctx); @@ -631,13 +631,13 @@ ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass) { + Object *o = ctx->d()->engine->globalObject; + if (l->classList[0] == o->internalClass()) { o = o->prototype(); - if (l->classList[1] == o->internalClass) { + if (l->classList[1] == o->internalClass()) { o = o->prototype(); - if (l->classList[2] == o->internalClass) { - return o->prototype()->memberData[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass()) { + return o->prototype()->memberData()[l->index].asReturnedValue(); } } } @@ -647,8 +647,8 @@ ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass) { + Object *o = ctx->d()->engine->globalObject; + if (l->classList[0] == o->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->propertyAt(l->index)->getter(); if (!getter) @@ -664,9 +664,9 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass && - l->classList[1] == o->prototype()->internalClass) { + Object *o = ctx->d()->engine->globalObject; + if (l->classList[0] == o->internalClass() && + l->classList[1] == o->prototype()->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter(); if (!getter) @@ -682,12 +682,12 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx) ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx) { - Object *o = ctx->engine->globalObject; - if (l->classList[0] == o->internalClass) { + Object *o = ctx->d()->engine->globalObject; + if (l->classList[0] == o->internalClass()) { o = o->prototype(); - if (l->classList[1] == o->internalClass) { + if (l->classList[1] == o->internalClass()) { o = o->prototype(); - if (l->classList[2] == o->internalClass) { + if (l->classList[2] == o->internalClass()) { Scope scope(o->engine()); FunctionObject *getter = o->propertyAt(l->index)->getter(); if (!getter) @@ -712,7 +712,7 @@ void Lookup::setterGeneric(Lookup *l, const ValueRef object, const ValueRef valu if (!o) // type error return; ScopedString s(scope, l->name); - o->put(s, value); + o->put(s.getPointer(), value); return; } o->setLookup(l, value); @@ -743,15 +743,15 @@ void Lookup::setterFallback(Lookup *l, const ValueRef object, const ValueRef val QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext())); if (o) { QV4::ScopedString s(scope, l->name); - o->put(s, value); + o->put(s.getPointer(), value); } } 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; + if (o && o->internalClass() == l->classList[0]) { + o->memberData()[l->index] = *value; return; } @@ -761,12 +761,12 @@ void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value) void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef value) { Object *o = static_cast<Object *>(object->asManaged()); - if (o && o->internalClass == l->classList[0]) { + if (o && o->internalClass() == l->classList[0]) { if (!o->prototype()) { - if (l->index >= o->memberData.size()) + if (l->index >= o->memberData().size()) o->ensureMemberIndex(l->index); - o->memberData[l->index] = *value; - o->internalClass = l->classList[3]; + o->memberData()[l->index] = *value; + o->setInternalClass(l->classList[3]); return; } } @@ -778,13 +778,13 @@ void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef valu void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef value) { Object *o = static_cast<Object *>(object->asManaged()); - if (o && o->internalClass == l->classList[0]) { + 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 (p && p->internalClass() == l->classList[1]) { + if (l->index >= o->memberData().size()) o->ensureMemberIndex(l->index); - o->memberData[l->index] = *value; - o->internalClass = l->classList[3]; + o->memberData()[l->index] = *value; + o->setInternalClass(l->classList[3]); return; } } @@ -796,15 +796,15 @@ void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef valu void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef value) { Object *o = static_cast<Object *>(object->asManaged()); - if (o && o->internalClass == l->classList[0]) { + if (o && o->internalClass() == l->classList[0]) { Object *p = o->prototype(); - if (p && p->internalClass == l->classList[1]) { + if (p && p->internalClass() == l->classList[1]) { p = p->prototype(); - if (p && p->internalClass == l->classList[2]) { - if (l->index >= o->memberData.size()) + if (p && p->internalClass() == l->classList[2]) { + if (l->index >= o->memberData().size()) o->ensureMemberIndex(l->index); - o->memberData[l->index] = *value; - o->internalClass = l->classList[3]; + o->memberData()[l->index] = *value; + o->setInternalClass(l->classList[3]); return; } } @@ -818,12 +818,12 @@ 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; + if (o->internalClass() == l->classList[0]) { + o->memberData()[l->index] = *value; return; } - if (o->internalClass == l->classList[1]) { - o->memberData[l->index2] = *value; + if (o->internalClass() == l->classList[1]) { + o->memberData()[l->index2] = *value; return; } } diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index 1f4030a4ed..6fc402e48f 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -45,8 +45,10 @@ using namespace QV4; + const ManagedVTable Managed::static_vtbl = { + 0, Managed::IsExecutionContext, Managed::IsString, Managed::IsObject, @@ -56,7 +58,7 @@ const ManagedVTable Managed::static_vtbl = 0, Managed::MyType, "Managed", - destroy, + 0, 0 /*markObjects*/, isEqualTo }; @@ -69,33 +71,15 @@ void *Managed::operator new(size_t size, MemoryManager *mm) return mm->allocManaged(size); } -void Managed::operator delete(void *ptr) -{ - if (!ptr) - return; - - Managed *m = static_cast<Managed *>(ptr); - m->_data = 0; - m->markBit = 0; - m->~Managed(); -} - -void Managed::operator delete(void *ptr, MemoryManager *mm) -{ - Q_UNUSED(mm); - - operator delete(ptr); -} - ExecutionEngine *Managed::engine() const { - return internalClass ? internalClass->engine : 0; + return internalClass()->engine; } QString Managed::className() const { const char *s = 0; - switch (Type(internalClass->vtable->type)) { + switch (Type(internalClass()->vtable->type)) { case Type_Invalid: case Type_String: return QString(); @@ -124,7 +108,7 @@ QString Managed::className() const s = "RegExp"; break; case Type_ErrorObject: - switch (ErrorObject::ErrorType(subtype)) { + switch (ErrorObject::ErrorType(subtype())) { case ErrorObject::Error: s = "Error"; break; @@ -177,10 +161,17 @@ QString Managed::className() const void Managed::setVTable(const ManagedVTable *vt) { + Q_ASSERT(internalClass()); + d()->internalClass = internalClass()->changeVTable(vt); +} + +void Managed::Data::setVTable(const ManagedVTable *vt) +{ Q_ASSERT(internalClass); internalClass = internalClass->changeVTable(vt); } + bool Managed::isEqualTo(Managed *, Managed *) { return false; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 06d3e4884b..b88531d8ed 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -62,26 +62,44 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; } template <typename T1, typename T2> inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} -#define V4_MANAGED \ +#ifdef Q_COMPILER_STATIC_ASSERT +#define V4_MANAGED_SIZE_TEST void __dataTest() { Q_STATIC_ASSERT(sizeof(*this) == sizeof(Managed)); } +#else +#define V4_MANAGED_SIZE_TEST +#endif + +#define V4_MANAGED(superClass) \ public: \ Q_MANAGED_CHECK \ + typedef superClass SuperClass; \ static const QV4::ManagedVTable static_vtbl; \ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \ template <typename T> \ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \ + V4_MANAGED_SIZE_TEST \ + const Data *d() const { return &static_cast<const Data &>(Managed::data); } \ + Data *d() { return &static_cast<Data &>(Managed::data); } -#define V4_OBJECT \ +#define V4_OBJECT(superClass) \ public: \ Q_MANAGED_CHECK \ + typedef superClass SuperClass; \ static const QV4::ObjectVTable static_vtbl; \ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \ template <typename T> \ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \ + V4_MANAGED_SIZE_TEST \ + const Data *d() const { return &static_cast<const Data &>(Managed::data); } \ + Data *d() { return &static_cast<Data &>(Managed::data); } #define Q_MANAGED_TYPE(type) \ public: \ enum { MyType = Type_##type }; +#define Q_VTABLE_FUNCTION(classname, func) \ + (classname::func == QV4::Managed::func ? 0 : classname::func) + + struct GCDeletable { GCDeletable() : next(0), lastCall(false) {} @@ -92,6 +110,7 @@ struct GCDeletable struct ManagedVTable { + const ManagedVTable * const parent; uint isExecutionContext : 1; uint isString : 1; uint isObject : 1; @@ -111,22 +130,23 @@ struct ObjectVTable ManagedVTable managedVTable; ReturnedValue (*call)(Managed *, CallData *data); ReturnedValue (*construct)(Managed *, CallData *data); - ReturnedValue (*get)(Managed *, const StringRef name, bool *hasProperty); + ReturnedValue (*get)(Managed *, String *name, bool *hasProperty); ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty); - void (*put)(Managed *, const StringRef name, const ValueRef value); + void (*put)(Managed *, String *name, const ValueRef value); void (*putIndexed)(Managed *, uint index, const ValueRef value); - PropertyAttributes (*query)(const Managed *, StringRef name); + PropertyAttributes (*query)(const Managed *, String *name); PropertyAttributes (*queryIndexed)(const Managed *, uint index); - bool (*deleteProperty)(Managed *m, const StringRef name); + bool (*deleteProperty)(Managed *m, String *name); bool (*deleteIndexedProperty)(Managed *m, uint index); ReturnedValue (*getLookup)(Managed *m, Lookup *l); void (*setLookup)(Managed *m, Lookup *l, const ValueRef v); uint (*getLength)(const Managed *m); - void (*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes); + void (*advanceIterator)(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes); }; -#define DEFINE_MANAGED_VTABLE_INT(classname) \ +#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \ { \ + parentVTable, \ classname::IsExecutionContext, \ classname::IsString, \ classname::IsObject, \ @@ -135,21 +155,20 @@ struct ObjectVTable classname::IsArrayData, \ 0, \ classname::MyType, \ - #classname, \ - destroy, \ + #classname, \ + Q_VTABLE_FUNCTION(classname, destroy), \ markObjects, \ isEqualTo \ } - #define DEFINE_MANAGED_VTABLE(classname) \ -const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname) +const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) #define DEFINE_OBJECT_VTABLE(classname) \ const QV4::ObjectVTable classname::static_vtbl = \ { \ - DEFINE_MANAGED_VTABLE_INT(classname), \ + DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \ call, \ construct, \ get, \ @@ -166,30 +185,43 @@ const QV4::ObjectVTable classname::static_vtbl = \ advanceIterator \ } -#define DEFINE_MANAGED_VTABLE_WITH_NAME(classname, name) \ -const QV4::ObjectVTable classname::static_vtbl = \ -{ \ - DEFINE_MANAGED_VTABLE_INT(name), \ - call, \ - construct, \ - get, \ - getIndexed, \ - put, \ - putIndexed, \ - query, \ - queryIndexed, \ - deleteProperty, \ - deleteIndexedProperty, \ - getLookup, \ - setLookup, \ - getLength, \ - advanceIterator \ -} - - struct Q_QML_PRIVATE_EXPORT Managed { - V4_MANAGED + struct Q_QML_PRIVATE_EXPORT Data : HeapObject { + Data() {} + Data(InternalClass *internal) + : internalClass(internal) + , inUse(1) + , extensible(1) + { + // #### +// Q_ASSERT(internal && internal->vtable); + } + InternalClass *internalClass; + struct { + uchar markBit : 1; + uchar inUse : 1; + uchar extensible : 1; // used by Object + uchar _unused : 1; + uchar needsActivation : 1; // used by FunctionObject + uchar strictMode : 1; // used by FunctionObject + uchar bindingKeyFlag : 1; + uchar hasAccessorProperty : 1; + uchar _type; + mutable uchar subtype; + uchar _flags; + }; + + void setVTable(const ManagedVTable *vt); + ReturnedValue asReturnedValue() const { + return reinterpret_cast<Managed *>(const_cast<Data *>(this))->asReturnedValue(); + } + + void *operator new(size_t, Managed *m) { return m; } + void *operator new(size_t, Managed::Data *m) { return m; } + }; + Data data; + V4_MANAGED(Managed) enum { IsExecutionContext = false, IsString = false, @@ -205,17 +237,13 @@ private: protected: Managed(InternalClass *internal) - : internalClass(internal), _data(0) + : data(internal) { - Q_ASSERT(internalClass && internalClass->vtable); - inUse = 1; extensible = 1; } public: void *operator new(size_t size, MemoryManager *mm); void *operator new(size_t, Managed *m) { return m; } - void operator delete(void *ptr); - void operator delete(void *ptr, MemoryManager *mm); inline void mark(QV4::ExecutionEngine *engine); @@ -248,12 +276,18 @@ public: template <typename T> T *as() { // ### FIXME: - if (!this || !internalClass) + if (!this || !internalClass()) return 0; #if !defined(QT_NO_QOBJECT_CHECK) static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this)); #endif - return internalClass->vtable == T::staticVTable() ? static_cast<T *>(this) : 0; + const ManagedVTable *vt = internalClass()->vtable; + while (vt) { + if (vt == T::staticVTable()) + return static_cast<T *>(this); + vt = vt->parent; + } + return 0; } template <typename T> const T *as() const { @@ -263,24 +297,30 @@ public: #if !defined(QT_NO_QOBJECT_CHECK) static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this))); #endif - return internalClass->vtable == T::staticVTable() ? static_cast<const T *>(this) : 0; + const ManagedVTable *vt = internalClass()->vtable; + while (vt) { + if (vt == T::staticVTable()) + return static_cast<T *>(this); + vt = vt->parent; + } + return 0; } - String *asString() { return internalClass->vtable->isString ? reinterpret_cast<String *>(this) : 0; } - Object *asObject() { return internalClass->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; } - ArrayObject *asArrayObject() { return internalClass->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; } - FunctionObject *asFunctionObject() { return internalClass->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; } - BooleanObject *asBooleanObject() { return internalClass->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; } - NumberObject *asNumberObject() { return internalClass->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; } - StringObject *asStringObject() { return internalClass->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; } - DateObject *asDateObject() { return internalClass->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; } - ErrorObject *asErrorObject() { return internalClass->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; } - ArgumentsObject *asArgumentsObject() { return internalClass->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; } + String *asString() { return internalClass()->vtable->isString ? reinterpret_cast<String *>(this) : 0; } + Object *asObject() { return internalClass()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; } + ArrayObject *asArrayObject() { return internalClass()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; } + FunctionObject *asFunctionObject() { return internalClass()->vtable->isFunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; } + BooleanObject *asBooleanObject() { return internalClass()->vtable->type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; } + NumberObject *asNumberObject() { return internalClass()->vtable->type == Type_NumberObject ? reinterpret_cast<NumberObject *>(this) : 0; } + StringObject *asStringObject() { return internalClass()->vtable->type == Type_StringObject ? reinterpret_cast<StringObject *>(this) : 0; } + DateObject *asDateObject() { return internalClass()->vtable->type == Type_DateObject ? reinterpret_cast<DateObject *>(this) : 0; } + ErrorObject *asErrorObject() { return internalClass()->vtable->isErrorObject ? reinterpret_cast<ErrorObject *>(this) : 0; } + ArgumentsObject *asArgumentsObject() { return internalClass()->vtable->type == Type_ArgumentsObject ? reinterpret_cast<ArgumentsObject *>(this) : 0; } - bool isListType() const { return internalClass->vtable->type == Type_QmlSequence; } + bool isListType() const { return internalClass()->vtable->type == Type_QmlSequence; } - bool isArrayObject() const { return internalClass->vtable->type == Type_ArrayObject; } - bool isStringObject() const { return internalClass->vtable->type == Type_StringObject; } + bool isArrayObject() const { return internalClass()->vtable->type == Type_ArrayObject; } + bool isStringObject() const { return internalClass()->vtable->type == Type_StringObject; } QString className() const; @@ -297,33 +337,22 @@ public: void setVTable(const ManagedVTable *vt); bool isEqualTo(Managed *other) - { return internalClass->vtable->isEqualTo(this, other); } + { return internalClass()->vtable->isEqualTo(this, other); } - static void destroy(Managed *that) { that->_data = 0; } static bool isEqualTo(Managed *m, Managed *other); ReturnedValue asReturnedValue() { return Value::fromManaged(this).asReturnedValue(); } + InternalClass *internalClass() const { return d()->internalClass; } + void setInternalClass(InternalClass *ic) { d()->internalClass = ic; } - InternalClass *internalClass; + uchar subtype() const { return d()->subtype; } + void setSubtype(uchar subtype) const { d()->subtype = subtype; } - union { - uint _data; - struct { - uchar markBit : 1; - uchar inUse : 1; - uchar extensible : 1; // used by Object - uchar _unused : 1; - uchar needsActivation : 1; // used by FunctionObject - uchar strictMode : 1; // used by FunctionObject - uchar bindingKeyFlag : 1; - uchar hasAccessorProperty : 1; - uchar _type; - mutable uchar subtype; - uchar _flags; - }; - }; + bool inUse() const { return d()->inUse; } + bool markBit() const { return d()->markBit; } + static void destroy(Managed *) {} private: friend class MemoryManager; friend struct Identifiers; @@ -358,69 +387,6 @@ inline FunctionObject *managed_cast(Managed *m) return m->asFunctionObject(); } - -Value *extractValuePointer(const ScopedValue &); -template<typename T> -Value *extractValuePointer(const Scoped<T> &); - -#define DEFINE_REF_METHODS(Class, Base) \ - Class##Ref(const QV4::ScopedValue &v) \ - { QV4::Value *val = extractValuePointer(v); ptr = QV4::value_cast<Class>(*val) ? val : 0; } \ - Class##Ref(const QV4::Scoped<Class> &v) { ptr = extractValuePointer(v); } \ - Class##Ref(QV4::TypedValue<Class> &v) { ptr = &v; } \ - Class##Ref(QV4::Value &v) { ptr = QV4::value_cast<Class>(v) ? &v : 0; } \ - Class##Ref &operator=(Class *t) { \ - if (sizeof(void *) == 4) \ - ptr->tag = QV4::Value::Managed_Type; \ - ptr->m = t; \ - return *this; \ - } \ - Class##Ref &operator=(QV4::Returned<Class> *t) { \ - if (sizeof(void *) == 4) \ - ptr->tag = QV4::Value::Managed_Type; \ - ptr->m = t->getPointer(); \ - return *this; \ - } \ - operator const Class *() const { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \ - const Class *operator->() const { return static_cast<Class*>(ptr->managed()); } \ - operator Class *() { return ptr ? static_cast<Class*>(ptr->managed()) : 0; } \ - Class *operator->() { return static_cast<Class*>(ptr->managed()); } \ - Class *getPointer() const { return static_cast<Class *>(ptr->managed()); } \ - operator QV4::Returned<Class> *() const { return ptr ? QV4::Returned<Class>::create(getPointer()) : 0; } \ - static Class##Ref null() { Class##Ref c; c.ptr = 0; return c; } \ -protected: \ - Class##Ref() {} \ -public: \ - -#define DEFINE_REF(Class, Base) \ -struct Class##Ref : public Base##Ref \ -{ DEFINE_REF_METHODS(Class, Base) } \ - - -struct ManagedRef { - // Important: Do NOT add a copy constructor to this class or any derived class - // adding a copy constructor actually changes the calling convention, ie. - // is not even binary compatible. Adding it would break assumptions made - // in the jit'ed code. - DEFINE_REF_METHODS(Managed, Managed); - - bool operator==(const ManagedRef &other) { - if (ptr == other.ptr) - return true; - return ptr && other.ptr && ptr->m == other.ptr->m; - } - bool operator!=(const ManagedRef &other) { - return !operator==(other); - } - bool operator!() const { return !ptr || !ptr->managed(); } - - bool isNull() const { return !ptr; } - ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); } - -public: - Value *ptr; -}; - } diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 16d76e6914..3b8100c3fb 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -55,39 +55,39 @@ DEFINE_OBJECT_VTABLE(MathObject); static const double qt_PI = 2.0 * ::asin(1.0); -MathObject::MathObject(InternalClass *ic) - : Object(ic) +MathObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { Scope scope(ic->engine); - ScopedObject protectThis(scope, this); - - defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0))); - defineReadonlyProperty(QStringLiteral("LN2"), Primitive::fromDouble(::log(2.0))); - defineReadonlyProperty(QStringLiteral("LN10"), Primitive::fromDouble(::log(10.0))); - defineReadonlyProperty(QStringLiteral("LOG2E"), Primitive::fromDouble(1.0/::log(2.0))); - defineReadonlyProperty(QStringLiteral("LOG10E"), Primitive::fromDouble(1.0/::log(10.0))); - defineReadonlyProperty(QStringLiteral("PI"), Primitive::fromDouble(qt_PI)); - defineReadonlyProperty(QStringLiteral("SQRT1_2"), Primitive::fromDouble(::sqrt(0.5))); - defineReadonlyProperty(QStringLiteral("SQRT2"), Primitive::fromDouble(::sqrt(2.0))); - - defineDefaultProperty(QStringLiteral("abs"), method_abs, 1); - defineDefaultProperty(QStringLiteral("acos"), method_acos, 1); - defineDefaultProperty(QStringLiteral("asin"), method_asin, 0); - defineDefaultProperty(QStringLiteral("atan"), method_atan, 1); - defineDefaultProperty(QStringLiteral("atan2"), method_atan2, 2); - defineDefaultProperty(QStringLiteral("ceil"), method_ceil, 1); - defineDefaultProperty(QStringLiteral("cos"), method_cos, 1); - defineDefaultProperty(QStringLiteral("exp"), method_exp, 1); - defineDefaultProperty(QStringLiteral("floor"), method_floor, 1); - defineDefaultProperty(QStringLiteral("log"), method_log, 1); - defineDefaultProperty(QStringLiteral("max"), method_max, 2); - defineDefaultProperty(QStringLiteral("min"), method_min, 2); - defineDefaultProperty(QStringLiteral("pow"), method_pow, 2); - defineDefaultProperty(QStringLiteral("random"), method_random, 0); - defineDefaultProperty(QStringLiteral("round"), method_round, 1); - defineDefaultProperty(QStringLiteral("sin"), method_sin, 1); - defineDefaultProperty(QStringLiteral("sqrt"), method_sqrt, 1); - defineDefaultProperty(QStringLiteral("tan"), method_tan, 1); + ScopedObject m(scope, this); + + m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0))); + m->defineReadonlyProperty(QStringLiteral("LN2"), Primitive::fromDouble(::log(2.0))); + m->defineReadonlyProperty(QStringLiteral("LN10"), Primitive::fromDouble(::log(10.0))); + m->defineReadonlyProperty(QStringLiteral("LOG2E"), Primitive::fromDouble(1.0/::log(2.0))); + m->defineReadonlyProperty(QStringLiteral("LOG10E"), Primitive::fromDouble(1.0/::log(10.0))); + m->defineReadonlyProperty(QStringLiteral("PI"), Primitive::fromDouble(qt_PI)); + m->defineReadonlyProperty(QStringLiteral("SQRT1_2"), Primitive::fromDouble(::sqrt(0.5))); + m->defineReadonlyProperty(QStringLiteral("SQRT2"), Primitive::fromDouble(::sqrt(2.0))); + + m->defineDefaultProperty(QStringLiteral("abs"), method_abs, 1); + m->defineDefaultProperty(QStringLiteral("acos"), method_acos, 1); + m->defineDefaultProperty(QStringLiteral("asin"), method_asin, 0); + m->defineDefaultProperty(QStringLiteral("atan"), method_atan, 1); + m->defineDefaultProperty(QStringLiteral("atan2"), method_atan2, 2); + m->defineDefaultProperty(QStringLiteral("ceil"), method_ceil, 1); + m->defineDefaultProperty(QStringLiteral("cos"), method_cos, 1); + m->defineDefaultProperty(QStringLiteral("exp"), method_exp, 1); + m->defineDefaultProperty(QStringLiteral("floor"), method_floor, 1); + m->defineDefaultProperty(QStringLiteral("log"), method_log, 1); + m->defineDefaultProperty(QStringLiteral("max"), method_max, 2); + m->defineDefaultProperty(QStringLiteral("min"), method_min, 2); + m->defineDefaultProperty(QStringLiteral("pow"), method_pow, 2); + m->defineDefaultProperty(QStringLiteral("random"), method_random, 0); + m->defineDefaultProperty(QStringLiteral("round"), method_round, 1); + m->defineDefaultProperty(QStringLiteral("sin"), method_sin, 1); + m->defineDefaultProperty(QStringLiteral("sqrt"), method_sqrt, 1); + m->defineDefaultProperty(QStringLiteral("tan"), method_tan, 1); } /* copies the sign from y to x and returns the result */ @@ -104,15 +104,15 @@ static double copySign(double x, double y) ReturnedValue MathObject::method_abs(CallContext *context) { - if (!context->callData->argc) + if (!context->d()->callData->argc) return Encode(qSNaN()); - if (context->callData->args[0].isInteger()) { - int i = context->callData->args[0].integerValue(); + if (context->d()->callData->args[0].isInteger()) { + int i = context->d()->callData->args[0].integerValue(); return Encode(i < 0 ? - i : i); } - double v = context->callData->args[0].toNumber(); + double v = context->d()->callData->args[0].toNumber(); if (v == 0) // 0 | -0 return Encode(0); @@ -121,7 +121,7 @@ ReturnedValue MathObject::method_abs(CallContext *context) ReturnedValue MathObject::method_acos(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : 2; + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : 2; if (v > 1) return Encode(qSNaN()); @@ -130,7 +130,7 @@ ReturnedValue MathObject::method_acos(CallContext *context) ReturnedValue MathObject::method_asin(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : 2; + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : 2; if (v > 1) return Encode(qSNaN()); else @@ -139,7 +139,7 @@ ReturnedValue MathObject::method_asin(CallContext *context) ReturnedValue MathObject::method_atan(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); if (v == 0.0) return Encode(v); else @@ -148,8 +148,8 @@ ReturnedValue MathObject::method_atan(CallContext *context) ReturnedValue MathObject::method_atan2(CallContext *context) { - double v1 = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); - double v2 = context->callData->argc > 1 ? context->callData->args[1].toNumber() : qSNaN(); + double v1 = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); + double v2 = context->d()->callData->argc > 1 ? context->d()->callData->args[1].toNumber() : qSNaN(); if ((v1 < 0) && qIsFinite(v1) && qIsInf(v2) && (copySign(1.0, v2) == 1.0)) return Encode(copySign(0, -1.0)); @@ -166,7 +166,7 @@ ReturnedValue MathObject::method_atan2(CallContext *context) ReturnedValue MathObject::method_ceil(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); if (v < 0.0 && v > -1.0) return Encode(copySign(0, -1.0)); else @@ -175,13 +175,13 @@ ReturnedValue MathObject::method_ceil(CallContext *context) ReturnedValue MathObject::method_cos(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); return Encode(::cos(v)); } ReturnedValue MathObject::method_exp(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); if (qIsInf(v)) { if (copySign(1.0, v) == -1.0) return Encode(0); @@ -194,13 +194,13 @@ ReturnedValue MathObject::method_exp(CallContext *context) ReturnedValue MathObject::method_floor(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); return Encode(::floor(v)); } ReturnedValue MathObject::method_log(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); if (v < 0) return Encode(qSNaN()); else @@ -210,8 +210,8 @@ ReturnedValue MathObject::method_log(CallContext *context) ReturnedValue MathObject::method_max(CallContext *context) { double mx = -qInf(); - for (int i = 0; i < context->callData->argc; ++i) { - double x = context->callData->args[i].toNumber(); + for (int i = 0; i < context->d()->callData->argc; ++i) { + double x = context->d()->callData->args[i].toNumber(); if (x > mx || std::isnan(x)) mx = x; } @@ -221,8 +221,8 @@ ReturnedValue MathObject::method_max(CallContext *context) ReturnedValue MathObject::method_min(CallContext *context) { double mx = qInf(); - for (int i = 0; i < context->callData->argc; ++i) { - double x = context->callData->args[i].toNumber(); + for (int i = 0; i < context->d()->callData->argc; ++i) { + double x = context->d()->callData->args[i].toNumber(); if ((x == 0 && mx == x && copySign(1.0, x) == -1.0) || (x < mx) || std::isnan(x)) { mx = x; @@ -233,8 +233,8 @@ ReturnedValue MathObject::method_min(CallContext *context) ReturnedValue MathObject::method_pow(CallContext *context) { - double x = context->callData->argc > 0 ? context->callData->args[0].toNumber() : qSNaN(); - double y = context->callData->argc > 1 ? context->callData->args[1].toNumber() : qSNaN(); + double x = context->d()->callData->argc > 0 ? context->d()->callData->args[0].toNumber() : qSNaN(); + double y = context->d()->callData->argc > 1 ? context->d()->callData->args[1].toNumber() : qSNaN(); if (std::isnan(y)) return Encode(qSNaN()); @@ -294,26 +294,26 @@ ReturnedValue MathObject::method_random(CallContext *context) ReturnedValue MathObject::method_round(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); v = copySign(::floor(v + 0.5), v); return Encode(v); } ReturnedValue MathObject::method_sin(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); return Encode(::sin(v)); } ReturnedValue MathObject::method_sqrt(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); return Encode(::sqrt(v)); } ReturnedValue MathObject::method_tan(CallContext *context) { - double v = context->callData->argc ? context->callData->args[0].toNumber() : qSNaN(); + double v = context->d()->callData->argc ? context->d()->callData->args[0].toNumber() : qSNaN(); if (v == 0.0) return Encode(v); else diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index 18a80c2ba0..65366aab86 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -49,9 +49,12 @@ namespace QV4 { struct MathObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(InternalClass *ic); + }; + + V4_OBJECT(Object) Q_MANAGED_TYPE(MathObject) - MathObject(InternalClass *ic); static ReturnedValue method_abs(CallContext *context); static ReturnedValue method_acos(CallContext *context); diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index aeb4c38a8e..7eca47c3ce 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -44,29 +44,13 @@ using namespace QV4; -const ManagedVTable MemberData::static_vtbl = -{ - MemberData::IsExecutionContext, - MemberData::IsString, - MemberData::IsObject, - MemberData::IsFunctionObject, - MemberData::IsErrorObject, - MemberData::IsArrayData, - 0, - MemberData::MyType, - "MemberData", - destroy, - markObjects, - isEqualTo -}; - - +DEFINE_MANAGED_VTABLE(MemberData); void MemberData::markObjects(Managed *that, ExecutionEngine *e) { MemberData *m = static_cast<MemberData *>(that); - for (uint i = 0; i < m->size; ++i) - m->data[i].mark(e); + for (uint i = 0; i < m->d()->size; ++i) + m->d()->data[i].mark(e); } void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx) @@ -74,13 +58,13 @@ void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx) uint s = size(); if (idx >= s) { int newAlloc = qMax((uint)4, 2*idx); - uint alloc = sizeof(MemberData) + (newAlloc)*sizeof(Value); - MemberData *newMemberData = reinterpret_cast<MemberData *>(e->memoryManager->allocManaged(alloc)); + uint alloc = sizeof(MemberData::Data) + (newAlloc)*sizeof(Value); + MemberData *newMemberData = static_cast<MemberData *>(e->memoryManager->allocManaged(alloc)); if (d()) - memcpy(newMemberData, d(), sizeof(MemberData) + s*sizeof(Value)); + memcpy(newMemberData, d(), sizeof(MemberData::Data) + s*sizeof(Value)); else new (newMemberData) MemberData(e->memberDataClass); - newMemberData->size = newAlloc; + newMemberData->d()->size = newAlloc; m = newMemberData; } } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index 03aa75a365..cd8667adb7 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -50,23 +50,29 @@ namespace QV4 { struct MemberData : Managed { - V4_MANAGED - uint size; - Value data[1]; + struct Data : Managed::Data { + union { + uint size; + double _dummy; + }; + Value data[1]; + }; + V4_MANAGED(Managed) MemberData(QV4::InternalClass *ic) : Managed(ic) {} - Value &operator[] (uint idx) { return data[idx]; } + Value &operator[] (uint idx) { return d()->data[idx]; } static void markObjects(Managed *that, ExecutionEngine *e); }; struct Members : Value { + void reset() { m = 0; } void ensureIndex(QV4::ExecutionEngine *e, uint idx); - Value &operator[] (uint idx) const { return static_cast<MemberData *>(managed())->data[idx]; } - inline uint size() const { return d() ? d()->size : 0; } + 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())->data; } + Value *data() const { return static_cast<MemberData *>(managed())->d()->data; } void mark(ExecutionEngine *e) const { MemberData *m = d(); diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index ca2ccd33f7..3e7ac17078 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -57,6 +57,7 @@ #include <cstdlib> #include <algorithm> #include "qv4alloca_p.h" +#include "qv4profiling_p.h" #ifdef V4_USE_VALGRIND #include <valgrind/valgrind.h> @@ -102,6 +103,7 @@ struct MemoryManager::Data struct LargeItem { LargeItem *next; + size_t size; void *data; Managed *managed() { @@ -149,8 +151,10 @@ struct MemoryManager::Data ~Data() { - for (QVector<Chunk>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) + for (QVector<Chunk>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) { + Q_V4_PROFILE_DEALLOC(engine, 0, i->memory.size(), Profiling::HeapPage); i->memory.deallocate(); + } } }; @@ -174,7 +178,7 @@ MemoryManager::MemoryManager() #endif } -Managed *MemoryManager::alloc(std::size_t size) +Managed *MemoryManager::allocData(std::size_t size) { if (m_d->aggressiveGC) runGC(); @@ -190,9 +194,12 @@ Managed *MemoryManager::alloc(std::size_t size) // doesn't fit into a small bucket if (size >= MemoryManager::Data::MaxItemSize) { // we use malloc for this - MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(malloc(size + sizeof(MemoryManager::Data::LargeItem))); + MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>( + malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem), + Profiling::LargeItem))); memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem)); item->next = m_d->largeItems; + item->size = size; m_d->largeItems = item; return item->managed(); } @@ -218,7 +225,9 @@ Managed *MemoryManager::alloc(std::size_t size) std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift); allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize); Data::Chunk allocation; - allocation.memory = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages); + allocation.memory = PageAllocation::allocate( + Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage), + OSAllocator::JSGCHeapPages); allocation.chunkSize = int(size); m_d->heapChunks.append(allocation); std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end()); @@ -228,7 +237,6 @@ Managed *MemoryManager::alloc(std::size_t size) Managed **last = &m_d->smallItems[pos]; while (chunk <= end) { Managed *o = reinterpret_cast<Managed *>(chunk); - o->_data = 0; *last = o; last = o->nextFreeRef(); chunk += size; @@ -247,6 +255,7 @@ Managed *MemoryManager::alloc(std::size_t size) #ifdef V4_USE_VALGRIND VALGRIND_MEMPOOL_ALLOC(this, m, size); #endif + Q_V4_PROFILE_ALLOC(m_d->engine, size, Profiling::SmallItem); ++m_d->allocCount[pos]; ++m_d->totalAlloc; @@ -308,8 +317,8 @@ void MemoryManager::mark() // now that we marked all roots, start marking recursively and popping from the mark stack while (m_d->engine->jsStackTop > markBase) { Managed *m = m_d->engine->popForGC(); - Q_ASSERT (m->internalClass->vtable->markObjects); - m->internalClass->vtable->markObjects(m, m_d->engine); + Q_ASSERT (m->internalClass()->vtable->markObjects); + m->internalClass()->vtable->markObjects(m, m_d->engine); } } @@ -325,7 +334,7 @@ void MemoryManager::sweep(bool lastSweep) continue; } if (Managed *m = weak->value.asManaged()) { - if (!m->markBit) { + if (!m->markBit()) { weak->value = Primitive::undefinedValue(); PersistentValuePrivate *n = weak->next; weak->removeFromList(); @@ -338,7 +347,7 @@ void MemoryManager::sweep(bool lastSweep) if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) { for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) { - if (!it.value()->markBit) + if (!it.value()->markBit()) it = multiplyWrappedQObjects->erase(it); else ++it; @@ -352,18 +361,19 @@ void MemoryManager::sweep(bool lastSweep) Data::LargeItem **last = &m_d->largeItems; while (i) { Managed *m = i->managed(); - Q_ASSERT(m->inUse); - if (m->markBit) { - m->markBit = 0; + Q_ASSERT(m->inUse()); + if (m->markBit()) { + m->d()->markBit = 0; last = &i->next; i = i->next; continue; } - if (m->internalClass->vtable->destroy) - m->internalClass->vtable->destroy(m); + if (m->internalClass()->vtable->destroy) + m->internalClass()->vtable->destroy(m); *last = i->next; - free(i); + free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem), + Profiling::LargeItem)); i = *last; } @@ -392,16 +402,16 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size) Q_ASSERT((qintptr) chunk % 16 == 0); - if (m->inUse) { - if (m->markBit) { - m->markBit = 0; + if (m->inUse()) { + if (m->markBit()) { + m->d()->markBit = 0; } else { // qDebug() << "-- collecting it." << m << *f << m->nextFree(); #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif - if (m->internalClass->vtable->destroy) - m->internalClass->vtable->destroy(m); + if (m->internalClass()->vtable->destroy) + m->internalClass()->vtable->destroy(m); memset(m, 0, size); m->setNextFree(*f); @@ -409,6 +419,7 @@ void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size) VALGRIND_DISABLE_ERROR_REPORTING; VALGRIND_MEMPOOL_FREE(this, m); #endif + Q_V4_PROFILE_DEALLOC(m_d->engine, m, size, Profiling::SmallItem); *f = m; } } @@ -439,9 +450,7 @@ void MemoryManager::runGC() mark(); sweep(); } else { - int totalMem = 0; - for (int i = 0; i < m_d->heapChunks.size(); ++i) - totalMem += m_d->heapChunks.at(i).memory.size(); + int totalMem = getAllocatedMem(); QTime t; t.start(); @@ -467,22 +476,38 @@ void MemoryManager::runGC() m_d->totalAlloc = 0; } -uint MemoryManager::getUsedMem() +size_t MemoryManager::getUsedMem() const { - uint usedMem = 0; - for (QVector<Data::Chunk>::iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) { + size_t usedMem = 0; + for (QVector<Data::Chunk>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) { char *chunkStart = reinterpret_cast<char *>(i->memory.base()); char *chunkEnd = chunkStart + i->memory.size() - i->chunkSize; for (char *chunk = chunkStart; chunk <= chunkEnd; chunk += i->chunkSize) { Managed *m = reinterpret_cast<Managed *>(chunk); Q_ASSERT((qintptr) chunk % 16 == 0); - if (m->inUse) + if (m->inUse()) usedMem += i->chunkSize; } } return usedMem; } +size_t MemoryManager::getAllocatedMem() const +{ + size_t total = 0; + for (int i = 0; i < m_d->heapChunks.size(); ++i) + total += m_d->heapChunks.at(i).memory.size(); + return total; +} + +size_t MemoryManager::getLargeItemsMem() const +{ + size_t total = 0; + for (const Data::LargeItem *i = m_d->largeItems; i != 0; i = i->next) + total += i->size; + return total; +} + MemoryManager::~MemoryManager() { PersistentValuePrivate *persistent = m_persistentValues; @@ -526,11 +551,6 @@ void MemoryManager::registerDeletable(GCDeletable *d) m_d->deletable = d; } -ExecutionEngine *MemoryManager::engine() const -{ - return m_d->engine; -} - #ifdef DETAILED_MM_STATS void MemoryManager::willAllocate(std::size_t size) { @@ -545,11 +565,11 @@ void MemoryManager::willAllocate(std::size_t size) void MemoryManager::collectFromJSStack() const { - Value *v = engine()->jsStackBase; - Value *top = engine()->jsStackTop; + Value *v = m_d->engine->jsStackBase; + Value *top = m_d->engine->jsStackTop; while (v < top) { Managed *m = v->asManaged(); - if (m && m->inUse) + if (m && m->inUse()) // Skip pointers to already freed objects, they are bogus as well m->mark(m_d->engine); ++v; diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h index 47020c12f0..f0025dc70e 100644 --- a/src/qml/jsruntime/qv4mm_p.h +++ b/src/qml/jsruntime/qv4mm_p.h @@ -99,10 +99,58 @@ public: inline Managed *allocManaged(std::size_t size) { size = align(size); - Managed *o = alloc(size); + Managed *o = allocData(size); return o; } + template <typename ManagedType> + ManagedType *alloc() + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(); + return t; + } + + template <typename ManagedType, typename Arg1> + ManagedType *alloc(Arg1 arg1) + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(arg1); + return t; + } + + template <typename ManagedType, typename Arg1, typename Arg2> + ManagedType *alloc(Arg1 arg1, Arg2 arg2) + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(arg1, arg2); + return t; + } + + template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3> + ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3); + return t; + } + + template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> + ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4); + return t; + } + + template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> + ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + { + ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))); + (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5); + return t; + } + bool isGCBlocked() const; void setGCBlocked(bool blockGC); void runGC(); @@ -113,12 +161,14 @@ public: void registerDeletable(GCDeletable *d); + size_t getUsedMem() const; + size_t getAllocatedMem() const; + size_t getLargeItemsMem() const; + protected: /// expects size to be aligned // TODO: try to inline - Managed *alloc(std::size_t size); - - ExecutionEngine *engine() const; + Managed *allocData(std::size_t size); #ifdef DETAILED_MM_STATS void willAllocate(std::size_t size); @@ -129,7 +179,6 @@ private: void mark(); void sweep(bool lastSweep = false); void sweep(char *chunkStart, std::size_t chunkSize, size_t size); - uint getUsedMem(); protected: QScopedPointer<Data> m_d; diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index c97e86f2cd..f1bac1109a 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -51,8 +51,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(NumberCtor); DEFINE_OBJECT_VTABLE(NumberObject); -NumberCtor::NumberCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Number")) +NumberCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Number")) { setVTable(staticVTable()); } @@ -71,7 +71,7 @@ ReturnedValue NumberCtor::call(Managed *, CallData *callData) return Encode(dbl); } -void NumberPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void NumberPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -103,40 +103,40 @@ void NumberPrototype::init(ExecutionEngine *engine, ObjectRef ctor) inline ReturnedValue thisNumberValue(ExecutionContext *ctx) { - if (ctx->callData->thisObject.isNumber()) - return ctx->callData->thisObject.asReturnedValue(); - NumberObject *n = ctx->callData->thisObject.asNumberObject(); + if (ctx->d()->callData->thisObject.isNumber()) + return ctx->d()->callData->thisObject.asReturnedValue(); + NumberObject *n = ctx->d()->callData->thisObject.asNumberObject(); if (!n) return ctx->throwTypeError(); - return n->value.asReturnedValue(); + return n->value().asReturnedValue(); } inline double thisNumber(ExecutionContext *ctx) { - if (ctx->callData->thisObject.isNumber()) - return ctx->callData->thisObject.asDouble(); - NumberObject *n = ctx->callData->thisObject.asNumberObject(); + if (ctx->d()->callData->thisObject.isNumber()) + return ctx->d()->callData->thisObject.asDouble(); + NumberObject *n = ctx->d()->callData->thisObject.asNumberObject(); if (!n) return ctx->throwTypeError(); - return n->value.asDouble(); + return n->value().asDouble(); } ReturnedValue NumberPrototype::method_toString(CallContext *ctx) { double num = thisNumber(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); - if (ctx->callData->argc && !ctx->callData->args[0].isUndefined()) { - int radix = ctx->callData->args[0].toInt32(); + if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) { + int radix = ctx->d()->callData->args[0].toInt32(); if (radix < 2 || radix > 36) return ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix") .arg(radix)); if (std::isnan(num)) { - return ctx->engine->newString(QStringLiteral("NaN"))->asReturnedValue(); + return ctx->d()->engine->newString(QStringLiteral("NaN"))->asReturnedValue(); } else if (qIsInf(num)) { - return ctx->engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue(); + return ctx->d()->engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue(); } if (radix != 10) { @@ -166,7 +166,7 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx) } if (negative) str.prepend(QLatin1Char('-')); - return ctx->engine->newString(str)->asReturnedValue(); + return ctx->d()->engine->newString(str)->asReturnedValue(); } } @@ -178,7 +178,7 @@ ReturnedValue NumberPrototype::method_toLocaleString(CallContext *ctx) Scope scope(ctx); ScopedValue v(scope, thisNumberValue(ctx)); ScopedString str(scope, v->toString(ctx)); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); return str.asReturnedValue(); } @@ -191,19 +191,19 @@ ReturnedValue NumberPrototype::method_valueOf(CallContext *ctx) ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx) { double v = thisNumber(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); double fdigits = 0; - if (ctx->callData->argc > 0) - fdigits = ctx->callData->args[0].toInteger(); + if (ctx->d()->callData->argc > 0) + fdigits = ctx->d()->callData->args[0].toInteger(); if (std::isnan(fdigits)) fdigits = 0; if (fdigits < 0 || fdigits > 20) - return ctx->throwRangeError(ctx->callData->thisObject); + return ctx->throwRangeError(ctx->d()->callData->thisObject); QString str; if (std::isnan(v)) @@ -214,22 +214,22 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx) str = QString::number(v, 'f', int (fdigits)); else return RuntimeHelpers::stringFromNumber(ctx, v)->asReturnedValue(); - return ctx->engine->newString(str)->asReturnedValue(); + return ctx->d()->engine->newString(str)->asReturnedValue(); } ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx) { Scope scope(ctx); double d = thisNumber(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); int fdigits = -1; - if (ctx->callData->argc && !ctx->callData->args[0].isUndefined()) { - fdigits = ctx->callData->args[0].toInt32(); + if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) { + fdigits = ctx->d()->callData->args[0].toInt32(); if (fdigits < 0 || fdigits > 20) { - ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); + ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range"))); return ctx->throwRangeError(error); } } @@ -239,22 +239,22 @@ ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx) double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(d, fdigits, &builder); QString result = QString::fromLatin1(builder.Finalize()); - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx) { Scope scope(ctx); ScopedValue v(scope, thisNumberValue(ctx)); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); - if (!ctx->callData->argc || ctx->callData->args[0].isUndefined()) + if (!ctx->d()->callData->argc || ctx->d()->callData->args[0].isUndefined()) return RuntimeHelpers::toString(ctx, v); - double precision = ctx->callData->args[0].toInt32(); + double precision = ctx->d()->callData->args[0].toInt32(); if (precision < 1 || precision > 21) { - ScopedString error(scope, ctx->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); + ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range"))); return ctx->throwRangeError(error); } @@ -263,5 +263,5 @@ ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx) double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder); QString result = QString::fromLatin1(builder.Finalize()); - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index ccabcf6727..3e776f0f2f 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -51,8 +51,10 @@ namespace QV4 { struct NumberCtor: FunctionObject { - V4_OBJECT - NumberCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *that, CallData *callData); static ReturnedValue call(Managed *, CallData *callData); @@ -60,8 +62,7 @@ struct NumberCtor: FunctionObject struct NumberPrototype: NumberObject { - NumberPrototype(InternalClass *ic): NumberObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_toLocaleString(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index c8d360d511..e0f05a65f8 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -70,29 +70,16 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(Object); -Object::Object(ExecutionEngine *engine) - : Managed(engine->objectClass) +Object::Data::Data(InternalClass *internalClass) + : Managed::Data(internalClass) { -} - -Object::Object(InternalClass *ic) - : Managed(ic) -{ - Q_ASSERT(internalClass->vtable && internalClass->vtable != &Managed::static_vtbl); - - Q_ASSERT(!memberData.d()); if (internalClass->size) { - Scope scope(engine()); - ScopedObject protectThis(scope, this); - memberData.ensureIndex(engine(), internalClass->size); + Scope scope(internalClass->engine); + ScopedObject o(scope, this); + o->memberData().ensureIndex(internalClass->engine, internalClass->size); } } -Object::~Object() -{ - _data = 0; -} - bool Object::setPrototype(Object *proto) { Object *pp = proto; @@ -101,20 +88,15 @@ bool Object::setPrototype(Object *proto) return false; pp = pp->prototype(); } - internalClass = internalClass->changePrototype(proto); + setInternalClass(internalClass()->changePrototype(proto)); return true; } -void Object::destroy(Managed *that) -{ - static_cast<Object *>(that)->~Object(); -} - void Object::put(ExecutionContext *ctx, const QString &name, const ValueRef value) { Scope scope(ctx); - ScopedString n(scope, ctx->engine->newString(name)); - put(n, value); + ScopedString n(scope, ctx->d()->engine->newString(name)); + put(n.getPointer(), value); } ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, PropertyAttributes attrs) @@ -133,7 +115,7 @@ ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, Pro void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef value) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return; if (attrs.isAccessor()) { @@ -155,7 +137,7 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val return; reject: - if (engine()->currentContext()->strictMode) + if (engine()->currentContext()->d()->strictMode) engine()->currentContext()->throwTypeError(); } @@ -164,7 +146,7 @@ void Object::defineDefaultProperty(const QString &name, ValueRef value) ExecutionEngine *e = engine(); Scope scope(e); ScopedString s(scope, e->newIdentifier(name)); - defineDefaultProperty(s, value); + defineDefaultProperty(s.getPointer(), value); } void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount) @@ -172,16 +154,16 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca ExecutionEngine *e = engine(); Scope scope(e); ScopedString s(scope, e->newIdentifier(name)); - Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, s, code)); + Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, s.getPointer(), code)); function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount)); - defineDefaultProperty(s, function); + defineDefaultProperty(s.getPointer(), function); } -void Object::defineDefaultProperty(const StringRef name, ReturnedValue (*code)(CallContext *), int argumentCount) +void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount) { ExecutionEngine *e = engine(); Scope scope(e); - Scoped<FunctionObject> function(scope, e->newBuiltinFunction(e->rootContext, name, code)); + Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, name, code)); function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount)); defineDefaultProperty(name, function); } @@ -191,16 +173,16 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter) ExecutionEngine *e = engine(); Scope scope(e); Scoped<String> s(scope, e->newIdentifier(name)); - defineAccessorProperty(s, getter, setter); + defineAccessorProperty(s.getPointer(), getter, setter); } -void Object::defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)) +void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)) { ExecutionEngine *v4 = engine(); QV4::Scope scope(v4); ScopedProperty p(scope); - p->setGetter(getter ? v4->newBuiltinFunction(v4->rootContext, name, getter)->getPointer() : 0); - p->setSetter(setter ? v4->newBuiltinFunction(v4->rootContext, name, setter)->getPointer() : 0); + p->setGetter(getter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, getter)).getPointer() : 0); + p->setSetter(setter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, setter)).getPointer() : 0); insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); } @@ -209,10 +191,10 @@ void Object::defineReadonlyProperty(const QString &name, ValueRef value) QV4::ExecutionEngine *e = engine(); Scope scope(e); ScopedString s(scope, e->newIdentifier(name)); - defineReadonlyProperty(s, value); + defineReadonlyProperty(s.getPointer(), value); } -void Object::defineReadonlyProperty(const StringRef name, ValueRef value) +void Object::defineReadonlyProperty(String *name, ValueRef value) { insertMember(name, value, Attr_ReadOnly); } @@ -221,45 +203,45 @@ void Object::markObjects(Managed *that, ExecutionEngine *e) { Object *o = static_cast<Object *>(that); - o->memberData.mark(e); - if (o->arrayData) - o->arrayData->mark(e); + o->memberData().mark(e); + if (o->arrayData()) + o->arrayData()->mark(e); } void Object::ensureMemberIndex(uint idx) { - memberData.ensureIndex(engine(), idx); + memberData().ensureIndex(engine(), idx); } -void Object::insertMember(const StringRef s, const Property &p, PropertyAttributes attributes) +void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes) { uint idx; - InternalClass::addMember(this, s.getPointer(), attributes, &idx); + InternalClass::addMember(this, s, attributes, &idx); - ensureMemberIndex(internalClass->size); + ensureMemberIndex(internalClass()->size); if (attributes.isAccessor()) { - hasAccessorProperty = 1; + setHasAccessorProperty(); Property *pp = propertyAt(idx); pp->value = p.value; pp->set = p.set; } else { - memberData[idx] = p.value; + memberData()[idx] = p.value; } } // Section 8.12.1 -Property *Object::__getOwnProperty__(const StringRef name, PropertyAttributes *attrs) +Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) return __getOwnProperty__(idx, attrs); - uint member = internalClass->find(name); + uint member = internalClass()->find(name); if (member < UINT_MAX) { if (attrs) - *attrs = internalClass->propertyData[member]; + *attrs = internalClass()->propertyData[member]; return propertyAt(member); } @@ -270,10 +252,10 @@ Property *Object::__getOwnProperty__(const StringRef name, PropertyAttributes *a Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs) { - Property *p = arrayData->getProperty(index); + Property *p = arrayData()->getProperty(index); if (p) { if (attrs) - *attrs = arrayData->attributes(index); + *attrs = arrayData()->attributes(index); return p; } if (isStringObject()) { @@ -288,7 +270,7 @@ Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs) } // Section 8.12.2 -Property *Object::__getPropertyDescriptor__(const StringRef name, PropertyAttributes *attrs) const +Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *attrs) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -297,10 +279,10 @@ Property *Object::__getPropertyDescriptor__(const StringRef name, PropertyAttrib const Object *o = this; while (o) { - uint idx = o->internalClass->find(name.getPointer()); + uint idx = o->internalClass()->find(name); if (idx < UINT_MAX) { if (attrs) - *attrs = o->internalClass->propertyData[idx]; + *attrs = o->internalClass()->propertyData[idx]; return o->propertyAt(idx); } @@ -315,10 +297,10 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr { const Object *o = this; while (o) { - Property *p = o->arrayData->getProperty(index); + Property *p = o->arrayData()->getProperty(index); if (p) { if (attrs) - *attrs = o->arrayData->attributes(index); + *attrs = o->arrayData()->attributes(index); return p; } if (o->isStringObject()) { @@ -336,7 +318,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr return 0; } -bool Object::hasProperty(const StringRef name) const +bool Object::hasProperty(String *name) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -366,13 +348,13 @@ bool Object::hasProperty(uint index) const return false; } -bool Object::hasOwnProperty(const StringRef name) const +bool Object::hasOwnProperty(String *name) const { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) return hasOwnProperty(idx); - if (internalClass->find(name) < UINT_MAX) + if (internalClass()->find(name) < UINT_MAX) return true; if (!query(name).isEmpty()) return true; @@ -381,11 +363,11 @@ bool Object::hasOwnProperty(const StringRef name) const bool Object::hasOwnProperty(uint index) const { - if (!arrayData->isEmpty(index)) + if (!arrayData()->isEmpty(index)) return true; if (isStringObject()) { - String *s = static_cast<const StringObject *>(this)->value.asString(); - if (index < (uint)s->length()) + String *s = static_cast<const StringObject *>(this)->d()->value.asString(); + if (index < (uint)s->d()->length()) return true; } if (!queryIndexed(index).isEmpty()) @@ -403,7 +385,7 @@ ReturnedValue Object::call(Managed *m, CallData *) return m->engine()->currentContext()->throwTypeError(); } -ReturnedValue Object::get(Managed *m, const StringRef name, bool *hasProperty) +ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty) { return static_cast<Object *>(m)->internalGet(name, hasProperty); } @@ -413,7 +395,7 @@ ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty) return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty); } -void Object::put(Managed *m, const StringRef name, const ValueRef value) +void Object::put(Managed *m, String *name, const ValueRef value) { static_cast<Object *>(m)->internalPut(name, value); } @@ -423,16 +405,16 @@ void Object::putIndexed(Managed *m, uint index, const ValueRef value) static_cast<Object *>(m)->internalPutIndexed(index, value); } -PropertyAttributes Object::query(const Managed *m, StringRef name) +PropertyAttributes Object::query(const Managed *m, String *name) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) return queryIndexed(m, idx); const Object *o = static_cast<const Object *>(m); - idx = o->internalClass->find(name.getPointer()); + idx = o->internalClass()->find(name); if (idx < UINT_MAX) - return o->internalClass->propertyData[idx]; + return o->internalClass()->propertyData[idx]; return Attr_Invalid; } @@ -440,18 +422,18 @@ PropertyAttributes Object::query(const Managed *m, StringRef name) PropertyAttributes Object::queryIndexed(const Managed *m, uint index) { const Object *o = static_cast<const Object *>(m); - if (o->arrayData->get(index) != Primitive::emptyValue().asReturnedValue()) - return o->arrayData->attributes(index); + if (o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue()) + return o->arrayData()->attributes(index); if (o->isStringObject()) { - String *s = static_cast<const StringObject *>(o)->value.asString(); - if (index < (uint)s->length()) + String *s = static_cast<const StringObject *>(o)->d()->value.asString(); + if (index < (uint)s->d()->length()) return (Attr_NotWritable|Attr_NotConfigurable); } return Attr_Invalid; } -bool Object::deleteProperty(Managed *m, const StringRef name) +bool Object::deleteProperty(Managed *m, String *name) { return static_cast<Object *>(m)->internalDeleteProperty(name); } @@ -497,46 +479,46 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value) Scope scope(m->engine()); ScopedObject o(scope, static_cast<Object *>(m)); - InternalClass *c = o->internalClass; + InternalClass *c = o->internalClass(); uint idx = c->find(l->name); if (!o->isArrayObject() || idx != ArrayObject::LengthPropertyIndex) { - if (idx != UINT_MAX && o->internalClass->propertyData[idx].isData() && o->internalClass->propertyData[idx].isWritable()) { - l->classList[0] = o->internalClass; + if (idx != UINT_MAX && o->internalClass()->propertyData[idx].isData() && o->internalClass()->propertyData[idx].isWritable()) { + l->classList[0] = o->internalClass(); l->index = idx; l->setter = Lookup::setter0; - o->memberData[idx] = *value; + o->memberData()[idx] = *value; return; } if (idx != UINT_MAX) { - o->putValue(o->propertyAt(idx), o->internalClass->propertyData[idx], value); + o->putValue(o->propertyAt(idx), o->internalClass()->propertyData[idx], value); return; } } ScopedString s(scope, l->name); - o->put(s, value); + o->put(s.getPointer(), value); - if (o->internalClass == c) + if (o->internalClass() == c) return; - idx = o->internalClass->find(l->name); + idx = o->internalClass()->find(l->name); if (idx == UINT_MAX) return; l->classList[0] = c; - l->classList[3] = o->internalClass; + l->classList[3] = o->internalClass(); l->index = idx; if (!o->prototype()) { l->setter = Lookup::setterInsert0; return; } o = o->prototype(); - l->classList[1] = o->internalClass; + l->classList[1] = o->internalClass(); if (!o->prototype()) { l->setter = Lookup::setterInsert1; return; } o = o->prototype(); - l->classList[2] = o->internalClass; + l->classList[2] = o->internalClass(); if (!o->prototype()) { l->setter = Lookup::setterInsert2; return; @@ -544,13 +526,13 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value) l->setter = Lookup::setterGeneric; } -void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *pd, PropertyAttributes *attrs) +void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *pd, PropertyAttributes *attrs) { Object *o = static_cast<Object *>(m); name = (String *)0; *index = UINT_MAX; - if (o->arrayData) { + if (o->arrayData()) { if (!it->arrayIndex) it->arrayNode = o->sparseBegin(); @@ -559,9 +541,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin while (it->arrayNode != o->sparseEnd()) { int k = it->arrayNode->key(); uint pidx = it->arrayNode->value; - Property *p = reinterpret_cast<Property *>(o->arrayData->data + pidx); + Property *p = reinterpret_cast<Property *>(o->arrayData()->arrayData() + pidx); it->arrayNode = it->arrayNode->nextNode(); - PropertyAttributes a = o->arrayData->attributes(k); + PropertyAttributes a = o->arrayData()->attributes(k); if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { it->arrayIndex = k + 1; *index = k; @@ -574,9 +556,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin it->arrayIndex = UINT_MAX; } // dense arrays - while (it->arrayIndex < o->arrayData->length()) { - Value *val = o->arrayData->data + it->arrayIndex; - PropertyAttributes a = o->arrayData->attributes(it->arrayIndex); + while (it->arrayIndex < o->arrayData()->length()) { + Value *val = o->arrayData()->arrayData() + it->arrayIndex; + PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex); ++it->arrayIndex; if (!val->isEmpty() && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) { @@ -588,8 +570,8 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin } } - while (it->memberIndex < o->internalClass->size) { - String *n = o->internalClass->nameMap.at(it->memberIndex); + while (it->memberIndex < o->internalClass()->size) { + String *n = o->internalClass()->nameMap.at(it->memberIndex); if (!n) { // accessor properties have a dummy entry with n == 0 ++it->memberIndex; @@ -597,7 +579,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin } Property *p = o->propertyAt(it->memberIndex); - PropertyAttributes a = o->internalClass->propertyData[it->memberIndex]; + PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex]; ++it->memberIndex; if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { name = n; @@ -611,7 +593,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uin } // Section 8.12.3 -ReturnedValue Object::internalGet(const StringRef name, bool *hasProperty) +ReturnedValue Object::internalGet(String *name, bool *hasProperty) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -621,11 +603,11 @@ ReturnedValue Object::internalGet(const StringRef name, bool *hasProperty) Object *o = this; while (o) { - uint idx = o->internalClass->find(name.getPointer()); + uint idx = o->internalClass()->find(name); if (idx < UINT_MAX) { if (hasProperty) *hasProperty = true; - return getValue(o->propertyAt(idx), o->internalClass->propertyData.at(idx)); + return getValue(o->propertyAt(idx), o->internalClass()->propertyData.at(idx)); } o = o->prototype(); @@ -642,10 +624,10 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) PropertyAttributes attrs; Object *o = this; while (o) { - Property *p = o->arrayData->getProperty(index); + Property *p = o->arrayData()->getProperty(index); if (p) { pd = p; - attrs = o->arrayData->attributes(index); + attrs = o->arrayData()->attributes(index); break; } if (o->isStringObject()) { @@ -671,9 +653,9 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) // Section 8.12.5 -void Object::internalPut(const StringRef name, const ValueRef value) +void Object::internalPut(String *name, const ValueRef value) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return; uint idx = name->asArrayIndex(); @@ -682,12 +664,12 @@ void Object::internalPut(const StringRef name, const ValueRef value) name->makeIdentifier(); - uint member = internalClass->find(name.getPointer()); + uint member = internalClass()->find(name); Property *pd = 0; PropertyAttributes attrs; if (member < UINT_MAX) { pd = propertyAt(member); - attrs = internalClass->propertyData[member]; + attrs = internalClass()->propertyData[member]; } // clause 1 @@ -713,7 +695,7 @@ void Object::internalPut(const StringRef name, const ValueRef value) } return; } else if (!prototype()) { - if (!extensible) + if (!isExtensible()) goto reject; } else { // clause 4 @@ -721,10 +703,10 @@ void Object::internalPut(const StringRef name, const ValueRef value) if (attrs.isAccessor()) { if (!pd->setter()) goto reject; - } else if (!extensible || !attrs.isWritable()) { + } else if (!isExtensible() || !attrs.isWritable()) { goto reject; } - } else if (!extensible) { + } else if (!isExtensible()) { goto reject; } } @@ -747,7 +729,7 @@ void Object::internalPut(const StringRef name, const ValueRef value) return; reject: - if (engine()->currentContext()->strictMode) { + if (engine()->currentContext()->d()->strictMode) { QString message = QStringLiteral("Cannot assign to read-only property \""); message += name->toQString(); message += QLatin1Char('\"'); @@ -757,14 +739,14 @@ void Object::internalPut(const StringRef name, const ValueRef value) void Object::internalPutIndexed(uint index, const ValueRef value) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return; PropertyAttributes attrs; - Property *pd = arrayData->getProperty(index); + Property *pd = arrayData()->getProperty(index); if (pd) - attrs = arrayData->attributes(index); + attrs = arrayData()->attributes(index); if (!pd && isStringObject()) { pd = static_cast<StringObject *>(this)->getIndex(index); @@ -785,7 +767,7 @@ void Object::internalPutIndexed(uint index, const ValueRef value) pd->value = *value; return; } else if (!prototype()) { - if (!extensible) + if (!isExtensible()) goto reject; } else { // clause 4 @@ -793,10 +775,10 @@ void Object::internalPutIndexed(uint index, const ValueRef value) if (attrs.isAccessor()) { if (!pd->setter()) goto reject; - } else if (!extensible || !attrs.isWritable()) { + } else if (!isExtensible() || !attrs.isWritable()) { goto reject; } - } else if (!extensible) { + } else if (!isExtensible()) { goto reject; } } @@ -819,14 +801,14 @@ void Object::internalPutIndexed(uint index, const ValueRef value) return; reject: - if (engine()->currentContext()->strictMode) + if (engine()->currentContext()->d()->strictMode) engine()->currentContext()->throwTypeError(); } // Section 8.12.7 -bool Object::internalDeleteProperty(const StringRef name) +bool Object::internalDeleteProperty(String *name) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return false; uint idx = name->asArrayIndex(); @@ -835,13 +817,13 @@ bool Object::internalDeleteProperty(const StringRef name) name->makeIdentifier(); - uint memberIdx = internalClass->find(name); + uint memberIdx = internalClass()->find(name); if (memberIdx != UINT_MAX) { - if (internalClass->propertyData[memberIdx].isConfigurable()) { - InternalClass::removeMember(this, name->identifier); + if (internalClass()->propertyData[memberIdx].isConfigurable()) { + InternalClass::removeMember(this, name->identifier()); return true; } - if (engine()->currentContext()->strictMode) + if (engine()->currentContext()->d()->strictMode) engine()->currentContext()->throwTypeError(); return false; } @@ -851,19 +833,19 @@ bool Object::internalDeleteProperty(const StringRef name) bool Object::internalDeleteIndexedProperty(uint index) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return false; - if (!arrayData || arrayData->vtable()->del(this, index)) + if (!arrayData() || arrayData()->vtable()->del(this, index)) return true; - if (engine()->currentContext()->strictMode) + if (engine()->currentContext()->d()->strictMode) engine()->currentContext()->throwTypeError(); return false; } // Section 8.12.9 -bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -876,10 +858,10 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, PropertyAttributes *cattrs; uint memberIndex; - if (isArrayObject() && name->equals(ctx->engine->id_length)) { - assert(ArrayObject::LengthPropertyIndex == internalClass->find(ctx->engine->id_length)); + if (isArrayObject() && name->equals(ctx->d()->engine->id_length)) { + assert(ArrayObject::LengthPropertyIndex == internalClass()->find(ctx->d()->engine->id_length)); Property *lp = propertyAt(ArrayObject::LengthPropertyIndex); - cattrs = internalClass->propertyData.constData() + ArrayObject::LengthPropertyIndex; + cattrs = internalClass()->propertyData.constData() + ArrayObject::LengthPropertyIndex; if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs)) return true; if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable()) @@ -900,18 +882,18 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, if (!succeeded) goto reject; if (attrs.isAccessor()) - hasAccessorProperty = 1; + setHasAccessorProperty(); return true; } // Clause 1 - memberIndex = internalClass->find(name.getPointer()); + memberIndex = internalClass()->find(name); current = (memberIndex < UINT_MAX) ? propertyAt(memberIndex) : 0; - cattrs = internalClass->propertyData.constData() + memberIndex; + cattrs = internalClass()->propertyData.constData() + memberIndex; if (!current) { // clause 3 - if (!extensible) + if (!isExtensible()) goto reject; // clause 4 Property pd; @@ -923,7 +905,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name, return __defineOwnProperty__(ctx, memberIndex, name, p, attrs); reject: - if (ctx->strictMode) + if (ctx->d()->strictMode) ctx->throwTypeError(); return false; } @@ -931,7 +913,7 @@ reject: bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs) { // 15.4.5.1, 4b - if (isArrayObject() && index >= getLength() && !internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable()) + if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable()) goto reject; if (ArgumentsObject::isNonStrictArgumentsObject(this)) @@ -939,7 +921,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Prop return defineOwnProperty2(ctx, index, p, attrs); reject: - if (ctx->strictMode) + if (ctx->d()->strictMode) ctx->throwTypeError(); return false; } @@ -950,14 +932,14 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert // Clause 1 { - current = arrayData->getProperty(index); + current = arrayData()->getProperty(index); if (!current && isStringObject()) current = static_cast<StringObject *>(this)->getIndex(index); } if (!current) { // clause 3 - if (!extensible) + if (!isExtensible()) goto reject; // clause 4 Property pp; @@ -973,14 +955,14 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert return true; } - return __defineOwnProperty__(ctx, index, StringRef::null(), p, attrs); + return __defineOwnProperty__(ctx, index, 0, p, attrs); reject: - if (ctx->strictMode) + if (ctx->d()->strictMode) ctx->throwTypeError(); return false; } -bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs) +bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs) { // clause 5 if (attrs.isEmpty()) @@ -988,12 +970,12 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri Property *current; PropertyAttributes cattrs; - if (!member.isNull()) { + if (member) { current = propertyAt(index); - cattrs = internalClass->propertyData[index]; + cattrs = internalClass()->propertyData[index]; } else { - current = arrayData->getProperty(index); - cattrs = arrayData->attributes(index); + current = arrayData()->getProperty(index); + cattrs = arrayData()->attributes(index); } // clause 6 @@ -1021,11 +1003,11 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri // 9b cattrs.setType(PropertyAttributes::Accessor); cattrs.clearWritable(); - if (member.isNull()) { + if (!member) { // need to convert the array and the slot initSparseArray(); setArrayAttributes(index, cattrs); - current = arrayData->getProperty(index); + current = arrayData()->getProperty(index); } current->setGetter(0); current->setSetter(0); @@ -1033,10 +1015,10 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri // 9c cattrs.setType(PropertyAttributes::Data); cattrs.setWritable(false); - if (member.isNull()) { + if (!member) { // need to convert the array and the slot setArrayAttributes(index, cattrs); - current = arrayData->getProperty(index); + current = arrayData()->getProperty(index); } current->value = Primitive::undefinedValue(); } @@ -1058,16 +1040,16 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri accept: current->merge(cattrs, p, attrs); - if (!member.isNull()) { - InternalClass::changeMember(this, member.getPointer(), cattrs); + if (member) { + InternalClass::changeMember(this, member, cattrs); } else { setArrayAttributes(index, cattrs); } if (cattrs.isAccessor()) - hasAccessorProperty = 1; + setHasAccessorProperty(); return true; reject: - if (ctx->strictMode) + if (ctx->d()->strictMode) ctx->throwTypeError(); return false; } @@ -1076,8 +1058,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Stri bool Object::__defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs) { Scope scope(ctx); - ScopedString s(scope, ctx->engine->newString(name)); - return __defineOwnProperty__(ctx, s, p, attrs); + ScopedString s(scope, ctx->d()->engine->newString(name)); + return __defineOwnProperty__(ctx, s.getPointer(), p, attrs); } @@ -1086,7 +1068,7 @@ void Object::copyArrayData(Object *other) Q_ASSERT(isArrayObject()); Scope scope(engine()); - if (other->protoHasArray() || other->hasAccessorProperty) { + if (other->protoHasArray() || other->hasAccessorProperty()) { uint len = other->getLength(); Q_ASSERT(len); @@ -1094,30 +1076,30 @@ void Object::copyArrayData(Object *other) for (uint i = 0; i < len; ++i) { arraySet(i, (v = other->getIndexed(i))); } - } else if (!other->arrayData) { + } else if (!other->arrayData()) { ; - } else if (other->hasAccessorProperty && other->arrayData->attrs && other->arrayData->isSparse()){ + } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){ // do it the slow way ScopedValue v(scope); - for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other->arrayData)->sparse->begin(); - it != static_cast<const SparseArrayData *>(other->arrayData)->sparse->end(); it = it->nextNode()) { - v = other->getValue(reinterpret_cast<Property *>(other->arrayData->data + it->value), other->arrayData->attrs[it->value]); + for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other->arrayData())->sparse()->begin(); + it != static_cast<const SparseArrayData *>(other->arrayData())->sparse()->end(); it = it->nextNode()) { + v = other->getValue(reinterpret_cast<Property *>(other->arrayData()->arrayData() + it->value), other->arrayData()->attrs()[it->value]); arraySet(it->key(), v); } } else { - Q_ASSERT(!arrayData && other->arrayData); - ArrayData::realloc(this, other->arrayData->type, 0, other->arrayData->alloc, other->arrayData->attrs); + Q_ASSERT(!arrayData() && other->arrayData()); + ArrayData::realloc(this, other->arrayData()->type(), 0, other->arrayData()->alloc(), other->arrayData()->attrs()); if (other->arrayType() == ArrayData::Sparse) { - SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData); - SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData); - dd->sparse = new SparseArray(*od->sparse); - dd->freeList = od->freeList; + SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData()); + SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData()); + dd->setSparse(new SparseArray(*od->sparse())); + dd->freeList() = od->freeList(); } else { - SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData); - d->len = static_cast<SimpleArrayData *>(other->arrayData)->len; - d->offset = 0; + SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData()); + d->len() = static_cast<SimpleArrayData *>(other->arrayData())->len(); + d->offset() = 0; } - memcpy(arrayData->data, other->arrayData->data, arrayData->alloc*sizeof(Value)); + memcpy(arrayData()->arrayData(), other->arrayData()->arrayData(), arrayData()->alloc()*sizeof(Value)); } setArrayLengthUnchecked(other->getLength()); } @@ -1132,15 +1114,15 @@ uint Object::getLength(const Managed *m) bool Object::setArrayLength(uint newLen) { Q_ASSERT(isArrayObject()); - if (!internalClass->propertyData[ArrayObject::LengthPropertyIndex].isWritable()) + if (!internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable()) return false; uint oldLen = getLength(); bool ok = true; if (newLen < oldLen) { - if (!arrayData) { + if (!arrayData()) { Q_ASSERT(!newLen); } else { - uint l = arrayData->vtable()->truncate(this, newLen); + uint l = arrayData()->vtable()->truncate(this, newLen); if (l != newLen) ok = false; newLen = l; @@ -1164,30 +1146,23 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); -ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) - : Object(engine->arrayClass) +ArrayObject::Data::Data(ExecutionEngine *engine, const QStringList &list) + : Object::Data(engine->arrayClass) { - init(engine); + init(); Scope scope(engine); - ScopedValue protectThis(scope, this); + ScopedObject a(scope, this); // Converts a QStringList to JS. // The result is a new Array object with length equal to the length // of the QStringList, and the elements being the QStringList's // elements converted to JS Strings. int len = list.count(); - arrayReserve(len); + a->arrayReserve(len); ScopedValue v(scope); for (int ii = 0; ii < len; ++ii) - arrayPut(ii, (v = engine->newString(list.at(ii)))); - setArrayLengthUnchecked(len); -} - -void ArrayObject::init(ExecutionEngine *engine) -{ - Q_UNUSED(engine); - - memberData[LengthPropertyIndex] = Primitive::fromInt32(0); + a->arrayPut(ii, (v = engine->newString(list.at(ii)))); + a->setArrayLengthUnchecked(len); } ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l) @@ -1196,7 +1171,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()[ArrayObject::LengthPropertyIndex].asReturnedValue(); } return Object::getLookup(m, l); } @@ -1204,16 +1179,16 @@ 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()[ArrayObject::LengthPropertyIndex].isInteger()) + return a->memberData()[ArrayObject::LengthPropertyIndex].integerValue(); + return Primitive::toUInt32(a->memberData()[ArrayObject::LengthPropertyIndex].doubleValue()); } QStringList ArrayObject::toQStringList() const { QStringList result; - QV4::ExecutionEngine *engine = internalClass->engine; + QV4::ExecutionEngine *engine = internalClass()->engine; Scope scope(engine); ScopedValue v(scope); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 40f38ee347..67459d5e77 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -103,39 +103,49 @@ struct URIErrorPrototype; struct Q_QML_EXPORT Object: Managed { - V4_OBJECT + struct Data : Managed::Data { + Data(ExecutionEngine *engine) + : Managed::Data(engine->objectClass) + { + } + Data(InternalClass *internal = 0); + + Members memberData; + ArrayData *arrayData; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(Object) + enum { IsObject = true }; - Members memberData; - ArrayData *arrayData; + Members &memberData() { return d()->memberData; } + const Members &memberData() const { return d()->memberData; } + const ArrayData *arrayData() const { return d()->arrayData; } + ArrayData *arrayData() { return d()->arrayData; } + void setArrayData(ArrayData *a) { d()->arrayData = a; } - Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData.data() + index); } + Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData().data() + index); } - Object(ExecutionEngine *engine); - Object(InternalClass *internalClass); - ~Object(); - - const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass->vtable); } - Object *prototype() const { return internalClass->prototype; } + const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass()->vtable); } + Object *prototype() const { return internalClass()->prototype; } bool setPrototype(Object *proto); - Property *__getOwnProperty__(const StringRef name, PropertyAttributes *attrs = 0); + Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0); Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0); - Property *__getPropertyDescriptor__(const StringRef name, PropertyAttributes *attrs = 0) const; + Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const; Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const; - bool hasProperty(const StringRef name) const; + bool hasProperty(String *name) const; bool hasProperty(uint index) const; - bool hasOwnProperty(const StringRef name) const; + bool hasOwnProperty(String *name) const; bool hasOwnProperty(uint index) const; - bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const StringRef member, const Property &p, PropertyAttributes attrs); - bool __defineOwnProperty__(ExecutionContext *ctx, const StringRef name, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs); bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs); bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs); bool defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs); @@ -155,24 +165,31 @@ struct Q_QML_EXPORT Object: Managed { void putValue(Property *pd, PropertyAttributes attrs, const ValueRef value); /* The spec default: Writable: true, Enumerable: false, Configurable: true */ - void defineDefaultProperty(const StringRef name, ValueRef value) { + void defineDefaultProperty(String *name, ValueRef value) { insertMember(name, value, Attr_Data|Attr_NotEnumerable); } void defineDefaultProperty(const QString &name, ValueRef value); void defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount = 0); - void defineDefaultProperty(const StringRef name, ReturnedValue (*code)(CallContext *), int argumentCount = 0); + void defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount = 0); void defineAccessorProperty(const QString &name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); - void defineAccessorProperty(const StringRef name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); + void defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *)); /* Fixed: Writable: false, Enumerable: false, Configurable: false */ void defineReadonlyProperty(const QString &name, ValueRef value); - void defineReadonlyProperty(const StringRef name, ValueRef value); + void defineReadonlyProperty(String *name, ValueRef value); - void insertMember(const StringRef s, const ValueRef v, PropertyAttributes attributes = Attr_Data) { - insertMember(s, Property(*v), attributes); + void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) { + Property p(*v); + insertMember(s, p, attributes); } - void insertMember(const StringRef s, const Property &p, PropertyAttributes attributes); + void insertMember(String *s, const Property &p, PropertyAttributes attributes); + + inline ExecutionEngine *engine() const { return internalClass()->engine; } - inline ExecutionEngine *engine() const { return internalClass->engine; } + inline bool hasAccessorProperty() const { return d()->hasAccessorProperty; } + inline void setHasAccessorProperty() { d()->hasAccessorProperty = true; } + + bool isExtensible() const { return d()->extensible; } + void setExtensible(bool b) { d()->extensible = b; } // Array handling @@ -186,30 +203,30 @@ public: void arraySet(uint index, ValueRef value); bool arrayPut(uint index, ValueRef value) { - return arrayData->vtable()->put(this, index, value); + return arrayData()->vtable()->put(this, index, value); } bool arrayPut(uint index, Value *values, uint n) { - return arrayData->vtable()->putArray(this, index, values, n); + return arrayData()->vtable()->putArray(this, index, values, n); } void setArrayAttributes(uint i, PropertyAttributes a) { - Q_ASSERT(arrayData); - if (arrayData->attrs || a != Attr_Data) { + Q_ASSERT(arrayData()); + if (arrayData()->attrs() || a != Attr_Data) { ArrayData::ensureAttributes(this); a.resolve(); - arrayData->vtable()->setAttribute(this, i, a); + arrayData()->vtable()->setAttribute(this, i, a); } } void push_back(const ValueRef v); ArrayData::Type arrayType() const { - return arrayData ? arrayData->type : ArrayData::Simple; + return arrayData() ? arrayData()->type() : ArrayData::Simple; } // ### remove me void setArrayType(ArrayData::Type t) { Q_ASSERT(t != ArrayData::Simple && t != ArrayData::Sparse); arrayCreate(); - arrayData->type = t; + arrayData()->setType(t); } inline void arrayReserve(uint n) { @@ -217,7 +234,7 @@ public: } void arrayCreate() { - if (!arrayData) + if (!arrayData()) ArrayData::realloc(this, ArrayData::Simple, 0, 0, false); #ifdef CHECK_SPARSE_ARRAYS initSparseArray(); @@ -225,34 +242,34 @@ public: } void initSparseArray(); - SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->begin() : 0; } - SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData)->sparse->end() : 0; } + SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->begin() : 0; } + SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->end() : 0; } inline bool protoHasArray() { Scope scope(engine()); Scoped<Object> p(scope, this); while ((p = p->prototype())) - if (p->arrayData) + if (p->arrayData()) return true; return false; } void ensureMemberIndex(uint idx); - inline ReturnedValue get(const StringRef name, bool *hasProperty = 0) + inline ReturnedValue get(String *name, bool *hasProperty = 0) { return vtable()->get(this, name, hasProperty); } inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0) { return vtable()->getIndexed(this, idx, hasProperty); } - inline void put(const StringRef name, const ValueRef v) + inline void put(String *name, const ValueRef v) { vtable()->put(this, name, v); } inline void putIndexed(uint idx, const ValueRef v) { vtable()->putIndexed(this, idx, v); } - PropertyAttributes query(StringRef name) const + PropertyAttributes query(String *name) const { return vtable()->query(this, name); } PropertyAttributes queryIndexed(uint index) const { return vtable()->queryIndexed(this, index); } - bool deleteProperty(const StringRef name) + bool deleteProperty(String *name) { return vtable()->deleteProperty(this, name); } bool deleteIndexedProperty(uint index) { return vtable()->deleteIndexedProperty(this, index); } @@ -260,7 +277,7 @@ public: { return vtable()->getLookup(this, l); } void setLookup(Lookup *l, const ValueRef v) { vtable()->setLookup(this, l, v); } - void advanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes) + void advanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes) { vtable()->advanceIterator(this, it, name, index, p, attributes); } uint getLength() const { return vtable()->getLength(this); } @@ -269,29 +286,28 @@ public: inline ReturnedValue call(CallData *d) { return vtable()->call(this, d); } protected: - static void destroy(Managed *that); static void markObjects(Managed *that, ExecutionEngine *e); static ReturnedValue construct(Managed *m, CallData *); static ReturnedValue call(Managed *m, CallData *); - static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty); + static ReturnedValue get(Managed *m, String *name, bool *hasProperty); static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); - static void put(Managed *m, const StringRef name, const ValueRef value); + static void put(Managed *m, String *name, const ValueRef value); static void putIndexed(Managed *m, uint index, const ValueRef value); - static PropertyAttributes query(const Managed *m, StringRef name); + static PropertyAttributes query(const Managed *m, String *name); static PropertyAttributes queryIndexed(const Managed *m, uint index); - static bool deleteProperty(Managed *m, const StringRef name); + static bool deleteProperty(Managed *m, String *name); static bool deleteIndexedProperty(Managed *m, uint index); static ReturnedValue getLookup(Managed *m, Lookup *l); static void setLookup(Managed *m, Lookup *l, const ValueRef v); - static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes); + static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes); static uint getLength(const Managed *m); private: - ReturnedValue internalGet(const StringRef name, bool *hasProperty); + ReturnedValue internalGet(String *name, bool *hasProperty); ReturnedValue internalGetIndexed(uint index, bool *hasProperty); - void internalPut(const StringRef name, const ValueRef value); + void internalPut(String *name, const ValueRef value); void internalPutIndexed(uint index, const ValueRef value); - bool internalDeleteProperty(const StringRef name); + bool internalDeleteProperty(String *name); bool internalDeleteIndexedProperty(uint index); friend struct ObjectIterator; @@ -299,48 +315,62 @@ private: }; struct BooleanObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, const ValueRef val) + : Object::Data(engine->booleanClass) + { + value = val; + } + Data(InternalClass *ic) + : Object::Data(ic) + { + Q_ASSERT(internalClass->vtable == staticVTable()); + value = Encode(false); + } + Value value; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(BooleanObject) - Value value; - BooleanObject(ExecutionEngine *engine, const ValueRef val) - : Object(engine->booleanClass) { - value = val; - } -protected: - BooleanObject(InternalClass *ic) - : Object(ic) { - Q_ASSERT(internalClass->vtable == staticVTable()); - value = Encode(false); - } + + Value value() const { return d()->value; } + }; struct NumberObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, const ValueRef val) + : Object::Data(engine->numberClass) { + value = val; + } + Data(InternalClass *ic) + : Object::Data(ic) { + Q_ASSERT(internalClass->vtable == staticVTable()); + value = Encode((int)0); + } + Value value; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(NumberObject) - Value value; - NumberObject(ExecutionEngine *engine, const ValueRef val) - : Object(engine->numberClass) { - value = val; - } -protected: - NumberObject(InternalClass *ic) - : Object(ic) { - Q_ASSERT(internalClass->vtable == staticVTable()); - value = Encode((int)0); - } + + Value value() const { return d()->value; } + }; struct ArrayObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine) : Object::Data(engine->arrayClass) { init(); } + Data(ExecutionEngine *engine, const QStringList &list); + Data(InternalClass *ic) : Object::Data(ic) { init(); } + void init() + { memberData[LengthPropertyIndex] = Primitive::fromInt32(0); } + }; + + V4_OBJECT(Object) Q_MANAGED_TYPE(ArrayObject) enum { LengthPropertyIndex = 0 }; - ArrayObject(ExecutionEngine *engine) : Object(engine->arrayClass) { init(engine); } - ArrayObject(ExecutionEngine *engine, const QStringList &list); - ArrayObject(InternalClass *ic) : Object(ic) { init(ic->engine); } - void init(ExecutionEngine *engine); static ReturnedValue getLookup(Managed *m, Lookup *l); @@ -353,7 +383,7 @@ struct ArrayObject: Object { inline void Object::setArrayLengthUnchecked(uint l) { if (isArrayObject()) - memberData[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l); + memberData()[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l); } inline void Object::push_back(const ValueRef v) @@ -371,12 +401,12 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a // ### Clean up arrayCreate(); if (attributes.isAccessor()) { - hasAccessorProperty = 1; + setHasAccessorProperty(); initSparseArray(); - } else if (index > 0x1000 && index > 2*arrayData->alloc) { + } else if (index > 0x1000 && index > 2*arrayData()->alloc()) { initSparseArray(); } else { - arrayData->vtable()->reallocate(this, index + 1, false); + arrayData()->vtable()->reallocate(this, index + 1, false); } setArrayAttributes(index, attributes); Property *pd = ArrayData::insert(this, index, attributes.isAccessor()); @@ -391,7 +421,7 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a inline void Object::arraySet(uint index, ValueRef value) { arrayCreate(); - if (index > 0x1000 && index > 2*arrayData->alloc) { + if (index > 0x1000 && index > 2*arrayData()->alloc()) { initSparseArray(); } Property *pd = ArrayData::insert(this, index); @@ -418,23 +448,6 @@ inline ReturnedValue value_convert<Object>(ExecutionEngine *e, const Value &v) } #endif -struct ObjectRef : public ManagedRef -{ - DEFINE_REF_METHODS(Object, Managed) - - static ObjectRef fromValuePointer(Value *s) { - ObjectRef r; - r.ptr = s; - if (sizeof(void *) == 8) - r.ptr->val = 0; - else - *r.ptr = Value::fromManaged(0); - return r; - } -}; - -DEFINE_REF(ArrayObject, Object); - } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index e5f693c323..216700fe69 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -46,63 +46,71 @@ using namespace QV4; -ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags) - : object(ObjectRef::fromValuePointer(scratch1)) - , current(ObjectRef::fromValuePointer(scratch2)) +ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags) + : object(scratch1) + , current(scratch2) , arrayNode(0) , arrayIndex(0) , memberIndex(0) , flags(flags) { - object = o.getPointer(); - current = o.getPointer(); - - if (!!object && object->asArgumentsObject()) { + object->o = o; + current->o = o; +#if QT_POINTER_SIZE == 4 + object->tag = QV4::Value::Managed_Type; + current->tag = QV4::Value::Managed_Type; +#endif + + if (object->as<ArgumentsObject>()) { Scope scope(object->engine()); Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate(); } } -ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags) - : object(ObjectRef::fromValuePointer(scope.alloc(1))) - , current(ObjectRef::fromValuePointer(scope.alloc(1))) +ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags) + : object(scope.alloc(1)) + , current(scope.alloc(1)) , arrayNode(0) , arrayIndex(0) , memberIndex(0) , flags(flags) { - object = o; - current = o; - - if (!!object && object->asArgumentsObject()) { + object->o = o; + current->o = o; +#if QT_POINTER_SIZE == 4 + object->tag = QV4::Value::Managed_Type; + current->tag = QV4::Value::Managed_Type; +#endif + + if (object->as<ArgumentsObject>()) { Scope scope(object->engine()); Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate(); } } -void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAttributes *attrs) +void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttributes *attrs) { name = (String *)0; *index = UINT_MAX; - if (!object) { + if (!object->asObject()) { *attrs = PropertyAttributes(); return; } while (1) { - if (!current) + if (!current->asObject()) break; while (1) { - current->advanceIterator(this, name, index, pd, attrs); + current->asObject()->advanceIterator(this, name, index, pd, attrs); if (attrs->isEmpty()) break; // check the property is not already defined earlier in the proto chain - if (current != object) { - Object *o = object; + if (current->asObject() != object->asObject()) { + Object *o = object->asObject(); bool shadowed = false; - while (o != current) { + while (o != current->asObject()) { if ((!!name && o->hasOwnProperty(name)) || (*index != UINT_MAX && o->hasOwnProperty(*index))) { shadowed = true; @@ -117,9 +125,9 @@ void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAtt } if (flags & WithProtoChain) - current = current->prototype(); + current->o = current->objectValue()->prototype(); else - current = (Object *)0; + current->o = (Object *)0; arrayIndex = 0; memberIndex = 0; @@ -129,7 +137,7 @@ void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAtt ReturnedValue ObjectIterator::nextPropertyName(ValueRef value) { - if (!object) + if (!object->asObject()) return Encode::null(); PropertyAttributes attrs; @@ -137,11 +145,13 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value) uint index; Scope scope(object->engine()); ScopedString name(scope); - next(name, &index, &p, &attrs); + String *n; + next(n, &index, &p, &attrs); + name = n; if (attrs.isEmpty()) return Encode::null(); - value = object->getValue(&p, attrs); + value = object->objectValue()->getValue(&p, attrs); if (!!name) return name->asReturnedValue(); @@ -151,7 +161,7 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value) ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value) { - if (!object) + if (!object->asObject()) return Encode::null(); PropertyAttributes attrs; @@ -159,11 +169,13 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value) uint index; Scope scope(object->engine()); ScopedString name(scope); - next(name, &index, &p, &attrs); + String *n; + next(n, &index, &p, &attrs); + name = n; if (attrs.isEmpty()) return Encode::null(); - value = object->getValue(&p, attrs); + value = object->objectValue()->getValue(&p, attrs); if (!!name) return name->asReturnedValue(); @@ -173,7 +185,7 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value) ReturnedValue ObjectIterator::nextPropertyNameAsString() { - if (!object) + if (!object->asObject()) return Encode::null(); PropertyAttributes attrs; @@ -181,7 +193,9 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString() uint index; Scope scope(object->engine()); ScopedString name(scope); - next(name, &index, &p, &attrs); + String *n; + next(n, &index, &p, &attrs); + name = n; if (attrs.isEmpty()) return Encode::null(); @@ -197,7 +211,7 @@ DEFINE_OBJECT_VTABLE(ForEachIteratorObject); void ForEachIteratorObject::markObjects(Managed *that, ExecutionEngine *e) { ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that); - o->workArea[0].mark(e); - o->workArea[1].mark(e); + o->d()->workArea[0].mark(e); + o->d()->workArea[1].mark(e); Object::markObjects(that, e); } diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h index c87f284288..f20ad17b4a 100644 --- a/src/qml/jsruntime/qv4objectiterator_p.h +++ b/src/qml/jsruntime/qv4objectiterator_p.h @@ -67,37 +67,38 @@ struct Q_QML_EXPORT ObjectIterator WithProtoChain = 0x2, }; - ObjectRef object; - ObjectRef current; + Value *object; + Value *current; SparseArrayNode *arrayNode; uint arrayIndex; uint memberIndex; uint flags; - ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags); - ObjectIterator(Scope &scope, const ObjectRef o, uint flags); - void next(StringRef name, uint *index, Property *pd, PropertyAttributes *attributes = 0); + ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags); + ObjectIterator(Scope &scope, Object *o, uint flags); + void next(String *&name, uint *index, Property *pd, PropertyAttributes *attributes = 0); ReturnedValue nextPropertyName(ValueRef value); ReturnedValue nextPropertyNameAsString(ValueRef value); ReturnedValue nextPropertyNameAsString(); }; struct ForEachIteratorObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionContext *ctx, Object *o) + : Object::Data(ctx->engine()) + , it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) { + setVTable(staticVTable()); + } + ObjectIterator it; + Value workArea[2]; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(ForeachIteratorObject) - ObjectIterator it; - ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o) - : Object(ctx->engine), it(workArea, workArea + 1, - o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) { - setVTable(staticVTable()); - } - ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); } + ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); } protected: static void markObjects(Managed *that, ExecutionEngine *e); - - Value workArea[2]; }; diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 5c824bdfbd..6b8a19c7e6 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -74,8 +74,8 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ObjectCtor); -ObjectCtor::ObjectCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("Object")) +ObjectCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("Object")) { setVTable(staticVTable()); } @@ -102,7 +102,7 @@ ReturnedValue ObjectCtor::call(Managed *m, CallData *callData) return RuntimeHelpers::toObject(m->engine()->currentContext(), ValueRef(&callData->args[0])); } -void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor) +void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor) { Scope scope(v4); ScopedObject o(scope, this); @@ -133,10 +133,9 @@ void ObjectPrototype::init(ExecutionEngine *v4, ObjectRef ctor) defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2); defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2); - Scoped<String> id_proto(scope, v4->id___proto__); - Property p(v4->newBuiltinFunction(v4->rootContext, id_proto, method_get_proto)->getPointer(), - v4->newBuiltinFunction(v4->rootContext, id_proto, method_set_proto)->getPointer()); - insertMember(StringRef(v4->id___proto__), p, Attr_Accessor|Attr_NotEnumerable); + Property p(ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_get_proto)).getPointer(), + ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_set_proto)).getPointer()); + insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable); } ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx) @@ -165,7 +164,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx) if (scope.hasException()) return Encode::undefined(); PropertyAttributes attrs; - Property *desc = O->__getOwnProperty__(name, &attrs); + Property *desc = O->__getOwnProperty__(name.getPointer(), &attrs); return fromPropertyDescriptor(ctx, desc, attrs); } @@ -176,7 +175,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context) if (!O) return context->throwTypeError(); - ScopedArrayObject array(scope, getOwnPropertyNames(context->engine, context->callData->args[0])); + ScopedArrayObject array(scope, getOwnPropertyNames(context->d()->engine, context->d()->callData->args[0])); return array.asReturnedValue(); } @@ -187,11 +186,11 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx) if (!O->isObject() && !O->isNull()) return ctx->throwTypeError(); - Scoped<Object> newObject(scope, ctx->engine->newObject()); + Scoped<Object> newObject(scope, ctx->d()->engine->newObject()); newObject->setPrototype(O->asObject()); - if (ctx->callData->argc > 1 && !ctx->callData->args[1].isUndefined()) { - ctx->callData->args[0] = newObject.asReturnedValue(); + if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isUndefined()) { + ctx->d()->callData->args[0] = newObject.asReturnedValue(); return method_defineProperties(ctx); } @@ -216,7 +215,7 @@ ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx) if (scope.engine->hasException) return Encode::undefined(); - if (!O->__defineOwnProperty__(ctx, name, pd, attrs)) + if (!O->__defineOwnProperty__(ctx, name.getPointer(), pd, attrs)) return ctx->throwTypeError(); return O.asReturnedValue(); @@ -240,7 +239,9 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx) uint index; PropertyAttributes attrs; Property pd; - it.next(name, &index, &pd, &attrs); + String *nm; + it.next(nm, &index, &pd, &attrs); + name = nm; if (attrs.isEmpty()) break; Property n; @@ -251,7 +252,7 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx) return Encode::undefined(); bool ok; if (name) - ok = O->__defineOwnProperty__(ctx, name, n, nattrs); + ok = O->__defineOwnProperty__(ctx, name.getPointer(), n, nattrs); else ok = O->__defineOwnProperty__(ctx, index, n, nattrs); if (!ok) @@ -268,15 +269,15 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx) if (!o) return ctx->throwTypeError(); - o->extensible = false; + o->setExtensible(false); - o->internalClass = o->internalClass->sealed(); + o->setInternalClass(o->internalClass()->sealed()); - if (o->arrayData) { + if (o->arrayData()) { ArrayData::ensureAttributes(o.getPointer()); - for (uint i = 0; i < o->arrayData->alloc; ++i) { - if (!o->arrayData->isEmpty(i)) - o->arrayData->attrs[i].setConfigurable(false); + for (uint i = 0; i < o->arrayData()->alloc(); ++i) { + if (!o->arrayData()->isEmpty(i)) + o->arrayData()->attrs()[i].setConfigurable(false); } } @@ -293,17 +294,17 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx) if (ArgumentsObject::isNonStrictArgumentsObject(o.getPointer())) Scoped<ArgumentsObject>(scope, o)->fullyCreate(); - o->extensible = false; + o->setExtensible(false); - o->internalClass = o->internalClass->frozen(); + o->setInternalClass(o->internalClass()->frozen()); - if (o->arrayData) { + if (o->arrayData()) { ArrayData::ensureAttributes(o.getPointer()); - for (uint i = 0; i < o->arrayData->alloc; ++i) { - if (!o->arrayData->isEmpty(i)) - o->arrayData->attrs[i].setConfigurable(false); - if (o->arrayData->attrs[i].isData()) - o->arrayData->attrs[i].setWritable(false); + for (uint i = 0; i < o->arrayData()->alloc(); ++i) { + if (!o->arrayData()->isEmpty(i)) + o->arrayData()->attrs()[i].setConfigurable(false); + if (o->arrayData()->attrs()[i].isData()) + o->arrayData()->attrs()[i].setWritable(false); } } return o.asReturnedValue(); @@ -316,7 +317,7 @@ ReturnedValue ObjectPrototype::method_preventExtensions(CallContext *ctx) if (!o) return ctx->throwTypeError(); - o->extensible = false; + o->setExtensible(false); return o.asReturnedValue(); } @@ -327,22 +328,22 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx) if (!o) return ctx->throwTypeError(); - if (o->extensible) + if (o->isExtensible()) return Encode(false); - if (o->internalClass != o->internalClass->sealed()) + if (o->internalClass() != o->internalClass()->sealed()) return Encode(false); - if (!o->arrayData || !o->arrayData->length()) + if (!o->arrayData() || !o->arrayData()->length()) return Encode(true); - if (o->arrayData->length() && !o->arrayData->attrs) + if (o->arrayData()->length() && !o->arrayData()->attrs()) return Encode(false); - for (uint i = 0; i < o->arrayData->alloc; ++i) { + for (uint i = 0; i < o->arrayData()->alloc(); ++i) { // ### Fix for sparse arrays - if (!o->arrayData->isEmpty(i)) - if (o->arrayData->attributes(i).isConfigurable()) + if (!o->arrayData()->isEmpty(i)) + if (o->arrayData()->attributes(i).isConfigurable()) return Encode(false); } @@ -356,22 +357,22 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx) if (!o) return ctx->throwTypeError(); - if (o->extensible) + if (o->isExtensible()) return Encode(false); - if (o->internalClass != o->internalClass->frozen()) + if (o->internalClass() != o->internalClass()->frozen()) return Encode(false); - if (!o->arrayData->length()) + if (!o->arrayData()->length()) return Encode(true); - if (o->arrayData->length() && !o->arrayData->attrs) + if (o->arrayData()->length() && !o->arrayData()->attrs()) return Encode(false); - for (uint i = 0; i < o->arrayData->alloc; ++i) { + for (uint i = 0; i < o->arrayData()->alloc(); ++i) { // ### Fix for sparse arrays - if (!o->arrayData->isEmpty(i)) - if (o->arrayData->attributes(i).isConfigurable() || o->arrayData->attributes(i).isWritable()) + if (!o->arrayData()->isEmpty(i)) + if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) return Encode(false); } @@ -385,7 +386,7 @@ ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx) if (!o) return ctx->throwTypeError(); - return Encode((bool)o->extensible); + return Encode((bool)o->isExtensible()); } ReturnedValue ObjectPrototype::method_keys(CallContext *ctx) @@ -395,7 +396,7 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx) if (!o) return ctx->throwTypeError(); - Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject()); ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); ScopedValue name(scope); @@ -412,24 +413,24 @@ ReturnedValue ObjectPrototype::method_keys(CallContext *ctx) ReturnedValue ObjectPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - if (ctx->callData->thisObject.isUndefined()) { - return ctx->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue(); - } else if (ctx->callData->thisObject.isNull()) { - return ctx->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue(); + if (ctx->d()->callData->thisObject.isUndefined()) { + return ctx->d()->engine->newString(QStringLiteral("[object Undefined]"))->asReturnedValue(); + } else if (ctx->d()->callData->thisObject.isNull()) { + return ctx->d()->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue(); } else { - ScopedObject obj(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->callData->thisObject))); + ScopedObject obj(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject))); QString className = obj->className(); - return ctx->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue(); + return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue(); } } ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx) { Scope scope(ctx); - ScopedObject o(scope, ctx->callData->thisObject.toObject(ctx)); + ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx)); if (!o) return Encode::undefined(); - Scoped<FunctionObject> f(scope, o->get(ctx->engine->id_toString)); + Scoped<FunctionObject> f(scope, o->get(ctx->d()->engine->id_toString)); if (!f) return ctx->throwTypeError(); ScopedCallData callData(scope, 0); @@ -440,8 +441,8 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx) ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx) { Scope scope(ctx); - ScopedValue v(scope, ctx->callData->thisObject.toObject(ctx)); - if (ctx->engine->hasException) + ScopedValue v(scope, ctx->d()->callData->thisObject.toObject(ctx)); + if (ctx->d()->engine->hasException) return Encode::undefined(); return v.asReturnedValue(); } @@ -452,12 +453,12 @@ ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx) Scoped<String> P(scope, ctx->argument(0), Scoped<String>::Convert); if (scope.engine->hasException) return Encode::undefined(); - Scoped<Object> O(scope, ctx->callData->thisObject, Scoped<Object>::Convert); + Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert); if (scope.engine->hasException) return Encode::undefined(); - bool r = O->hasOwnProperty(P); + bool r = O->hasOwnProperty(P.getPointer()); if (!r) - r = !O->query(P).isEmpty(); + r = !O->query(P.getPointer()).isEmpty(); return Encode(r); } @@ -468,7 +469,7 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx) if (!V) return Encode(false); - Scoped<Object> O(scope, ctx->callData->thisObject, Scoped<Object>::Convert); + Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert); if (scope.engine->hasException) return Encode::undefined(); Scoped<Object> proto(scope, V->prototype()); @@ -487,17 +488,17 @@ ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx) if (scope.engine->hasException) return Encode::undefined(); - Scoped<Object> o(scope, ctx->callData->thisObject, Scoped<Object>::Convert); + Scoped<Object> o(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert); if (scope.engine->hasException) return Encode::undefined(); PropertyAttributes attrs; - o->__getOwnProperty__(p, &attrs); + o->__getOwnProperty__(p.getPointer(), &attrs); return Encode(attrs.isEnumerable()); } ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx) { - if (ctx->callData->argc < 2) + if (ctx->d()->callData->argc < 2) return ctx->throwTypeError(); Scope scope(ctx); @@ -509,23 +510,23 @@ ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx) if (scope.engine->hasException) return Encode::undefined(); - Scoped<Object> o(scope, ctx->callData->thisObject); + Scoped<Object> o(scope, ctx->d()->callData->thisObject); if (!o) { - if (!ctx->callData->thisObject.isUndefined()) + if (!ctx->d()->callData->thisObject.isUndefined()) return Encode::undefined(); - o = ctx->engine->globalObject; + o = ctx->d()->engine->globalObject; } Property pd; pd.value = f; pd.set = Primitive::emptyValue(); - o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor); + o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor); return Encode::undefined(); } ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) { - if (ctx->callData->argc < 2) + if (ctx->d()->callData->argc < 2) return ctx->throwTypeError(); Scope scope(ctx); @@ -537,24 +538,24 @@ ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx) if (scope.engine->hasException) return Encode::undefined(); - Scoped<Object> o(scope, ctx->callData->thisObject); + Scoped<Object> o(scope, ctx->d()->callData->thisObject); if (!o) { - if (!ctx->callData->thisObject.isUndefined()) + if (!ctx->d()->callData->thisObject.isUndefined()) return Encode::undefined(); - o = ctx->engine->globalObject; + o = ctx->d()->engine->globalObject; } Property pd; pd.value = Primitive::emptyValue(); pd.set = f; - o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor); + o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor); return Encode::undefined(); } ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx) { Scope scope(ctx); - ScopedObject o(scope, ctx->callData->thisObject.asObject()); + ScopedObject o(scope, ctx->d()->callData->thisObject.asObject()); if (!o) return ctx->throwTypeError(); @@ -564,21 +565,21 @@ ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx) ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx) { Scope scope(ctx); - Scoped<Object> o(scope, ctx->callData->thisObject); - if (!o || !ctx->callData->argc) + Scoped<Object> o(scope, ctx->d()->callData->thisObject); + if (!o || !ctx->d()->callData->argc) return ctx->throwTypeError(); - if (ctx->callData->args[0].isNull()) { + if (ctx->d()->callData->args[0].isNull()) { o->setPrototype(0); return Encode::undefined(); } - Scoped<Object> p(scope, ctx->callData->args[0]); + Scoped<Object> p(scope, ctx->d()->callData->args[0]); bool ok = false; if (!!p) { if (o->prototype() == p.getPointer()) { ok = true; - } else if (o->extensible) { + } else if (o->isExtensible()) { ok = o->setPrototype(p.getPointer()); } } @@ -601,14 +602,14 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef desc->set = Primitive::emptyValue(); ScopedValue tmp(scope); - if (o->hasProperty(ctx->engine->id_enumerable)) - attrs->setEnumerable((tmp = o->get(ctx->engine->id_enumerable))->toBoolean()); + if (o->hasProperty(ctx->d()->engine->id_enumerable)) + attrs->setEnumerable((tmp = o->get(ctx->d()->engine->id_enumerable))->toBoolean()); - if (o->hasProperty(ctx->engine->id_configurable)) - attrs->setConfigurable((tmp = o->get(ctx->engine->id_configurable))->toBoolean()); + if (o->hasProperty(ctx->d()->engine->id_configurable)) + attrs->setConfigurable((tmp = o->get(ctx->d()->engine->id_configurable))->toBoolean()); - if (o->hasProperty(ctx->engine->id_get)) { - ScopedValue get(scope, o->get(ctx->engine->id_get)); + if (o->hasProperty(ctx->d()->engine->id_get)) { + ScopedValue get(scope, o->get(ctx->d()->engine->id_get)); FunctionObject *f = get->asFunctionObject(); if (f || get->isUndefined()) { desc->value = get; @@ -619,8 +620,8 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef attrs->setType(PropertyAttributes::Accessor); } - if (o->hasProperty(ctx->engine->id_set)) { - ScopedValue set(scope, o->get(ctx->engine->id_set)); + if (o->hasProperty(ctx->d()->engine->id_set)) { + ScopedValue set(scope, o->get(ctx->d()->engine->id_set)); FunctionObject *f = set->asFunctionObject(); if (f || set->isUndefined()) { desc->set = set; @@ -631,22 +632,22 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef attrs->setType(PropertyAttributes::Accessor); } - if (o->hasProperty(ctx->engine->id_writable)) { + if (o->hasProperty(ctx->d()->engine->id_writable)) { if (attrs->isAccessor()) { ctx->throwTypeError(); return; } - attrs->setWritable((tmp = o->get(ctx->engine->id_writable))->toBoolean()); + attrs->setWritable((tmp = o->get(ctx->d()->engine->id_writable))->toBoolean()); // writable forces it to be a data descriptor desc->value = Primitive::undefinedValue(); } - if (o->hasProperty(ctx->engine->id_value)) { + if (o->hasProperty(ctx->d()->engine->id_value)) { if (attrs->isAccessor()) { ctx->throwTypeError(); return; } - desc->value = o->get(ctx->engine->id_value); + desc->value = o->get(ctx->d()->engine->id_value); attrs->setType(PropertyAttributes::Data); } @@ -660,7 +661,7 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con if (!desc) return Encode::undefined(); - ExecutionEngine *engine = ctx->engine; + ExecutionEngine *engine = ctx->d()->engine; Scope scope(engine); // Let obj be the result of creating a new object as if by the expression new Object() where Object // is the standard built-in constructor with that name. @@ -671,24 +672,24 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con if (attrs.isData()) { pd.value = desc->value; s = engine->newString(QStringLiteral("value")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); pd.value = Primitive::fromBoolean(attrs.isWritable()); s = engine->newString(QStringLiteral("writable")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); } else { pd.value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined(); s = engine->newString(QStringLiteral("get")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); pd.value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined(); s = engine->newString(QStringLiteral("set")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); } pd.value = Primitive::fromBoolean(attrs.isEnumerable()); s = engine->newString(QStringLiteral("enumerable")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); pd.value = Primitive::fromBoolean(attrs.isConfigurable()); s = engine->newString(QStringLiteral("configurable")); - o->__defineOwnProperty__(ctx, s, pd, Attr_Data); + o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data); return o.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index 2b9974be06..c34b367223 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -51,8 +51,10 @@ namespace QV4 { struct ObjectCtor: FunctionObject { - V4_OBJECT - ObjectCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *that, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -60,9 +62,7 @@ struct ObjectCtor: FunctionObject struct ObjectPrototype: Object { - ObjectPrototype(InternalClass *ic) : Object(ic) {} - - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_getPrototypeOf(CallContext *ctx); static ReturnedValue method_getOwnPropertyDescriptor(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 21f37f3d96..7b0f80e06a 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -84,13 +84,11 @@ public: PersistentValue(ReturnedValue val); template<typename T> PersistentValue(Returned<T> *obj); - PersistentValue(const ManagedRef obj); PersistentValue &operator=(const ValueRef other); PersistentValue &operator=(const ScopedValue &other); PersistentValue &operator =(ReturnedValue other); template<typename T> PersistentValue &operator=(Returned<T> *obj); - PersistentValue &operator=(const ManagedRef obj); ~PersistentValue(); ReturnedValue value() const { diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp index 8a0cc56448..b70e9de1a0 100644 --- a/src/qml/jsruntime/qv4profiling.cpp +++ b/src/qml/jsruntime/qv4profiling.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qv4profiling_p.h" +#include "qv4mm_p.h" QT_BEGIN_NAMESPACE @@ -60,10 +61,12 @@ FunctionCallProperties FunctionCall::resolve() const } -Profiler::Profiler() : enabled(false) +Profiler::Profiler(QV4::ExecutionEngine *engine) : enabled(false), m_engine(engine) { static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >(); + static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >(); Q_UNUSED(metatype); + Q_UNUSED(metatype2); m_timer.start(); } @@ -87,13 +90,29 @@ void Profiler::reportData() FunctionCallProperties props = call.resolve(); resolved.insert(std::upper_bound(resolved.begin(), resolved.end(), props, comp), props); } - emit dataReady(resolved); + emit dataReady(resolved, m_memory_data); } void Profiler::startProfiling() { if (!enabled) { m_data.clear(); + m_memory_data.clear(); + + qint64 timestamp = m_timer.nsecsElapsed(); + MemoryAllocationProperties heap = {timestamp, + (qint64)m_engine->memoryManager->getAllocatedMem(), + HeapPage}; + m_memory_data.append(heap); + MemoryAllocationProperties small = {timestamp, + (qint64)m_engine->memoryManager->getUsedMem(), + SmallItem}; + m_memory_data.append(small); + MemoryAllocationProperties large = {timestamp, + (qint64)m_engine->memoryManager->getLargeItemsMem(), + LargeItem}; + m_memory_data.append(large); + enabled = true; } } diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 6869b3134d..b9ddac0309 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -54,6 +54,12 @@ namespace QV4 { namespace Profiling { +enum MemoryType { + HeapPage, + LargeItem, + SmallItem +}; + struct FunctionCallProperties { qint64 start; qint64 end; @@ -63,6 +69,12 @@ struct FunctionCallProperties { int column; }; +struct MemoryAllocationProperties { + qint64 timestamp; + qint64 size; + MemoryType type; +}; + class FunctionCall { public: @@ -101,6 +113,14 @@ private: qint64 m_end; }; +#define Q_V4_PROFILE_ALLOC(engine, size, type)\ + (engine->profiler && engine->profiler->enabled ?\ + engine->profiler->trackAlloc(size, type) : size) + +#define Q_V4_PROFILE_DEALLOC(engine, pointer, size, type) \ + (engine->profiler && engine->profiler->enabled ?\ + engine->profiler->trackDealloc(pointer, size, type) : pointer) + #define Q_V4_PROFILE(engine, ctx, function)\ ((engine->profiler && engine->profiler->enabled) ?\ Profiling::FunctionCallProfiler::profileCall(engine->profiler, ctx, function) :\ @@ -110,7 +130,21 @@ class Q_QML_EXPORT Profiler : public QObject { Q_OBJECT Q_DISABLE_COPY(Profiler) public: - Profiler(); + Profiler(QV4::ExecutionEngine *engine); + + size_t trackAlloc(size_t size, MemoryType type) + { + MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type}; + m_memory_data.append(allocation); + return size; + } + + void *trackDealloc(void *pointer, size_t size, MemoryType type) + { + MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type}; + m_memory_data.append(allocation); + return pointer; + } bool enabled; @@ -121,11 +155,14 @@ public slots: void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: - void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &); + void dataReady(const QList<QV4::Profiling::FunctionCallProperties> &, + const QList<QV4::Profiling::MemoryAllocationProperties> &); private: + QV4::ExecutionEngine *m_engine; QElapsedTimer m_timer; QVector<FunctionCall> m_data; + QList<MemoryAllocationProperties> m_memory_data; friend class FunctionCallProfiler; }; @@ -160,10 +197,12 @@ public: } // namespace Profiling } // namespace QV4 +Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE); QT_END_NAMESPACE Q_DECLARE_METATYPE(QList<QV4::Profiling::FunctionCallProperties>) +Q_DECLARE_METATYPE(QList<QV4::Profiling::MemoryAllocationProperties>) #endif // QV4PROFILING_H diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index d64f821a38..e12b8f1756 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE using namespace QV4; -static QPair<QObject *, int> extractQtMethod(QV4::FunctionObjectRef function) +static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function) { QV4::ExecutionEngine *v4 = function->engine(); if (v4) { @@ -239,14 +239,11 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object, } } -QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object) - : Object(engine) - , m_object(object) +QObjectWrapper::Data::Data(ExecutionEngine *engine, QObject *object) + : Object::Data(engine) + , object(object) { setVTable(staticVTable()); - - Scope scope(engine); - ScopedObject protectThis(scope, this); } void QObjectWrapper::initializeBindings(ExecutionEngine *engine) @@ -259,21 +256,21 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont { Q_UNUSED(revisionMode); - QQmlData *ddata = QQmlData::get(m_object, false); + QQmlData *ddata = QQmlData::get(d()->object, false); if (!ddata) return 0; QQmlPropertyData *result = 0; if (ddata && ddata->propertyCache) - result = ddata->propertyCache->property(name, m_object, qmlContext); + result = ddata->propertyCache->property(name, d()->object, qmlContext); else - result = QQmlPropertyCache::property(engine->v8Engine->engine(), m_object, name, qmlContext, *local); + result = QQmlPropertyCache::property(engine->v8Engine->engine(), d()->object, name, qmlContext, *local); return result; } ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, bool includeImports) { - if (QQmlData::wasDeleted(m_object)) { + if (QQmlData::wasDeleted(d()->object)) { if (hasProperty) *hasProperty = false; return QV4::Encode::undefined(); @@ -284,14 +281,14 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD if (name->equals(scope.engine->id_destroy) || name->equals(scope.engine->id_toString)) { int index = name->equals(scope.engine->id_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod; - QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, index)); + QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->d()->engine->rootContext, d()->object, index)); if (hasProperty) *hasProperty = true; return method.asReturnedValue(); } QQmlPropertyData local; - QQmlPropertyData *result = findProperty(ctx->engine, qmlContext, name.getPointer(), revisionMode, &local); + QQmlPropertyData *result = findProperty(ctx->d()->engine, qmlContext, name.getPointer(), revisionMode, &local); if (!result) { if (includeImports && name->startsWithUpper()) { @@ -306,18 +303,18 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD if (r.scriptIndex != -1) { return QV4::Encode::undefined(); } else if (r.type) { - return QmlTypeWrapper::create(ctx->engine->v8Engine, m_object, r.type, QmlTypeWrapper::ExcludeEnums); + return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, r.type, QmlTypeWrapper::ExcludeEnums); } else if (r.importNamespace) { - return QmlTypeWrapper::create(ctx->engine->v8Engine, m_object, qmlContext->imports, r.importNamespace, QmlTypeWrapper::ExcludeEnums); + return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, qmlContext->imports, r.importNamespace, QmlTypeWrapper::ExcludeEnums); } Q_ASSERT(!"Unreachable"); } } } - return QV4::Object::get(this, name, hasProperty); + return QV4::Object::get(this, name.getPointer(), hasProperty); } - QQmlData *ddata = QQmlData::get(m_object, false); + QQmlData *ddata = QQmlData::get(d()->object, false); if (revisionMode == QV4::QObjectWrapper::CheckRevision && result->hasRevision()) { if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) { @@ -330,7 +327,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD if (hasProperty) *hasProperty = true; - return getProperty(m_object, ctx, result); + return getProperty(d()->object, ctx, result); } ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired) @@ -345,23 +342,23 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx Q_ASSERT(vmemo); return vmemo->vmeMethod(property->coreIndex); } else if (property->isV4Function()) { - QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->engine->qmlContextObject()); - return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex, qmlcontextobject); + QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->d()->engine->qmlContextObject()); + return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex, qmlcontextobject); } else if (property->isSignalHandler()) { - QV4::Scoped<QV4::QmlSignalHandler> handler(scope, new (ctx->engine->memoryManager) QV4::QmlSignalHandler(ctx->engine, object, property->coreIndex)); + QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex)); - QV4::ScopedString connect(scope, ctx->engine->newIdentifier(QStringLiteral("connect"))); - QV4::ScopedString disconnect(scope, ctx->engine->newIdentifier(QStringLiteral("disconnect"))); - handler->put(connect, QV4::ScopedValue(scope, ctx->engine->functionClass->prototype->get(connect))); - handler->put(disconnect, QV4::ScopedValue(scope, ctx->engine->functionClass->prototype->get(disconnect))); + QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect"))); + QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect"))); + handler->put(connect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(connect.getPointer()))); + handler->put(disconnect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(disconnect.getPointer()))); return handler.asReturnedValue(); } else { - return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex); + return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex); } } - QQmlEnginePrivate *ep = ctx->engine->v8Engine->engine() ? QQmlEnginePrivate::get(ctx->engine->v8Engine->engine()) : 0; + QQmlEnginePrivate *ep = ctx->d()->engine->v8Engine->engine() ? QQmlEnginePrivate::get(ctx->d()->engine->v8Engine->engine()) : 0; if (property->hasAccessors()) { QQmlNotifier *n = 0; @@ -370,7 +367,7 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx if (ep && ep->propertyCapture && property->accessors->notifier) nptr = &n; - QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, object, *property, nptr)); + QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine->v8Engine, object, *property, nptr)); if (captureRequired) { if (property->accessors->notifier) { @@ -392,9 +389,9 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx Q_ASSERT(vmemo); return vmemo->vmeProperty(property->coreIndex); } else if (property->isDirect()) { - return LoadProperty<ReadAccessor::Direct>(ctx->engine->v8Engine, object, *property, 0); + return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine->v8Engine, object, *property, 0); } else { - return LoadProperty<ReadAccessor::Indirect>(ctx->engine->v8Engine, object, *property, 0); + return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine->v8Engine, object, *property, 0); } } @@ -413,7 +410,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD return QV4::Encode::null(); } - QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->engine, object)); + QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->d()->engine, object)); if (!wrapper) { if (hasProperty) *hasProperty = false; @@ -431,7 +428,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC QQmlPropertyData local; QQmlPropertyData *result = 0; { - result = QQmlPropertyCache::property(ctx->engine->v8Engine->engine(), object, name, qmlContext, local); + result = QQmlPropertyCache::property(ctx->d()->engine->v8Engine->engine(), object, name, qmlContext, local); } if (!result) @@ -460,7 +457,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro QV4::Scope scope(ctx); QV4::ScopedFunctionObject f(scope, value); if (f) { - if (!f->bindingKeyFlag) { + if (!f->bindingKeyFlag()) { if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) { // assigning a JS function to a non var or QJSValue property or is not allowed. QString error = QLatin1String("Cannot assign JavaScript function to "); @@ -473,7 +470,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro } } else { // binding assignment. - QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine); + QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine); QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f); bindingFunction->initBindingLocation(); @@ -513,7 +510,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro } else if (value->isUndefined() && property->propType == QMetaType::QJsonValue) { PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined)); } else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) { - PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->engine, value)); + PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->d()->engine, value)); } else if (value->isUndefined()) { QString error = QLatin1String("Cannot assign [undefined] to "); if (!QMetaType::typeName(property->propType)) @@ -541,11 +538,11 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro } else { QVariant v; if (property->isQList()) - v = ctx->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >()); + v = ctx->d()->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >()); else - v = ctx->engine->v8Engine->toVariant(value, property->propType); + v = ctx->d()->engine->v8Engine->toVariant(value, property->propType); - QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine); + QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine); if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) { const char *valueType = 0; if (v.userType() == QVariant::Invalid) valueType = "null"; @@ -634,9 +631,9 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value) { - if (QQmlData::wasDeleted(m_object)) + if (QQmlData::wasDeleted(d()->object)) return; - QQmlData *ddata = QQmlData::get(m_object, /*create*/false); + QQmlData *ddata = QQmlData::get(d()->object, /*create*/false); if (!ddata) return; @@ -644,7 +641,7 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const Q_ASSERT(cache); QQmlPropertyData *property = cache->property(propertyIndex); Q_ASSERT(property); // We resolved this property earlier, so it better exist! - return setProperty(m_object, ctx, property, value); + return setProperty(d()->object, ctx, property, value); } bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) @@ -661,28 +658,28 @@ ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) QQmlEngine *qmlEngine = engine->v8Engine->engine(); if (qmlEngine) QQmlData::ensurePropertyCache(qmlEngine, object); - return (new (engine->memoryManager) QV4::QObjectWrapper(engine, object))->asReturnedValue(); + return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue(); } -QV4::ReturnedValue QObjectWrapper::get(Managed *m, const StringRef name, bool *hasProperty) +QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty) { QObjectWrapper *that = static_cast<QObjectWrapper*>(m); ExecutionEngine *v4 = m->engine(); QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4); - return that->getQmlProperty(v4->currentContext(), qmlContext, name.getPointer(), IgnoreRevision, hasProperty, /*includeImports*/ true); + return that->getQmlProperty(v4->currentContext(), qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true); } -void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value) +void QObjectWrapper::put(Managed *m, String *name, const ValueRef value) { QObjectWrapper *that = static_cast<QObjectWrapper*>(m); ExecutionEngine *v4 = m->engine(); - if (v4->hasException || QQmlData::wasDeleted(that->m_object)) + if (v4->hasException || QQmlData::wasDeleted(that->d()->object)) return; QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4); - if (!setQmlProperty(v4->currentContext(), qmlContext, that->m_object, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value)) { - QQmlData *ddata = QQmlData::get(that->m_object); + if (!setQmlProperty(v4->currentContext(), qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) { + QQmlData *ddata = QQmlData::get(that->d()->object); // Types created by QML are not extensible at run-time, but for other QObjects we can store them // as regular JavaScript properties, like on JavaScript objects. if (ddata && ddata->context) { @@ -695,7 +692,7 @@ void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value) } } -PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name) +PropertyAttributes QObjectWrapper::query(const Managed *m, String *name) { const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m); ExecutionEngine *engine = that->engine(); @@ -708,27 +705,36 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name) return QV4::Object::query(m, name); } -void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes) +void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes) { + // Used to block access to QObject::destroyed() and QObject::deleteLater() from QML + static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); + static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()"); + static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()"); + name = (String *)0; *index = UINT_MAX; QObjectWrapper *that = static_cast<QObjectWrapper*>(m); - if (that->m_object) { - const QMetaObject *mo = that->m_object->metaObject(); + if (that->d()->object) { + const QMetaObject *mo = that->d()->object->metaObject(); const int propertyCount = mo->propertyCount(); if (it->arrayIndex < static_cast<uint>(propertyCount)) { - name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())); + name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()))->getPointer(); ++it->arrayIndex; *attributes = QV4::Attr_Data; p->value = that->get(name); return; } const int methodCount = mo->methodCount(); - if (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) { - name = that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name())); + while (it->arrayIndex < static_cast<uint>(propertyCount + methodCount)) { + const int index = it->arrayIndex - propertyCount; + const QMetaMethod method = mo->method(index); ++it->arrayIndex; + if (method.access() == QMetaMethod::Private || index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2) + continue; + name = that->engine()->newString(QString::fromUtf8(method.name()))->getPointer(); *attributes = QV4::Attr_Data; p->value = that->get(name); return; @@ -857,10 +863,10 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase ReturnedValue QObjectWrapper::method_connect(CallContext *ctx) { - if (ctx->callData->argc == 0) + if (ctx->d()->callData->argc == 0) V4THROW_ERROR("Function.prototype.connect: no arguments given"); - QPair<QObject *, int> signalInfo = extractQtSignal(ctx->callData->thisObject); + QPair<QObject *, int> signalInfo = extractQtSignal(ctx->d()->callData->thisObject); QObject *signalObject = signalInfo.first; int signalIndex = signalInfo.second; // in method range, not signal range! @@ -877,11 +883,11 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx) QV4::ScopedFunctionObject f(scope); QV4::ScopedValue thisObject (scope, QV4::Encode::undefined()); - if (ctx->callData->argc == 1) { - f = ctx->callData->args[0]; - } else if (ctx->callData->argc >= 2) { - thisObject = ctx->callData->args[0]; - f = ctx->callData->args[1]; + if (ctx->d()->callData->argc == 1) { + f = ctx->d()->callData->args[0]; + } else if (ctx->d()->callData->argc >= 2) { + thisObject = ctx->d()->callData->args[0]; + f = ctx->d()->callData->args[1]; } if (!f) @@ -908,12 +914,12 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx) ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) { - if (ctx->callData->argc == 0) + if (ctx->d()->callData->argc == 0) V4THROW_ERROR("Function.prototype.disconnect: no arguments given"); QV4::Scope scope(ctx); - QPair<QObject *, int> signalInfo = extractQtSignal(ctx->callData->thisObject); + QPair<QObject *, int> signalInfo = extractQtSignal(ctx->d()->callData->thisObject); QObject *signalObject = signalInfo.first; int signalIndex = signalInfo.second; @@ -929,11 +935,11 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) QV4::ScopedFunctionObject functionValue(scope); QV4::ScopedValue functionThisValue(scope, QV4::Encode::undefined()); - if (ctx->callData->argc == 1) { - functionValue = ctx->callData->args[0]; - } else if (ctx->callData->argc >= 2) { - functionThisValue = ctx->callData->args[0]; - functionValue = ctx->callData->args[1]; + if (ctx->d()->callData->argc == 1) { + functionValue = ctx->d()->callData->args[0]; + } else if (ctx->d()->callData->argc >= 2) { + functionThisValue = ctx->d()->callData->args[0]; + functionValue = ctx->d()->callData->args[1]; } if (!functionValue) @@ -945,7 +951,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) QPair<QObject *, int> functionData = extractQtMethod(functionValue); void *a[] = { - ctx->engine, + ctx->d()->engine, functionValue.ptr, functionThisValue.ptr, functionData.first, @@ -975,7 +981,7 @@ void QObjectWrapper::markObjects(Managed *that, QV4::ExecutionEngine *e) { QObjectWrapper *This = static_cast<QObjectWrapper*>(that); - if (QObject *o = This->m_object.data()) { + if (QObject *o = This->d()->object.data()) { QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o); if (vme) vme->mark(e); @@ -1017,9 +1023,9 @@ namespace { void QObjectWrapper::destroy(Managed *that) { QObjectWrapper *This = static_cast<QObjectWrapper*>(that); - QPointer<QObject> object = This->m_object; + QPointer<QObject> object = This->d()->object; ExecutionEngine *engine = This->engine(); - This->~QObjectWrapper(); + This->d()->~Data(); This = 0; if (!object) return; @@ -1728,7 +1734,7 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine) } else if (type == -1 || type == qMetaTypeId<QVariant>()) { QVariant value = *qvariantPtr; QV4::ScopedValue rv(scope, engine->fromVariant(value)); - QV4::QObjectWrapperRef qobjectWrapper = rv; + QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, rv); if (!!qobjectWrapper) { if (QObject *object = qobjectWrapper->object()) QQmlData::get(object, true)->setImplicitDestructible(); @@ -1741,28 +1747,28 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine) ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal) { - return (new (scope->engine->memoryManager) QObjectMethod(scope, object, index, qmlGlobal))->asReturnedValue(); + return (scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope, object, index, qmlGlobal))->asReturnedValue(); } -QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal) - : FunctionObject(scope) - , m_object(object) - , m_index(index) +QObjectMethod::Data::Data(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal) + : FunctionObject::Data(scope) + , object(object) + , index(index) + , qmlGlobal(qmlGlobal) { setVTable(staticVTable()); subtype = WrappedQtMethod; - m_qmlGlobal = qmlGlobal; } QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) { QString result; - if (m_object) { - QString objectName = m_object->objectName(); + if (d()->object) { + QString objectName = d()->object->objectName(); - result += QString::fromUtf8(m_object->metaObject()->className()); + result += QString::fromUtf8(d()->object->metaObject()->className()); result += QLatin1String("(0x"); - result += QString::number((quintptr)m_object.data(),16); + result += QString::number((quintptr)d()->object.data(),16); if (!objectName.isEmpty()) { result += QLatin1String(", \""); @@ -1775,14 +1781,14 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) result = QLatin1String("null"); } - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const ValueRef args, int argc) { - if (!m_object) + if (!d()->object) return Encode::undefined(); - if (QQmlData::keepAliveDuringGarbageCollection(m_object)) + if (QQmlData::keepAliveDuringGarbageCollection(d()->object)) return ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object")); int delay = 0; @@ -1790,9 +1796,9 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con delay = args[0].toUInt32(); if (delay > 0) - QTimer::singleShot(delay, m_object, SLOT(deleteLater())); + QTimer::singleShot(delay, d()->object, SLOT(deleteLater())); else - m_object->deleteLater(); + d()->object->deleteLater(); return Encode::undefined(); } @@ -1806,12 +1812,12 @@ ReturnedValue QObjectMethod::call(Managed *m, CallData *callData) ReturnedValue QObjectMethod::callInternal(CallData *callData) { ExecutionContext *context = engine()->currentContext(); - if (m_index == DestroyMethod) + if (d()->index == DestroyMethod) return method_destroy(context, callData->args, callData->argc); - else if (m_index == ToStringMethod) + else if (d()->index == ToStringMethod) return method_toString(context); - QObject *object = m_object.data(); + QObject *object = d()->object.data(); if (!object) return Encode::undefined(); @@ -1819,7 +1825,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) if (!ddata) return Encode::undefined(); - QV8Engine *v8Engine = context->engine->v8Engine; + QV8Engine *v8Engine = context->d()->engine->v8Engine; QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine); QV4::Scope scope(v4); @@ -1827,16 +1833,16 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(object)->declarativeData)) { if (ddata->propertyCache) { - QQmlPropertyData *d = ddata->propertyCache->method(m_index); - if (!d) + QQmlPropertyData *data = ddata->propertyCache->method(d()->index); + if (!data) return QV4::Encode::undefined(); - method = *d; + method = *data; } } if (method.coreIndex == -1) { const QMetaObject *mo = object->metaObject(); - const QMetaMethod moMethod = mo->method(m_index); + const QMetaMethod moMethod = mo->method(d()->index); method.load(moMethod); if (method.coreIndex == -1) @@ -1845,7 +1851,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) // Look for overloaded methods QByteArray methodName = moMethod.name(); const int methodOffset = mo->methodOffset(); - for (int ii = m_index - 1; ii >= methodOffset; --ii) { + for (int ii = d()->index - 1; ii >= methodOffset; --ii) { if (methodName == mo->method(ii).name()) { method.setFlags(method.getFlags() | QQmlPropertyData::IsOverload); method.overrideIndexIsProperty = 0; @@ -1858,7 +1864,7 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) if (method.isV4Function()) { QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue()); - QV4::ScopedValue qmlGlobal(scope, m_qmlGlobal.value()); + QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal.value()); QQmlV4Function func(callData, rv, qmlGlobal, QmlContextWrapper::getContext(qmlGlobal), v8Engine); @@ -1879,10 +1885,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData) DEFINE_OBJECT_VTABLE(QObjectMethod); -QmlSignalHandler::QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex) - : Object(engine) - , m_object(object) - , m_signalIndex(signalIndex) +QmlSignalHandler::Data::Data(ExecutionEngine *engine, QObject *object, int signalIndex) + : Object::Data(engine) + , object(object) + , signalIndex(signalIndex) { setVTable(staticVTable()); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 0af01c5614..a774917713 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -77,13 +77,17 @@ struct QObjectSlotDispatcher; struct Q_QML_EXPORT QObjectWrapper : public QV4::Object { - V4_OBJECT + struct Data : QV4::Object::Data { + Data(ExecutionEngine *engine, QObject *object); + QPointer<QObject> object; + }; + V4_OBJECT(QV4::Object) enum RevisionMode { IgnoreRevision, CheckRevision }; static void initializeBindings(ExecutionEngine *engine); - QObject *object() const { return m_object.data(); } + QObject *object() const { return d()->object.data(); } ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false); static ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0); @@ -106,16 +110,12 @@ private: static ReturnedValue create(ExecutionEngine *engine, QObject *object); - QObjectWrapper(ExecutionEngine *engine, QObject *object); - QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const; - QPointer<QObject> m_object; - - static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty); - static void put(Managed *m, const StringRef name, const ValueRef value); - static PropertyAttributes query(const Managed *, StringRef name); - static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attributes); + static ReturnedValue get(Managed *m, String *name, bool *hasProperty); + static void put(Managed *m, String *name, const ValueRef value); + static PropertyAttributes query(const Managed *, String *name); + static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes); static void markObjects(Managed *that, QV4::ExecutionEngine *e); static void destroy(Managed *that); @@ -125,51 +125,52 @@ private: struct QObjectMethod : public QV4::FunctionObject { - V4_OBJECT + struct Data : QV4::FunctionObject::Data { + Data(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal); + QPointer<QObject> object; + int index; + QV4::PersistentValue qmlGlobal; + }; + V4_OBJECT(QV4::FunctionObject) enum { DestroyMethod = -1, ToStringMethod = -2 }; static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal = Primitive::undefinedValue()); - int methodIndex() const { return m_index; } - QObject *object() const { return m_object.data(); } - -private: - QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal); + int methodIndex() const { return d()->index; } + QObject *object() const { return d()->object.data(); } QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx); QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const ValueRef args, int argc); - QPointer<QObject> m_object; - int m_index; - QV4::PersistentValue m_qmlGlobal; - static ReturnedValue call(Managed *, CallData *callData); ReturnedValue callInternal(CallData *callData); static void destroy(Managed *that) { - static_cast<QObjectMethod *>(that)->~QObjectMethod(); + static_cast<QObjectMethod *>(that)->d()->~Data(); } }; struct QmlSignalHandler : public QV4::Object { - V4_OBJECT + struct Data : QV4::Object::Data { + Data(ExecutionEngine *engine, QObject *object, int signalIndex); + QPointer<QObject> object; + int signalIndex; + }; + V4_OBJECT(QV4::Object) - QmlSignalHandler(ExecutionEngine *engine, QObject *object, int signalIndex); - int signalIndex() const { return m_signalIndex; } - QObject *object() const { return m_object.data(); } + int signalIndex() const { return d()->signalIndex; } + QObject *object() const { return d()->object.data(); } private: - QPointer<QObject> m_object; - int m_signalIndex; static void destroy(Managed *that) { - static_cast<QmlSignalHandler *>(that)->~QmlSignalHandler(); + static_cast<QmlSignalHandler *>(that)->d()->~Data(); } }; @@ -195,8 +196,6 @@ private Q_SLOTS: void removeDestroyedObject(QObject*); }; -DEFINE_REF(QObjectWrapper, Object); - } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index e5490cffd1..e2de584e31 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -42,6 +42,7 @@ #include "qv4regexp_p.h" #include "qv4engine_p.h" #include "qv4scopedvalue_p.h" +#include "qv4mm_p.h" using namespace QV4; @@ -49,7 +50,7 @@ RegExpCache::~RegExpCache() { for (RegExpCache::Iterator it = begin(), e = end(); it != e; ++it) - it.value()->m_cache = 0; + it.value()->d()->cache = 0; clear(); } @@ -63,11 +64,11 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) WTF::String s(string); #if ENABLE(YARR_JIT) - if (!m_jitCode.isFallBack() && m_jitCode.has16BitCode()) - return m_jitCode.execute(s.characters16(), start, s.length(), (int*)matchOffsets).start; + if (!jitCode().isFallBack() && jitCode().has16BitCode()) + return jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start; #endif - return JSC::Yarr::interpret(m_byteCode.get(), s.characters16(), string.length(), start, matchOffsets); + return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets); } RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) @@ -80,53 +81,49 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign return result; } - RegExp *result = new (engine->memoryManager) RegExp(engine, pattern, ignoreCase, multiline); + RegExp *result = engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline); if (!cache) cache = engine->regExpCache = new RegExpCache; - result->m_cache = cache; + result->d()->cache = cache; cache->insert(key, result); return result; } -RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) - : Managed(engine->regExpValueClass) - , m_pattern(pattern) - , m_cache(0) - , m_subPatternCount(0) - , m_ignoreCase(ignoreCase) - , m_multiLine(multiline) +RegExp::Data::Data(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) + : Managed::Data(engine->regExpValueClass) + , pattern(pattern) + , ignoreCase(ignoreCase) + , multiLine(multiline) { - if (!engine) - return; + setVTable(staticVTable()); const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) return; - m_subPatternCount = yarrPattern.m_numSubpatterns; - m_byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + subPatternCount = yarrPattern.m_numSubpatterns; + byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); #if ENABLE(YARR_JIT) if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { JSC::JSGlobalData dummy(engine->regExpAllocator); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, m_jitCode); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode); } #endif } -RegExp::~RegExp() +RegExp::Data::~Data() { - if (m_cache) { + if (cache) { RegExpCacheKey key(this); - m_cache->remove(key); + cache->remove(key); } - _data = 0; } void RegExp::destroy(Managed *that) { - static_cast<RegExp*>(that)->~RegExp(); + static_cast<RegExp*>(that)->d()->~Data(); } void RegExp::markObjects(Managed *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 1bcc2c6f5a..e1d3a9ef90 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -62,6 +62,50 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct ExecutionEngine; +struct RegExpCacheKey; + +struct RegExp : public Managed +{ + struct Data : Managed::Data { + Data(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); + ~Data(); + QString pattern; + OwnPtr<JSC::Yarr::BytecodePattern> byteCode; +#if ENABLE(YARR_JIT) + JSC::Yarr::YarrCodeBlock jitCode; +#endif + RegExpCache *cache; + int subPatternCount; + bool ignoreCase; + bool multiLine; + }; + V4_MANAGED(Managed) + Q_MANAGED_TYPE(RegExp) + + + QString pattern() const { return d()->pattern; } + OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; } +#if ENABLE(YARR_JIT) + JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; } +#endif + RegExpCache *cache() const { return d()->cache; } + int subPatternCount() const { return d()->subPatternCount; } + bool ignoreCase() const { return d()->ignoreCase; } + bool multiLine() const { return d()->multiLine; } + + static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); + + bool isValid() const { return d()->byteCode.get(); } + + uint match(const QString& string, int start, uint *matchOffsets); + + int captureCount() const { return subPatternCount() + 1; } + + static void destroy(Managed *that); + static void markObjects(Managed *that, QV4::ExecutionEngine *e); + + friend class RegExpCache; +}; struct RegExpCacheKey { @@ -70,7 +114,7 @@ struct RegExpCacheKey , ignoreCase(ignoreCase) , multiLine(multiLine) { } - explicit inline RegExpCacheKey(const RegExp *re); + explicit inline RegExpCacheKey(const RegExp::Data *re); bool operator==(const RegExpCacheKey &other) const { return pattern == other.pattern && ignoreCase == other.ignoreCase && multiLine == other.multiLine; } @@ -82,6 +126,12 @@ struct RegExpCacheKey uint multiLine : 1; }; +inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re) + : pattern(re->pattern) + , ignoreCase(re->ignoreCase) + , multiLine(re->multiLine) +{} + inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.pattern, seed); } @@ -91,49 +141,6 @@ public: ~RegExpCache(); }; -class RegExp : public Managed -{ - V4_MANAGED - Q_MANAGED_TYPE(RegExp) -public: - static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); - ~RegExp(); - - QString pattern() const { return m_pattern; } - - bool isValid() const { return m_byteCode.get(); } - - uint match(const QString& string, int start, uint *matchOffsets); - - bool ignoreCase() const { return m_ignoreCase; } - bool multiLine() const { return m_multiLine; } - int captureCount() const { return m_subPatternCount + 1; } - -protected: - static void destroy(Managed *that); - static void markObjects(Managed *that, QV4::ExecutionEngine *e); - -private: - friend class RegExpCache; - Q_DISABLE_COPY(RegExp); - RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); - - const QString m_pattern; - OwnPtr<JSC::Yarr::BytecodePattern> m_byteCode; -#if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock m_jitCode; -#endif - RegExpCache *m_cache; - int m_subPatternCount; - const bool m_ignoreCase; - const bool m_multiLine; -}; - -inline RegExpCacheKey::RegExpCacheKey(const RegExp *re) - : pattern(re->pattern()) - , ignoreCase(re->ignoreCase()) - , multiLine(re->multiLine()) -{} } diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 956d1c594e..6a592ee792 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -70,32 +70,43 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyn using namespace QV4; DEFINE_OBJECT_VTABLE(RegExpObject); +DEFINE_OBJECT_VTABLE(RegExpPrototype); -RegExpObject::RegExpObject(InternalClass *ic) - : Object(ic) - , value(RegExp::create(ic->engine, QString(), false, false)) - , global(false) +RegExpObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { - Q_ASSERT(internalClass->vtable == staticVTable()); - init(ic->engine); + setVTable(staticVTable()); + + Scope scope(ic->engine); + Scoped<RegExpObject> o(scope, this); + o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(ic->engine, QString(), false, false)); + o->d()->global = false; + o->init(ic->engine); } -RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global) - : Object(engine->regExpClass) +RegExpObject::Data::Data(ExecutionEngine *engine, RegExp *value, bool global) + : Object::Data(engine->regExpClass) , value(value) , global(global) { - init(engine); + setVTable(staticVTable()); + + Scope scope(engine); + Scoped<RegExpObject> o(scope, this); + o->init(engine); } // Converts a QRegExp to a JS RegExp. // The conversion is not 100% exact since ECMA regexp and QRegExp // have different semantics/flags, but we try to do our best. -RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) - : Object(engine->regExpClass) - , value(0) - , global(false) +RegExpObject::Data::Data(ExecutionEngine *engine, const QRegExp &re) + : Object::Data(engine->regExpClass) { + setVTable(staticVTable()); + + value = 0; + global = false; + // Convert the pattern to a ECMAScript pattern. QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); if (re.isMinimal()) { @@ -134,27 +145,25 @@ RegExpObject::RegExpObject(ExecutionEngine *engine, const QRegExp &re) } Scope scope(engine); - ScopedObject protectThis(scope, this); + Scoped<RegExpObject> o(scope, this); - value = RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false); + o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false)); - init(engine); + o->init(engine); } void RegExpObject::init(ExecutionEngine *engine) { - setVTable(staticVTable()); - Scope scope(engine); ScopedObject protectThis(scope, this); ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex"))); ScopedValue v(scope, Primitive::fromInt32(0)); - insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable); - if (!this->value) + insertMember(lastIndex.getPointer(), v, Attr_NotEnumerable|Attr_NotConfigurable); + if (!this->value()) return; - QString p = this->value->pattern(); + QString p = this->value()->pattern(); if (p.isEmpty()) { p = QStringLiteral("(?:)"); } else { @@ -163,29 +172,24 @@ void RegExpObject::init(ExecutionEngine *engine) } defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p))); - defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global)); - defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value->ignoreCase())); - defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value->multiLine())); + defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global())); + defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase())); + defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine())); } -void RegExpObject::destroy(Managed *that) -{ - static_cast<RegExpObject *>(that)->~RegExpObject(); -} - void RegExpObject::markObjects(Managed *that, ExecutionEngine *e) { RegExpObject *re = static_cast<RegExpObject*>(that); - if (re->value) - re->value->mark(e); + if (re->value()) + re->value()->mark(e); Object::markObjects(that, e); } Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx) { Q_UNUSED(ctx); - Q_ASSERT(0 == internalClass->find(ctx->engine->newIdentifier(QStringLiteral("lastIndex")))); + Q_ASSERT(0 == internalClass()->find(ctx->d()->engine->newIdentifier(QStringLiteral("lastIndex")))); return propertyAt(0); } @@ -194,19 +198,19 @@ Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx) // have different semantics/flags, but we try to do our best. QRegExp RegExpObject::toQRegExp() const { - Qt::CaseSensitivity caseSensitivity = value->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive; - return QRegExp(value->pattern(), caseSensitivity, QRegExp::RegExp2); + Qt::CaseSensitivity caseSensitivity = value()->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive; + return QRegExp(value()->pattern(), caseSensitivity, QRegExp::RegExp2); } QString RegExpObject::toString() const { QString result = QLatin1Char('/') + source(); result += QLatin1Char('/'); - if (global) + if (global()) result += QLatin1Char('g'); - if (value->ignoreCase()) + if (value()->ignoreCase()) result += QLatin1Char('i'); - if (value->multiLine()) + if (value()->multiLine()) result += QLatin1Char('m'); return result; } @@ -215,35 +219,35 @@ QString RegExpObject::source() const { Scope scope(engine()); ScopedString source(scope, scope.engine->newIdentifier(QStringLiteral("source"))); - ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source)); + ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source.getPointer())); return s->toQString(); } uint RegExpObject::flags() const { uint f = 0; - if (global) + if (global()) f |= QV4::RegExpObject::RegExp_Global; - if (value->ignoreCase()) + if (value()->ignoreCase()) f |= QV4::RegExpObject::RegExp_IgnoreCase; - if (value->multiLine()) + if (value()->multiLine()) f |= QV4::RegExpObject::RegExp_Multiline; return f; } DEFINE_OBJECT_VTABLE(RegExpCtor); -RegExpCtor::RegExpCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("RegExp")) +RegExpCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("RegExp")) { setVTable(staticVTable()); clearLastMatch(); } -void RegExpCtor::clearLastMatch() +void RegExpCtor::Data::clearLastMatch() { lastMatch = Primitive::nullValue(); - lastInput = engine()->id_empty; + lastInput = internalClass->engine->id_empty; lastMatchStart = 0; lastMatchEnd = 0; } @@ -260,8 +264,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) if (!f->isUndefined()) return ctx->throwTypeError(); - Scoped<RegExp> newRe(scope, re->value); - return Encode(ctx->engine->newRegExpObject(newRe, re->global)); + return Encode(ctx->d()->engine->newRegExpObject(re->value(), re->global())); } QString pattern; @@ -291,11 +294,11 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData) } } - Scoped<RegExp> regexp(scope, RegExp::create(ctx->engine, pattern, ignoreCase, multiLine)); + RegExp *regexp = reinterpret_cast<RegExp *>(RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine)); if (!regexp->isValid()) return ctx->throwSyntaxError(QStringLiteral("Invalid regular expression")); - return Encode(ctx->engine->newRegExpObject(regexp, global)); + return Encode(ctx->d()->engine->newRegExpObject(regexp, global)); } ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) @@ -311,15 +314,16 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData) void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e) { RegExpCtor *This = static_cast<RegExpCtor*>(that); - This->lastMatch.mark(e); - This->lastInput.mark(e); + This->lastMatch().mark(e); + This->lastInput().mark(e); FunctionObject::markObjects(that, e); } -void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor) { Scope scope(engine); ScopedObject o(scope); + ScopedObject ctor(scope, constructor); ctor->defineReadonlyProperty(engine->id_prototype, (o = this)); ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2)); @@ -355,7 +359,7 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor) ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>()); + Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>()); if (!r) return ctx->throwTypeError(); @@ -365,17 +369,17 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) return Encode::undefined(); QString s = arg->stringValue()->toQString(); - int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0; + int offset = r->global() ? r->lastIndexProperty(ctx)->value.toInt32() : 0; if (offset < 0 || offset > s.length()) { r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0); return Encode::null(); } - uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint)); - const int result = r->value->match(s, offset, matchOffsets); + uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint)); + const int result = r->value()->match(s, offset, matchOffsets); - Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); - regExpCtor->clearLastMatch(); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + regExpCtor->d()->clearLastMatch(); if (result == -1) { r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0); @@ -383,26 +387,27 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx) } // fill in result data - Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass)); - int len = r->value->captureCount(); + Scoped<ArrayObject> array(scope, ctx->d()->engine->newArrayObject(ctx->d()->engine->regExpExecArrayClass)); + int len = r->value()->captureCount(); array->arrayReserve(len); ScopedValue v(scope); for (int i = 0; i < len; ++i) { int start = matchOffsets[i * 2]; int end = matchOffsets[i * 2 + 1]; - v = (start != -1 && end != -1) ? ctx->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); + v = (start != -1 && end != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined(); array->arrayPut(i, v); } array->setArrayLengthUnchecked(len); - array->memberData[Index_ArrayIndex] = Primitive::fromInt32(result); - array->memberData[Index_ArrayInput] = arg.asReturnedValue(); + array->memberData()[Index_ArrayIndex] = Primitive::fromInt32(result); + array->memberData()[Index_ArrayInput] = arg.asReturnedValue(); - regExpCtor->lastMatch = array; - regExpCtor->lastInput = arg->stringValue(); - regExpCtor->lastMatchStart = matchOffsets[0]; - regExpCtor->lastMatchEnd = matchOffsets[1]; + RegExpCtor::Data *dd = regExpCtor->d(); + dd->lastMatch = array; + dd->lastInput = arg->stringValue(); + dd->lastMatchStart = matchOffsets[0]; + dd->lastMatchEnd = matchOffsets[1]; - if (r->global) + if (r->global()) r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]); return array.asReturnedValue(); @@ -418,27 +423,27 @@ ReturnedValue RegExpPrototype::method_test(CallContext *ctx) ReturnedValue RegExpPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>()); + Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>()); if (!r) return ctx->throwTypeError(); - return ctx->engine->newString(r->toString())->asReturnedValue(); + return ctx->d()->engine->newString(r->toString())->asReturnedValue(); } ReturnedValue RegExpPrototype::method_compile(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpObject> r(scope, ctx->callData->thisObject.as<RegExpObject>()); + Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>()); if (!r) return ctx->throwTypeError(); - ScopedCallData callData(scope, ctx->callData->argc); - memcpy(callData->args, ctx->callData->args, ctx->callData->argc*sizeof(Value)); + ScopedCallData callData(scope, ctx->d()->callData->argc); + memcpy(callData->args, ctx->d()->callData->args, ctx->d()->callData->argc*sizeof(Value)); - Scoped<RegExpObject> re(scope, ctx->engine->regExpCtor.asFunctionObject()->construct(callData)); + Scoped<RegExpObject> re(scope, ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData)); - r->value = re->value; - r->global = re->global; + r->d()->value = re->value(); + r->d()->global = re->global(); return Encode::undefined(); } @@ -446,42 +451,42 @@ template <int index> ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined()); if (result->isUndefined()) - return ctx->engine->newString(QString())->asReturnedValue(); + return ctx->d()->engine->newString(QString())->asReturnedValue(); return result.asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx) { Scope scope(ctx); - ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch); + ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch()); ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined()); if (result->isUndefined()) - return ctx->engine->newString(QString())->asReturnedValue(); + return ctx->d()->engine->newString(QString())->asReturnedValue(); return result.asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx) { - return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue(); + return static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastInput().asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); - QString lastInput = regExpCtor->lastInput->toQString(); - return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue(); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + QString lastInput = regExpCtor->lastInput()->toQString(); + return ctx->d()->engine->newString(lastInput.left(regExpCtor->lastMatchStart()))->asReturnedValue(); } ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx) { Scope scope(ctx); - Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor); - QString lastInput = regExpCtor->lastInput->toQString(); - return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue(); + Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor); + QString lastInput = regExpCtor->lastInput()->toQString(); + return ctx->d()->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))->asReturnedValue(); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 1b408749d3..ac07707b2f 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -63,11 +63,18 @@ QT_BEGIN_NAMESPACE namespace QV4 { -class RegExp; - struct RegExpObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, RegExp *value, bool global); + Data(ExecutionEngine *engine, const QRegExp &re); + Data(InternalClass *ic); + + RegExp *value; + bool global; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(RegExpObject) + // needs to be compatible with the flags in qv4jsir_p.h enum Flags { RegExp_Global = 0x01, @@ -80,39 +87,37 @@ struct RegExpObject: Object { Index_ArrayInput = Index_ArrayIndex + 1 }; - RegExp* value; - Property *lastIndexProperty(ExecutionContext *ctx); - bool global; - - RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global); - RegExpObject(ExecutionEngine *engine, const QRegExp &re); - ~RegExpObject() {} + RegExp *value() const { return d()->value; } + bool global() const { return d()->global; } void init(ExecutionEngine *engine); + Property *lastIndexProperty(ExecutionContext *ctx); QRegExp toQRegExp() const; QString toString() const; QString source() const; uint flags() const; protected: - RegExpObject(InternalClass *ic); - static void destroy(Managed *that); static void markObjects(Managed *that, ExecutionEngine *e); }; -DEFINE_REF(RegExp, Object); - struct RegExpCtor: FunctionObject { - V4_OBJECT - RegExpCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + Value lastMatch; + StringValue lastInput; + int lastMatchStart; + int lastMatchEnd; + void clearLastMatch(); + }; + V4_OBJECT(FunctionObject) - Value lastMatch; - StringValue lastInput; - int lastMatchStart; - int lastMatchEnd; - void clearLastMatch(); + Value lastMatch() { return d()->lastMatch; } + StringValue lastInput() { return d()->lastInput; } + int lastMatchStart() { return d()->lastMatchStart; } + int lastMatchEnd() { return d()->lastMatchEnd; } static ReturnedValue construct(Managed *m, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -121,8 +126,16 @@ struct RegExpCtor: FunctionObject struct RegExpPrototype: RegExpObject { - RegExpPrototype(InternalClass *ic): RegExpObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor); + struct Data : RegExpObject::Data + { + Data(InternalClass *ic): RegExpObject::Data(ic) + { + setVTable(staticVTable()); + } + }; + V4_OBJECT(RegExpObject) + + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_exec(CallContext *ctx); static ReturnedValue method_test(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index e44d1a07a6..7ea8dbd0aa 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -265,10 +265,9 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) ReturnedValue Runtime::closure(ExecutionContext *ctx, int functionId) { - QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId]; + QV4::Function *clos = ctx->d()->compilationUnit->runtimeFunctions[functionId]; Q_ASSERT(clos); - FunctionObject *f = FunctionObject::createScriptFunction(ctx, clos); - return f->asReturnedValue(); + return FunctionObject::createScriptFunction(ctx, clos)->asReturnedValue(); } ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index) @@ -283,10 +282,10 @@ ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base, } ScopedString name(scope, index->toString(ctx)); - return Runtime::deleteMember(ctx, base, name); + return Runtime::deleteMember(ctx, base, name.getPointer()); } -ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, const StringRef name) +ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, String *name) { Scope scope(ctx); ScopedObject obj(scope, base->toObject(ctx)); @@ -295,7 +294,7 @@ ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, return Encode(obj->deleteProperty(name)); } -ReturnedValue Runtime::deleteName(ExecutionContext *ctx, const StringRef name) +ReturnedValue Runtime::deleteName(ExecutionContext *ctx, String *name) { Scope scope(ctx); return Encode(ctx->deleteProperty(name)); @@ -310,8 +309,8 @@ QV4::ReturnedValue Runtime::instanceof(ExecutionContext *ctx, const ValueRef lef if (!f) return ctx->throwTypeError(); - if (f->subtype == FunctionObject::BoundFunction) - f = static_cast<BoundFunction *>(f)->target; + if (f->subtype() == FunctionObject::BoundFunction) + f = static_cast<BoundFunction *>(f)->target(); Object *v = left->asObject(); if (!v) @@ -341,7 +340,7 @@ QV4::ReturnedValue Runtime::in(ExecutionContext *ctx, const ValueRef left, const ScopedString s(scope, left->toString(ctx)); if (scope.hasException()) return Encode::undefined(); - bool r = right->objectValue()->hasProperty(s); + bool r = right->objectValue()->hasProperty(s.getPointer()); return Encode(r); } @@ -370,7 +369,7 @@ Returned<String> *RuntimeHelpers::stringFromNumber(ExecutionContext *ctx, double { QString qstr; RuntimeHelpers::numberToString(&qstr, number, 10); - return ctx->engine->newString(qstr); + return ctx->engine()->newString(qstr); } ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint) @@ -382,7 +381,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint) typeHint = NUMBER_HINT; } - ExecutionEngine *engine = object->internalClass->engine; + ExecutionEngine *engine = object->internalClass()->engine; if (engine->hasException) return Encode::undefined(); @@ -428,13 +427,13 @@ Returned<Object> *RuntimeHelpers::convertToObject(ExecutionContext *ctx, const V ctx->throwTypeError(); return 0; case Value::Boolean_Type: - return ctx->engine->newBooleanObject(value); + return ctx->engine()->newBooleanObject(value); case Value::Managed_Type: Q_ASSERT(value->isString()); - return ctx->engine->newStringObject(value); + return ctx->engine()->newStringObject(value); case Value::Integer_Type: default: // double - return ctx->engine->newNumberObject(value); + return ctx->engine()->newNumberObject(value); } } @@ -444,14 +443,14 @@ Returned<String> *RuntimeHelpers::convertToString(ExecutionContext *ctx, const V case Value::Empty_Type: Q_ASSERT(!"empty Value encountered"); case Value::Undefined_Type: - return ctx->engine->id_undefined.ret(); + return ctx->engine()->id_undefined.ret(); case Value::Null_Type: - return ctx->engine->id_null.ret(); + return ctx->engine()->id_null.ret(); case Value::Boolean_Type: if (value->booleanValue()) - return ctx->engine->id_true.ret(); + return ctx->engine()->id_true.ret(); else - return ctx->engine->id_false.ret(); + return ctx->engine()->id_false.ret(); case Value::Managed_Type: if (value->isString()) return value->stringValue()->asReturned<String>(); @@ -475,14 +474,14 @@ static Returned<String> *convert_to_string_add(ExecutionContext *ctx, const Valu case Value::Empty_Type: Q_ASSERT(!"empty Value encountered"); case Value::Undefined_Type: - return ctx->engine->id_undefined.ret(); + return ctx->engine()->id_undefined.ret(); case Value::Null_Type: - return ctx->engine->id_null.ret(); + return ctx->engine()->id_null.ret(); case Value::Boolean_Type: if (value->booleanValue()) - return ctx->engine->id_true.ret(); + return ctx->engine()->id_true.ret(); else - return ctx->engine->id_false.ret(); + return ctx->engine()->id_false.ret(); case Value::Managed_Type: if (value->isString()) return value->stringValue()->asReturned<String>(); @@ -511,11 +510,11 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionContext *ctx, const ValueR pright = convert_to_string_add(ctx, pright); if (scope.engine->hasException) return Encode::undefined(); - if (!pleft->stringValue()->length()) + if (!pleft->stringValue()->d()->length()) return pright->asReturnedValue(); - if (!pright->stringValue()->length()) + if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); - return (new (ctx->engine->memoryManager) String(ctx->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue(); + return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue(); } double x = RuntimeHelpers::toNumber(pleft); double y = RuntimeHelpers::toNumber(pright); @@ -527,11 +526,11 @@ QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::Val Q_ASSERT(left->isString() || right->isString()); if (left->isString() && right->isString()) { - if (!left->stringValue()->length()) + if (!left->stringValue()->d()->length()) return right->asReturnedValue(); - if (!right->stringValue()->length()) + if (!right->stringValue()->d()->length()) return left->asReturnedValue(); - return (new (ctx->engine->memoryManager) String(ctx->engine, left->stringValue(), right->stringValue()))->asReturnedValue(); + return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, left->stringValue(), right->stringValue()))->asReturnedValue(); } Scope scope(ctx); @@ -544,14 +543,14 @@ QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::Val pright = convert_to_string_add(ctx, right); if (scope.engine->hasException) return Encode::undefined(); - if (!pleft->stringValue()->length()) + if (!pleft->stringValue()->d()->length()) return pright->asReturnedValue(); - if (!pright->stringValue()->length()) + if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); - return (new (ctx->engine->memoryManager) String(ctx->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue(); + return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue(); } -void Runtime::setProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name, const ValueRef value) +void Runtime::setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value) { Scope scope(ctx); ScopedObject o(scope, object->toObject(ctx)); @@ -588,8 +587,8 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object, } if (idx < UINT_MAX) { - if (!o->arrayData->hasAttributes()) { - ScopedValue v(scope, o->arrayData->get(idx)); + if (!o->arrayData()->hasAttributes()) { + ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); } @@ -600,7 +599,7 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object, ScopedString name(scope, index->toString(ctx)); if (scope.hasException()) return Encode::undefined(); - return o->get(name); + return o->get(name.getPointer()); } void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value) @@ -613,9 +612,9 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val uint idx = index->asArrayIndex(); if (idx < UINT_MAX) { if (o->arrayType() == ArrayData::Simple) { - SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData); - if (s && idx < s->len && !s->data[idx].isEmpty()) { - s->data[idx] = value; + SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData()); + if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) { + s->arrayData()[idx] = value; return; } } @@ -624,7 +623,7 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val } ScopedString name(scope, index->toString(ctx)); - o->put(name, value); + o->put(name.getPointer(), value); } ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in) @@ -633,7 +632,7 @@ ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in) Scoped<Object> o(scope, (Object *)0); if (!in->isNullOrUndefined()) o = in->toObject(ctx); - Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o)); + Scoped<Object> it(scope, ctx->engine()->newForEachIteratorObject(ctx, o)); return it.asReturnedValue(); } @@ -648,12 +647,12 @@ ReturnedValue Runtime::foreachNextPropertyName(const ValueRef foreach_iterator) } -void Runtime::setActivationProperty(ExecutionContext *ctx, const StringRef name, const ValueRef value) +void Runtime::setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value) { ctx->setProperty(name, value); } -ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name) +ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, String *name) { Scope scope(ctx); @@ -672,7 +671,7 @@ ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, return o->get(name); } -ReturnedValue Runtime::getActivationProperty(ExecutionContext *ctx, const StringRef name) +ReturnedValue Runtime::getActivationProperty(ExecutionContext *ctx, String *name) { return ctx->getProperty(name); } @@ -866,31 +865,31 @@ QV4::Bool Runtime::compareLessEqual(const QV4::ValueRef l, const QV4::ValueRef r } #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::callGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData) +ReturnedValue Runtime::callGlobalLookup(ExecutionContext *context, uint index, CallData *callData) { Scope scope(context); Q_ASSERT(callData->thisObject.isUndefined()); - Lookup *l = context->lookups + index; + Lookup *l = context->d()->lookups + index; Scoped<FunctionObject> o(scope, l->globalGetter(l, context)); if (!o) return context->throwTypeError(); - if (o.getPointer() == context->engine->evalFunction && l->name->equals(context->engine->id_eval)) + if (o.getPointer() == scope.engine->evalFunction && l->name->equals(scope.engine->id_eval)) return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true); return o->call(callData); } -ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, const StringRef name, CallDataRef callData) +ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, String *name, CallData *callData) { Q_ASSERT(callData->thisObject.isUndefined()); Scope scope(context); ScopedObject base(scope); - ScopedValue func(scope, context->getPropertyAndBase(name, base)); - if (context->engine->hasException) + ScopedValue func(scope, context->getPropertyAndBase(name, base.ptr->o)); + if (scope.engine->hasException) return Encode::undefined(); if (base) @@ -905,14 +904,14 @@ ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, const S return context->throwTypeError(msg); } - if (o == context->engine->evalFunction && name->equals(context->engine->id_eval)) { + if (o == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) { return static_cast<EvalFunction *>(o)->evalCall(callData, true); } return o->call(callData); } -ReturnedValue Runtime::callProperty(ExecutionContext *context, const StringRef name, CallDataRef callData) +ReturnedValue Runtime::callProperty(ExecutionContext *context, String *name, CallData *callData) { Scope scope(context); Scoped<Object> baseObject(scope, callData->thisObject); @@ -938,9 +937,9 @@ ReturnedValue Runtime::callProperty(ExecutionContext *context, const StringRef n return o->call(callData); } -ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData) +ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, CallData *callData) { - Lookup *l = context->lookups + index; + Lookup *l = context->d()->lookups + index; Value v; v = l->getter(l, callData->thisObject); if (!v.isObject()) @@ -949,7 +948,7 @@ ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, return v.objectValue()->call(callData); } -ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef index, CallDataRef callData) +ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef index, CallData *callData) { Scope scope(context); ScopedObject baseObject(scope, callData->thisObject.toObject(context)); @@ -959,14 +958,14 @@ ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef ind return Encode::undefined(); callData->thisObject = baseObject; - ScopedObject o(scope, baseObject->get(s)); + ScopedObject o(scope, baseObject->get(s.getPointer())); if (!o) return context->throwTypeError(); return o->call(callData); } -ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, CallDataRef callData) +ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, CallData *callData) { if (!func->isObject()) return context->throwTypeError(); @@ -975,12 +974,12 @@ ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, } -ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData) +ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData) { Scope scope(context); Q_ASSERT(callData->thisObject.isUndefined()); - Lookup *l = context->lookups + index; + Lookup *l = context->d()->lookups + index; Scoped<Object> f(scope, l->globalGetter(l, context)); if (!f) return context->throwTypeError(); @@ -989,11 +988,11 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint ind } -ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, const StringRef name, CallDataRef callData) +ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, String *name, CallData *callData) { Scope scope(context); ScopedValue func(scope, context->getProperty(name)); - if (context->engine->hasException) + if (scope.engine->hasException) return Encode::undefined(); Object *f = func->asObject(); @@ -1003,7 +1002,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, co return f->construct(callData); } -ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef func, CallDataRef callData) +ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef func, CallData *callData) { Object *f = func->asObject(); if (!f) @@ -1012,7 +1011,7 @@ ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef return f->construct(callData); } -ReturnedValue Runtime::constructProperty(ExecutionContext *context, const StringRef name, CallDataRef callData) +ReturnedValue Runtime::constructProperty(ExecutionContext *context, String *name, CallData *callData) { Scope scope(context); ScopedObject thisObject(scope, callData->thisObject.toObject(context)); @@ -1026,9 +1025,9 @@ ReturnedValue Runtime::constructProperty(ExecutionContext *context, const String return f->construct(callData); } -ReturnedValue Runtime::constructPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData) +ReturnedValue Runtime::constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData) { - Lookup *l = context->lookups + index; + Lookup *l = context->d()->lookups + index; Value v; v = l->getter(l, callData->thisObject); if (!v.isObject()) @@ -1050,39 +1049,39 @@ ReturnedValue Runtime::typeofValue(ExecutionContext *ctx, const ValueRef value) ScopedString res(scope); switch (value->type()) { case Value::Undefined_Type: - res = ctx->engine->id_undefined; + res = ctx->engine()->id_undefined; break; case Value::Null_Type: - res = ctx->engine->id_object; + res = ctx->engine()->id_object; break; case Value::Boolean_Type: - res = ctx->engine->id_boolean; + res = ctx->engine()->id_boolean; break; case Value::Managed_Type: if (value->isString()) - res = ctx->engine->id_string; + res = ctx->engine()->id_string; else if (value->objectValue()->asFunctionObject()) - res = ctx->engine->id_function; + res = ctx->engine()->id_function; else - res = ctx->engine->id_object; // ### implementation-defined + res = ctx->engine()->id_object; // ### implementation-defined break; default: - res = ctx->engine->id_number; + res = ctx->engine()->id_number; break; } return res.asReturnedValue(); } -QV4::ReturnedValue Runtime::typeofName(ExecutionContext *context, const StringRef name) +QV4::ReturnedValue Runtime::typeofName(ExecutionContext *context, String *name) { Scope scope(context); ScopedValue prop(scope, context->getProperty(name)); // typeof doesn't throw. clear any possible exception - context->engine->hasException = false; + scope.engine->hasException = false; return Runtime::typeofValue(context, prop); } -QV4::ReturnedValue Runtime::typeofMember(ExecutionContext *context, const ValueRef base, const StringRef name) +QV4::ReturnedValue Runtime::typeofMember(ExecutionContext *context, const ValueRef base, String *name) { Scope scope(context); ScopedObject obj(scope, base->toObject(context)); @@ -1099,7 +1098,7 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionContext *context, const Value ScopedObject obj(scope, base->toObject(context)); if (scope.engine->hasException) return Encode::undefined(); - ScopedValue prop(scope, obj->get(name)); + ScopedValue prop(scope, obj->get(name.getPointer())); return Runtime::typeofValue(context, prop); } @@ -1107,29 +1106,29 @@ ExecutionContext *Runtime::pushWithScope(const ValueRef o, ExecutionContext *ctx { Scope scope(ctx); ScopedObject obj(scope, o->toObject(ctx)); - return ctx->newWithContext(obj); + return reinterpret_cast<ExecutionContext *>(ctx->newWithContext(obj)); } ReturnedValue Runtime::unwindException(ExecutionContext *ctx) { - if (!ctx->engine->hasException) + if (!ctx->engine()->hasException) return Primitive::emptyValue().asReturnedValue(); - return ctx->engine->catchException(ctx, 0); + return ctx->engine()->catchException(ctx, 0); } -ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, const StringRef exceptionVarName) +ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, String *exceptionVarName) { Scope scope(ctx); - ScopedValue v(scope, ctx->engine->catchException(ctx, 0)); - return ctx->newCatchContext(exceptionVarName, v); + ScopedValue v(scope, ctx->engine()->catchException(ctx, 0)); + return reinterpret_cast<ExecutionContext *>(ctx->newCatchContext(exceptionVarName, v)); } ExecutionContext *Runtime::popScope(ExecutionContext *ctx) { - return ctx->engine->popContext(); + return ctx->engine()->popContext(); } -void Runtime::declareVar(ExecutionContext *ctx, bool deletable, const StringRef name) +void Runtime::declareVar(ExecutionContext *ctx, bool deletable, String *name) { ctx->createMutableBinding(name, deletable); } @@ -1137,7 +1136,7 @@ void Runtime::declareVar(ExecutionContext *ctx, bool deletable, const StringRef ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint length) { Scope scope(ctx); - Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject()); + Scoped<ArrayObject> a(scope, ctx->engine()->newArrayObject()); if (length) { a->arrayReserve(length); @@ -1150,8 +1149,8 @@ ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint l ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(ctx); - QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId]; - Scoped<Object> o(scope, ctx->engine->newObject(klass)); + QV4::InternalClass *klass = ctx->d()->compilationUnit->runtimeClasses[classId]; + Scoped<Object> o(scope, ctx->engine()->newObject(klass)); { bool needSparseArray = arrayGetterSetterCountAndFlags >> 30; @@ -1160,26 +1159,30 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu } for (uint i = 0; i < klass->size; ++i) - o->memberData[i] = *args++; - - ScopedValue entry(scope); - for (int i = 0; i < arrayValueCount; ++i) { - uint idx = args->toUInt32(); - ++args; - entry = *args++; - o->arraySet(idx, entry); + o->memberData()[i] = *args++; + + if (arrayValueCount > 0) { + ScopedValue entry(scope); + for (int i = 0; i < arrayValueCount; ++i) { + uint idx = args->toUInt32(); + ++args; + entry = *args++; + o->arraySet(idx, entry); + } } - ScopedProperty pd(scope); uint arrayGetterSetterCount = arrayGetterSetterCountAndFlags & ((1 << 30) - 1); - for (uint i = 0; i < arrayGetterSetterCount; ++i) { - uint idx = args->toUInt32(); - ++args; - pd->value = *args; - ++args; - pd->set = *args; - ++args; - o->arraySet(idx, pd, Attr_Accessor); + if (arrayGetterSetterCount > 0) { + ScopedProperty pd(scope); + for (uint i = 0; i < arrayGetterSetterCount; ++i) { + uint idx = args->toUInt32(); + ++args; + pd->value = *args; + ++args; + pd->set = *args; + ++args; + o->arraySet(idx, pd, Attr_Accessor); + } } return o.asReturnedValue(); @@ -1187,9 +1190,9 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionContext *ctx) { - assert(ctx->type >= ExecutionContext::Type_CallContext); + Q_ASSERT(ctx->d()->type >= ExecutionContext::Type_CallContext); CallContext *c = static_cast<CallContext *>(ctx); - return (new (c->engine->memoryManager) ArgumentsObject(c))->asReturnedValue(); + return (c->engine()->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue(); } #endif // V4_BOOTSTRAP @@ -1275,27 +1278,27 @@ unsigned Runtime::doubleToUInt(const double &d) ReturnedValue Runtime::regexpLiteral(ExecutionContext *ctx, int id) { - return ctx->compilationUnit->runtimeRegularExpressions[id].asReturnedValue(); + return ctx->d()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue(); } ReturnedValue Runtime::getQmlIdArray(NoThrowContext *ctx) { - return ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->idObjectsArray(); + return ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->idObjectsArray(); } ReturnedValue Runtime::getQmlContextObject(NoThrowContext *ctx) { - QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine); + QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine()); if (!context) return Encode::undefined(); - return QObjectWrapper::wrap(ctx->engine, context->contextObject); + return QObjectWrapper::wrap(ctx->d()->engine, context->contextObject); } ReturnedValue Runtime::getQmlScopeObject(NoThrowContext *ctx) { Scope scope(ctx); - QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()); - return QObjectWrapper::wrap(ctx->engine, c->getScopeObject()); + QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()); + return QObjectWrapper::wrap(ctx->d()->engine, c->getScopeObject()); } ReturnedValue Runtime::getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired) @@ -1312,11 +1315,11 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionContext *ctx, const ValueR QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex) { Scope scope(ctx); - QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()); + QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()); QObject *scopeObject = c->getScopeObject(); QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject); - QQmlEngine *qmlEngine = ctx->engine->v8Engine->engine(); + QQmlEngine *qmlEngine = ctx->engine()->v8Engine->engine(); QQmlData::ensurePropertyCache(qmlEngine, attachedObject); return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true); } @@ -1334,24 +1337,24 @@ void Runtime::setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object ReturnedValue Runtime::getQmlImportedScripts(NoThrowContext *ctx) { - QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine); + QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine()); if (!context) return Encode::undefined(); return context->importedScripts.value(); } -QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowContext *ctx, const QV4::StringRef name) +QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowContext *ctx, String *name) { - return ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->qmlSingletonWrapper(ctx->engine->v8Engine, name); + return ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>()->qmlSingletonWrapper(ctx->engine()->v8Engine, name); } void Runtime::convertThisToObject(ExecutionContext *ctx) { - Value *t = &ctx->callData->thisObject; + Value *t = &ctx->d()->callData->thisObject; if (t->isObject()) return; if (t->isNullOrUndefined()) { - *t = ctx->engine->globalObject->asReturnedValue(); + *t = ctx->engine()->globalObject->asReturnedValue(); } else { *t = t->toObject(ctx)->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 0979105680..992b027379 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -105,51 +105,51 @@ struct NoThrowContext : public ExecutionContext struct Q_QML_PRIVATE_EXPORT Runtime { // call - static ReturnedValue callGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData); - static ReturnedValue callActivationProperty(ExecutionContext *, const StringRef name, CallDataRef callData); - static ReturnedValue callProperty(ExecutionContext *context, const StringRef name, CallDataRef callData); - static ReturnedValue callPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData); - static ReturnedValue callElement(ExecutionContext *context, const ValueRef index, CallDataRef callData); - static ReturnedValue callValue(ExecutionContext *context, const ValueRef func, CallDataRef callData); + static ReturnedValue callGlobalLookup(ExecutionContext *context, uint index, CallData *callData); + static ReturnedValue callActivationProperty(ExecutionContext *, String *name, CallData *callData); + static ReturnedValue callProperty(ExecutionContext *context, String *name, CallData *callData); + static ReturnedValue callPropertyLookup(ExecutionContext *context, uint index, CallData *callData); + static ReturnedValue callElement(ExecutionContext *context, const ValueRef index, CallData *callData); + static ReturnedValue callValue(ExecutionContext *context, const ValueRef func, CallData *callData); // construct - static ReturnedValue constructGlobalLookup(ExecutionContext *context, uint index, CallDataRef callData); - static ReturnedValue constructActivationProperty(ExecutionContext *, const StringRef name, CallDataRef callData); - static ReturnedValue constructProperty(ExecutionContext *context, const StringRef name, CallDataRef callData); - static ReturnedValue constructPropertyLookup(ExecutionContext *context, uint index, CallDataRef callData); - static ReturnedValue constructValue(ExecutionContext *context, const ValueRef func, CallDataRef callData); + static ReturnedValue constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData); + static ReturnedValue constructActivationProperty(ExecutionContext *, String *name, CallData *callData); + static ReturnedValue constructProperty(ExecutionContext *context, String *name, CallData *callData); + static ReturnedValue constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData); + static ReturnedValue constructValue(ExecutionContext *context, const ValueRef func, CallData *callData); // set & get - static void setActivationProperty(ExecutionContext *ctx, const StringRef name, const ValueRef value); - static void setProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name, const ValueRef value); + static void setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value); + static void setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value); static void setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value); - static ReturnedValue getProperty(ExecutionContext *ctx, const ValueRef object, const StringRef name); - static ReturnedValue getActivationProperty(ExecutionContext *ctx, const StringRef name); + static ReturnedValue getProperty(ExecutionContext *ctx, const ValueRef object, String *name); + static ReturnedValue getActivationProperty(ExecutionContext *ctx, String *name); static ReturnedValue getElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index); // typeof static ReturnedValue typeofValue(ExecutionContext *ctx, const ValueRef val); - static ReturnedValue typeofName(ExecutionContext *context, const StringRef name); - static ReturnedValue typeofMember(ExecutionContext* context, const ValueRef base, const StringRef name); + static ReturnedValue typeofName(ExecutionContext *context, String *name); + static ReturnedValue typeofMember(ExecutionContext* context, const ValueRef base, String *name); static ReturnedValue typeofElement(ExecutionContext* context, const ValueRef base, const ValueRef index); // delete static ReturnedValue deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index); - static ReturnedValue deleteMember(ExecutionContext *ctx, const ValueRef base, const StringRef name); - static ReturnedValue deleteName(ExecutionContext *ctx, const StringRef name); + static ReturnedValue deleteMember(ExecutionContext *ctx, const ValueRef base, String *name); + static ReturnedValue deleteName(ExecutionContext *ctx, String *name); // exceptions & scopes static void throwException(ExecutionContext*, const ValueRef value); static ReturnedValue unwindException(ExecutionContext *ctx); static ExecutionContext *pushWithScope(const ValueRef o, ExecutionContext *ctx); - static ExecutionContext *pushCatchScope(ExecutionContext *ctx, const StringRef exceptionVarName); + static ExecutionContext *pushCatchScope(ExecutionContext *ctx, String *exceptionVarName); static ExecutionContext *popScope(ExecutionContext *ctx); // closures static ReturnedValue closure(ExecutionContext *ctx, int functionId); // function header - static void declareVar(ExecutionContext *ctx, bool deletable, const StringRef name); + static void declareVar(ExecutionContext *ctx, bool deletable, String *name); static ReturnedValue setupArgumentsObject(ExecutionContext *ctx); static void convertThisToObject(ExecutionContext *ctx); @@ -226,7 +226,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime { static ReturnedValue getQmlImportedScripts(NoThrowContext *ctx); static ReturnedValue getQmlContextObject(NoThrowContext *ctx); static ReturnedValue getQmlScopeObject(NoThrowContext *ctx); - static ReturnedValue getQmlSingleton(NoThrowContext *ctx, const StringRef name); + static ReturnedValue getQmlSingleton(NoThrowContext *ctx, String *name); static ReturnedValue getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex); static ReturnedValue getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired); static void setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 5d471ab4fb..563d097440 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -117,6 +117,18 @@ struct ScopedValue #endif } + ScopedValue(const Scope &scope, HeapObject *o) + { + ptr = scope.engine->jsStackTop++; + ptr->m = reinterpret_cast<Managed *>(o); +#if QT_POINTER_SIZE == 4 + ptr->tag = QV4::Value::Managed_Type; +#endif +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + ScopedValue(const Scope &scope, Managed *m) { ptr = scope.engine->jsStackTop++; @@ -150,6 +162,14 @@ struct ScopedValue return *this; } + ScopedValue &operator=(HeapObject *o) { + ptr->m = reinterpret_cast<Managed *>(o); +#if QT_POINTER_SIZE == 4 + ptr->tag = QV4::Value::Managed_Type; +#endif + return *this; + } + ScopedValue &operator=(Managed *m) { ptr->val = m->asReturnedValue(); return *this; @@ -215,6 +235,19 @@ struct Scoped ++scope.size; #endif } + Scoped(const Scope &scope, HeapObject *o) + { + Value v; + v.m = reinterpret_cast<Managed *>(o); +#if QT_POINTER_SIZE == 4 + v.tag = QV4::Value::Managed_Type; +#endif + ptr = scope.engine->jsStackTop++; + setPointer(value_cast<T>(v)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } Scoped(const Scope &scope, const ScopedValue &v) { ptr = scope.engine->jsStackTop++; @@ -280,6 +313,15 @@ struct Scoped #endif } + Scoped<T> &operator=(HeapObject *o) { + Value v; + v.m = reinterpret_cast<Managed *>(o); +#if QT_POINTER_SIZE == 4 + v.tag = QV4::Value::Managed_Type; +#endif + setPointer(value_cast<T>(v)); + return *this; + } Scoped<T> &operator=(const Value &v) { setPointer(value_cast<T>(v)); return *this; @@ -308,6 +350,9 @@ struct Scoped return *this; } + operator T *() { + return static_cast<T *>(ptr->managed()); + } T *operator->() { return static_cast<T *>(ptr->managed()); @@ -379,10 +424,6 @@ struct ScopedCallData { }; -struct StringRef; -struct ObjectRef; -struct FunctionObjectRef; - template<typename T> inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v) { @@ -400,38 +441,6 @@ inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v) return *this; } -struct CallDataRef { - CallDataRef(const ScopedCallData &c) - : ptr(c.ptr) {} - CallDataRef(CallData *v) { ptr = v; } - // Important: Do NOT add a copy constructor to this class - // adding a copy constructor actually changes the calling convention, ie. - // is not even binary compatible. Adding it would break assumptions made - // in the jit'ed code. - CallDataRef &operator=(const ScopedCallData &c) - { *ptr = *c.ptr; return *this; } - CallDataRef &operator=(const CallDataRef &o) - { *ptr = *o.ptr; return *this; } - - operator const CallData *() const { - return ptr; - } - const CallData *operator->() const { - return ptr; - } - - operator CallData *() { - return ptr; - } - CallData *operator->() { - return ptr; - } - -private: - CallData *ptr; -}; - - template <typename T> inline Value &Value::operator=(Returned<T> *t) { @@ -467,14 +476,20 @@ inline Returned<T> *Value::as() template<typename T> inline TypedValue<T> &TypedValue<T>::operator =(T *t) { - val = t->asReturnedValue(); + m = t; +#if QT_POINTER_SIZE == 4 + tag = Managed_Type; +#endif return *this; } template<typename T> inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v) { - val = v.ptr->val; + m = v.ptr->managed(); +#if QT_POINTER_SIZE == 4 + tag = Managed_Type; +#endif return *this; } @@ -517,22 +532,12 @@ PersistentValue::PersistentValue(Returned<T> *obj) { } -inline PersistentValue::PersistentValue(const ManagedRef obj) - : d(new PersistentValuePrivate(obj.asReturnedValue())) -{ -} - template<typename T> inline PersistentValue &PersistentValue::operator=(Returned<T> *obj) { return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue()); } -inline PersistentValue &PersistentValue::operator=(const ManagedRef obj) -{ - return operator=(obj.asReturnedValue()); -} - inline PersistentValue &PersistentValue::operator=(const ScopedValue &other) { return operator=(other.asReturnedValue()); @@ -573,18 +578,6 @@ inline ValueRef &ValueRef::operator=(const ScopedValue &o) return *this; } - -inline Value *extractValuePointer(const ScopedValue &v) -{ - return v.ptr; -} - -template<typename T> -Value *extractValuePointer(const Scoped<T> &v) -{ - return v.ptr; -} - struct ScopedProperty { ScopedProperty(Scope &scope) diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 36f61a1df5..e08a63bd1f 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -61,12 +61,11 @@ using namespace QV4; -QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml) - : FunctionObject(scope, scope->engine->id_eval, /*createProto = */ false) +QmlBindingWrapper::Data::Data(ExecutionContext *scope, Function *f, Object *qml) + : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false) , qml(qml) - , qmlContext(0) { - Q_ASSERT(scope->inUse); + Q_ASSERT(scope->inUse()); setVTable(staticVTable()); function = f; @@ -75,32 +74,30 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec needsActivation = function ? function->needsActivation() : false; Scope s(scope); - ScopedValue protectThis(s, this); + Scoped<QmlBindingWrapper> o(s, this); - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1)); + o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1)); - qmlContext = scope->engine->currentContext()->newQmlContext(this, qml); - scope->engine->popContext(); + o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml)); + s.engine->popContext(); } -QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml) - : FunctionObject(scope, scope->engine->id_eval, /*createProto = */ false) +QmlBindingWrapper::Data::Data(ExecutionContext *scope, Object *qml) + : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false) , qml(qml) - , qmlContext(0) { - Q_ASSERT(scope->inUse); + Q_ASSERT(scope->inUse()); setVTable(staticVTable()); - function = 0; needsActivation = false; Scope s(scope); - ScopedValue protectThis(s, this); + Scoped<QmlBindingWrapper> o(s, this); - defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1)); + o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1)); - qmlContext = scope->engine->currentContext()->newQmlContext(this, qml); - scope->engine->popContext(); + o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml)); + s.engine->popContext(); } ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *) @@ -110,13 +107,13 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *) Scope scope(engine); QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that); - if (!This->function) + if (!This->function()) return QV4::Encode::undefined(); - CallContext *ctx = This->qmlContext; - std::fill(ctx->locals, ctx->locals + ctx->function->varCount(), Primitive::undefinedValue()); + CallContext *ctx = This->d()->qmlContext; + std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue()); engine->pushContext(ctx); - ScopedValue result(scope, This->function->code(ctx, This->function->codeData)); + ScopedValue result(scope, This->function()->code(ctx, This->function()->codeData)); engine->popContext(); return result.asReturnedValue(); @@ -125,16 +122,16 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *) void QmlBindingWrapper::markObjects(Managed *m, ExecutionEngine *e) { QmlBindingWrapper *wrapper = static_cast<QmlBindingWrapper*>(m); - if (wrapper->qml) - wrapper->qml->mark(e); + if (wrapper->d()->qml) + wrapper->d()->qml->mark(e); FunctionObject::markObjects(m, e); - if (wrapper->qmlContext) - wrapper->qmlContext->mark(e); + if (wrapper->d()->qmlContext) + wrapper->d()->qmlContext->mark(e); } static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex) { - QV4::CallContext *signalEmittingContext = ctx->parent->asCallContext(); + QV4::CallContext *signalEmittingContext = ctx->d()->parent->asCallContext(); Q_ASSERT(signalEmittingContext); return signalEmittingContext->argument(parameterIndex); } @@ -144,7 +141,7 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine); QV4::Scope valueScope(engine); QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine->v8Engine, qmlContext, scopeObject)); - QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, new (engine->memoryManager) QV4::QmlBindingWrapper(engine->rootContext, qmlScopeObject)); + QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(engine->rootContext, qmlScopeObject)); if (!signalParameters.isEmpty()) { if (error) @@ -153,10 +150,11 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo QV4::ScopedString s(valueScope); int index = 0; foreach (const QByteArray ¶m, signalParameters) { - p->setGetter(new (engine->memoryManager) QV4::IndexedBuiltinFunction(wrapper->context(), index++, signalParameterGetter)); + QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapper->context(), index++, signalParameterGetter)); + p->setGetter(g); p->setSetter(0); s = engine->newString(QString::fromUtf8(param)); - qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable); + qmlScopeObject->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable); } } @@ -166,35 +164,37 @@ Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlCo DEFINE_OBJECT_VTABLE(QmlBindingWrapper); -struct CompilationUnitHolder : public QV4::Object +struct CompilationUnitHolder : public Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, CompiledData::CompilationUnit *unit) + : Object::Data(engine) + , unit(unit) + { + unit->ref(); + setVTable(staticVTable()); + } + ~Data() + { + unit->deref(); + } + QV4::CompiledData::CompilationUnit *unit; + }; + V4_OBJECT(Object) - CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit) - : Object(engine) - , unit(unit) - { - unit->ref(); - setVTable(staticVTable()); - } - ~CompilationUnitHolder() - { - unit->deref(); - } static void destroy(Managed *that) { - static_cast<CompilationUnitHolder*>(that)->~CompilationUnitHolder(); + static_cast<CompilationUnitHolder*>(that)->d()->~Data(); } - QV4::CompiledData::CompilationUnit *unit; }; DEFINE_OBJECT_VTABLE(CompilationUnitHolder); -Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit) +Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit) : line(0), column(0), scope(v4->rootContext), strictMode(false), inheritContext(true), parsed(false) - , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true) + , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true) { parsed = true; @@ -202,7 +202,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit vmFunction = compilationUnit->linkToEngine(v4); Q_ASSERT(vmFunction); Scope valueScope(v4); - ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); + ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit)); compilationUnitHolder = holder.asReturnedValue(); } else vmFunction = 0; @@ -221,7 +221,7 @@ void Script::parse() parsed = true; - ExecutionEngine *v4 = scope->engine; + ExecutionEngine *v4 = scope->d()->engine; Scope valueScope(v4); MemoryManager::GCBlocker gcBlocker(v4->memoryManager); @@ -274,7 +274,7 @@ void Script::parse() isel->setUseFastLookups(false); QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); vmFunction = compilationUnit->linkToEngine(v4); - ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); + ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit)); compilationUnitHolder = holder.asReturnedValue(); } @@ -295,16 +295,16 @@ ReturnedValue Script::run() ContextStateSaver(ExecutionContext *context) : savedContext(context) - , strictMode(context->strictMode) - , lookups(context->lookups) - , compilationUnit(context->compilationUnit) + , strictMode(context->d()->strictMode) + , lookups(context->d()->lookups) + , compilationUnit(context->d()->compilationUnit) {} ~ContextStateSaver() { - savedContext->strictMode = strictMode; - savedContext->lookups = lookups; - savedContext->compilationUnit = compilationUnit; + savedContext->d()->strictMode = strictMode; + savedContext->d()->lookups = lookups; + savedContext->d()->compilationUnit = compilationUnit; } }; @@ -313,7 +313,7 @@ ReturnedValue Script::run() if (!vmFunction) return Encode::undefined(); - QV4::ExecutionEngine *engine = scope->engine; + QV4::ExecutionEngine *engine = scope->d()->engine; QV4::Scope valueScope(engine); if (qml.isUndefined()) { @@ -321,14 +321,14 @@ ReturnedValue Script::run() ExecutionContextSaver ctxSaver(scope); ContextStateSaver stateSaver(scope); - scope->strictMode = vmFunction->isStrict(); - scope->lookups = vmFunction->compilationUnit->runtimeLookups; - scope->compilationUnit = vmFunction->compilationUnit; + scope->d()->strictMode = vmFunction->isStrict(); + scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups; + scope->d()->compilationUnit = vmFunction->compilationUnit; return vmFunction->code(scope, vmFunction->codeData); } else { ScopedObject qmlObj(valueScope, qml.value()); - FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj); + ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj)); ScopedCallData callData(valueScope, 0); callData->thisObject = Primitive::undefinedValue(); return f->call(callData); @@ -401,14 +401,14 @@ ReturnedValue Script::qmlBinding() { if (!parsed) parse(); - ExecutionEngine *v4 = scope->engine; + ExecutionEngine *v4 = scope->d()->engine; Scope valueScope(v4); ScopedObject qmlObj(valueScope, qml.value()); - ScopedObject v(valueScope, new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj)); + ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj)); return v.asReturnedValue(); } -QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject) +QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject) { QV4::Scope scope(engine); QV4::Script qmlScript(engine, scopeObject, script, QString()); diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index de582f9674..6a749d1438 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -55,23 +55,25 @@ namespace QV4 { struct ExecutionContext; -struct QmlBindingWrapper : FunctionObject { - V4_OBJECT - - QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml); - // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable! - QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml); +struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject { + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope, Function *f, Object *qml); + // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable! + Data(ExecutionContext *scope, Object *qml); + Object *qml; + CallContext *qmlContext; + }; + V4_OBJECT(FunctionObject) static ReturnedValue call(Managed *that, CallData *); static void markObjects(Managed *m, ExecutionEngine *e); - CallContext *context() const { return qmlContext; } + CallContext *context() const { return d()->qmlContext; } - static Returned<FunctionObject> *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction, const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0); + static Returned<FunctionObject> *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction, + const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0); private: - Object *qml; - CallContext *qmlContext; }; struct Q_QML_EXPORT Script { @@ -79,11 +81,11 @@ struct Q_QML_EXPORT Script { : sourceFile(source), line(line), column(column), sourceCode(sourceCode) , scope(scope), strictMode(false), inheritContext(false), parsed(false) , vmFunction(0), parseAsBinding(false) {} - Script(ExecutionEngine *engine, ObjectRef qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0) + Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0) : sourceFile(source), line(line), column(column), sourceCode(sourceCode) , scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false) - , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true) {} - Script(ExecutionEngine *engine, ObjectRef qml, CompiledData::CompilationUnit *compilationUnit); + , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true) {} + Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit); ~Script(); QString sourceFile; int line; @@ -106,7 +108,7 @@ struct Q_QML_EXPORT Script { static QV4::CompiledData::CompilationUnit *precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors = 0); - static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject); + static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject); }; } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 89231cfe5f..b55cd2daad 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -58,13 +58,13 @@ using namespace QV4; // helper function to generate valid warnings if errors occur during sequence operations. static void generateWarning(QV4::ExecutionContext *ctx, const QString& description) { - QQmlEngine *engine = ctx->engine->v8Engine->engine(); + QQmlEngine *engine = ctx->d()->engine->v8Engine->engine(); if (!engine) return; QQmlError retn; retn.setDescription(description); - QV4::StackFrame frame = ctx->engine->currentStackFrame(); + QV4::StackFrame frame = ctx->d()->engine->currentStackFrame(); retn.setLine(frame.line); retn.setUrl(QUrl(frame.source)); @@ -163,38 +163,41 @@ template <> bool convertValueToElement(const ValueRef value) } template <typename Container> -class QQmlSequence : public QV4::Object +struct QQmlSequence : public QV4::Object { - V4_OBJECT + struct Data : Object::Data { + Data(QV4::ExecutionEngine *engine, const Container &container) + : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) + , container(container) + , propertyIndex(-1) + , isReference(false) + { + QV4::Scope scope(engine); + QV4::Scoped<QQmlSequence<Container> > o(scope, this); + o->setArrayType(ArrayData::Custom); + o->init(); + } + + Data(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) + : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) + , object(object) + , propertyIndex(propertyIndex) + , isReference(true) + { + QV4::Scope scope(engine); + QV4::Scoped<QQmlSequence<Container> > o(scope, this); + o->setArrayType(ArrayData::Custom); + o->loadReference(); + o->init(); + } + mutable Container container; + QPointer<QObject> object; + int propertyIndex; + bool isReference; + }; + V4_OBJECT(QV4::Object) Q_MANAGED_TYPE(QmlSequence) public: - QQmlSequence(QV4::ExecutionEngine *engine, const Container &container) - : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) - , m_container(container) - , m_object(0) - , m_propertyIndex(-1) - , m_isReference(false) - { - QV4::Scope scope(engine); - QV4::ScopedObject protectThis(scope, this); - Q_UNUSED(protectThis); - setArrayType(ArrayData::Custom); - init(); - } - - QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) - : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) - , m_object(object) - , m_propertyIndex(propertyIndex) - , m_isReference(true) - { - QV4::Scope scope(engine); - QV4::ScopedObject protectThis(scope, this); - Q_UNUSED(protectThis); - setArrayType(ArrayData::Custom); - loadReference(); - init(); - } void init() { @@ -210,8 +213,8 @@ public: *hasProperty = false; return Encode::undefined(); } - if (m_isReference) { - if (!m_object) { + if (d()->isReference) { + if (!d()->object) { if (hasProperty) *hasProperty = false; return Encode::undefined(); @@ -219,10 +222,10 @@ public: loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx < m_container.count()) { + if (signedIdx < d()->container.count()) { if (hasProperty) *hasProperty = true; - return convertElementToValue(engine(), m_container.at(signedIdx)); + return convertElementToValue(engine(), d()->container.at(signedIdx)); } if (hasProperty) *hasProperty = false; @@ -231,7 +234,7 @@ public: void containerPutIndexed(uint index, const QV4::ValueRef value) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return; /* Qt containers have int (rather than uint) allowable indexes. */ @@ -240,33 +243,33 @@ public: return; } - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - int count = m_container.count(); + int count = d()->container.count(); typename Container::value_type element = convertValueToElement<typename Container::value_type>(value); if (signedIdx == count) { - m_container.append(element); + d()->container.append(element); } else if (signedIdx < count) { - m_container[signedIdx] = element; + d()->container[signedIdx] = element; } else { /* according to ECMA262r3 we need to insert */ /* the value at the given index, increasing length to index+1. */ - m_container.reserve(signedIdx + 1); + d()->container.reserve(signedIdx + 1); while (signedIdx > count++) { - m_container.append(typename Container::value_type()); + d()->container.append(typename Container::value_type()); } - m_container.append(element); + d()->container.append(element); } - if (m_isReference) + if (d()->isReference) storeReference(); } @@ -277,33 +280,33 @@ public: generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed query")); return QV4::Attr_Invalid; } - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return QV4::Attr_Invalid; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; + return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; } - void containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs) + void containerAdvanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) { name = (String *)0; *index = UINT_MAX; - if (m_isReference) { - if (!m_object) { + if (d()->isReference) { + if (!d()->object) { QV4::Object::advanceIterator(this, it, name, index, p, attrs); return; } loadReference(); } - if (it->arrayIndex < static_cast<uint>(m_container.count())) { + if (it->arrayIndex < static_cast<uint>(d()->container.count())) { *index = it->arrayIndex; ++it->arrayIndex; *attrs = QV4::Attr_Data; - p->value = convertElementToValue(engine(), m_container.at(*index)); + p->value = convertElementToValue(engine(), d()->container.at(*index)); return; } QV4::Object::advanceIterator(this, it, name, index, p, attrs); @@ -314,21 +317,21 @@ public: /* Qt containers have int (rather than uint) allowable indexes. */ if (index > INT_MAX) return false; - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return false; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx >= m_container.count()) + if (signedIdx >= d()->container.count()) return false; /* according to ECMA262r3 it should be Undefined, */ /* but we cannot, so we insert a default-value instead. */ - m_container.replace(signedIdx, typename Container::value_type()); + d()->container.replace(signedIdx, typename Container::value_type()); - if (m_isReference) + if (d()->isReference) storeReference(); return true; @@ -339,9 +342,9 @@ public: QQmlSequence<Container> *otherSequence = other->as<QQmlSequence<Container> >(); if (!otherSequence) return false; - if (m_isReference && otherSequence->m_isReference) { - return m_object == otherSequence->m_object && m_propertyIndex == otherSequence->m_propertyIndex; - } else if (!m_isReference && !otherSequence->m_isReference) { + if (d()->isReference && otherSequence->d()->isReference) { + return d()->object == otherSequence->d()->object && d()->propertyIndex == otherSequence->d()->propertyIndex; + } else if (!d()->isReference && !otherSequence->d()->isReference) { return this == otherSequence; } return false; @@ -366,9 +369,9 @@ public: QV4::Scope scope(m_ctx); ScopedObject compare(scope, m_compareFn); ScopedCallData callData(scope, 2); - callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs); - callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs); - callData->thisObject = this->m_ctx->engine->globalObject; + callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs); + callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs); + callData->thisObject = this->m_ctx->d()->engine->globalObject; QV4::ScopedValue result(scope, compare->call(callData)); return result->toNumber() < 0; } @@ -380,82 +383,82 @@ public: void sort(QV4::CallContext *ctx) { - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return; loadReference(); } QV4::Scope scope(ctx); - if (ctx->callData->argc == 1 && ctx->callData->args[0].asFunctionObject()) { - CompareFunctor cf(ctx, ctx->callData->args[0]); - std::sort(m_container.begin(), m_container.end(), cf); + if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].asFunctionObject()) { + CompareFunctor cf(ctx, ctx->d()->callData->args[0]); + std::sort(d()->container.begin(), d()->container.end(), cf); } else { DefaultCompareFunctor cf; - std::sort(m_container.begin(), m_container.end(), cf); + std::sort(d()->container.begin(), d()->container.end(), cf); } - if (m_isReference) + if (d()->isReference) storeReference(); } static QV4::ReturnedValue method_get_length(QV4::CallContext *ctx) { QV4::Scope scope(ctx); - QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >()); + QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >()); if (!This) return ctx->throwTypeError(); - if (This->m_isReference) { - if (!This->m_object) + if (This->d()->isReference) { + if (!This->d()->object) return QV4::Encode(0); This->loadReference(); } - return QV4::Encode(This->m_container.count()); + return QV4::Encode(This->d()->container.count()); } static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx) { QV4::Scope scope(ctx); - QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >()); + QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >()); if (!This) return ctx->throwTypeError(); - quint32 newLength = ctx->callData->args[0].toUInt32(); + quint32 newLength = ctx->d()->callData->args[0].toUInt32(); /* Qt containers have int (rather than uint) allowable indexes. */ if (newLength > INT_MAX) { generateWarning(ctx, QLatin1String("Index out of range during length set")); return QV4::Encode::undefined(); } /* Read the sequence from the QObject property if we're a reference */ - if (This->m_isReference) { - if (!This->m_object) + if (This->d()->isReference) { + if (!This->d()->object) return QV4::Encode::undefined(); This->loadReference(); } /* Determine whether we need to modify the sequence */ qint32 newCount = static_cast<qint32>(newLength); - qint32 count = This->m_container.count(); + qint32 count = This->d()->container.count(); if (newCount == count) { return QV4::Encode::undefined(); } else if (newCount > count) { /* according to ECMA262r3 we need to insert */ /* undefined values increasing length to newLength. */ /* We cannot, so we insert default-values instead. */ - This->m_container.reserve(newCount); + This->d()->container.reserve(newCount); while (newCount > count++) { - This->m_container.append(typename Container::value_type()); + This->d()->container.append(typename Container::value_type()); } } else { /* according to ECMA262r3 we need to remove */ /* elements until the sequence is the required length. */ while (newCount < count) { count--; - This->m_container.removeAt(count); + This->d()->container.removeAt(count); } } /* write back if required. */ - if (This->m_isReference) { + if (This->d()->isReference) { /* write back. already checked that object is non-null, so skip that check here. */ This->storeReference(); } @@ -463,9 +466,9 @@ public: } QVariant toVariant() const - { return QVariant::fromValue<Container>(m_container); } + { return QVariant::fromValue<Container>(d()->container); } - static QVariant toVariant(QV4::ArrayObjectRef array) + static QVariant toVariant(QV4::ArrayObject *array) { QV4::Scope scope(array->engine()); Container result; @@ -479,27 +482,22 @@ public: private: void loadReference() const { - Q_ASSERT(m_object); - Q_ASSERT(m_isReference); - void *a[] = { &m_container, 0 }; - QMetaObject::metacall(m_object, QMetaObject::ReadProperty, m_propertyIndex, a); + Q_ASSERT(d()->object); + Q_ASSERT(d()->isReference); + void *a[] = { &d()->container, 0 }; + QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a); } void storeReference() { - Q_ASSERT(m_object); - Q_ASSERT(m_isReference); + Q_ASSERT(d()->object); + Q_ASSERT(d()->isReference); int status = -1; QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding; - void *a[] = { &m_container, 0, &status, &flags }; - QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIndex, a); + void *a[] = { &d()->container, 0, &status, &flags }; + QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a); } - mutable Container m_container; - QPointer<QObject> m_object; - int m_propertyIndex; - bool m_isReference; - static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty) { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); } static void putIndexed(Managed *that, uint index, const QV4::ValueRef value) @@ -510,7 +508,7 @@ private: { return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); } static bool isEqualTo(Managed *that, Managed *other) { return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); } - static void advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs) + static void advanceIterator(Managed *that, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); } static void destroy(Managed *that) @@ -539,27 +537,22 @@ template<> DEFINE_OBJECT_VTABLE(QQmlRealList); #define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(#SequenceType); -SequencePrototype::SequencePrototype(InternalClass *ic) - : QV4::Object(ic) -{ - FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE) -} -#undef REGISTER_QML_SEQUENCE_METATYPE - void SequencePrototype::init() { + FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE) defineDefaultProperty(QStringLiteral("sort"), method_sort, 1); defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0); } +#undef REGISTER_QML_SEQUENCE_METATYPE QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx) { QV4::Scope scope(ctx); - QV4::ScopedObject o(scope, ctx->callData->thisObject); + QV4::ScopedObject o(scope, ctx->d()->callData->thisObject); if (!o || !o->isListType()) return ctx->throwTypeError(); - if (ctx->callData->argc >= 2) + if (ctx->d()->callData->argc >= 2) return o.asReturnedValue(); #define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \ @@ -587,7 +580,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId) #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex)); \ + QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \ return obj.asReturnedValue(); \ } else @@ -605,7 +598,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >())); \ + QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \ return obj.asReturnedValue(); \ } else @@ -627,7 +620,7 @@ ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const return list->toVariant(); \ else -QVariant SequencePrototype::toVariant(ObjectRef object) +QVariant SequencePrototype::toVariant(Object *object) { Q_ASSERT(object->isListType()); FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ return QVariant(); } @@ -660,7 +653,7 @@ QVariant SequencePrototype::toVariant(const QV4::ValueRef array, int typeHint, b return qMetaTypeId<SequenceType>(); \ } else -int SequencePrototype::metaTypeForSequence(QV4::ObjectRef object) +int SequencePrototype::metaTypeForSequence(QV4::Object *object) { FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE) /*else*/ { diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 4a5e82b688..727f312930 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -65,13 +65,11 @@ namespace QV4 { struct SequencePrototype : public QV4::Object { - SequencePrototype(QV4::InternalClass *ic); - void init(); static ReturnedValue method_valueOf(QV4::CallContext *ctx) { - return ctx->callData->thisObject.toString(ctx)->asReturnedValue(); + return ctx->d()->callData->thisObject.toString(ctx)->asReturnedValue(); } static ReturnedValue method_sort(QV4::CallContext *ctx); @@ -79,8 +77,8 @@ struct SequencePrototype : public QV4::Object static bool isSequenceType(int sequenceTypeId); static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded); static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded); - static int metaTypeForSequence(ObjectRef object); - static QVariant toVariant(QV4::ObjectRef object); + static int metaTypeForSequence(Object *object); + static QVariant toVariant(Object *object); static QVariant toVariant(const ValueRef array, int typeHint, bool *succeeded); }; diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index 3d754389a2..4e88a331a4 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -208,7 +208,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en } else if (QV4::DateObject *d = v->asDateObject()) { reserve(data, sizeof(quint32) + sizeof(double)); push(data, valueheader(WorkerDate)); - push(data, d->value.asDouble()); + push(data, d->date().asDouble()); } else if (v->as<RegExpObject>()) { Scoped<RegExpObject> re(scope, v); quint32 flags = re->flags(); @@ -281,7 +281,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en QV4::ExecutionContext *ctx = v4->currentContext(); str = s; - val = o->get(str); + val = o->get(str.getPointer()); if (scope.hasException()) ctx->catchException(); @@ -342,7 +342,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) name = deserialize(data, engine); value = deserialize(data, engine); n = name.asReturnedValue(); - o->put(n, value); + o->put(n.getPointer(), value); } return o.asReturnedValue(); } @@ -372,7 +372,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) QVariant var = qVariantFromValue(ref); QV4::ScopedValue v(scope, engine->fromVariant((var))); QV4::ScopedString s(scope, v4->newString(QStringLiteral("__qml:hidden:ref"))); - rv->asObject()->defineReadonlyProperty(s, v); + rv->asObject()->defineReadonlyProperty(s.getPointer(), v); agent->release(); agent->setV8Engine(engine); diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index d9aa881f21..123d1648c2 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -108,7 +108,7 @@ static uint toArrayIndex(const char *ch, const char *end, bool *ok) const ObjectVTable String::static_vtbl = { - DEFINE_MANAGED_VTABLE_INT(String), + DEFINE_MANAGED_VTABLE_INT(String, 0), 0, 0, get, @@ -133,13 +133,13 @@ void String::destroy(Managed *that) void String::markObjects(Managed *that, ExecutionEngine *e) { String *s = static_cast<String *>(that); - if (s->largestSubLength) { - s->left->mark(e); - s->right->mark(e); + if (s->d()->largestSubLength) { + s->d()->left->mark(e); + s->d()->right->mark(e); } } -ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty) +ReturnedValue String::get(Managed *m, String *name, bool *hasProperty) { ExecutionEngine *v4 = m->engine(); Scope scope(v4); @@ -148,7 +148,7 @@ ReturnedValue String::get(Managed *m, const StringRef name, bool *hasProperty) if (name->equals(v4->id_length)) { if (hasProperty) *hasProperty = true; - return Primitive::fromInt32(that->_text->size).asReturnedValue(); + return Primitive::fromInt32(that->d()->text->size).asReturnedValue(); } PropertyAttributes attrs; Property *pd = v4->stringObjectClass->prototype->__getPropertyDescriptor__(name, &attrs); @@ -168,7 +168,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty) Scope scope(engine); ScopedString that(scope, static_cast<String *>(m)); - if (index < static_cast<uint>(that->_text->size)) { + if (index < static_cast<uint>(that->d()->text->size)) { if (hasProperty) *hasProperty = true; return Encode(engine->newString(that->toQString().mid(index, 1))); @@ -185,7 +185,7 @@ ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty) return engine->stringObjectClass->prototype->getValue(that, pd, attrs); } -void String::put(Managed *m, const StringRef name, const ValueRef value) +void String::put(Managed *m, String *name, const ValueRef value) { Scope scope(m->engine()); if (scope.hasException()) @@ -206,7 +206,7 @@ void String::putIndexed(Managed *m, uint index, const ValueRef value) o->putIndexed(index, value); } -PropertyAttributes String::query(const Managed *m, StringRef name) +PropertyAttributes String::query(const Managed *m, String *name) { uint idx = name->asArrayIndex(); if (idx != UINT_MAX) @@ -217,10 +217,10 @@ PropertyAttributes String::query(const Managed *m, StringRef name) PropertyAttributes String::queryIndexed(const Managed *m, uint index) { const String *that = static_cast<const String *>(m); - return (index < static_cast<uint>(that->_text->size)) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid; + return (index < static_cast<uint>(that->d()->text->size)) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid; } -bool String::deleteProperty(Managed *, const StringRef) +bool String::deleteProperty(Managed *, String *) { return false; } @@ -235,44 +235,50 @@ bool String::isEqualTo(Managed *t, Managed *o) if (t == o) return true; - if (!o->internalClass->vtable->isString) + if (!o->internalClass()->vtable->isString) return false; String *that = static_cast<String *>(t); String *other = static_cast<String *>(o); if (that->hashValue() != other->hashValue()) return false; - if (that->identifier && that->identifier == other->identifier) + if (that->identifier() && that->identifier() == other->identifier()) return true; - if (that->subtype >= StringType_UInt && that->subtype == other->subtype) + if (that->subtype() >= StringType_UInt && that->subtype() == other->subtype()) return true; return that->toQString() == other->toQString(); } -String::String(ExecutionEngine *engine, const QString &text) - : Managed(engine->stringClass), _text(const_cast<QString &>(text).data_ptr()) - , identifier(0), stringHash(UINT_MAX) - , largestSubLength(0) +String::Data::Data(ExecutionEngine *engine, const QString &t) + : Managed::Data(engine->stringClass) { - _text->ref.ref(); - len = _text->size; subtype = StringType_Unknown; + + text = const_cast<QString &>(t).data_ptr(); + text->ref.ref(); + identifier = 0; + stringHash = UINT_MAX; + largestSubLength = 0; + len = text->size; } -String::String(ExecutionEngine *engine, String *l, String *r) - : Managed(engine->stringClass) - , left(l), right(r) - , stringHash(UINT_MAX), largestSubLength(qMax(l->largestSubLength, r->largestSubLength)) - , len(l->len + r->len) +String::Data::Data(ExecutionEngine *engine, String *l, String *r) + : Managed::Data(engine->stringClass) { subtype = StringType_Unknown; - if (!l->largestSubLength && l->len > largestSubLength) - largestSubLength = l->len; - if (!r->largestSubLength && r->len > largestSubLength) - largestSubLength = r->len; + left = l; + right = r; + stringHash = UINT_MAX; + largestSubLength = qMax(l->d()->largestSubLength, r->d()->largestSubLength); + len = l->d()->len + r->d()->len; + + if (!l->d()->largestSubLength && l->d()->len > largestSubLength) + largestSubLength = l->d()->len; + if (!r->d()->largestSubLength && r->d()->len > largestSubLength) + largestSubLength = r->d()->len; // make sure we don't get excessive depth in our strings if (len > 256 && len >= 2*largestSubLength) @@ -283,10 +289,10 @@ uint String::toUInt(bool *ok) const { *ok = true; - if (subtype == StringType_Unknown) + if (subtype() == StringType_Unknown) createHashValue(); - if (subtype >= StringType_UInt) - return stringHash; + if (subtype() >= StringType_UInt) + return d()->stringHash; // ### this conversion shouldn't be required double d = RuntimeHelpers::stringToNumber(toQString()); @@ -297,15 +303,15 @@ uint String::toUInt(bool *ok) const return UINT_MAX; } -bool String::equals(const StringRef other) const +bool String::equals(String *other) const { - if (this == other.getPointer()) + if (this == other) return true; if (hashValue() != other->hashValue()) return false; - if (identifier && identifier == other->identifier) + if (identifier() && identifier() == other->identifier()) return true; - if (subtype >= StringType_UInt && subtype == other->subtype) + if (subtype() >= StringType_UInt && subtype() == other->subtype()) return true; return toQString() == other->toQString(); @@ -313,13 +319,13 @@ bool String::equals(const StringRef other) const void String::makeIdentifierImpl() const { - if (largestSubLength) - simplifyString(); - Q_ASSERT(!largestSubLength); + if (d()->largestSubLength) + d()->simplifyString(); + Q_ASSERT(!d()->largestSubLength); engine()->identifierTable->identifier(this); } -void String::simplifyString() const +void String::Data::simplifyString() const { Q_ASSERT(largestSubLength); @@ -327,20 +333,20 @@ void String::simplifyString() const QString result(l, Qt::Uninitialized); QChar *ch = const_cast<QChar *>(result.constData()); recursiveAppend(ch); - _text = result.data_ptr(); - _text->ref.ref(); + text = result.data_ptr(); + text->ref.ref(); identifier = 0; largestSubLength = 0; } -QChar *String::recursiveAppend(QChar *ch) const +QChar *String::Data::recursiveAppend(QChar *ch) const { if (largestSubLength) { - ch = left->recursiveAppend(ch); - ch = right->recursiveAppend(ch); + ch = left->d()->recursiveAppend(ch); + ch = right->d()->recursiveAppend(ch); } else { - memcpy(ch, _text->data(), _text->size*sizeof(QChar)); - ch += _text->size; + memcpy(ch, text->data(), text->size*sizeof(QChar)); + ch += text->size; } return ch; } @@ -348,17 +354,17 @@ QChar *String::recursiveAppend(QChar *ch) const void String::createHashValue() const { - if (largestSubLength) - simplifyString(); - Q_ASSERT(!largestSubLength); - const QChar *ch = reinterpret_cast<const QChar *>(_text->data()); - const QChar *end = ch + _text->size; + if (d()->largestSubLength) + d()->simplifyString(); + Q_ASSERT(!d()->largestSubLength); + const QChar *ch = reinterpret_cast<const QChar *>(d()->text->data()); + const QChar *end = ch + d()->text->size; // array indices get their number as hash value bool ok; - stringHash = ::toArrayIndex(ch, end, &ok); + d()->stringHash = ::toArrayIndex(ch, end, &ok); if (ok) { - subtype = (stringHash == UINT_MAX) ? StringType_UInt : StringType_ArrayIndex; + setSubtype((d()->stringHash == UINT_MAX) ? StringType_UInt : StringType_ArrayIndex); return; } @@ -368,8 +374,8 @@ void String::createHashValue() const ++ch; } - stringHash = h; - subtype = StringType_Regular; + d()->stringHash = h; + setSubtype(StringType_Regular); } uint String::createHashValue(const QChar *ch, int length) @@ -414,7 +420,7 @@ uint String::createHashValue(const char *ch, int length) uint String::getLength(const Managed *m) { - return static_cast<const String *>(m)->length(); + return static_cast<const String *>(m)->d()->length(); } #endif // V4_BOOTSTRAP diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index ed2a4e3646..f9d3cd1cc0 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -53,8 +53,36 @@ struct Identifier; struct Q_QML_PRIVATE_EXPORT String : public Managed { #ifndef V4_BOOTSTRAP + struct Q_QML_PRIVATE_EXPORT Data : Managed::Data { + Data(ExecutionEngine *engine, const QString &text); + Data(ExecutionEngine *engine, String *l, String *n); + ~Data() { + if (!largestSubLength && !text->ref.deref()) + QStringData::deallocate(text); + } + void simplifyString() const; + int length() const { + Q_ASSERT((largestSubLength && + (len == left->d()->len + right->d()->len)) || + len == (uint)text->size); + return len; + } + union { + mutable QStringData *text; + mutable String *left; + }; + union { + mutable Identifier *identifier; + mutable String *right; + }; + mutable uint stringHash; + mutable uint largestSubLength; + uint len; + private: + QChar *recursiveAppend(QChar *ch) const; + }; // ### FIXME: Should this be a V4_OBJECT - V4_OBJECT + V4_OBJECT(QV4::Managed) Q_MANAGED_TYPE(String) enum { IsString = true @@ -67,24 +95,16 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed { StringType_ArrayIndex }; - String(ExecutionEngine *engine, const QString &text); - String(ExecutionEngine *engine, String *l, String *n); - ~String() { - if (!largestSubLength && !_text->ref.deref()) - QStringData::deallocate(_text); - _data = 0; - } - - bool equals(const StringRef other) const; + bool equals(String *other) const; inline bool isEqualTo(const String *other) const { if (this == other) return true; if (hashValue() != other->hashValue()) return false; - Q_ASSERT(!largestSubLength); - if (identifier && identifier == other->identifier) + Q_ASSERT(!d()->largestSubLength); + if (d()->identifier && d()->identifier == other->d()->identifier) return true; - if (subtype >= StringType_UInt && subtype == other->subtype) + if (subtype() >= StringType_UInt && subtype() == other->subtype()) return true; return toQString() == other->toQString(); @@ -95,34 +115,32 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed { } inline QString toQString() const { - if (largestSubLength) - simplifyString(); - QStringDataPtr ptr = { _text }; - _text->ref.ref(); + if (d()->largestSubLength) + d()->simplifyString(); + QStringDataPtr ptr = { d()->text }; + d()->text->ref.ref(); return QString(ptr); } - void simplifyString() const; - inline unsigned hashValue() const { - if (subtype == StringType_Unknown) + if (subtype() == StringType_Unknown) createHashValue(); - Q_ASSERT(!largestSubLength); + Q_ASSERT(!d()->largestSubLength); - return stringHash; + return d()->stringHash; } uint asArrayIndex() const { - if (subtype == StringType_Unknown) + if (subtype() == StringType_Unknown) createHashValue(); - Q_ASSERT(!largestSubLength); - if (subtype == StringType_ArrayIndex) - return stringHash; + Q_ASSERT(!d()->largestSubLength); + if (subtype() == StringType_ArrayIndex) + return d()->stringHash; return UINT_MAX; } uint toUInt(bool *ok) const; void makeIdentifier() const { - if (identifier) + if (d()->identifier) return; makeIdentifierImpl(); } @@ -135,44 +153,26 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed { bool startsWithUpper() const { const String *l = this; - while (l->largestSubLength) - l = l->left; - return l->_text->size && QChar::isUpper(l->_text->data()[0]); - } - int length() const { - Q_ASSERT((largestSubLength && (len == left->len + right->len)) || len == (uint)_text->size); - return len; + while (l->d()->largestSubLength) + l = l->d()->left; + return l->d()->text->size && QChar::isUpper(l->d()->text->data()[0]); } - union { - mutable QStringData *_text; - mutable String *left; - }; - union { - mutable Identifier *identifier; - mutable String *right; - }; - mutable uint stringHash; - mutable uint largestSubLength; - uint len; - + Identifier *identifier() const { return d()->identifier; } protected: static void destroy(Managed *); static void markObjects(Managed *that, ExecutionEngine *e); - static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty); + static ReturnedValue get(Managed *m, String *name, bool *hasProperty); static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty); - static void put(Managed *m, const StringRef name, const ValueRef value); + static void put(Managed *m, String *name, const ValueRef value); static void putIndexed(Managed *m, uint index, const ValueRef value); - static PropertyAttributes query(const Managed *m, StringRef name); + static PropertyAttributes query(const Managed *m, String *name); static PropertyAttributes queryIndexed(const Managed *m, uint index); - static bool deleteProperty(Managed *, const StringRef); + static bool deleteProperty(Managed *, String *); static bool deleteIndexedProperty(Managed *m, uint index); static bool isEqualTo(Managed *that, Managed *o); static uint getLength(const Managed *m); - -private: - QChar *recursiveAppend(QChar *ch) const; #endif public: @@ -191,7 +191,6 @@ inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v) return v.toString(e)->asReturnedValue(); } -DEFINE_REF(String, Managed); #endif } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index f1e51703a8..3f683495cd 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -77,44 +77,38 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -StringObject::StringObject(InternalClass *ic) - : Object(ic) +StringObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { Q_ASSERT(internalClass->vtable == staticVTable()); - - Scope scope(engine()); - ScopedObject protectThis(scope, this); - value = ic->engine->newString(QStringLiteral(""))->asReturnedValue(); - tmpProperty.value = Primitive::undefinedValue(); - defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0)); + Scope scope(ic->engine); + ScopedObject s(scope, this); + s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0)); } -StringObject::StringObject(ExecutionEngine *engine, const ValueRef val) - : Object(engine->stringObjectClass) +StringObject::Data::Data(ExecutionEngine *engine, const ValueRef val) + : Object::Data(engine->stringObjectClass) { + value = val; + Q_ASSERT(value.isString()); + tmpProperty.value = Primitive::undefinedValue(); setVTable(staticVTable()); Scope scope(engine); - ScopedObject protectThis(scope, this); - - value = *val; - - tmpProperty.value = Primitive::undefinedValue(); - - assert(value.isString()); - defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length())); + ScopedObject s(scope, this); + s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length())); } Property *StringObject::getIndex(uint index) const { - QString str = value.stringValue()->toQString(); + QString str = d()->value.stringValue()->toQString(); if (index >= (uint)str.length()) return 0; - tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1))); - return &tmpProperty; + d()->tmpProperty.value = Encode(internalClass()->engine->newString(str.mid(index, 1))); + return &d()->tmpProperty; } bool StringObject::deleteIndexedProperty(Managed *m, uint index) @@ -127,19 +121,19 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index) return false; } - if (index < static_cast<uint>(o->value.stringValue()->toQString().length())) { - if (v4->currentContext()->strictMode) + if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) { + if (v4->currentContext()->d()->strictMode) v4->currentContext()->throwTypeError(); return false; } return true; } -void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs) +void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) { name = (String *)0; StringObject *s = static_cast<StringObject *>(m); - uint slen = s->value.stringValue()->toQString().length(); + uint slen = s->d()->value.stringValue()->toQString().length(); if (it->arrayIndex <= slen) { while (it->arrayIndex < slen) { *index = it->arrayIndex; @@ -152,7 +146,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef nam return; } } - if (s->arrayData) { + if (s->arrayData()) { it->arrayNode = s->sparseBegin(); // iterate until we're past the end of the string while (it->arrayNode && it->arrayNode->key() < slen) @@ -166,15 +160,15 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef nam void StringObject::markObjects(Managed *that, ExecutionEngine *e) { StringObject *o = static_cast<StringObject *>(that); - o->value.stringValue()->mark(e); - o->tmpProperty.value.mark(e); + o->d()->value.stringValue()->mark(e); + o->d()->tmpProperty.value.mark(e); Object::markObjects(that, e); } DEFINE_OBJECT_VTABLE(StringCtor); -StringCtor::StringCtor(ExecutionContext *scope) - : FunctionObject(scope, QStringLiteral("String")) +StringCtor::Data::Data(ExecutionContext *scope) + : FunctionObject::Data(scope, QStringLiteral("String")) { setVTable(staticVTable()); } @@ -203,7 +197,7 @@ ReturnedValue StringCtor::call(Managed *m, CallData *callData) return value.asReturnedValue(); } -void StringPrototype::init(ExecutionEngine *engine, ObjectRef ctor) +void StringPrototype::init(ExecutionEngine *engine, Object *ctor) { Scope scope(engine); ScopedObject o(scope); @@ -238,11 +232,11 @@ void StringPrototype::init(ExecutionEngine *engine, ObjectRef ctor) static QString getThisString(ExecutionContext *ctx) { Scope scope(ctx); - ScopedValue t(scope, ctx->callData->thisObject); + ScopedValue t(scope, ctx->d()->callData->thisObject); if (t->isString()) return t->stringValue()->toQString(); if (StringObject *thisString = t->asStringObject()) - return thisString->value.stringValue()->toQString(); + return thisString->d()->value.stringValue()->toQString(); if (t->isUndefined() || t->isNull()) { ctx->throwTypeError(); return QString(); @@ -252,41 +246,41 @@ static QString getThisString(ExecutionContext *ctx) ReturnedValue StringPrototype::method_toString(CallContext *context) { - if (context->callData->thisObject.isString()) - return context->callData->thisObject.asReturnedValue(); + if (context->d()->callData->thisObject.isString()) + return context->d()->callData->thisObject.asReturnedValue(); - StringObject *o = context->callData->thisObject.asStringObject(); + StringObject *o = context->d()->callData->thisObject.asStringObject(); if (!o) return context->throwTypeError(); - return o->value.asReturnedValue(); + return o->d()->value.asReturnedValue(); } ReturnedValue StringPrototype::method_charAt(CallContext *context) { const QString str = getThisString(context); - if (context->engine->hasException) + if (context->d()->engine->hasException) return Encode::undefined(); int pos = 0; - if (context->callData->argc > 0) - pos = (int) context->callData->args[0].toInteger(); + if (context->d()->callData->argc > 0) + pos = (int) context->d()->callData->args[0].toInteger(); QString result; if (pos >= 0 && pos < str.length()) result += str.at(pos); - return context->engine->newString(result)->asReturnedValue(); + return context->d()->engine->newString(result)->asReturnedValue(); } ReturnedValue StringPrototype::method_charCodeAt(CallContext *context) { const QString str = getThisString(context); - if (context->engine->hasException) + if (context->d()->engine->hasException) return Encode::undefined(); int pos = 0; - if (context->callData->argc > 0) - pos = (int) context->callData->args[0].toInteger(); + if (context->d()->callData->argc > 0) + pos = (int) context->d()->callData->args[0].toInteger(); if (pos >= 0 && pos < str.length()) @@ -304,30 +298,30 @@ ReturnedValue StringPrototype::method_concat(CallContext *context) return Encode::undefined(); ScopedValue v(scope); - for (int i = 0; i < context->callData->argc; ++i) { - v = RuntimeHelpers::toString(context, ValueRef(&context->callData->args[i])); + for (int i = 0; i < context->d()->callData->argc; ++i) { + v = RuntimeHelpers::toString(context, ValueRef(&context->d()->callData->args[i])); if (scope.hasException()) return Encode::undefined(); Q_ASSERT(v->isString()); value += v->stringValue()->toQString(); } - return context->engine->newString(value)->asReturnedValue(); + return context->d()->engine->newString(value)->asReturnedValue(); } ReturnedValue StringPrototype::method_indexOf(CallContext *context) { QString value = getThisString(context); - if (context->engine->hasException) + if (context->d()->engine->hasException) return Encode::undefined(); QString searchString; - if (context->callData->argc) - searchString = context->callData->args[0].toString(context)->toQString(); + if (context->d()->callData->argc) + searchString = context->d()->callData->args[0].toString(context)->toQString(); int pos = 0; - if (context->callData->argc > 1) - pos = (int) context->callData->args[1].toInteger(); + if (context->d()->callData->argc > 1) + pos = (int) context->d()->callData->args[1].toInteger(); int index = -1; if (! value.isEmpty()) @@ -345,8 +339,8 @@ ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) return Encode::undefined(); QString searchString; - if (context->callData->argc) - searchString = context->callData->args[0].toQString(); + if (context->d()->callData->argc) + searchString = context->d()->callData->args[0].toQString(); ScopedValue posArg(scope, context->argument(1)); double position = RuntimeHelpers::toNumber(posArg); @@ -371,36 +365,36 @@ ReturnedValue StringPrototype::method_localeCompare(CallContext *context) if (scope.engine->hasException) return Encode::undefined(); - ScopedValue v(scope, context->callData->argument(0)); + ScopedValue v(scope, context->d()->callData->argument(0)); const QString that = v->toQString(); return Encode(QString::localeAwareCompare(value, that)); } ReturnedValue StringPrototype::method_match(CallContext *context) { - if (context->callData->thisObject.isUndefined() || context->callData->thisObject.isNull()) + if (context->d()->callData->thisObject.isUndefined() || context->d()->callData->thisObject.isNull()) return context->throwTypeError(); Scope scope(context); - ScopedString s(scope, context->callData->thisObject.toString(context)); + ScopedString s(scope, context->d()->callData->thisObject.toString(context)); - ScopedValue regexp(scope, context->callData->argument(0)); + ScopedValue regexp(scope, context->d()->callData->argument(0)); Scoped<RegExpObject> rx(scope, regexp); if (!rx) { ScopedCallData callData(scope, 1); callData->args[0] = regexp; - rx = context->engine->regExpCtor.asFunctionObject()->construct(callData); + rx = context->d()->engine->regExpCtor.asFunctionObject()->construct(callData); } if (!rx) // ### CHECK return context->throwTypeError(); - bool global = rx->global; + bool global = rx->global(); // ### use the standard builtin function, not the one that might be redefined in the proto - ScopedString execString(scope, context->engine->newString(QStringLiteral("exec"))); - Scoped<FunctionObject> exec(scope, context->engine->regExpClass->prototype->get(execString)); + ScopedString execString(scope, context->d()->engine->newString(QStringLiteral("exec"))); + Scoped<FunctionObject> exec(scope, context->d()->engine->regExpClass->prototype->get(execString.getPointer())); ScopedCallData callData(scope, 1); callData->thisObject = rx; @@ -408,9 +402,9 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (!global) return exec->call(callData); - ScopedString lastIndex(scope, context->engine->newString(QStringLiteral("lastIndex"))); - rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0))); - Scoped<ArrayObject> a(scope, context->engine->newArrayObject()); + ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex"))); + rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromInt32(0))); + Scoped<ArrayObject> a(scope, context->d()->engine->newArrayObject()); double previousLastIndex = 0; uint n = 0; @@ -422,11 +416,11 @@ ReturnedValue StringPrototype::method_match(CallContext *context) if (result->isNull()) break; assert(result->isObject()); - index = rx->get(lastIndex, 0); + index = rx->get(lastIndex.getPointer(), 0); double thisIndex = index->toInteger(); if (previousLastIndex == thisIndex) { previousLastIndex = thisIndex + 1; - rx->put(lastIndex, ScopedValue(scope, Primitive::fromDouble(previousLastIndex))); + rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromDouble(previousLastIndex))); } else { previousLastIndex = thisIndex; } @@ -491,10 +485,10 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) { Scope scope(ctx); QString string; - if (StringObject *thisString = ctx->callData->thisObject.asStringObject()) - string = thisString->value.stringValue()->toQString(); + if (StringObject *thisString = ctx->d()->callData->thisObject.asStringObject()) + string = thisString->d()->value.stringValue()->toQString(); else - string = ctx->callData->thisObject.toString(ctx)->toQString(); + string = ctx->d()->callData->thisObject.toString(ctx)->toQString(); int numCaptures = 0; int numStringMatches = 0; @@ -510,7 +504,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) uint offset = 0; // We extract the pointer here to work around a compiler bug on Android. - Scoped<RegExp> re(scope, regExp->value); + Scoped<RegExp> re(scope, regExp->value()); while (true) { int oldSize = nMatchOffsets; if (allocatedMatchOffsets < nMatchOffsets + re->captureCount() * 2) { @@ -526,14 +520,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) break; } nMatchOffsets += re->captureCount() * 2; - if (!regExp->global) + if (!regExp->d()->global) break; offset = qMax(offset + 1, matchOffsets[oldSize + 1]); } - if (regExp->global) + if (regExp->global()) regExp->lastIndexProperty(ctx)->value = Primitive::fromUInt32(0); - numStringMatches = nMatchOffsets / (regExp->value->captureCount() * 2); - numCaptures = regExp->value->captureCount(); + numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2); + numCaptures = regExp->value()->captureCount(); } else { numCaptures = 1; QString searchString = searchValue->toString(ctx)->toQString(); @@ -563,14 +557,14 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) uint end = matchOffsets[idx + 1]; entry = Primitive::undefinedValue(); if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch) - entry = ctx->engine->newString(string.mid(start, end - start)); + entry = ctx->d()->engine->newString(string.mid(start, end - start)); callData->args[k] = entry; } uint matchStart = matchOffsets[i * numCaptures * 2]; Q_ASSERT(matchStart >= static_cast<uint>(lastEnd)); uint matchEnd = matchOffsets[i * numCaptures * 2 + 1]; callData->args[numCaptures] = Primitive::fromUInt32(matchStart); - callData->args[numCaptures + 1] = ctx->engine->newString(string); + callData->args[numCaptures + 1] = ctx->d()->engine->newString(string); replacement = searchCallback->call(callData); result += string.midRef(lastEnd, matchStart - lastEnd); @@ -600,7 +594,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx) if (matchOffsets != _matchOffsets) free(matchOffsets); - return ctx->engine->newString(result)->asReturnedValue(); + return ctx->d()->engine->newString(result)->asReturnedValue(); } ReturnedValue StringPrototype::method_search(CallContext *ctx) @@ -614,14 +608,14 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) if (!regExp) { ScopedCallData callData(scope, 1); callData->args[0] = regExpValue; - regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData); + regExpValue = ctx->d()->engine->regExpCtor.asFunctionObject()->construct(callData); if (scope.engine->hasException) return Encode::undefined(); regExp = regExpValue->as<RegExpObject>(); Q_ASSERT(regExp); } - uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint)); - uint result = regExp->value->match(string, /*offset*/0, matchOffsets); + uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint)); + uint result = regExp->value()->match(string, /*offset*/0, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) return Encode(-1); return Encode(result); @@ -630,14 +624,14 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx) ReturnedValue StringPrototype::method_slice(CallContext *ctx) { const QString text = getThisString(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); const double length = text.length(); - double start = ctx->callData->argc ? ctx->callData->args[0].toInteger() : 0; - double end = (ctx->callData->argc < 2 || ctx->callData->args[1].isUndefined()) - ? length : ctx->callData->args[1].toInteger(); + double start = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toInteger() : 0; + double end = (ctx->d()->callData->argc < 2 || ctx->d()->callData->args[1].isUndefined()) + ? length : ctx->d()->callData->args[1].toInteger(); if (start < 0) start = qMax(length + start, 0.); @@ -653,7 +647,7 @@ ReturnedValue StringPrototype::method_slice(CallContext *ctx) const int intEnd = int(end); int count = qMax(0, intEnd - intStart); - return ctx->engine->newString(text.mid(intStart, count))->asReturnedValue(); + return ctx->d()->engine->newString(text.mid(intStart, count))->asReturnedValue(); } ReturnedValue StringPrototype::method_split(CallContext *ctx) @@ -666,15 +660,15 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) ScopedValue separatorValue(scope, ctx->argument(0)); ScopedValue limitValue(scope, ctx->argument(1)); - ScopedArrayObject array(scope, ctx->engine->newArrayObject()); + ScopedArrayObject array(scope, ctx->d()->engine->newArrayObject()); if (separatorValue->isUndefined()) { if (limitValue->isUndefined()) { - ScopedString s(scope, ctx->engine->newString(text)); + ScopedString s(scope, ctx->d()->engine->newString(text)); array->push_back(s); return array.asReturnedValue(); } - return ctx->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue(); + return ctx->d()->engine->newString(text.left(limitValue->toInteger()))->asReturnedValue(); } uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32(); @@ -684,55 +678,55 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) Scoped<RegExpObject> re(scope, separatorValue); if (re) { - if (re->value->pattern().isEmpty()) { + if (re->value()->pattern().isEmpty()) { re = (RegExpObject *)0; - separatorValue = ctx->engine->newString(QString()); + separatorValue = ctx->d()->engine->newString(QString()); } } ScopedString s(scope); if (re) { uint offset = 0; - uint* matchOffsets = (uint*)alloca(re->value->captureCount() * 2 * sizeof(uint)); + uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint)); while (true) { - uint result = re->value->match(text, offset, matchOffsets); + uint result = re->value()->match(text, offset, matchOffsets); if (result == JSC::Yarr::offsetNoMatch) break; - array->push_back((s = ctx->engine->newString(text.mid(offset, matchOffsets[0] - offset)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(offset, matchOffsets[0] - offset)))); offset = qMax(offset + 1, matchOffsets[1]); if (array->getLength() >= limit) break; - for (int i = 1; i < re->value->captureCount(); ++i) { + for (int i = 1; i < re->value()->captureCount(); ++i) { uint start = matchOffsets[i * 2]; uint end = matchOffsets[i * 2 + 1]; - array->push_back((s = ctx->engine->newString(text.mid(start, end - start)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start)))); if (array->getLength() >= limit) break; } } if (array->getLength() < limit) - array->push_back((s = ctx->engine->newString(text.mid(offset)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(offset)))); } else { QString separator = separatorValue->toString(ctx)->toQString(); if (separator.isEmpty()) { for (uint i = 0; i < qMin(limit, uint(text.length())); ++i) - array->push_back((s = ctx->engine->newString(text.mid(i, 1)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1)))); return array.asReturnedValue(); } int start = 0; int end; while ((end = text.indexOf(separator, start)) != -1) { - array->push_back((s = ctx->engine->newString(text.mid(start, end - start)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(start, end - start)))); start = end + separator.size(); if (array->getLength() >= limit) break; } if (array->getLength() < limit && start != -1) - array->push_back((s = ctx->engine->newString(text.mid(start)))); + array->push_back((s = ctx->d()->engine->newString(text.mid(start)))); } return array.asReturnedValue(); } @@ -740,16 +734,16 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) ReturnedValue StringPrototype::method_substr(CallContext *context) { const QString value = getThisString(context); - if (context->engine->hasException) + if (context->d()->engine->hasException) return Encode::undefined(); double start = 0; - if (context->callData->argc > 0) - start = context->callData->args[0].toInteger(); + if (context->d()->callData->argc > 0) + start = context->d()->callData->args[0].toInteger(); double length = +qInf(); - if (context->callData->argc > 1) - length = context->callData->args[1].toInteger(); + if (context->d()->callData->argc > 1) + length = context->d()->callData->args[1].toInteger(); double count = value.length(); if (start < 0) @@ -759,21 +753,21 @@ ReturnedValue StringPrototype::method_substr(CallContext *context) qint32 x = Primitive::toInt32(start); qint32 y = Primitive::toInt32(length); - return context->engine->newString(value.mid(x, y))->asReturnedValue(); + return context->d()->engine->newString(value.mid(x, y))->asReturnedValue(); } ReturnedValue StringPrototype::method_substring(CallContext *context) { QString value = getThisString(context); - if (context->engine->hasException) + if (context->d()->engine->hasException) return Encode::undefined(); int length = value.length(); double start = 0; double end = length; - if (context->callData->argc > 0) - start = context->callData->args[0].toInteger(); + if (context->d()->callData->argc > 0) + start = context->d()->callData->args[0].toInteger(); Scope scope(context); ScopedValue endValue(scope, context->argument(1)); @@ -800,15 +794,15 @@ ReturnedValue StringPrototype::method_substring(CallContext *context) qint32 x = (int)start; qint32 y = (int)(end - start); - return context->engine->newString(value.mid(x, y))->asReturnedValue(); + return context->d()->engine->newString(value.mid(x, y))->asReturnedValue(); } ReturnedValue StringPrototype::method_toLowerCase(CallContext *ctx) { QString value = getThisString(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); - return ctx->engine->newString(value.toLower())->asReturnedValue(); + return ctx->d()->engine->newString(value.toLower())->asReturnedValue(); } ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx) @@ -819,9 +813,9 @@ ReturnedValue StringPrototype::method_toLocaleLowerCase(CallContext *ctx) ReturnedValue StringPrototype::method_toUpperCase(CallContext *ctx) { QString value = getThisString(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); - return ctx->engine->newString(value.toUpper())->asReturnedValue(); + return ctx->d()->engine->newString(value.toUpper())->asReturnedValue(); } ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx) @@ -831,19 +825,19 @@ ReturnedValue StringPrototype::method_toLocaleUpperCase(CallContext *ctx) ReturnedValue StringPrototype::method_fromCharCode(CallContext *context) { - QString str(context->callData->argc, Qt::Uninitialized); + QString str(context->d()->callData->argc, Qt::Uninitialized); QChar *ch = str.data(); - for (int i = 0; i < context->callData->argc; ++i) { - *ch = QChar(context->callData->args[i].toUInt16()); + for (int i = 0; i < context->d()->callData->argc; ++i) { + *ch = QChar(context->d()->callData->args[i].toUInt16()); ++ch; } - return context->engine->newString(str)->asReturnedValue(); + return context->d()->engine->newString(str)->asReturnedValue(); } ReturnedValue StringPrototype::method_trim(CallContext *ctx) { QString s = getThisString(ctx); - if (ctx->engine->hasException) + if (ctx->d()->engine->hasException) return Encode::undefined(); const QChar *chars = s.constData(); @@ -857,5 +851,5 @@ ReturnedValue StringPrototype::method_trim(CallContext *ctx) break; } - return ctx->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue(); + return ctx->d()->engine->newString(QString(chars + start, end - start + 1))->asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index c38fd5b75f..0fc556f849 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -50,27 +50,32 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct StringObject: Object { - V4_OBJECT + struct Data : Object::Data { + Data(ExecutionEngine *engine, const ValueRef value); + Data(InternalClass *ic); + Value value; + // ### get rid of tmpProperty + mutable Property tmpProperty; + }; + V4_OBJECT(Object) Q_MANAGED_TYPE(StringObject) - Value value; - mutable Property tmpProperty; - StringObject(ExecutionEngine *engine, const ValueRef value); Property *getIndex(uint index) const; static bool deleteIndexedProperty(Managed *m, uint index); protected: - StringObject(InternalClass *ic); - static void advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs); + static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs); static void markObjects(Managed *that, ExecutionEngine *e); }; struct StringCtor: FunctionObject { - V4_OBJECT - StringCtor(ExecutionContext *scope); + struct Data : FunctionObject::Data { + Data(ExecutionContext *scope); + }; + V4_OBJECT(FunctionObject) static ReturnedValue construct(Managed *m, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); @@ -78,8 +83,7 @@ struct StringCtor: FunctionObject struct StringPrototype: StringObject { - StringPrototype(InternalClass *ic): StringObject(ic) {} - void init(ExecutionEngine *engine, ObjectRef ctor); + void init(ExecutionEngine *engine, Object *ctor); static ReturnedValue method_toString(CallContext *context); static ReturnedValue method_charAt(CallContext *context); diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index e9246f7a14..e122b18892 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -95,7 +95,7 @@ double Value::toNumberImpl() const if (isString()) return RuntimeHelpers::stringToNumber(stringValue()->toQString()); { - ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext(); + ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext(); Scope scope(ctx); ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), NUMBER_HINT)); return prim->toNumber(); @@ -129,7 +129,7 @@ QString Value::toQStringNoThrow() const if (isString()) return stringValue()->toQString(); { - ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext(); + ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext(); Scope scope(ctx); ScopedValue ex(scope); bool caughtException = false; @@ -182,7 +182,7 @@ QString Value::toQString() const if (isString()) return stringValue()->toQString(); { - ExecutionContext *ctx = objectValue()->internalClass->engine->currentContext(); + ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext(); Scope scope(ctx); ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), STRING_HINT)); return prim->toQString(); diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h index 1fe9e1c165..84a8e1adf2 100644 --- a/src/qml/jsruntime/qv4value_inl_p.h +++ b/src/qml/jsruntime/qv4value_inl_p.h @@ -64,13 +64,13 @@ inline bool Value::isString() const { if (!isManaged()) return false; - return managed() && managed()->internalClass->vtable->isString; + return managed() && managed()->internalClass()->vtable->isString; } inline bool Value::isObject() const { if (!isManaged()) return false; - return managed() && managed()->internalClass->vtable->isObject; + return managed() && managed()->internalClass()->vtable->isObject; } inline bool Value::isPrimitive() const diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 29cb8b42ed..7b49db74d9 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -64,6 +64,8 @@ struct Returned : private T using T::asReturnedValue; }; +struct HeapObject {}; + struct Q_QML_PRIVATE_EXPORT Value { /* @@ -347,6 +349,10 @@ struct Q_QML_PRIVATE_EXPORT Value val = Value::fromManaged(t).val; return *this; } + Value &operator=(HeapObject *o) { + m = reinterpret_cast<Managed *>(o); + return *this; + } template<typename T> Value &operator=(const Scoped<T> &t); @@ -430,7 +436,10 @@ struct TypedValue : public Value { template<typename X> TypedValue &operator =(X *x) { - val = Value::fromManaged(x).val; + m = x; +#if QT_POINTER_SIZE == 4 + tag = Managed_Type; +#endif } TypedValue &operator =(T *t); TypedValue &operator =(const Scoped<T> &v); @@ -441,6 +450,7 @@ struct TypedValue : public Value bool operator!() const { return !managed(); } + operator T *() { return static_cast<T *>(managed()); } T *operator->() { return static_cast<T *>(managed()); } const T *operator->() const { return static_cast<T *>(managed()); } T *getPointer() const { return static_cast<T *>(managed()); } diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 92cc19d8b9..a5b22a2de8 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -51,18 +51,15 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(VariantObject); -VariantObject::VariantObject(InternalClass *ic) - : Object(ic) - , ExecutionEngine::ScarceResourceData(QVariant()) - , m_vmePropertyReferenceCount(0) +VariantObject::Data::Data(InternalClass *ic) + : Object::Data(ic) { } -VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value) - : Object(engine->variantClass) - , ExecutionEngine::ScarceResourceData(value) - , m_vmePropertyReferenceCount(0) +VariantObject::Data::Data(ExecutionEngine *engine, const QVariant &value) + : Object::Data(engine->variantClass) { + data = value; if (isScarce()) engine->scarceResources.insert(this); } @@ -89,7 +86,7 @@ QVariant VariantObject::toVariant(const QV4::ValueRef v) return QVariant(); } -bool VariantObject::isScarce() const +bool VariantObject::Data::isScarce() const { QVariant::Type t = data.type(); return t == QVariant::Pixmap || t == QVariant::Image; @@ -98,9 +95,7 @@ bool VariantObject::isScarce() const void VariantObject::destroy(Managed *that) { VariantObject *v = static_cast<VariantObject *>(that); - if (v->isScarce()) - v->node.remove(); - v->~VariantObject(); + v->d()->~Data(); } bool VariantObject::isEqualTo(Managed *m, Managed *other) @@ -109,40 +104,35 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other) assert(lv); if (QV4::VariantObject *rv = other->as<QV4::VariantObject>()) - return lv->data == rv->data; + return lv->d()->data == rv->d()->data; if (QV4::QmlValueTypeWrapper *v = other->as<QmlValueTypeWrapper>()) - return v->isEqual(lv->data); + return v->isEqual(lv->d()->data); return false; } void VariantObject::addVmePropertyReference() { - if (isScarce() && ++m_vmePropertyReferenceCount == 1) { + if (d()->isScarce() && ++d()->vmePropertyReferenceCount == 1) { // remove from the ep->scarceResources list // since it is now no longer eligible to be // released automatically by the engine. - node.remove(); + d()->node.remove(); } } void VariantObject::removeVmePropertyReference() { - if (isScarce() && --m_vmePropertyReferenceCount == 0) { + if (d()->isScarce() && --d()->vmePropertyReferenceCount == 0) { // and add to the ep->scarceResources list // since it is now eligible to be released // automatically by the engine. - internalClass->engine->scarceResources.insert(this); + internalClass()->engine->scarceResources.insert(d()); } } -VariantPrototype::VariantPrototype(InternalClass *ic) - : VariantObject(ic) -{ -} - void VariantPrototype::init() { defineDefaultProperty(QStringLiteral("preserve"), method_preserve, 0); @@ -154,20 +144,20 @@ void VariantPrototype::init() QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx) { Scope scope(ctx); - Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>()); - if (o && o->isScarce()) - o->node.remove(); + Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>()); + if (o && o->d()->isScarce()) + o->d()->node.remove(); return Encode::undefined(); } QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx) { Scope scope(ctx); - Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>()); + Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>()); if (o) { - if (o->isScarce()) - o->node.remove(); - o->data = QVariant(); + if (o->d()->isScarce()) + o->d()->node.remove(); + o->d()->data = QVariant(); } return Encode::undefined(); } @@ -175,26 +165,26 @@ QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx) QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); - Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>()); + Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>()); if (!o) return Encode::undefined(); - QString result = o->data.toString(); - if (result.isEmpty() && !o->data.canConvert(QVariant::String)) - result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->data.typeName())); - return Encode(ctx->engine->newString(result)); + QString result = o->d()->data.toString(); + if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String)) + result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->d()->data.typeName())); + return Encode(ctx->d()->engine->newString(result)); } QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx) { Scope scope(ctx); - Scoped<VariantObject> o(scope, ctx->callData->thisObject.as<QV4::VariantObject>()); + Scoped<VariantObject> o(scope, ctx->d()->callData->thisObject.as<QV4::VariantObject>()); if (o) { - QVariant v = o->data; + QVariant v = o->d()->data; switch (v.type()) { case QVariant::Invalid: return Encode::undefined(); case QVariant::String: - return Encode(ctx->engine->newString(v.toString())); + return Encode(ctx->d()->engine->newString(v.toString())); case QVariant::Int: return Encode(v.toInt()); case QVariant::Double: @@ -206,7 +196,7 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx) break; } } - return ctx->callData->thisObject.asReturnedValue(); + return ctx->d()->callData->thisObject.asReturnedValue(); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 656608d49b..18e93f6ca7 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -64,31 +64,33 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct VariantObject : Object, public ExecutionEngine::ScarceResourceData +struct VariantObject : Object { - V4_OBJECT -public: - VariantObject(InternalClass *ic); - VariantObject(ExecutionEngine *engine, const QVariant &value); + struct Data : Object::Data, public ExecutionEngine::ScarceResourceData + { + Data(InternalClass *ic); + Data(ExecutionEngine *engine, const QVariant &value); + ~Data() { + if (isScarce()) + node.remove(); + } + bool isScarce() const; + int vmePropertyReferenceCount; + }; + V4_OBJECT(Object) static QVariant toVariant(const ValueRef v); void addVmePropertyReference(); void removeVmePropertyReference(); - bool isScarce() const; - int m_vmePropertyReferenceCount; static void destroy(Managed *that); static bool isEqualTo(Managed *m, Managed *other); }; -DEFINE_REF(VariantObject, Object); - struct VariantPrototype : VariantObject { public: - VariantPrototype(InternalClass *ic); - void init(); static ReturnedValue method_preserve(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 8e52ed5a96..7f058bf8b7 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -185,14 +185,14 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code const uchar *exceptionHandler = 0; - context->lineNumber = -1; - QV4::ExecutionEngine *engine = context->engine; + context->d()->lineNumber = -1; + QV4::ExecutionEngine *engine = context->d()->engine; #ifdef DO_TRACE_INSTR qDebug("Starting VME with context=%p and code=%p", context, code); #endif // DO_TRACE_INSTR - QV4::StringValue * const runtimeStrings = context->compilationUnit->runtimeStrings; + QV4::StringValue * const runtimeStrings = context->d()->compilationUnit->runtimeStrings; // setup lookup scopes int scopeDepth = 0; @@ -200,28 +200,28 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code QV4::ExecutionContext *scope = context; while (scope) { ++scopeDepth; - scope = scope->outer; + scope = scope->d()->outer; } } QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth))); { - scopes[0] = const_cast<QV4::Value *>(context->compilationUnit->data->constants()); + scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants()); // stack gets setup in push instruction scopes[1] = 0; QV4::ExecutionContext *scope = context; int i = 0; while (scope) { - if (scope->type >= QV4::ExecutionContext::Type_SimpleCallContext) { + if (scope->d()->type >= QV4::ExecutionContext::Type_SimpleCallContext) { QV4::CallContext *cc = static_cast<QV4::CallContext *>(scope); - scopes[2*i + 2] = cc->callData->args; - scopes[2*i + 3] = cc->locals; + scopes[2*i + 2] = cc->d()->callData->args; + scopes[2*i + 3] = cc->d()->locals; } else { scopes[2*i + 2] = 0; scopes[2*i + 3] = 0; } ++i; - scope = scope->outer; + scope = scope->d()->outer; } } @@ -253,7 +253,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(LoadRegExp) // TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData()); - VALUE(instr.result) = context->compilationUnit->runtimeRegularExpressions[instr.regExpId]; + VALUE(instr.result) = context->d()->compilationUnit->runtimeRegularExpressions[instr.regExpId]; MOTH_END_INSTR(LoadRegExp) MOTH_BEGIN_INSTR(LoadClosure) @@ -267,7 +267,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(GetGlobalLookup) TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData()); - QV4::Lookup *l = context->lookups + instr.index; + QV4::Lookup *l = context->d()->lookups + instr.index; STOREVALUE(instr.result, l->globalGetter(l, context)); MOTH_END_INSTR(GetGlobalLookup) @@ -282,7 +282,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(LoadElement) MOTH_BEGIN_INSTR(LoadElementLookup) - QV4::Lookup *l = context->lookups + instr.lookup; + QV4::Lookup *l = context->d()->lookups + instr.lookup; STOREVALUE(instr.result, l->indexedGetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index))); MOTH_END_INSTR(LoadElementLookup) @@ -292,7 +292,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(StoreElement) MOTH_BEGIN_INSTR(StoreElementLookup) - QV4::Lookup *l = context->lookups + instr.lookup; + QV4::Lookup *l = context->d()->lookups + instr.lookup; l->indexedSetter(l, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreElementLookup) @@ -302,7 +302,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(LoadProperty) MOTH_BEGIN_INSTR(GetLookup) - QV4::Lookup *l = context->lookups + instr.index; + QV4::Lookup *l = context->d()->lookups + instr.index; STOREVALUE(instr.result, l->getter(l, VALUEPTR(instr.base))); MOTH_END_INSTR(GetLookup) @@ -312,7 +312,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(StoreProperty) MOTH_BEGIN_INSTR(SetLookup) - QV4::Lookup *l = context->lookups + instr.index; + QV4::Lookup *l = context->d()->lookups + instr.index; l->setter(l, VALUEPTR(instr.base), VALUEPTR(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(SetLookup) @@ -333,7 +333,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(Push) TRACE(inline, "stack size: %u", instr.value); stackSize = instr.value; - stack = context->engine->stackPush(stackSize); + stack = context->engine()->stackPush(stackSize); #ifndef QT_NO_DEBUG memset(stack, 0, stackSize * sizeof(QV4::Value)); #endif @@ -342,7 +342,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(CallValue) #if 0 //def DO_TRACE_INSTR - if (Debugging::Debugger *debugger = context->engine->debugger) { + if (Debugging::Debugger *debugger = context->engine()->debugger) { if (QV4::FunctionObject *o = (VALUE(instr.dest)).asFunctionObject()) { if (Debugging::FunctionDebugInfo *info = debugger->debugInfo(o)) { QString n = debugger->name(o); @@ -655,24 +655,24 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_END_INSTR(BinopContext) MOTH_BEGIN_INSTR(Ret) - context->engine->stackPop(stackSize); + context->engine()->stackPop(stackSize); // TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData()); return VALUE(instr.result).asReturnedValue(); MOTH_END_INSTR(Ret) MOTH_BEGIN_INSTR(Debug) - context->lineNumber = instr.lineNumber; - QV4::Debugging::Debugger *debugger = context->engine->debugger; + context->d()->lineNumber = instr.lineNumber; + QV4::Debugging::Debugger *debugger = context->engine()->debugger; if (debugger && debugger->pauseAtNextOpportunity()) debugger->maybeBreakAtInstruction(); MOTH_END_INSTR(Debug) MOTH_BEGIN_INSTR(Line) - context->lineNumber = instr.lineNumber; + context->d()->lineNumber = instr.lineNumber; MOTH_END_INSTR(Debug) MOTH_BEGIN_INSTR(LoadThis) - VALUE(instr.result) = context->callData->thisObject; + VALUE(instr.result) = context->d()->callData->thisObject; MOTH_END_INSTR(LoadThis) MOTH_BEGIN_INSTR(LoadQmlIdArray) @@ -706,9 +706,9 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code Q_ASSERT(false); catchException: - Q_ASSERT(context->engine->hasException); + Q_ASSERT(context->engine()->hasException); if (!exceptionHandler) { - context->engine->stackPop(stackSize); + context->engine()->stackPop(stackSize); return QV4::Encode::undefined(); } code = exceptionHandler; @@ -732,7 +732,7 @@ void **VME::instructionJumpTable() QV4::ReturnedValue VME::exec(QV4::ExecutionContext *ctxt, const uchar *code) { VME vme; - QV4::Debugging::Debugger *debugger = ctxt->engine->debugger; + QV4::Debugging::Debugger *debugger = ctxt->engine()->debugger; if (debugger) debugger->enteringFunction(); QV4::ReturnedValue retVal = vme.run(ctxt, code); |