diff options
Diffstat (limited to 'src/qml/jsruntime')
64 files changed, 809 insertions, 577 deletions
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 63cf8779d2..4343924436 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -38,7 +38,6 @@ SOURCES += \ $$PWD/qv4sequenceobject.cpp \ $$PWD/qv4include.cpp \ $$PWD/qv4qobjectwrapper.cpp \ - $$PWD/qv4vme_moth.cpp \ $$PWD/qv4arraybuffer.cpp \ $$PWD/qv4typedarray.cpp \ $$PWD/qv4dataview.cpp @@ -87,12 +86,18 @@ HEADERS += \ $$PWD/qv4sequenceobject_p.h \ $$PWD/qv4include_p.h \ $$PWD/qv4qobjectwrapper_p.h \ - $$PWD/qv4vme_moth_p.h \ $$PWD/qv4profiling_p.h \ $$PWD/qv4arraybuffer_p.h \ $$PWD/qv4typedarray_p.h \ $$PWD/qv4dataview_p.h +qtConfig(qml-interpreter) { + HEADERS += \ + $$PWD/qv4vme_moth_p.h + SOURCES += \ + $$PWD/qv4vme_moth.cpp +} + } diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 156c21ca66..0dfdf25158 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -45,9 +45,10 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArgumentsObject); -Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context) - : fullyCreated(false) +void Heap::ArgumentsObject::init(QV4::CallContext *context) { + Object::init(); + fullyCreated = false; this->context = context->d(); Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable()); diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 6ccfd89fd4..37a8d0a94a 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -60,12 +60,12 @@ namespace QV4 { namespace Heap { struct ArgumentsGetterFunction : FunctionObject { - inline ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index); + inline void init(QV4::ExecutionContext *scope, uint index); uint index; }; struct ArgumentsSetterFunction : FunctionObject { - inline ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index); + inline void init(QV4::ExecutionContext *scope, uint index); uint index; }; @@ -75,7 +75,7 @@ struct ArgumentsObject : Object { CalleePropertyIndex = 1, CallerPropertyIndex = 3 }; - ArgumentsObject(QV4::CallContext *context); + void init(QV4::CallContext *context); Pointer<CallContext> context; bool fullyCreated; Pointer<MemberData> mappedArguments; @@ -91,11 +91,11 @@ struct ArgumentsGetterFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *d); }; -inline -Heap::ArgumentsGetterFunction::ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index) - : Heap::FunctionObject(scope) - , index(index) +inline void +Heap::ArgumentsGetterFunction::init(QV4::ExecutionContext *scope, uint index) { + Heap::FunctionObject::init(scope); + this->index = index; } struct ArgumentsSetterFunction: FunctionObject @@ -106,11 +106,11 @@ struct ArgumentsSetterFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *callData); }; -inline -Heap::ArgumentsSetterFunction::ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index) - : Heap::FunctionObject(scope) - , index(index) +inline void +Heap::ArgumentsSetterFunction::init(QV4::ExecutionContext *scope, uint index) { + Heap::FunctionObject::init(scope); + this->index = index; } diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 34c7746684..23075aa78c 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -46,9 +46,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayBufferCtor); DEFINE_OBJECT_VTABLE(ArrayBuffer); -Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("ArrayBuffer")) +void Heap::ArrayBufferCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("ArrayBuffer")); } void ArrayBufferCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -94,8 +94,9 @@ ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx) } -Heap::ArrayBuffer::ArrayBuffer(size_t length) +void Heap::ArrayBuffer::init(size_t length) { + Object::init(); data = QTypedArrayData<char>::allocate(length + 1); if (!data) { data = 0; @@ -106,16 +107,18 @@ Heap::ArrayBuffer::ArrayBuffer(size_t length) memset(data->data(), 0, length + 1); } -Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array) - : data(const_cast<QByteArray&>(array).data_ptr()) +void Heap::ArrayBuffer::init(const QByteArray& array) { + Object::init(); + data = const_cast<QByteArray&>(array).data_ptr(); data->ref.ref(); } -Heap::ArrayBuffer::~ArrayBuffer() +void Heap::ArrayBuffer::destroy() { if (!data->ref.deref()) QTypedArrayData<char>::deallocate(data); + Object::destroy(); } QByteArray ArrayBuffer::asByteArray() const diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index b552cef9f1..bc56d1ea31 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -60,13 +60,13 @@ namespace QV4 { namespace Heap { struct ArrayBufferCtor : FunctionObject { - ArrayBufferCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object { - ArrayBuffer(size_t length); - ArrayBuffer(const QByteArray& array); - ~ArrayBuffer(); + void init(size_t length); + void init(const QByteArray& array); + void destroy(); QTypedArrayData<char> *data; uint byteLength() const { return data->size; } diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 74c83b1940..bfeb3d4699 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -46,6 +46,8 @@ using namespace QV4; +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON + const QV4::VTable QV4::ArrayData::static_vtbl = { 0, QV4::ArrayData::IsExecutionContext, @@ -94,13 +96,15 @@ const ArrayVTable SparseArrayData::static_vtbl = SparseArrayData::length }; +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF + Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData)); Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData)); static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value) { Value v; - v.setTagValue(Value::fromReturnedValue(*target).tag(), value); + v.setEmpty(value); *target = v.asReturnedValue(); } @@ -189,6 +193,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } else { sparse->sparse = new SparseArray; lastFree = &sparse->freeList; + storeValue(lastFree, 0); for (uint i = 0; i < toCopy; ++i) { if (!sparse->arrayData[i].isEmpty()) { SparseArrayNode *n = sparse->sparse->insert(i); @@ -209,6 +214,8 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } storeValue(lastFree, UINT_MAX); } + + Q_ASSERT(Value::fromReturnedValue(sparse->freeList).isEmpty()); // ### Could explicitly free the old data } @@ -357,12 +364,12 @@ void SparseArrayData::free(Heap::ArrayData *d, uint idx) Value *v = d->arrayData + idx; if (d->attrs && d->attrs[idx].isAccessor()) { // double slot, free both. Order is important, so we have a double slot for allocation again afterwards. - v[1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value()); - v[0].setTagValue(Value::Empty_Type, idx + 1); + v[1].setEmpty(Value::fromReturnedValue(d->freeList).emptyValue()); + v[0].setEmpty(idx + 1); } else { - v->setTagValue(Value::Empty_Type, Value::fromReturnedValue(d->freeList).value()); + v->setEmpty(Value::fromReturnedValue(d->freeList).emptyValue()); } - d->freeList = idx; + d->freeList = Primitive::emptyValue(idx).asReturnedValue(); if (d->attrs) d->attrs[idx].clear(); } @@ -400,9 +407,9 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) Q_ASSERT(dd->arrayData[Value::fromReturnedValue(*last).value()].value() != Value::fromReturnedValue(*last).value()); if (dd->arrayData[Value::fromReturnedValue(*last).value()].value() == (Value::fromReturnedValue(*last).value() + 1)) { // found two slots in a row - uint idx = Value::fromReturnedValue(*last).uint_32(); + uint idx = Value::fromReturnedValue(*last).emptyValue(); Value lastV = Value::fromReturnedValue(*last); - lastV.setTagValue(lastV.tag(), dd->arrayData[lastV.value() + 1].value()); + lastV.setEmpty(dd->arrayData[lastV.emptyValue() + 1].value()); *last = lastV.rawValue(); dd->attrs[idx] = Attr_Accessor; return idx; @@ -416,7 +423,8 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) } uint idx = Value::fromReturnedValue(dd->freeList).value(); Q_ASSERT(idx != UINT_MAX); - dd->freeList = dd->arrayData[idx].uint_32(); + dd->freeList = dd->arrayData[idx].asReturnedValue(); + Q_ASSERT(Value::fromReturnedValue(dd->freeList).isEmpty()); if (dd->attrs) dd->attrs[idx] = Attr_Data; return idx; @@ -471,13 +479,14 @@ bool SparseArrayData::del(Object *o, uint index) if (isAccessor) { // free up both indices - dd->arrayData[pidx + 1].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value()); - dd->arrayData[pidx].setTagValue(Value::Undefined_Type, pidx + 1); + dd->arrayData[pidx + 1].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); + dd->arrayData[pidx].setEmpty(pidx + 1); } else { - dd->arrayData[pidx].setTagValue(Value::Empty_Type, Value::fromReturnedValue(dd->freeList).value()); + Q_ASSERT(dd->type == Heap::ArrayData::Sparse); + dd->arrayData[pidx].setEmpty(Value::fromReturnedValue(dd->freeList).emptyValue()); } - dd->freeList = pidx; + dd->freeList = Primitive::emptyValue(pidx).asReturnedValue(); dd->sparse->erase(n); return true; } diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index d7ee4798b0..24b948f01e 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -133,7 +133,7 @@ struct ArrayData : public Base { } }; -Q_STATIC_ASSERT(std::is_trivial<ArrayData>::value); +V4_ASSERT_IS_TRIVIAL(ArrayData) struct SimpleArrayData : public ArrayData { uint mappedIndex(uint index) const { return (index + offset) % alloc; } @@ -153,10 +153,13 @@ struct SimpleArrayData : public ArrayData { return attrs ? attrs[i] : Attr_Data; } }; -Q_STATIC_ASSERT(std::is_trivial<SimpleArrayData>::value); +V4_ASSERT_IS_TRIVIAL(SimpleArrayData) struct SparseArrayData : public ArrayData { - inline ~SparseArrayData(); + void destroy() { + delete sparse; + ArrayData::destroy(); + } uint mappedIndex(uint index) const { SparseArrayNode *n = sparse->findNode(index); @@ -287,11 +290,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData namespace Heap { -inline SparseArrayData::~SparseArrayData() -{ - delete sparse; -} - void ArrayData::getProperty(uint index, Property *p, PropertyAttributes *attrs) { Property *pd = getProperty(index); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 4d15c6c137..659ede7552 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -49,9 +49,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ArrayCtor); -Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Array")) +void Heap::ArrayCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Array")); } void ArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -186,6 +186,10 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) { Scope scope(ctx); ScopedValue arg(scope, ctx->argument(0)); + ScopedObject instance(scope, ctx->thisObject().toObject(scope.engine)); + + if (!instance) + return ctx->d()->engine->newString()->asReturnedValue(); QString r4; if (arg->isUndefined()) @@ -193,8 +197,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) else r4 = arg->toQString(); - ScopedObject self(scope, ctx->thisObject()); - ScopedValue length(scope, self->get(ctx->d()->engine->id_length())); + ScopedValue length(scope, instance->get(ctx->d()->engine->id_length())); const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); if (!r2) @@ -203,7 +206,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) QString R; // ### FIXME - if (ArrayObject *a = self->as<ArrayObject>()) { + if (ArrayObject *a = instance->as<ArrayObject>()) { ScopedValue e(scope); for (uint i = 0; i < a->getLength(); ++i) { if (i) @@ -220,7 +223,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) // crazy! // ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0"))); - ScopedValue r6(scope, self->get(name)); + ScopedValue r6(scope, instance->get(name)); if (!r6->isNullOrUndefined()) R = r6->toQString(); @@ -229,7 +232,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx) R += r4; name = Primitive::fromDouble(k).toString(scope.engine); - r12 = self->get(name); + r12 = instance->get(name); if (scope.hasException()) return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index f49ed76b02..9a05bb8681 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct ArrayCtor : FunctionObject { - ArrayCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 57c54e15c4..8047993266 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -45,9 +45,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(BooleanCtor); DEFINE_OBJECT_VTABLE(BooleanObject); -Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Boolean")) +void Heap::BooleanCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Boolean")); } void BooleanCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 17543e33e0..4c2f3c09e7 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct BooleanCtor : FunctionObject { - BooleanCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index ffedf737ce..0b42288ccc 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -128,7 +128,7 @@ struct ExecutionContext : Base { bool strictMode : 8; int lineNumber; }; -Q_STATIC_ASSERT(std::is_trivial<ExecutionContext>::value); +V4_ASSERT_IS_TRIVIAL(ExecutionContext) struct CallContext : ExecutionContext { static CallContext createOnStack(ExecutionEngine *v4); @@ -145,20 +145,20 @@ struct CallContext : ExecutionContext { Value *locals; Pointer<Object> activation; }; -Q_STATIC_ASSERT(std::is_trivial<CallContext>::value); +V4_ASSERT_IS_TRIVIAL(CallContext) struct GlobalContext : ExecutionContext { void init(ExecutionEngine *engine); Pointer<Object> global; }; -Q_STATIC_ASSERT(std::is_trivial<GlobalContext>::value); +V4_ASSERT_IS_TRIVIAL(GlobalContext) struct CatchContext : ExecutionContext { void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); Pointer<String> exceptionVarName; Value exceptionValue; }; -Q_STATIC_ASSERT(std::is_trivial<CatchContext>::value); +V4_ASSERT_IS_TRIVIAL(CatchContext) struct WithContext : ExecutionContext { void init(ExecutionContext *outerContext, Object *with) @@ -175,7 +175,7 @@ struct WithContext : ExecutionContext { Pointer<Object> withObject; }; -Q_STATIC_ASSERT(std::is_trivial<WithContext>::value); +V4_ASSERT_IS_TRIVIAL(WithContext) struct QmlContextWrapper; diff --git a/src/qml/jsruntime/qv4context_p_p.h b/src/qml/jsruntime/qv4context_p_p.h index 0da9f678ed..ca8dc0b518 100644 --- a/src/qml/jsruntime/qv4context_p_p.h +++ b/src/qml/jsruntime/qv4context_p_p.h @@ -69,7 +69,7 @@ QObject *QmlContext::qmlScope() const QQmlContextData *QmlContext::qmlContext() const { - return d()->qml->context; + return *d()->qml->context; } void QmlContext::takeContextOwnership() { diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp index fac3d5316c..db8376272d 100644 --- a/src/qml/jsruntime/qv4dataview.cpp +++ b/src/qml/jsruntime/qv4dataview.cpp @@ -49,9 +49,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(DataViewCtor); DEFINE_OBJECT_VTABLE(DataView); -Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("DataView")) +void Heap::DataViewCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("DataView")); } void DataViewCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4dataview_p.h b/src/qml/jsruntime/qv4dataview_p.h index f996a4c2f1..246124394a 100644 --- a/src/qml/jsruntime/qv4dataview_p.h +++ b/src/qml/jsruntime/qv4dataview_p.h @@ -60,11 +60,11 @@ namespace QV4 { namespace Heap { struct DataViewCtor : FunctionObject { - DataViewCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct DataView : Object { - DataView() {} + void init() { Object::init(); } Pointer<ArrayBuffer> buffer; uint byteLength; uint byteOffset; diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 04358fe3b5..4f3138a452 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -634,13 +634,15 @@ static double getLocalTZA() DEFINE_OBJECT_VTABLE(DateObject); -Heap::DateObject::DateObject(const QDateTime &date) +void Heap::DateObject::init(const QDateTime &date) { + Object::init(); this->date = date.isValid() ? date.toMSecsSinceEpoch() : qt_qnan(); } -Heap::DateObject::DateObject(const QTime &time) +void Heap::DateObject::init(const QTime &time) { + Object::init(); if (!time.isValid()) { date = qt_qnan(); return; @@ -668,9 +670,9 @@ QDateTime DateObject::toQDateTime() const DEFINE_OBJECT_VTABLE(DateCtor); -Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Date")) +void Heap::DateCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Date")); } void DateCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index c67acdcfa2..2d0648396e 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -63,24 +63,26 @@ namespace QV4 { namespace Heap { struct DateObject : Object { - DateObject() + void init() { + Object::init(); date = qt_qnan(); } - DateObject(const Value &date) + void init(const Value &date) { + Object::init(); this->date = date.toNumber(); } - DateObject(const QDateTime &date); - double date; + void init(const QDateTime &date); + void init(const QTime &time); - DateObject(const QTime &time); + double date; }; struct DateCtor : FunctionObject { - DateCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index fea6bbbd70..7265952f72 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -86,7 +86,9 @@ #include "qv4isel_masm_p.h" #endif // V4_ENABLE_JIT +#if QT_CONFIG(qml_interpreter) #include "qv4isel_moth_p.h" +#endif #if USE(PTHREADS) # include <pthread.h> @@ -160,6 +162,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) MemoryManager::GCBlocker gcBlocker(memoryManager); if (!factory) { +#if QT_CONFIG(qml_interpreter) bool jitDisabled = true; #ifdef V4_ENABLE_JIT @@ -180,6 +183,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) "very slow. Visit https://wiki.qt.io/V4 to learn about possible " "solutions for your platform."); } +#else + factory = new JIT::ISelFactory; +#endif } iselFactory.reset(factory); @@ -744,7 +750,7 @@ QQmlContextData *ExecutionEngine::callingQmlContext() const if (!ctx) return 0; - return ctx->qml->context.contextData(); + return ctx->qml->context->contextData(); } QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const @@ -920,7 +926,7 @@ ReturnedValue ExecutionEngine::throwError(const Value &value) QV4::Scope scope(this); QV4::Scoped<ErrorObject> error(scope, value); if (!!error) - exceptionStackTrace = error->d()->stackTrace; + exceptionStackTrace = *error->d()->stackTrace; else exceptionStackTrace = stackTrace(); @@ -1079,7 +1085,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int QV4::Scope scope(e); if (const QV4::VariantObject *v = value.as<QV4::VariantObject>()) - return v->d()->data; + return v->d()->data(); if (typeHint == QVariant::Bool) return QVariant(value.toBoolean()); @@ -1153,7 +1159,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return str; } if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>()) - return ld->d()->locale; + return *ld->d()->locale; if (const QV4::DateObject *d = value.as<DateObject>()) return d->toQDateTime(); if (const ArrayBuffer *d = value.as<ArrayBuffer>()) @@ -1693,7 +1699,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) return true; if (value->as<QV4::VariantObject>() && name.endsWith('*')) { int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant &var = value->as<QV4::VariantObject>()->d()->data; + QVariant &var = value->as<QV4::VariantObject>()->d()->data(); if (valueType == var.userType()) { // We have T t, T* is requested, so return &t. *reinterpret_cast<void* *>(data) = var.data(); @@ -1705,7 +1711,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) while (proto) { bool canCast = false; if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) { - const QVariant &v = vo->d()->data; + const QVariant &v = vo->d()->data(); canCast = (type == v.userType()) || (valueType && (valueType == v.userType())); } else if (proto->as<QV4::QObjectWrapper>()) { @@ -1760,7 +1766,7 @@ static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const Value &value) QV4::Scoped<QV4::VariantObject> v(scope, value); if (v) { - QVariant variant = v->d()->data; + QVariant variant = v->d()->data(); int type = variant.userType(); if (type == QMetaType::QObjectStar) return *reinterpret_cast<QObject* const *>(variant.constData()); diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 3763bf2613..597ded6ae1 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -67,8 +67,11 @@ using namespace QV4; -Heap::ErrorObject::ErrorObject() +void Heap::ErrorObject::init() { + Object::init(); + stackTrace = nullptr; + Scope scope(internalClass->engine); Scoped<QV4::ErrorObject> e(scope, this); @@ -81,8 +84,9 @@ Heap::ErrorObject::ErrorObject() *propertyData(QV4::ErrorObject::Index_LineNumber) = Encode::undefined(); } -Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t) +void Heap::ErrorObject::init(const Value &message, ErrorType t) { + Object::init(); errorType = t; Scope scope(internalClass->engine); @@ -91,18 +95,19 @@ Heap::ErrorObject::ErrorObject(const Value &message, ErrorType t) *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction(); *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined(); - e->d()->stackTrace = scope.engine->stackTrace(); - if (!e->d()->stackTrace.isEmpty()) { - *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source); - *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line); + e->d()->stackTrace = new StackTrace(scope.engine->stackTrace()); + if (!e->d()->stackTrace->isEmpty()) { + *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source); + *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line); } if (!message.isUndefined()) *propertyData(QV4::ErrorObject::Index_Message) = message; } -Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) +void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t) { + Object::init(); errorType = t; Scope scope(internalClass->engine); @@ -111,16 +116,16 @@ Heap::ErrorObject::ErrorObject(const Value &message, const QString &fileName, in *propertyData(QV4::ErrorObject::Index_Stack) = scope.engine->getStackFunction(); *propertyData(QV4::ErrorObject::Index_Stack + QV4::Object::SetterOffset) = Encode::undefined(); - e->d()->stackTrace = scope.engine->stackTrace(); + e->d()->stackTrace = new StackTrace(scope.engine->stackTrace()); StackFrame frame; frame.source = fileName; frame.line = line; frame.column = column; - e->d()->stackTrace.prepend(frame); + e->d()->stackTrace->prepend(frame); - if (!e->d()->stackTrace.isEmpty()) { - *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace.at(0).source); - *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace.at(0).line); + if (!e->d()->stackTrace->isEmpty()) { + *propertyData(QV4::ErrorObject::Index_FileName) = scope.engine->newString(e->d()->stackTrace->at(0).source); + *propertyData(QV4::ErrorObject::Index_LineNumber) = Primitive::fromInt32(e->d()->stackTrace->at(0).line); } if (!message.isUndefined()) @@ -156,10 +161,10 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx) return ctx->engine()->throwTypeError(); if (!This->d()->stack) { QString trace; - for (int i = 0; i < This->d()->stackTrace.count(); ++i) { + for (int i = 0; i < This->d()->stackTrace->count(); ++i) { if (i > 0) trace += QLatin1Char('\n'); - const StackFrame &frame = This->d()->stackTrace[i]; + const StackFrame &frame = This->d()->stackTrace->at(i); trace += frame.function + QLatin1Char('@') + frame.source; if (frame.line >= 0) trace += QLatin1Char(':') + QString::number(frame.line); @@ -181,44 +186,44 @@ DEFINE_OBJECT_VTABLE(ErrorObject); DEFINE_OBJECT_VTABLE(SyntaxErrorObject); -Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg) - : Heap::ErrorObject(msg, SyntaxError) +void Heap::SyntaxErrorObject::init(const Value &msg) { + Heap::ErrorObject::init(msg, SyntaxError); } -Heap::SyntaxErrorObject::SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, SyntaxError) +void Heap::SyntaxErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) { + Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, SyntaxError); } -Heap::EvalErrorObject::EvalErrorObject(const Value &message) - : Heap::ErrorObject(message, EvalError) +void Heap::EvalErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, EvalError); } -Heap::RangeErrorObject::RangeErrorObject(const Value &message) - : Heap::ErrorObject(message, RangeError) +void Heap::RangeErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, RangeError); } -Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &message) - : Heap::ErrorObject(message, ReferenceError) +void Heap::ReferenceErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, ReferenceError); } -Heap::ReferenceErrorObject::ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) - : Heap::ErrorObject(msg, fileName, lineNumber, columnNumber, ReferenceError) +void Heap::ReferenceErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber) { + Heap::ErrorObject::init(msg, fileName, lineNumber, columnNumber, ReferenceError); } -Heap::TypeErrorObject::TypeErrorObject(const Value &message) - : Heap::ErrorObject(message, TypeError) +void Heap::TypeErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, TypeError); } -Heap::URIErrorObject::URIErrorObject(const Value &message) - : Heap::ErrorObject(message, URIError) +void Heap::URIErrorObject::init(const Value &message) { + Heap::ErrorObject::init(message, URIError); } DEFINE_OBJECT_VTABLE(ErrorCtor); @@ -229,14 +234,14 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor); DEFINE_OBJECT_VTABLE(TypeErrorCtor); DEFINE_OBJECT_VTABLE(URIErrorCtor); -Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Error")) +void Heap::ErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Error")); } -Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name) - : Heap::FunctionObject(scope, name) +void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name) { + Heap::FunctionObject::init(scope, name); } void ErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -250,9 +255,9 @@ void ErrorCtor::call(const Managed *that, Scope &scope, CallData *callData) static_cast<const Object *>(that)->construct(scope, callData); } -Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("EvalError")) +void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("EvalError")); } void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -261,9 +266,9 @@ void EvalErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) scope.result = ErrorObject::create<EvalErrorObject>(scope.engine, v); } -Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("RangeError")) +void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("RangeError")); } void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -272,9 +277,9 @@ void RangeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData scope.result = ErrorObject::create<RangeErrorObject>(scope.engine, v); } -Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("ReferenceError")) +void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("ReferenceError")); } void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -283,9 +288,9 @@ void ReferenceErrorCtor::construct(const Managed *, Scope &scope, CallData *call scope.result = ErrorObject::create<ReferenceErrorObject>(scope.engine, v); } -Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("SyntaxError")) +void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("SyntaxError")); } void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -294,9 +299,9 @@ void SyntaxErrorCtor::construct(const Managed *, Scope &scope, CallData *callDat scope.result = ErrorObject::create<SyntaxErrorObject>(scope.engine, v); } -Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("TypeError")) +void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("TypeError")); } void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) @@ -305,9 +310,9 @@ void TypeErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) scope.result = ErrorObject::create<TypeErrorObject>(scope.engine, v); } -Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope) - : Heap::ErrorCtor(scope, QStringLiteral("URIError")) +void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope) { + Heap::ErrorCtor::init(scope, QStringLiteral("URIError")); } void URIErrorCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 42a3d05d9f..42a6e0b4b1 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -73,68 +73,72 @@ struct ErrorObject : Object { URIError }; - ErrorObject(); - ErrorObject(const Value &message, ErrorType t = Error); - ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); + void init(); + void init(const Value &message, ErrorType t = Error); + void init(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); + void destroy() { + delete stackTrace; + Object::destroy(); + } ErrorType errorType; - StackTrace stackTrace; + StackTrace *stackTrace; Pointer<String> stack; }; struct EvalErrorObject : ErrorObject { - EvalErrorObject(const Value &message); + void init(const Value &message); }; struct RangeErrorObject : ErrorObject { - RangeErrorObject(const Value &message); + void init(const Value &message); }; struct ReferenceErrorObject : ErrorObject { - ReferenceErrorObject(const Value &message); - ReferenceErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); + void init(const Value &message); + void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); }; struct SyntaxErrorObject : ErrorObject { - SyntaxErrorObject(const Value &message); - SyntaxErrorObject(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); + void init(const Value &message); + void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber); }; struct TypeErrorObject : ErrorObject { - TypeErrorObject(const Value &message); + void init(const Value &message); }; struct URIErrorObject : ErrorObject { - URIErrorObject(const Value &message); + void init(const Value &message); }; struct ErrorCtor : Heap::FunctionObject { - ErrorCtor(QV4::ExecutionContext *scope); - ErrorCtor(QV4::ExecutionContext *scope, const QString &name); + void init(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope, const QString &name); }; struct EvalErrorCtor : ErrorCtor { - EvalErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct RangeErrorCtor : ErrorCtor { - RangeErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct ReferenceErrorCtor : ErrorCtor { - ReferenceErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct SyntaxErrorCtor : ErrorCtor { - SyntaxErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct TypeErrorCtor : ErrorCtor { - TypeErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct URIErrorCtor : ErrorCtor { - URIErrorCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 300e538d3d..caabee322a 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -73,7 +73,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, } // duplicate arguments, need some trick to store them MemoryManager *mm = engine->memoryManager; - arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)), true); + arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe))); } } nFormals = compiledFunction->nFormals; @@ -105,7 +105,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr break; } // duplicate arguments, need some trick to store them - arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)), true); + arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe))); } } nFormals = parameters.size(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index e160dd8a36..2cc58b74a6 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -68,18 +68,20 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedFunctionObject f(s, this); f->init(name, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedString name(s, function->name()); @@ -87,9 +89,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *fun f->init(name, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope->engine()); ScopedFunctionObject f(s, this); @@ -97,9 +100,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString f->init(n, createProto); } -Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(ExecutionContext *scope, const QString &name, bool createProto) { + Object::init(); + function = nullptr; this->scope = scope; Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -107,9 +111,10 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &nam f->init(n, createProto); } -Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const ReturnedValue name) { + Object::init(); + function = nullptr; this->scope = scope->d(); Scope s(scope); ScopedFunctionObject f(s, this); @@ -117,9 +122,10 @@ Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const Returne f->init(n, false); } -Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name) - : function(Q_NULLPTR) +void Heap::FunctionObject::init(ExecutionContext *scope, const ReturnedValue name) { + Object::init(); + function = nullptr; this->scope = scope; Scope s(scope->engine); ScopedFunctionObject f(s, this); @@ -127,19 +133,21 @@ Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValu f->init(n, false); } -Heap::FunctionObject::FunctionObject() - : function(Q_NULLPTR) +void Heap::FunctionObject::init() { + Object::init(); + function = nullptr; this->scope = internalClass->engine->rootContext()->d(); Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()) == Index_Prototype); *propertyData(Index_Prototype) = Encode::undefined(); } -Heap::FunctionObject::~FunctionObject() +void Heap::FunctionObject::destroy() { if (function) function->compilationUnit->release(); + Object::destroy(); } void FunctionObject::init(String *n, bool createProto) @@ -227,7 +235,7 @@ QQmlSourceLocation FunctionObject::sourceLocation() const { if (isBinding()) { Q_ASSERT(as<const QV4::QQmlBindingFunction>()); - return static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation; + return *static_cast<QV4::Heap::QQmlBindingFunction *>(d())->bindingLocation; } QV4::Function *function = d()->function; Q_ASSERT(function); @@ -237,9 +245,9 @@ QQmlSourceLocation FunctionObject::sourceLocation() const DEFINE_OBJECT_VTABLE(FunctionCtor); -Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Function")) +void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Function")); } // 15.3.2 @@ -305,8 +313,9 @@ void FunctionCtor::call(const Managed *that, Scope &scope, CallData *callData) DEFINE_OBJECT_VTABLE(FunctionPrototype); -Heap::FunctionPrototype::FunctionPrototype() +void Heap::FunctionPrototype::init() { + Heap::FunctionObject::init(); } void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) @@ -417,9 +426,9 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx) DEFINE_OBJECT_VTABLE(ScriptFunction); -Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *function) - : Heap::SimpleScriptFunction(scope, function, true) +void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) { + Heap::SimpleScriptFunction::init(scope, function, true); } void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *callData) @@ -478,8 +487,9 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData) DEFINE_OBJECT_VTABLE(SimpleScriptFunction); -Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto) +void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *function, bool createProto) { + FunctionObject::init(); this->scope = scope->d(); this->function = function; @@ -599,10 +609,10 @@ Heap::Object *SimpleScriptFunction::protoForConstructor() DEFINE_OBJECT_VTABLE(BuiltinFunction); -Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) - : Heap::FunctionObject(scope, name) - , code(code) +void Heap::BuiltinFunction::init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)) { + Heap::FunctionObject::init(scope, name); + this->code = code; } void BuiltinFunction::construct(const Managed *f, Scope &scope, CallData *) @@ -656,10 +666,10 @@ DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); DEFINE_OBJECT_VTABLE(BoundFunction); -Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, - const Value &boundThis, QV4::MemberData *boundArgs) - : Heap::FunctionObject(scope, QStringLiteral("__bound function__")) +void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, + const Value &boundThis, QV4::MemberData *boundArgs) { + Heap::FunctionObject::init(scope, QStringLiteral("__bound function__")); this->target = target->d(); this->boundArgs = boundArgs ? boundArgs->d() : 0; this->boundThis = boundThis; diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 182b762606..e58b83e2c3 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -69,14 +69,14 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { Index_ProtoConstructor = 0 }; - FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false); - FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); - FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name); - FunctionObject(ExecutionContext *scope, const ReturnedValue name); - FunctionObject(); - ~FunctionObject(); + void init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false); + void init(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false); + void init(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false); + void init(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); + void init(QV4::ExecutionContext *scope, const ReturnedValue name); + void init(ExecutionContext *scope, const ReturnedValue name); + void init(); + void destroy(); unsigned int formalParameterCount() { return function ? function->nFormals : 0; } unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } @@ -87,20 +87,20 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { }; struct FunctionCtor : FunctionObject { - FunctionCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; struct FunctionPrototype : FunctionObject { - FunctionPrototype(); + void init(); }; struct Q_QML_EXPORT BuiltinFunction : FunctionObject { - BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); + void init(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *)); ReturnedValue (*code)(QV4::CallContext *); }; struct IndexedBuiltinFunction : FunctionObject { - inline IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index)); + inline void init(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index)); ReturnedValue (*code)(QV4::CallContext *, uint index); uint index; }; @@ -110,15 +110,15 @@ struct SimpleScriptFunction : FunctionObject { Index_Name = FunctionObject::Index_Prototype + 1, Index_Length }; - SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto); + void init(QV4::ExecutionContext *scope, Function *function, bool createProto); }; struct ScriptFunction : SimpleScriptFunction { - ScriptFunction(QV4::ExecutionContext *scope, Function *function); + void init(QV4::ExecutionContext *scope, Function *function); }; struct BoundFunction : FunctionObject { - BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); + void init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const Value &boundThis, QV4::MemberData *boundArgs); Pointer<FunctionObject> target; Value boundThis; Pointer<MemberData> boundArgs; @@ -216,12 +216,12 @@ struct IndexedBuiltinFunction: FunctionObject static void call(const Managed *that, Scope &scope, CallData *callData); }; -Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, - ReturnedValue (*code)(QV4::CallContext *ctx, uint index)) - : Heap::FunctionObject(scope), - code(code) - , index(index) +void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index, + ReturnedValue (*code)(QV4::CallContext *ctx, uint index)) { + Heap::FunctionObject::init(scope); + this->index = index; + this->code = code; } diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index b88e271a26..feb0d90d26 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -330,9 +330,9 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok) DEFINE_OBJECT_VTABLE(EvalFunction); -Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, scope->d()->engine->id_eval()) +void Heap::EvalFunction::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, scope->d()->engine->id_eval()); Scope s(scope); ScopedFunctionObject f(s, this); f->defineReadonlyProperty(s.engine->id_length(), Primitive::fromInt32(1)); diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 403639f8c1..e8b3a92d34 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -60,7 +60,7 @@ namespace QV4 { namespace Heap { struct EvalFunction : FunctionObject { - EvalFunction(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index c33d2cad11..be8057e9f5 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -41,7 +41,7 @@ #include "qv4scopedvalue_p.h" #include <QtQml/qjsengine.h> -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> #endif @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback) : v4(engine), m_url(url) -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) , m_redirectCount(0), m_network(0) , m_reply(0) #endif { @@ -71,7 +71,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, m_resultObject.set(v4, resultValue(v4)); -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) m_network = engine->v8Engine->networkAccessManager(); QNetworkRequest request; @@ -86,7 +86,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4Include::~QV4Include() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) delete m_reply; m_reply = 0; #endif @@ -135,7 +135,7 @@ QV4::ReturnedValue QV4Include::result() #define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15 void QV4Include::finished() { -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) m_redirectCount++; if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) { @@ -184,7 +184,7 @@ void QV4Include::finished() QV4::ScopedObject resultObj(scope, m_resultObject.value()); QV4::ScopedString status(scope, v4->newString(QStringLiteral("status"))); resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); -#endif //QT_NO_NETWORK +#endif // qml_network QV4::ScopedValue cb(scope, m_callbackFunction.value()); callback(cb, resultObj); @@ -211,7 +211,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>()) callbackFunction = ctx->args()[1]; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor()) url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile); diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 1750e6a7e1..4c601a5e7b 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QQmlEngine; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) class QNetworkAccessManager; #endif class QNetworkReply; @@ -94,7 +94,7 @@ private: QV4::ExecutionEngine *v4; QUrl m_url; -#ifndef QT_NO_NETWORK +#if QT_CONFIG(qml_network) int m_redirectCount; QNetworkAccessManager *m_network; QPointer<QNetworkReply> m_reply; diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index bac45e18c8..d17da9af0c 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -132,16 +132,20 @@ static void insertHoleIntoPropertyData(Object *object, int idx) int icSize = object->internalClass()->size; int from = qMax(idx, inlineSize); int to = from + 1; - if (from < icSize) - memmove(object->propertyData(to), object->propertyData(from), icSize - from - 1); + if (from < icSize) { + memmove(object->propertyData(to), object->propertyData(from), + (icSize - from - 1) * sizeof(Value)); + } if (from == idx) return; if (inlineSize < icSize) *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1); from = idx; to = from + 1; - if (from < inlineSize - 1) - memmove(object->propertyData(to), object->propertyData(from), inlineSize - from - 1); + if (from < inlineSize - 1) { + memmove(object->propertyData(to), object->propertyData(from), + (inlineSize - from - 1) * sizeof(Value)); + } } static void removeFromPropertyData(Object *object, int idx, bool accessor = false) diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 5b665d8836..94a6e4daa1 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -44,6 +44,7 @@ #include <qv4objectiterator_p.h> #include <qv4scopedvalue_p.h> #include <qv4runtime_p.h> +#include <qv4variantobject_p.h> #include "qv4string_p.h" #include <qstack.h> @@ -734,6 +735,10 @@ QString Stringify::Str(const QString &key, const Value &v) return std::isfinite(d) ? scope.result.toQString() : QStringLiteral("null"); } + if (const QV4::VariantObject *v = scope.result.as<QV4::VariantObject>()) { + return v->d()->data().toString(); + } + o = scope.result.asReturnedValue(); if (o) { if (!o->as<FunctionObject>()) { @@ -867,8 +872,9 @@ QString Stringify::JA(ArrayObject *a) } -Heap::JsonObject::JsonObject() +void Heap::JsonObject::init() { + Object::init(); Scope scope(internalClass->engine); ScopedObject o(scope, this); diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index c3a3b191c0..43248a214d 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -64,7 +64,7 @@ namespace QV4 { namespace Heap { struct JsonObject : Object { - JsonObject(); + void init(); }; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 764a8e7f3f..1fff5a45da 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -74,7 +74,7 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} #define V4_MANAGED_SIZE_TEST #endif -#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->~Data(); } +#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->destroy(); } #define V4_MANAGED_ITSELF(DataClass, superClass) \ @@ -88,9 +88,10 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \ QV4::Heap::DataClass *d() const { \ QV4::Heap::DataClass *dptr = d_unchecked(); \ - if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass) #define V4_MANAGED(DataClass, superClass) \ private: \ @@ -105,6 +106,18 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} #define Q_VTABLE_FUNCTION(classname, func) \ (classname::func == QV4::Managed::func ? 0 : classname::func) +// Q_VTABLE_FUNCTION triggers a bogus tautological-compare warning in GCC6+ +#if defined(Q_CC_GNU) && Q_CC_GNU >= 600 +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ + QT_WARNING_PUSH; \ + QT_WARNING_DISABLE_GCC("-Wtautological-compare") + +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF \ + ;QT_WARNING_POP +#else +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON +#define QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF +#endif #define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \ { \ @@ -124,7 +137,9 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} } #define DEFINE_MANAGED_VTABLE(classname) \ -const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF struct Q_QML_PRIVATE_EXPORT Managed : Value { diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 9fe8224736..e03b2762cc 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -51,8 +51,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(MathObject); -Heap::MathObject::MathObject() +void Heap::MathObject::init() { + Object::init(); Scope scope(internalClass->engine); ScopedObject m(scope, this); diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index 01e778d9ec..f6b1a4395f 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -59,7 +59,7 @@ namespace QV4 { namespace Heap { struct MathObject : Object { - MathObject(); + void init(); }; } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index 41da730428..969eee3619 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -66,7 +66,7 @@ struct MemberData : Base { }; Value data[1]; }; -Q_STATIC_ASSERT(std::is_trivial<MemberData>::value); +V4_ASSERT_IS_TRIVIAL(MemberData) } diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 444a4cd6f0..9b1f72bc17 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -73,9 +73,9 @@ const NumberLocale *NumberLocale::instance() return numberLocaleHolder(); } -Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Number")) +void Heap::NumberCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Number")); } void NumberCtor::construct(const Managed *, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 2416165c78..6022b3a029 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct NumberCtor : FunctionObject { - NumberCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index aeb185049f..00e6d230da 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1160,10 +1160,10 @@ void Object::initSparseArray() DEFINE_OBJECT_VTABLE(ArrayObject); -Heap::ArrayObject::ArrayObject(const QStringList &list) - : Heap::Object() +void Heap::ArrayObject::init(const QStringList &list) { - init(); + Object::init(); + commonInit(); Scope scope(internalClass->engine); ScopedObject a(scope, this); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 54ce2ea60d..d5195adaf0 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -68,7 +68,8 @@ namespace QV4 { namespace Heap { struct Object : Base { - inline Object() { Base::init(); } + void init() { Base::init(); } + void destroy() { Base::destroy(); } const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } @@ -93,9 +94,10 @@ struct Object : Base { Data *d_unchecked() const { return static_cast<Data *>(m()); } \ Data *d() const { \ Data *dptr = d_unchecked(); \ - if (std::is_trivial<Data>::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(Data); #define V4_OBJECT2(DataClass, superClass) \ private: \ @@ -111,9 +113,10 @@ struct Object : Base { QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \ QV4::Heap::DataClass *d() const { \ QV4::Heap::DataClass *dptr = d_unchecked(); \ - if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \ + dptr->_checkIsInitialized(); \ return dptr; \ - } + } \ + V4_ASSERT_IS_TRIVIAL(QV4::Heap::DataClass); #define V4_INTERNALCLASS(c) \ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \ @@ -141,7 +144,7 @@ struct ObjectVTable void (*advanceIterator)(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes); }; -#define DEFINE_OBJECT_VTABLE(classname) \ +#define DEFINE_OBJECT_VTABLE_BASE(classname) \ const QV4::ObjectVTable classname::static_vtbl = \ { \ DEFINE_MANAGED_VTABLE_INT(classname, (QT_PREPEND_NAMESPACE(QtPrivate)::is_same<classname::SuperClass, Object>::value) ? Q_NULLPTR : &classname::SuperClass::static_vtbl.vTable), \ @@ -161,7 +164,15 @@ const QV4::ObjectVTable classname::static_vtbl = \ advanceIterator \ } +#define DEFINE_OBJECT_VTABLE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +DEFINE_OBJECT_VTABLE_BASE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF +#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_ON \ +template<> DEFINE_OBJECT_VTABLE_BASE(classname) \ +QT_WARNING_SUPPRESS_GCC_TAUTOLOGICAL_COMPARE_OFF struct Q_QML_EXPORT Object: Managed { V4_OBJECT2(Object, Object) @@ -375,18 +386,22 @@ private: namespace Heap { struct BooleanObject : Object { - BooleanObject() {} - BooleanObject(bool b) - : b(b) - {} + void init() { Object::init(); } + void init(bool b) { + Object::init(); + this->b = b; + } + bool b; }; struct NumberObject : Object { - NumberObject() {} - NumberObject(double val) - : value(val) - {} + void init() { Object::init(); } + void init(double val) { + Object::init(); + value = val; + } + double value; }; @@ -395,10 +410,15 @@ struct ArrayObject : Object { LengthPropertyIndex = 0 }; - ArrayObject() - { init(); } - ArrayObject(const QStringList &list); - void init() + void init() { + Object::init(); + commonInit(); + } + + void init(const QStringList &list); + +private: + void commonInit() { *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } }; diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index 4354e09248..7943a13ac0 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -45,30 +45,6 @@ using namespace QV4; -ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags) - : engine(e) - , object(scratch1) - , current(scratch2) - , arrayNode(0) - , arrayIndex(0) - , memberIndex(0) - , flags(flags) -{ - init(o); -} - -ObjectIterator::ObjectIterator(Scope &scope, const Object *o, uint flags) - : engine(scope.engine) - , object(scope.alloc(1)) - , current(scope.alloc(1)) - , arrayNode(0) - , arrayIndex(0) - , memberIndex(0) - , flags(flags) -{ - init(o); -} - void ObjectIterator::init(const Object *o) { object->setM(o ? o->m() : 0); diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h index 6bef703a4d..98e94a95ea 100644 --- a/src/qml/jsruntime/qv4objectiterator_p.h +++ b/src/qml/jsruntime/qv4objectiterator_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct Q_QML_EXPORT ObjectIterator +struct Q_QML_EXPORT ObjectIteratorData { enum Flags { NoFlags = 0, @@ -72,21 +72,52 @@ struct Q_QML_EXPORT ObjectIterator uint arrayIndex; uint memberIndex; uint flags; +}; +V4_ASSERT_IS_TRIVIAL(ObjectIteratorData) + +struct Q_QML_EXPORT ObjectIterator: ObjectIteratorData +{ + ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags) + { + engine = e; + object = scratch1; + current = scratch2; + arrayNode = nullptr; + arrayIndex = 0; + memberIndex = 0; + this->flags = flags; + init(o); + } + + ObjectIterator(Scope &scope, const Object *o, uint flags) + { + engine = scope.engine; + object = scope.alloc(1); + current = scope.alloc(1); + arrayNode = nullptr; + arrayIndex = 0; + memberIndex = 0; + this->flags = flags; + init(o); + } - ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags); - ObjectIterator(Scope &scope, const Object *o, uint flags); - void init(const Object *o); void next(Value *name, uint *index, Property *pd, PropertyAttributes *attributes = 0); ReturnedValue nextPropertyName(Value *value); ReturnedValue nextPropertyNameAsString(Value *value); ReturnedValue nextPropertyNameAsString(); + +private: + void init(const Object *o); }; namespace Heap { struct ForEachIteratorObject : Object { - ForEachIteratorObject(QV4::Object *o); - ObjectIterator it; + void init(QV4::Object *o); + ObjectIterator &it() { return *reinterpret_cast<ObjectIterator*>(&itData); } Value workArea[2]; + +private: + ObjectIteratorData itData; }; } @@ -95,16 +126,18 @@ struct ForEachIteratorObject: Object { V4_OBJECT2(ForEachIteratorObject, Object) Q_MANAGED_TYPE(ForeachIteratorObject) - ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); } + ReturnedValue nextPropertyName() { return d()->it().nextPropertyNameAsString(); } protected: static void markObjects(Heap::Base *that, ExecutionEngine *e); }; inline -Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::Object *o) - : it(internalClass->engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) +void Heap::ForEachIteratorObject::init(QV4::Object *o) { + Object::init(); + it() = ObjectIterator(internalClass->engine, workArea, workArea + 1, o, + ObjectIterator::EnumerableOnly | ObjectIterator::WithProtoChain); } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index cfd76166f2..6020c48250 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -54,9 +54,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(ObjectCtor); -Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("Object")) +void Heap::ObjectCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("Object")); } void ObjectCtor::construct(const Managed *that, Scope &scope, CallData *callData) diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index 47a37b196f..e3d85782d5 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -61,7 +61,7 @@ namespace QV4 { namespace Heap { struct ObjectCtor : FunctionObject { - ObjectCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 7ca0692804..a892194df3 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -139,7 +139,7 @@ PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() while (p) { while (index < kEntriesPerPage - 1) { ++index; - if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type) + if (!static_cast<Page *>(p)->values[index].isEmpty()) return *this; } index = -1; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index b901d9be85..295b3413da 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -195,8 +195,9 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object } } -Heap::QObjectWrapper::QObjectWrapper(QObject *object) +void Heap::QObjectWrapper::init(QObject *object) { + Object::init(); qObj.init(object); } @@ -613,8 +614,14 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b) ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object) { - if (engine->jsEngine()) - QQmlData::ensurePropertyCache(engine->jsEngine(), object); + if (QJSEngine *jsEngine = engine->jsEngine()) { + if (QQmlPropertyCache *cache = QQmlData::ensurePropertyCache(jsEngine, object)) { + ReturnedValue result = QV4::Encode::null(); + void *args[] = { &result, &engine }; + if (cache->callJSFactoryMethod(object, args)) + return result; + } + } return (engine->memoryManager->allocObject<QV4::QObjectWrapper>(object))->asReturnedValue(); } @@ -978,6 +985,10 @@ void QObjectWrapper::destroyObject(bool lastCall) delete h->object(); else h->object()->deleteLater(); + } else { + // If the object is C++-owned, we still have to release the weak reference we have + // to it. + ddata->jsWrapper.clear(); } } } @@ -1678,7 +1689,7 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, in method->d()->setObject(object); if (QQmlData *ddata = QQmlData::get(object)) - method->d()->propertyCache = ddata->propertyCache; + method->d()->setPropertyCache(ddata->propertyCache); method->d()->index = index; return method.asReturnedValue(); @@ -1688,21 +1699,21 @@ ReturnedValue QObjectMethod::create(ExecutionContext *scope, const QQmlValueType { Scope valueScope(scope); Scoped<QObjectMethod> method(valueScope, valueScope.engine->memoryManager->allocObject<QObjectMethod>(scope)); - method->d()->propertyCache = valueType->d()->propertyCache; + method->d()->setPropertyCache(valueType->d()->propertyCache()); method->d()->index = index; method->d()->valueTypeWrapper = valueType->d(); return method.asReturnedValue(); } -Heap::QObjectMethod::QObjectMethod(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope) +void Heap::QObjectMethod::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope); } const QMetaObject *Heap::QObjectMethod::metaObject() { - if (propertyCache) - return propertyCache->createMetaObject(); + if (propertyCache()) + return propertyCache()->createMetaObject(); return object()->metaObject(); } @@ -1774,13 +1785,13 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const return; } - object = QQmlObjectOrGadget(d()->propertyCache.data(), d()->valueTypeWrapper->gadgetPtr); + object = QQmlObjectOrGadget(d()->propertyCache(), d()->valueTypeWrapper->gadgetPtr); } QQmlPropertyData method; - if (d()->propertyCache) { - QQmlPropertyData *data = d()->propertyCache->method(d()->index); + if (d()->propertyCache()) { + QQmlPropertyData *data = d()->propertyCache()->method(d()->index); if (!data) { scope.result = QV4::Encode::undefined(); return; @@ -1823,7 +1834,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const if (!method.isOverload()) { scope.result = CallPrecise(object, method, v4, callData); } else { - scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache); + scope.result = CallOverloaded(object, method, v4, callData, d()->propertyCache()); } } @@ -1839,13 +1850,15 @@ void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e) DEFINE_OBJECT_VTABLE(QObjectMethod); -Heap::QMetaObjectWrapper::QMetaObjectWrapper(const QMetaObject *metaObject) - : metaObject(metaObject) - , constructors(nullptr) - , constructorCount(0) -{} +void Heap::QMetaObjectWrapper::init(const QMetaObject *metaObject) +{ + FunctionObject::init(); + this->metaObject = metaObject; + constructors = nullptr; + constructorCount = 0; +} -Heap::QMetaObjectWrapper::~QMetaObjectWrapper() +void Heap::QMetaObjectWrapper::destroy() { delete[] constructors; } @@ -2011,9 +2024,10 @@ DEFINE_OBJECT_VTABLE(QMetaObjectWrapper); -Heap::QmlSignalHandler::QmlSignalHandler(QObject *object, int signalIndex) - : signalIndex(signalIndex) +void Heap::QmlSignalHandler::init(QObject *object, int signalIndex) { + Object::init(); + this->signalIndex = signalIndex; setObject(object); } @@ -2021,7 +2035,7 @@ DEFINE_OBJECT_VTABLE(QmlSignalHandler); void QmlSignalHandler::initProto(ExecutionEngine *engine) { - if (engine->signalHandlerPrototype()->d()) + if (engine->signalHandlerPrototype()->d_unchecked()) return; Scope scope(engine); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 076f304fea..8b2fd506e8 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -77,9 +77,12 @@ namespace Heap { struct QQmlValueTypeWrapper; -struct QObjectWrapper : Object { - QObjectWrapper(QObject *object); - ~QObjectWrapper() { qObj.destroy(); } +struct Q_QML_EXPORT QObjectWrapper : Object { + void init(QObject *object); + void destroy() { + qObj.destroy(); + Object::destroy(); + } QObject *object() const { return qObj.data(); } @@ -88,10 +91,22 @@ private: }; struct QObjectMethod : FunctionObject { - QObjectMethod(QV4::ExecutionContext *scope); - ~QObjectMethod() { qObj.destroy(); } - QQmlRefPointer<QQmlPropertyCache> propertyCache; - int index; + void init(QV4::ExecutionContext *scope); + void destroy() + { + setPropertyCache(nullptr); + qObj.destroy(); + FunctionObject::destroy(); + } + + QQmlPropertyCache *propertyCache() const { return _propertyCache; } + void setPropertyCache(QQmlPropertyCache *c) { + if (c) + c->addref(); + if (_propertyCache) + _propertyCache->release(); + _propertyCache = c; + } Pointer<QQmlValueTypeWrapper> valueTypeWrapper; @@ -101,6 +116,10 @@ struct QObjectMethod : FunctionObject { private: QQmlQPointer<QObject> qObj; + QQmlPropertyCache *_propertyCache; + +public: + int index; }; struct QMetaObjectWrapper : FunctionObject { @@ -108,14 +127,17 @@ struct QMetaObjectWrapper : FunctionObject { QQmlPropertyData *constructors; int constructorCount; - QMetaObjectWrapper(const QMetaObject* metaObject); - ~QMetaObjectWrapper(); + void init(const QMetaObject* metaObject); + void destroy(); void ensureConstructorsCache(); }; struct QmlSignalHandler : Object { - QmlSignalHandler(QObject *object, int signalIndex); - ~QmlSignalHandler() { qObj.destroy(); } + void init(QObject *object, int signalIndex); + void destroy() { + qObj.destroy(); + Object::destroy(); + } int signalIndex; QObject *object() const { return qObj.data(); } @@ -130,6 +152,7 @@ private: struct Q_QML_EXPORT QObjectWrapper : public Object { V4_OBJECT2(QObjectWrapper, Object) + V4_NEEDS_DESTROY enum RevisionMode { IgnoreRevision, CheckRevision }; diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index 6d6d446ca2..9e94c58432 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -62,11 +62,11 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets) WTF::String s(string); #if ENABLE(YARR_JIT) - if (!jitCode().isFallBack() && jitCode().has16BitCode()) - return uint(jitCode().execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); + if (!jitCode()->isFallBack() && jitCode()->has16BitCode()) + return uint(jitCode()->execute(s.characters16(), start, s.length(), (int*)matchOffsets).start); #endif - return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets); + return JSC::Yarr::interpret(byteCode(), s.characters16(), string.length(), start, matchOffsets); } Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline) @@ -90,33 +90,41 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); } -Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) - : pattern(pattern) - , ignoreCase(ignoreCase) - , multiLine(multiline) +void Heap::RegExp::init(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline) { Base::init(); + this->pattern = new QString(pattern); + this->ignoreCase = ignoreCase; + this->multiLine = multiline; const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) return; subPatternCount = yarrPattern.m_numSubpatterns; - byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + OwnPtr<JSC::Yarr::BytecodePattern> p = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); + byteCode = p.take(); #if ENABLE(YARR_JIT) + jitCode = new JSC::Yarr::YarrCodeBlock; if (!yarrPattern.m_containsBackreferences && engine->iselFactory->jitCompileRegexps()) { JSC::JSGlobalData dummy(engine->regExpAllocator); - JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, jitCode); + JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode); } #endif } -Heap::RegExp::~RegExp() +void Heap::RegExp::destroy() { if (cache) { RegExpCacheKey key(this); cache->remove(key); } +#if ENABLE(YARR_JIT) + delete jitCode; +#endif + delete byteCode; + delete pattern; + Base::destroy(); } void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e) diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index b99d717847..d3e63375a5 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -76,12 +76,13 @@ struct RegExpCacheKey; namespace Heap { struct RegExp : Base { - RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); - ~RegExp(); - QString pattern; - OwnPtr<JSC::Yarr::BytecodePattern> byteCode; + void init(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); + void destroy(); + + QString *pattern; + JSC::Yarr::BytecodePattern *byteCode; #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode; + JSC::Yarr::YarrCodeBlock *jitCode; #endif RegExpCache *cache; int subPatternCount; @@ -90,6 +91,7 @@ struct RegExp : Base { int captureCount() const { return subPatternCount + 1; } }; +V4_ASSERT_IS_TRIVIAL(RegExp) } @@ -99,10 +101,10 @@ struct RegExp : public Managed Q_MANAGED_TYPE(RegExp) V4_NEEDS_DESTROY - QString pattern() const { return d()->pattern; } - OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; } + QString pattern() const { return *d()->pattern; } + JSC::Yarr::BytecodePattern *byteCode() { return d()->byteCode; } #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; } + JSC::Yarr::YarrCodeBlock *jitCode() const { return d()->jitCode; } #endif RegExpCache *cache() const { return d()->cache; } int subPatternCount() const { return d()->subPatternCount; } @@ -111,7 +113,7 @@ struct RegExp : public Managed static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false); - bool isValid() const { return d()->byteCode.get(); } + bool isValid() const { return d()->byteCode; } uint match(const QString& string, int start, uint *matchOffsets); @@ -142,7 +144,7 @@ struct RegExpCacheKey }; inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re) - : pattern(re->pattern) + : pattern(*re->pattern) , ignoreCase(re->ignoreCase) , multiLine(re->multiLine) {} diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 203def0bcf..4022d98c3f 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -69,8 +69,9 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(RegExpObject); -Heap::RegExpObject::RegExpObject() +void Heap::RegExpObject::init() { + Object::init(); Scope scope(internalClass->engine); Scoped<QV4::RegExpObject> o(scope, this); o->d()->value = QV4::RegExp::create(scope.engine, QString(), false, false); @@ -78,9 +79,10 @@ Heap::RegExpObject::RegExpObject() o->initProperties(); } -Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global) - : global(global) +void Heap::RegExpObject::init(QV4::RegExp *value, bool global) { + Object::init(); + this->global = global; this->value = value->d(); Scope scope(internalClass->engine); Scoped<QV4::RegExpObject> o(scope, this); @@ -90,8 +92,9 @@ Heap::RegExpObject::RegExpObject(QV4::RegExp *value, bool global) // 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. -Heap::RegExpObject::RegExpObject(const QRegExp &re) +void Heap::RegExpObject::init(const QRegExp &re) { + Object::init(); global = false; // Convert the pattern to a ECMAScript pattern. @@ -145,7 +148,7 @@ void RegExpObject::initProperties() Q_ASSERT(value()); - QString p = value()->pattern; + QString p = *value()->pattern; if (p.isEmpty()) { p = QStringLiteral("(?:)"); } else { @@ -180,7 +183,7 @@ Value *RegExpObject::lastIndexProperty() QRegExp RegExpObject::toQRegExp() const { Qt::CaseSensitivity caseSensitivity = value()->ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive; - return QRegExp(value()->pattern, caseSensitivity, QRegExp::RegExp2); + return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2); } QString RegExpObject::toString() const @@ -217,9 +220,9 @@ uint RegExpObject::flags() const DEFINE_OBJECT_VTABLE(RegExpCtor); -Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("RegExp")) +void Heap::RegExpCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("RegExp")); clearLastMatch(); } diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 655e120c16..2c82cfdfd1 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -74,16 +74,16 @@ namespace QV4 { namespace Heap { struct RegExpObject : Object { - RegExpObject(); - RegExpObject(QV4::RegExp *value, bool global); - RegExpObject(const QRegExp &re); + void init(); + void init(QV4::RegExp *value, bool global); + void init(const QRegExp &re); Pointer<RegExp> value; bool global; }; struct RegExpCtor : FunctionObject { - RegExpCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); Value lastMatch; Pointer<String> lastInput; int lastMatchStart; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 5460304e7b..fffa6b8009 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -555,7 +555,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } double x = RuntimeHelpers::toNumber(pleft); double y = RuntimeHelpers::toNumber(pright); @@ -572,7 +572,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!right.stringValue()->d()->length()) return left.asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue(); } Scope scope(engine); @@ -590,7 +590,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) @@ -1462,7 +1462,7 @@ ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast<const QmlContext &>(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, captureRequired); + return QV4::QObjectWrapper::getProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, captureRequired); } ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) @@ -1480,7 +1480,7 @@ ReturnedValue Runtime::method_getQmlIdObject(ExecutionEngine *engine, const Valu { Scope scope(engine); const QmlContext &qmlContext = static_cast<const QmlContext &>(c); - QQmlContextData *context = qmlContext.d()->qml->context; + QQmlContextData *context = *qmlContext.d()->qml->context; if (!context || index >= (uint)context->idValueCount) return Encode::undefined(); @@ -1500,7 +1500,7 @@ void Runtime::method_setQmlScopeObjectProperty(ExecutionEngine *engine, const Va void Runtime::method_setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast<const QmlContext &>(context); - return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value); + return QV4::QObjectWrapper::setProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, value); } void Runtime::method_setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 44d171e087..5022d7c3bc 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -324,7 +324,7 @@ struct ScopedCallData { { int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value); ptr = reinterpret_cast<CallData *>(scope.alloc(size)); - ptr->tag = QV4::Value::Integer_Type; + ptr->tag = QV4::Value::Integer_Type_Internal; ptr->argc = argc; } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index b40307d2f0..552171256f 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -65,7 +65,7 @@ namespace QV4 { namespace Heap { struct QmlBindingWrapper : FunctionObject { - QmlBindingWrapper(QV4::QmlContext *scope, Function *f); + void init(QV4::QmlContext *scope, Function *f); }; } @@ -84,9 +84,10 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(QmlBindingWrapper); -Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::QmlContext *scope, Function *f) - : Heap::FunctionObject(scope, scope->d()->engine->id_eval(), /*createProto = */ false) +void Heap::QmlBindingWrapper::init(QV4::QmlContext *scope, Function *f) { + Heap::FunctionObject::init(scope, scope->d()->engine->id_eval(), /*createProto = */ false); + Q_ASSERT(scope->inUse()); function = f; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 59086c245c..3eb7772db7 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -216,11 +216,15 @@ namespace Heap { template <typename Container> struct QQmlSequence : Object { - QQmlSequence(const Container &container); - QQmlSequence(QObject *object, int propertyIndex); - ~QQmlSequence() { object.destroy(); } + void init(const Container &container); + void init(QObject *object, int propertyIndex); + void destroy() { + delete container; + object.destroy(); + Object::destroy(); + } - mutable Container container; + mutable Container *container; QQmlQPointer<QObject> object; int propertyIndex; bool isReference; @@ -260,10 +264,10 @@ public: loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx < d()->container.count()) { + if (signedIdx < d()->container->count()) { if (hasProperty) *hasProperty = true; - return convertElementToValue(engine(), d()->container.at(signedIdx)); + return convertElementToValue(engine(), d()->container->at(signedIdx)); } if (hasProperty) *hasProperty = false; @@ -289,22 +293,22 @@ public: qint32 signedIdx = static_cast<qint32>(index); - int count = d()->container.count(); + int count = d()->container->count(); typename Container::value_type element = convertValueToElement<typename Container::value_type>(value); if (signedIdx == count) { - d()->container.append(element); + d()->container->append(element); } else if (signedIdx < count) { - d()->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. */ - d()->container.reserve(signedIdx + 1); + d()->container->reserve(signedIdx + 1); while (signedIdx > count++) { - d()->container.append(typename Container::value_type()); + d()->container->append(typename Container::value_type()); } - d()->container.append(element); + d()->container->append(element); } if (d()->isReference) @@ -324,7 +328,7 @@ public: loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; + return (signedIdx < d()->container->count()) ? QV4::Attr_Data : QV4::Attr_Invalid; } void containerAdvanceIterator(ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attrs) @@ -340,11 +344,11 @@ public: loadReference(); } - if (it->arrayIndex < static_cast<uint>(d()->container.count())) { + if (it->arrayIndex < static_cast<uint>(d()->container->count())) { *index = it->arrayIndex; ++it->arrayIndex; *attrs = QV4::Attr_Data; - p->value = convertElementToValue(engine(), d()->container.at(*index)); + p->value = convertElementToValue(engine(), d()->container->at(*index)); return; } QV4::Object::advanceIterator(this, it, name, index, p, attrs); @@ -362,12 +366,12 @@ public: } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx >= d()->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. */ - d()->container.replace(signedIdx, typename Container::value_type()); + d()->container->replace(signedIdx, typename Container::value_type()); if (d()->isReference) storeReference(); @@ -432,10 +436,10 @@ public: QV4::Scope scope(ctx); if (ctx->argc() == 1 && ctx->args()[0].as<FunctionObject>()) { CompareFunctor cf(ctx, ctx->args()[0]); - std::sort(d()->container.begin(), d()->container.end(), cf); + std::sort(d()->container->begin(), d()->container->end(), cf); } else { DefaultCompareFunctor cf; - std::sort(d()->container.begin(), d()->container.end(), cf); + std::sort(d()->container->begin(), d()->container->end(), cf); } if (d()->isReference) @@ -454,7 +458,7 @@ public: return QV4::Encode(0); This->loadReference(); } - return QV4::Encode(This->d()->container.count()); + return QV4::Encode(This->d()->container->count()); } static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx) @@ -478,23 +482,23 @@ public: } /* Determine whether we need to modify the sequence */ qint32 newCount = static_cast<qint32>(newLength); - qint32 count = This->d()->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->d()->container.reserve(newCount); + This->d()->container->reserve(newCount); while (newCount > count++) { - This->d()->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->d()->container.removeAt(count); + This->d()->container->removeAt(count); } } /* write back if required. */ @@ -506,7 +510,7 @@ public: } QVariant toVariant() const - { return QVariant::fromValue<Container>(d()->container); } + { return QVariant::fromValue<Container>(*d()->container); } static QVariant toVariant(QV4::ArrayObject *array) { @@ -523,7 +527,7 @@ public: { Q_ASSERT(d()->object); Q_ASSERT(d()->isReference); - void *a[] = { &d()->container, 0 }; + void *a[] = { d()->container, 0 }; QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a); } @@ -533,7 +537,7 @@ public: Q_ASSERT(d()->isReference); int status = -1; QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding; - void *a[] = { &d()->container, 0, &status, &flags }; + void *a[] = { d()->container, 0, &status, &flags }; QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a); } @@ -554,11 +558,12 @@ public: template <typename Container> -Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) - : container(container) - , propertyIndex(-1) - , isReference(false) +void Heap::QQmlSequence<Container>::init(const Container &container) { + Object::init(); + this->container = new Container(container); + propertyIndex = -1; + isReference = false; object.init(); QV4::Scope scope(internalClass->engine); @@ -568,10 +573,12 @@ Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) } template <typename Container> -Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex) - : propertyIndex(propertyIndex) - , isReference(true) +void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex) { + Object::init(); + this->container = new Container; + this->propertyIndex = propertyIndex; + isReference = true; this->object.init(object); QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this); @@ -594,29 +601,21 @@ typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList; template<> DEFINE_OBJECT_VTABLE(QQmlBoolVectorList); typedef QQmlSequence<QStringList> QQmlQStringList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQStringList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList); typedef QQmlSequence<QList<QString> > QQmlStringList; -template<> -DEFINE_OBJECT_VTABLE(QQmlStringList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList); typedef QQmlSequence<QList<int> > QQmlIntList; -template<> -DEFINE_OBJECT_VTABLE(QQmlIntList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList); typedef QQmlSequence<QList<QUrl> > QQmlUrlList; -template<> -DEFINE_OBJECT_VTABLE(QQmlUrlList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList); typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQModelIndexList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList); typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList; -template<> -DEFINE_OBJECT_VTABLE(QQmlQItemSelectionRangeList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQItemSelectionRangeList); typedef QQmlSequence<QList<bool> > QQmlBoolList; -template<> -DEFINE_OBJECT_VTABLE(QQmlBoolList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolList); typedef QQmlSequence<QList<qreal> > QQmlRealList; -template<> -DEFINE_OBJECT_VTABLE(QQmlRealList); +DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealList); } diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 8bc867e2cd..3365ffe637 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -74,10 +74,10 @@ bool String::isEqualTo(Managed *t, Managed *o) } -Heap::String::String(MemoryManager *mm, const QString &t) - : mm(mm) +void Heap::String::init(MemoryManager *mm, const QString &t) { Base::init(); + this->mm = mm; subtype = String::StringType_Unknown; @@ -89,10 +89,10 @@ Heap::String::String(MemoryManager *mm, const QString &t) len = text->size; } -Heap::String::String(MemoryManager *mm, String *l, String *r, bool) // TODO: remove the dummy bool when String is trivial - : mm(mm) +void Heap::String::init(MemoryManager *mm, String *l, String *r) { Base::init(); + this->mm = mm; subtype = String::StringType_Unknown; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index f347ea8897..23ec3349b9 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -71,11 +71,12 @@ struct Q_QML_PRIVATE_EXPORT String : Base { }; #ifndef V4_BOOTSTRAP - String(MemoryManager *mm, const QString &text); - String(MemoryManager *mm, String *l, String *n, bool dummy); - ~String() { + void init(MemoryManager *mm, const QString &text); + void init(MemoryManager *mm, String *l, String *n); + void destroy() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); + Base::destroy(); } void simplifyString() const; int length() const { @@ -133,6 +134,7 @@ private: static void append(const String *data, QChar *ch); #endif }; +V4_ASSERT_IS_TRIVIAL(String) } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 1989f747e9..829ada0c1a 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -73,15 +73,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(StringObject); -Heap::StringObject::StringObject() +void Heap::StringObject::init() { + Object::init(); Q_ASSERT(vtable() == QV4::StringObject::staticVTable()); string = internalClass->engine->id_empty()->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(0); } -Heap::StringObject::StringObject(const QV4::String *str) +void Heap::StringObject::init(const QV4::String *str) { + Object::init(); string = str->d(); *propertyData(LengthPropertyIndex) = Primitive::fromInt32(length()); } @@ -152,9 +154,9 @@ void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e) DEFINE_OBJECT_VTABLE(StringCtor); -Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope) - : Heap::FunctionObject(scope, QStringLiteral("String")) +void Heap::StringCtor::init(QV4::ExecutionContext *scope) { + Heap::FunctionObject::init(scope, QStringLiteral("String")); } void StringCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -715,7 +717,7 @@ 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->d()->engine->newString(); } diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 54425b0909..b9f9d44fe8 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -65,8 +65,8 @@ struct StringObject : Object { LengthPropertyIndex = 0 }; - StringObject(); - StringObject(const QV4::String *string); + void init(); + void init(const QV4::String *string); String *string; Heap::String *getIndex(uint index) const; @@ -74,7 +74,7 @@ struct StringObject : Object { }; struct StringCtor : FunctionObject { - StringCtor(QV4::ExecutionContext *scope); + void init(QV4::ExecutionContext *scope); }; } diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index ae5ebcad1b..009c573bf8 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -202,10 +202,10 @@ const TypedArrayOperations operations[Heap::TypedArray::NTypes] = { }; -Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t) - : Heap::FunctionObject(scope, QLatin1String(operations[t].name)) - , type(t) +void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t) { + Heap::FunctionObject::init(scope, QLatin1String(operations[t].name)); + type = t; } void TypedArrayCtor::construct(const Managed *m, Scope &scope, CallData *callData) @@ -363,10 +363,11 @@ void TypedArrayCtor::call(const Managed *that, Scope &scope, CallData *callData) construct(that, scope, callData); } -Heap::TypedArray::TypedArray(Type t) - : type(operations + t), - arrayType(t) +void Heap::TypedArray::init(Type t) { + Object::init(); + type = operations + t; + arrayType = t; } Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type t) diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h index d96027b96a..0112d2e4a1 100644 --- a/src/qml/jsruntime/qv4typedarray_p.h +++ b/src/qml/jsruntime/qv4typedarray_p.h @@ -86,7 +86,7 @@ struct TypedArray : Object { NTypes }; - TypedArray(Type t); + void init(Type t); const TypedArrayOperations *type; Pointer<ArrayBuffer> buffer; @@ -96,13 +96,13 @@ struct TypedArray : Object { }; struct TypedArrayCtor : FunctionObject { - TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t); + void init(QV4::ExecutionContext *scope, TypedArray::Type t); TypedArray::Type type; }; struct TypedArrayPrototype : Object { - inline TypedArrayPrototype(TypedArray::Type t); + inline void init(TypedArray::Type t); TypedArray::Type type; }; @@ -160,10 +160,11 @@ struct TypedArrayPrototype : Object static ReturnedValue method_subarray(CallContext *ctx); }; -inline -Heap::TypedArrayPrototype::TypedArrayPrototype(TypedArray::Type t) - : type(t) +inline void +Heap::TypedArrayPrototype::init(TypedArray::Type t) { + Object::init(); + type = t; } } // namespace QV4 diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 78cd4de9fb..4428c48d80 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -76,23 +76,85 @@ private: /* We use two different ways of encoding JS values. One for 32bit and one for 64bit systems. - In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double NaN (actually -qNaN) - is indicated by a number that has the top 13 bits set. The other values are usually set to 0 by the - processor, and are thus free for us to store other data. We keep pointers in there for managed objects, - and encode the other types using the free space given to use by the unused bits for NaN values. This also - works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory. - - On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that - will make the number a NaN. The Masks below are used for encoding the other types. - - On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will get encoded - with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These - can be used, as the highest valid pointer on a 64 bit system is 2^48-1. - - If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer. - This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set). - - Bit 15-17 is then used to encode other immediates. + In both cases, we use 8 bytes for a value and a different variant of NaN boxing. A Double + NaN (actually -qNaN) is indicated by a number that has the top 13 bits set, and for a + signalling NaN it is the top 14 bits. The other values are usually set to 0 by the + processor, and are thus free for us to store other data. We keep pointers in there for + managed objects, and encode the other types using the free space given to use by the unused + bits for NaN values. This also works for pointers on 64 bit systems, as they all currently + only have 48 bits of addressable memory. (Note: we do leave the lower 49 bits available for + pointers.) + + On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value + that will make the number a NaN. The Masks below are used for encoding the other types. + + On 64 bit, we xor Doubles with (0xffff8000 << 32). That has the effect that no doubles will + get encoded with bits 63-49 all set to 0. We then use bit 48 to distinguish between + managed/undefined (0), or Null/Int/Bool/Empty (1). So, storing a 49 bit pointer will leave + the top 15 bits 0, which is exactly the 'natural' representation of pointers. If bit 49 is + set, bit 48 indicates Empty (0) or integer-convertible (1). Then the 3 bit below that are + used to encode Null/Int/Bool. + + On both 32bit and 64bit, Undefined is encoded as a managed pointer with value 0. This is + the same as a nullptr. + + Specific bit-sequences: + 0 = always 0 + 1 = always 1 + x = stored value + a,b,c,d = specific bit values, see notes + + 64bit: + + 32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210 | + 66665555 55555544 44444444 33333333 33222222 22221111 11111100 00000000 | JS Value + ------------------------------------------------------------------------+-------------- + 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | Undefined + 00000000 0000000x xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Managed (heap pointer) + a0000000 0000bc00 00000000 00000000 00000000 00000000 00000000 00000000 | NaN/Inf + dddddddd ddddddxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | double + 00000000 00000010 00000000 00000000 00000000 00000000 00000000 00000000 | empty (non-sparse array hole) + 00000000 00000011 10000000 00000000 00000000 00000000 00000000 00000000 | Null + 00000000 00000011 01000000 00000000 00000000 00000000 00000000 0000000x | Bool + 00000000 00000011 00100000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Int + + Notes: + - a: xor-ed signbit, always 1 for NaN + - bc, xor-ed values: 11 = inf, 10 = sNaN, 01 = qNaN, 00 = boxed value + - d: xor-ed bits, where at least one bit is set, so: (val >> (64-14)) > 0 + - Undefined maps to C++ nullptr, so the "default" initialization is the same for both C++ + and JS + - Managed has the left 15 bits set to 0, so: (val >> (64-15)) == 0 + - empty, Null, Bool, and Int have the left 14 bits set to 0, and bit 49 set to 1, + so: (val >> (64-15)) == 1 + - Null, Bool, and Int have bit 48 set, indicating integer-convertible + - xoring _val with NaNEncodeMask will convert to a double in "natural" representation, where + any non double results in a NaN + + 32bit: + + 32109876 54321098 76543210 98765432 10987654 32109876 54321098 76543210 | + 66665555 55555544 44444444 33333333 33222222 22221111 11111100 00000000 | JS Value + ------------------------------------------------------------------------+-------------- + 01111111 11111100 00000000 00000000 00000000 00000000 00000000 00000000 | Undefined + 01111111 11111100 00000000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Managed (heap pointer) + a1111111 1111bc00 00000000 00000000 00000000 00000000 00000000 00000000 | NaN/Inf + xddddddd ddddddxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | double + 01111111 11111110 00000000 00000000 00000000 00000000 00000000 00000000 | empty (non-sparse array hole) + 01111111 11111111 10000000 00000000 00000000 00000000 00000000 00000000 | Null + 01111111 11111111 01000000 00000000 00000000 00000000 00000000 0000000x | Bool + 01111111 11111111 00100000 00000000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | Int + + Notes: + - the upper 32 bits are the tag, the lower 32 bits the value + - Undefined has a nullptr in the value, Managed has a non-nullptr stored in the value + - a: sign bit, always 0 for NaN + - b,c: 00=inf, 01 = sNaN, 10 = qNaN, 11 = boxed value + - d: stored double value, as long as not *all* of them are 1, because that's a boxed value + (see above) + - empty, Null, Bool, and Int have bit 63 set to 0, bits 62-50 set to 1 (same as undefined + and managed), and bit 49 set to 1 (where undefined and managed have it set to 0) + - Null, Bool, and Int have bit 48 set, indicating integer-convertible */ quint64 _val; @@ -140,7 +202,7 @@ public: { quint32 v; memcpy(&v, &b, 4); - setTagValue(Managed_Type, v); + setTagValue(Managed_Type_Internal, v); } #endif @@ -156,12 +218,43 @@ public: Q_ALWAYS_INLINE void setEmpty() { - setTagValue(Empty_Type, value()); + setTagValue(Empty_Type_Internal, value()); } Q_ALWAYS_INLINE void setEmpty(int i) { - setTagValue(Empty_Type, quint32(i)); + setTagValue(Empty_Type_Internal, quint32(i)); + } + + Q_ALWAYS_INLINE void setEmpty(quint32 i) + { + setTagValue(Empty_Type_Internal, i); + } + + Q_ALWAYS_INLINE quint32 emptyValue() + { + Q_ASSERT(isEmpty()); + return quint32(value()); + } + + enum Type { + Undefined_Type, + Managed_Type, + Empty_Type, + Integer_Type, + Boolean_Type, + Null_Type, + Double_Type + }; + + inline Type type() const { + if (isUndefined()) return Undefined_Type; + if (isManaged()) return Managed_Type; + if (isEmpty()) return Empty_Type; + if (isInteger()) return Integer_Type; + if (isBoolean()) return Boolean_Type; + if (isNull()) return Null_Type; + Q_ASSERT(isDouble()); return Double_Type; } #ifndef QV4_USE_64_BIT_VALUE_ENCODING @@ -169,101 +262,64 @@ public: SilentNaNBit = 0x00040000, NaN_Mask = 0x7ff80000, NotDouble_Mask = 0x7ffa0000, - Type_Mask = 0xffffc000, - Immediate_Mask = NotDouble_Mask | 0x00004000 | SilentNaNBit, - IsNullOrUndefined_Mask = Immediate_Mask | 0x08000, + Immediate_Mask = NotDouble_Mask | 0x00020000u | SilentNaNBit, Tag_Shift = 32 }; - enum ValueType { - Undefined_Type = Immediate_Mask | 0x00000, - Null_Type = Immediate_Mask | 0x10000, - Boolean_Type = Immediate_Mask | 0x08000, - Integer_Type = Immediate_Mask | 0x18000, - Managed_Type = NotDouble_Mask | 0x00000 | SilentNaNBit, - Empty_Type = NotDouble_Mask | 0x18000 | SilentNaNBit - }; - - enum ImmediateFlags { - ConvertibleToInt = Immediate_Mask | 0x1 - }; - - enum ValueTypeInternal { - Null_Type_Internal = Null_Type | ConvertibleToInt, - Boolean_Type_Internal = Boolean_Type | ConvertibleToInt, - Integer_Type_Internal = Integer_Type | ConvertibleToInt, + enum { + Managed_Type_Internal = NotDouble_Mask }; #else - static const quint64 NaNEncodeMask = 0xffff800000000000ll; - static const quint64 IsInt32Mask = 0x0002000000000000ll; - static const quint64 IsDoubleMask = 0xfffc000000000000ll; - static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask; - static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll; - static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll; - static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask; + static const quint64 NaNEncodeMask = 0xfffc000000000000ll; + static const quint64 Immediate_Mask = 0x00020000u; // bit 49 enum Masks { NaN_Mask = 0x7ff80000, - Type_Mask = 0xffff8000, - IsDouble_Mask = 0xfffc0000, - Immediate_Mask = 0x00018000, - IsNullOrUndefined_Mask = 0x00008000, - IsNullOrBoolean_Mask = 0x00010000, - Tag_Shift = 32 - }; - enum ValueType { - Undefined_Type = IsNullOrUndefined_Mask, - Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask, - Boolean_Type = IsNullOrBoolean_Mask, - Integer_Type = 0x20000|IsNullOrBoolean_Mask, - Managed_Type = 0, - Empty_Type = Undefined_Type | 0x4000 }; enum { IsDouble_Shift = 64-14, - IsNumber_Shift = 64-15, - IsConvertibleToInt_Shift = 64-16, - IsManaged_Shift = 64-17 + IsManagedOrUndefined_Shift = 64-15, + IsIntegerConvertible_Shift = 64-16, + Tag_Shift = 32, + IsDoubleTag_Shift = IsDouble_Shift - Tag_Shift, + Managed_Type_Internal = 0 }; - - +#endif enum ValueTypeInternal { - Null_Type_Internal = Null_Type, - Boolean_Type_Internal = Boolean_Type, - Integer_Type_Internal = Integer_Type + Empty_Type_Internal = Immediate_Mask | 0, + ConvertibleToInt = Immediate_Mask | 0x10000u, // bit 48 + Null_Type_Internal = ConvertibleToInt | 0x08000u, + Boolean_Type_Internal = ConvertibleToInt | 0x04000u, + Integer_Type_Internal = ConvertibleToInt | 0x02000u }; -#endif - - inline unsigned type() const { - return tag() & Type_Mask; - } // used internally in property - inline bool isEmpty() const { return tag() == Empty_Type; } - - inline bool isUndefined() const { return tag() == Undefined_Type; } + inline bool isEmpty() const { return tag() == Empty_Type_Internal; } inline bool isNull() const { return tag() == Null_Type_Internal; } - inline bool isBoolean() const { return tag ()== Boolean_Type_Internal; } + inline bool isBoolean() const { return tag() == Boolean_Type_Internal; } + inline bool isInteger() const { return tag() == Integer_Type_Internal; } + inline bool isNullOrUndefined() const { return isNull() || isUndefined(); } + inline bool isNumber() const { return isDouble() || isInteger(); } + #ifdef QV4_USE_64_BIT_VALUE_ENCODING - inline bool isInteger() const { return (_val >> IsNumber_Shift) == 1; } + inline bool isUndefined() const { return _val == 0; } inline bool isDouble() const { return (_val >> IsDouble_Shift); } - inline bool isNumber() const { return (_val >> IsNumber_Shift); } - inline bool isManaged() const { return !(_val >> IsManaged_Shift); } - inline bool isNullOrUndefined() const { return ((_val >> IsManaged_Shift) & ~2) == 1; } - inline bool integerCompatible() const { return ((_val >> IsConvertibleToInt_Shift) & ~2) == 1; } + inline bool isManaged() const { return !isUndefined() && ((_val >> IsManagedOrUndefined_Shift) == 0); } + + inline bool integerCompatible() const { + return (_val >> IsIntegerConvertible_Shift) == 3; + } static inline bool integerCompatible(Value a, Value b) { return a.integerCompatible() && b.integerCompatible(); } static inline bool bothDouble(Value a, Value b) { return a.isDouble() && b.isDouble(); } - inline bool isNaN() const { return (tag() & 0x7fff8000) == 0x00078000; } + inline bool isNaN() const { return (tag() & 0x7ffc0000 ) == 0x00040000; } #else - inline bool isInteger() const { return tag() == Integer_Type_Internal; } + inline bool isUndefined() const { return tag() == Managed_Type_Internal && value() == 0; } inline bool isDouble() const { return (tag() & NotDouble_Mask) != NotDouble_Mask; } - inline bool isNumber() const { return tag() == Integer_Type_Internal || (tag() & NotDouble_Mask) != NotDouble_Mask; } - inline bool isManaged() const { return tag() == Managed_Type; } - inline bool isNullOrUndefined() const { return (tag() & IsNullOrUndefined_Mask) == Undefined_Type; } + inline bool isManaged() const { return tag() == Managed_Type_Internal && !isUndefined(); } inline bool integerCompatible() const { return (tag() & ConvertibleToInt) == ConvertibleToInt; } static inline bool integerCompatible(Value a, Value b) { return ((a.tag() & b.tag()) & ConvertibleToInt) == ConvertibleToInt; @@ -428,7 +484,7 @@ public: template<typename T> Value &operator=(const Scoped<T> &t); }; -Q_STATIC_ASSERT(std::is_trivial<Value>::value); +V4_ASSERT_IS_TRIVIAL(Value) inline bool Value::isString() const { @@ -491,6 +547,7 @@ ReturnedValue Heap::Base::asReturnedValue() const struct Q_QML_PRIVATE_EXPORT Primitive : public Value { inline static Primitive emptyValue(); + inline static Primitive emptyValue(uint v); static inline Primitive fromBoolean(bool b); static inline Primitive fromInt32(int i); inline static Primitive undefinedValue(); @@ -509,14 +566,21 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value inline Primitive Primitive::undefinedValue() { Primitive v; - v.setTagValue(Undefined_Type, 0); + v.setM(Q_NULLPTR); return v; } inline Primitive Primitive::emptyValue() { Primitive v; - v.setTagValue(Value::Empty_Type, 0); + v.setEmpty(0); + return v; +} + +inline Primitive Primitive::emptyValue(uint e) +{ + Primitive v; + v.setEmpty(e); return v; } @@ -544,7 +608,6 @@ inline Primitive Primitive::fromDouble(double d) inline Primitive Primitive::fromInt32(int i) { Primitive v; - v.setTagValue(Integer_Type_Internal, 0); v.setInt_32(i); return v; } @@ -562,31 +625,23 @@ inline Primitive Primitive::fromUInt32(uint i) struct Encode { static ReturnedValue undefined() { - return quint64(Value::Undefined_Type) << Value::Tag_Shift; + return Primitive::undefinedValue().rawValue(); } static ReturnedValue null() { - return quint64(Value::Null_Type_Internal) << Value::Tag_Shift; + return Primitive::nullValue().rawValue(); } Encode(bool b) { - val = (quint64(Value::Boolean_Type_Internal) << Value::Tag_Shift) | (uint)b; + val = Primitive::fromBoolean(b).rawValue(); } Encode(double d) { - Value v; - v.setDouble(d); - val = v.rawValue(); + val = Primitive::fromDouble(d).rawValue(); } Encode(int i) { - val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | (uint)i; + val = Primitive::fromInt32(i).rawValue(); } Encode(uint i) { - if (i <= INT_MAX) { - val = (quint64(Value::Integer_Type_Internal) << Value::Tag_Shift) | i; - } else { - Value v; - v.setDouble(i); - val = v.rawValue(); - } + val = Primitive::fromUInt32(i).rawValue(); } Encode(ReturnedValue v) { val = v; diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp index 39b41dd0d8..455a7ccb65 100644 --- a/src/qml/jsruntime/qv4variantobject.cpp +++ b/src/qml/jsruntime/qv4variantobject.cpp @@ -50,20 +50,23 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(VariantObject); -Heap::VariantObject::VariantObject() +void Heap::VariantObject::init() { + Object::init(); + scarceData = new ExecutionEngine::ScarceResourceData; } -Heap::VariantObject::VariantObject(const QVariant &value) +void Heap::VariantObject::init(const QVariant &value) { - data = value; + Object::init(); + scarceData = new ExecutionEngine::ScarceResourceData(value); if (isScarce()) - internalClass->engine->scarceResources.insert(this); + removeVmePropertyReference(); } bool VariantObject::Data::isScarce() const { - QVariant::Type t = data.type(); + QVariant::Type t = data().type(); return t == QVariant::Pixmap || t == QVariant::Image; } @@ -73,10 +76,10 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other) QV4::VariantObject *lv = static_cast<QV4::VariantObject *>(m); if (QV4::VariantObject *rv = other->as<QV4::VariantObject>()) - return lv->d()->data == rv->d()->data; + return lv->d()->data() == rv->d()->data(); if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>()) - return v->isEqual(lv->d()->data); + return v->isEqual(lv->d()->data()); return false; } @@ -87,7 +90,7 @@ void VariantObject::addVmePropertyReference() // remove from the ep->scarceResources list // since it is now no longer eligible to be // released automatically by the engine. - d()->node.remove(); + d()->addVmePropertyReference(); } } @@ -97,7 +100,7 @@ void VariantObject::removeVmePropertyReference() // and add to the ep->scarceResources list // since it is now eligible to be released // automatically by the engine. - internalClass()->engine->scarceResources.insert(d()); + d()->removeVmePropertyReference(); } } @@ -115,7 +118,7 @@ QV4::ReturnedValue VariantPrototype::method_preserve(CallContext *ctx) Scope scope(ctx); Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>()); if (o && o->d()->isScarce()) - o->d()->node.remove(); + o->d()->addVmePropertyReference(); return Encode::undefined(); } @@ -125,8 +128,8 @@ QV4::ReturnedValue VariantPrototype::method_destroy(CallContext *ctx) Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>()); if (o) { if (o->d()->isScarce()) - o->d()->node.remove(); - o->d()->data = QVariant(); + o->d()->addVmePropertyReference(); + o->d()->data() = QVariant(); } return Encode::undefined(); } @@ -137,10 +140,10 @@ QV4::ReturnedValue VariantPrototype::method_toString(CallContext *ctx) Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>()); if (!o) return Encode::undefined(); - QString result = o->d()->data.toString(); - if (result.isEmpty() && !o->d()->data.canConvert(QVariant::String)) { + QString result = o->d()->data().toString(); + if (result.isEmpty() && !o->d()->data().canConvert(QVariant::String)) { result = QLatin1String("QVariant(") - + QLatin1String(o->d()->data.typeName()) + + QLatin1String(o->d()->data().typeName()) + QLatin1Char(')'); } return Encode(ctx->d()->engine->newString(result)); @@ -151,7 +154,7 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx) Scope scope(ctx); Scoped<VariantObject> o(scope, ctx->thisObject().as<QV4::VariantObject>()); if (o) { - QVariant v = o->d()->data; + QVariant v = o->d()->data(); switch (v.type()) { case QVariant::Invalid: return Encode::undefined(); diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index e50706ef94..9a04069c12 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -64,16 +64,28 @@ namespace QV4 { namespace Heap { -struct VariantObject : Object, public ExecutionEngine::ScarceResourceData +struct VariantObject : Object { - VariantObject(); - VariantObject(const QVariant &value); - ~VariantObject() { + void init(); + void init(const QVariant &value); + void destroy() { + Q_ASSERT(scarceData); if (isScarce()) - node.remove(); + addVmePropertyReference(); + delete scarceData; + Object::destroy(); } bool isScarce() const; int vmePropertyReferenceCount; + + const QVariant &data() const { return scarceData->data; } + QVariant &data() { return scarceData->data; } + + void addVmePropertyReference() { scarceData->node.remove(); } + void removeVmePropertyReference() { internalClass->engine->scarceResources.insert(scarceData); } + +private: + ExecutionEngine::ScarceResourceData *scarceData; }; } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 9d18713253..0f7f6b1f75 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -571,7 +571,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code #endif // DO_TRACE_INSTR Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, engine->runtime.callValue(engine, VALUE(instr.dest), callData)); @@ -581,7 +581,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.callProperty(engine, instr.name, callData)); @@ -590,7 +590,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallPropertyLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.callPropertyLookup(engine, instr.lookupIndex, callData)); @@ -600,7 +600,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.callQmlScopeObjectProperty(engine, instr.index, callData)); @@ -610,7 +610,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData()); Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.callQmlContextObjectProperty(engine, instr.index, callData)); @@ -619,7 +619,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallElement) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.callElement(engine, VALUE(instr.index), callData)); @@ -628,7 +628,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallActivationProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, engine->runtime.callActivationProperty(engine, instr.name, callData)); @@ -637,7 +637,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CallGlobalLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData)); @@ -743,7 +743,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateValue) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, engine->runtime.constructValue(engine, VALUE(instr.func), callData)); @@ -752,7 +752,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.constructProperty(engine, instr.name, callData)); @@ -761,7 +761,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(ConstructPropertyLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); STOREVALUE(instr.result, engine->runtime.constructPropertyLookup(engine, instr.index, callData)); @@ -770,7 +770,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(CreateActivationProperty) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, engine->runtime.constructActivationProperty(engine, instr.name, callData)); @@ -779,7 +779,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(ConstructGlobalLookup) Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize); QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData); - callData->tag = QV4::Value::Integer_Type; + callData->tag = QV4::Value::Integer_Type_Internal; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); STOREVALUE(instr.result, engine->runtime.constructGlobalLookup(engine, instr.index, callData)); diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h index cd8d335f1c..f8893509d9 100644 --- a/src/qml/jsruntime/qv4vme_moth_p.h +++ b/src/qml/jsruntime/qv4vme_moth_p.h @@ -51,9 +51,12 @@ // We mean it. // +#include <private/qv4global_p.h> #include <private/qv4runtime_p.h> #include <private/qv4instr_moth_p.h> +QT_REQUIRE_CONFIG(qml_interpreter); + QT_BEGIN_NAMESPACE namespace QV4 { |