diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-09-09 10:06:31 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-10-05 13:15:18 +0000 |
commit | 64afa01c32fc1824b280452ceb1ade4f655487f2 (patch) | |
tree | f5775f2ddfd5145ae26df41a356dfa14172200b7 | |
parent | a166367bd877a55e552e3dfe5cf2ee7fa1561100 (diff) |
QML: Introduce destroy() on Base subclasses
This removes the destructors of subclasses of Base, making them nearly
trivial.
Change-Id: Ia6f7d467e87899b5ad37b8709a8f633a51689d59
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
34 files changed, 244 insertions, 197 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index f76bca2747..609a8f6b8f 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -113,17 +113,26 @@ namespace Heap { QQmlSqlDatabaseWrapper() { type = Database; + database = new QSqlDatabase; + version = new QString; + sqlQuery = new QSqlQuery; + } + + void destroy() { + delete database; + delete version; + delete sqlQuery; } Type type; - QSqlDatabase database; + QSqlDatabase *database; - QString version; // type == Database + QString *version; // type == Database bool inTransaction; // type == Query bool readonly; // type == Query - QSqlQuery sqlQuery; // type == Rows + QSqlQuery *sqlQuery; // type == Rows bool forwardOnly; // type == Rows }; } @@ -160,7 +169,7 @@ static ReturnedValue qmlsqldatabase_version(CallContext *ctx) if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database) V4THROW_REFERENCE("Not a SQLDatabase object"); - return Encode(scope.engine->newString(r->d()->version)); + return Encode(scope.engine->newString(*r->d()->version)); } static ReturnedValue qmlsqldatabase_rows_length(CallContext *ctx) @@ -170,11 +179,11 @@ static ReturnedValue qmlsqldatabase_rows_length(CallContext *ctx) if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows) V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); - int s = r->d()->sqlQuery.size(); + int s = r->d()->sqlQuery->size(); if (s < 0) { // Inefficient - if (r->d()->sqlQuery.last()) { - s = r->d()->sqlQuery.at() + 1; + if (r->d()->sqlQuery->last()) { + s = r->d()->sqlQuery->at() + 1; } else { s = 0; } @@ -188,7 +197,7 @@ static ReturnedValue qmlsqldatabase_rows_forwardOnly(CallContext *ctx) QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->thisObject().as<QQmlSqlDatabaseWrapper>()); if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows) V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); - return Encode(r->d()->sqlQuery.isForwardOnly()); + return Encode(r->d()->sqlQuery->isForwardOnly()); } static ReturnedValue qmlsqldatabase_rows_setForwardOnly(CallContext *ctx) @@ -200,7 +209,7 @@ static ReturnedValue qmlsqldatabase_rows_setForwardOnly(CallContext *ctx) if (ctx->argc() < 1) return ctx->engine()->throwTypeError(); - r->d()->sqlQuery.setForwardOnly(ctx->args()[0].toBoolean()); + r->d()->sqlQuery->setForwardOnly(ctx->args()[0].toBoolean()); return Encode::undefined(); } @@ -230,8 +239,8 @@ static ReturnedValue qmlsqldatabase_rows_index(const QQmlSqlDatabaseWrapper *r, { Scope scope(v4); - if (r->d()->sqlQuery.at() == (int)index || r->d()->sqlQuery.seek(index)) { - QSqlRecord record = r->d()->sqlQuery.record(); + if (r->d()->sqlQuery->at() == (int)index || r->d()->sqlQuery->seek(index)) { + QSqlRecord record = r->d()->sqlQuery->record(); // XXX optimize ScopedObject row(scope, v4->newObject()); for (int ii = 0; ii < record.count(); ++ii) { @@ -289,7 +298,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx) if (!r->d()->inTransaction) V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()")); - QSqlDatabase db = r->d()->database; + QSqlDatabase db = *r->d()->database; QString sql = ctx->argc() ? ctx->args()[0].toQString() : QString(); @@ -338,8 +347,8 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx) QV4::ScopedObject p(scope, databaseData(scope.engine)->rowsProto.value()); rows->setPrototype(p.getPointer()); rows->d()->type = Heap::QQmlSqlDatabaseWrapper::Rows; - rows->d()->database = db; - rows->d()->sqlQuery = query; + *rows->d()->database = db; + *rows->d()->sqlQuery = query; ScopedObject resultObject(scope, scope.engine->newObject()); result = resultObject.asReturnedValue(); @@ -401,20 +410,20 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx) if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database) V4THROW_REFERENCE("Not a SQLDatabase object"); - QSqlDatabase db = r->d()->database; + QSqlDatabase db = *r->d()->database; QString from_version = ctx->args()[0].toQString(); QString to_version = ctx->args()[1].toQString(); ScopedFunctionObject callback(scope, ctx->argument(2)); - if (from_version != r->d()->version) - V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->d()->version)); + if (from_version != *r->d()->version) + V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(*r->d()->version)); Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine)); ScopedObject p(scope, databaseData(scope.engine)->queryProto.value()); w->setPrototype(p.getPointer()); w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query; - w->d()->database = db; - w->d()->version = r->d()->version; + *w->d()->database = db; + *w->d()->version = *r->d()->version; bool ok = true; if (!!callback) { @@ -437,7 +446,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx) } if (ok) { - w->d()->version = to_version; + *w->d()->version = to_version; #ifndef QT_NO_SETTINGS QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(), scope.engine) + QLatin1String(".ini"), QSettings::IniFormat); ini.setValue(QLatin1String("Version"), to_version); @@ -458,14 +467,14 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re if (!callback) V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback")); - QSqlDatabase db = r->d()->database; + QSqlDatabase db = *r->d()->database; Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine)); QV4::ScopedObject p(scope, databaseData(scope.engine)->queryProto.value()); w->setPrototype(p.getPointer()); w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query; - w->d()->database = db; - w->d()->version = r->d()->version; + *w->d()->database = db; + *w->d()->version = *r->d()->version; w->d()->readonly = readOnly; db.transaction(); @@ -748,8 +757,8 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(scope.engine)); QV4::ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value()); db->setPrototype(p.getPointer()); - db->d()->database = database; - db->d()->version = version; + *db->d()->database = database; + *db->d()->version = version; if (created && dbcreationCallback) { ScopedCallData callData(scope, 1); diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp index 34c7746684..e88f17a658 100644 --- a/src/qml/jsruntime/qv4arraybuffer.cpp +++ b/src/qml/jsruntime/qv4arraybuffer.cpp @@ -112,7 +112,7 @@ Heap::ArrayBuffer::ArrayBuffer(const QByteArray& array) data->ref.ref(); } -Heap::ArrayBuffer::~ArrayBuffer() +void Heap::ArrayBuffer::destroy() { if (!data->ref.deref()) QTypedArrayData<char>::deallocate(data); diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h index b552cef9f1..a5ca0f6bad 100644 --- a/src/qml/jsruntime/qv4arraybuffer_p.h +++ b/src/qml/jsruntime/qv4arraybuffer_p.h @@ -66,7 +66,7 @@ struct ArrayBufferCtor : FunctionObject { struct Q_QML_PRIVATE_EXPORT ArrayBuffer : Object { ArrayBuffer(size_t length); ArrayBuffer(const QByteArray& array); - ~ArrayBuffer(); + void destroy(); QTypedArrayData<char> *data; uint byteLength() const { return data->size; } diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index d7ee4798b0..ba0cc7cb30 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -156,7 +156,7 @@ struct SimpleArrayData : public ArrayData { Q_STATIC_ASSERT(std::is_trivial<SimpleArrayData>::value); struct SparseArrayData : public ArrayData { - inline ~SparseArrayData(); + void destroy() { delete sparse; } uint mappedIndex(uint index) const { SparseArrayNode *n = sparse->findNode(index); @@ -287,11 +287,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/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/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 7b33cec1f1..f630dfaee0 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -744,7 +744,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 +920,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(); @@ -1153,7 +1153,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>()) diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 3763bf2613..bb5d32cbd7 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -69,6 +69,8 @@ using namespace QV4; Heap::ErrorObject::ErrorObject() { + stackTrace = nullptr; + Scope scope(internalClass->engine); Scoped<QV4::ErrorObject> e(scope, this); @@ -91,10 +93,10 @@ 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()) @@ -111,16 +113,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 +158,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); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 42a3d05d9f..206c7e6c59 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -76,9 +76,10 @@ struct ErrorObject : Object { ErrorObject(); ErrorObject(const Value &message, ErrorType t = Error); ErrorObject(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error); + void destroy() { delete stackTrace; } ErrorType errorType; - StackTrace stackTrace; + StackTrace *stackTrace; Pointer<String> stack; }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index e160dd8a36..aa8c7d6a81 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -136,7 +136,7 @@ Heap::FunctionObject::FunctionObject() } -Heap::FunctionObject::~FunctionObject() +void Heap::FunctionObject::destroy() { if (function) function->compilationUnit->release(); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 182b762606..f5a9376b9e 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -76,7 +76,7 @@ struct Q_QML_PRIVATE_EXPORT FunctionObject : Object { FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name); FunctionObject(ExecutionContext *scope, const ReturnedValue name); FunctionObject(); - ~FunctionObject(); + void destroy(); unsigned int formalParameterCount() { return function ? function->nFormals : 0; } unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 764a8e7f3f..b56155b5db 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) \ diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 202b7d3525..c977573b9b 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1847,7 +1847,7 @@ Heap::QMetaObjectWrapper::QMetaObjectWrapper(const QMetaObject *metaObject) , constructorCount(0) {} -Heap::QMetaObjectWrapper::~QMetaObjectWrapper() +void Heap::QMetaObjectWrapper::destroy() { delete[] constructors; } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 076f304fea..37397db55b 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -79,7 +79,7 @@ struct QQmlValueTypeWrapper; struct QObjectWrapper : Object { QObjectWrapper(QObject *object); - ~QObjectWrapper() { qObj.destroy(); } + void destroy() { qObj.destroy(); } QObject *object() const { return qObj.data(); } @@ -89,7 +89,13 @@ private: struct QObjectMethod : FunctionObject { QObjectMethod(QV4::ExecutionContext *scope); - ~QObjectMethod() { qObj.destroy(); } + void destroy() + { + propertyCache = nullptr; + qObj.destroy(); + FunctionObject::destroy(); + } + QQmlRefPointer<QQmlPropertyCache> propertyCache; int index; @@ -109,13 +115,13 @@ struct QMetaObjectWrapper : FunctionObject { int constructorCount; QMetaObjectWrapper(const QMetaObject* metaObject); - ~QMetaObjectWrapper(); + void destroy(); void ensureConstructorsCache(); }; struct QmlSignalHandler : Object { QmlSignalHandler(QObject *object, int signalIndex); - ~QmlSignalHandler() { qObj.destroy(); } + void destroy() { qObj.destroy(); } int signalIndex; QObject *object() const { return qObj.data(); } @@ -130,6 +136,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..7e2f4697c5 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -62,8 +62,8 @@ 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); @@ -104,19 +104,23 @@ Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignor subPatternCount = yarrPattern.m_numSubpatterns; byteCode = JSC::Yarr::byteCompile(yarrPattern, engine->bumperPointerAllocator); #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 } 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..33ed1d1117 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -77,11 +77,12 @@ namespace Heap { struct RegExp : Base { RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline); - ~RegExp(); + void destroy(); + QString pattern; OwnPtr<JSC::Yarr::BytecodePattern> byteCode; #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode; + JSC::Yarr::YarrCodeBlock *jitCode; #endif RegExpCache *cache; int subPatternCount; @@ -102,7 +103,7 @@ struct RegExp : public Managed QString pattern() const { return d()->pattern; } OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; } #if ENABLE(YARR_JIT) - JSC::Yarr::YarrCodeBlock jitCode() const { return d()->jitCode; } + JSC::Yarr::YarrCodeBlock *jitCode() const { return d()->jitCode; } #endif RegExpCache *cache() const { return d()->cache; } int subPatternCount() const { return d()->subPatternCount; } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 88c1286c61..e65f4118fb 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -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/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 59086c245c..fb9ef4a2b2 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -218,9 +218,12 @@ template <typename Container> struct QQmlSequence : Object { QQmlSequence(const Container &container); QQmlSequence(QObject *object, int propertyIndex); - ~QQmlSequence() { object.destroy(); } + void destroy() { + delete container; + object.destroy(); + } - mutable Container container; + mutable Container *container; QQmlQPointer<QObject> object; int propertyIndex; bool isReference; @@ -260,10 +263,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 +292,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 +327,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 +343,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 +365,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 +435,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 +457,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 +481,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 +509,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 +526,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 +536,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); } @@ -555,7 +558,7 @@ public: template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) - : container(container) + : container(new Container(container)) , propertyIndex(-1) , isReference(false) { @@ -569,7 +572,8 @@ Heap::QQmlSequence<Container>::QQmlSequence(const Container &container) template <typename Container> Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex) - : propertyIndex(propertyIndex) + : container(new Container) + , propertyIndex(propertyIndex) , isReference(true) { this->object.init(object); diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index f347ea8897..50b7fb664a 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -73,7 +73,7 @@ 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 destroy() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); } diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 9b744faf75..5a6644bdcf 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -68,7 +68,7 @@ struct VariantObject : Object { VariantObject(); VariantObject(const QVariant &value); - ~VariantObject() { + void destroy() { Q_ASSERT(scarceData); if (isScarce()) addVmePropertyReference(); diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 6db5b54760..43cedbc165 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -256,24 +256,27 @@ public: template <typename ManagedType> typename ManagedType::Data *alloc() { + Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(); + t->d_unchecked()->init(); return t->d(); } template <typename ManagedType, typename Arg1> typename ManagedType::Data *alloc(Arg1 arg1) { + Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1); + t->d_unchecked()->init(arg1); return t->d(); } template <typename ManagedType, typename Arg1, typename Arg2> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) { + Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2); @@ -283,6 +286,7 @@ public: template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) { + Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3); @@ -301,9 +305,10 @@ public: template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { + Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5); + t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); return t->d(); } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 3cfbd7bed1..9a993d4ec3 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1059,8 +1059,8 @@ namespace Heap { struct QmlIncubatorObject : Object { QmlIncubatorObject(QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous); - ~QmlIncubatorObject() { parent.destroy(); } - QScopedPointer<QQmlComponentIncubator> incubator; + inline void destroy(); + QQmlComponentIncubator *incubator; QQmlQPointer<QObject> parent; QV4::Value valuemap; QV4::Value statusChanged; @@ -1389,7 +1389,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) r->d()->qmlContext = v4->qmlContext(); r->d()->parent = parent; - QQmlIncubator *incubator = r->d()->incubator.data(); + QQmlIncubator *incubator = r->d()->incubator; create(*incubator, creationContext()); if (incubator->status() == QQmlIncubator::Null) { @@ -1490,7 +1490,12 @@ QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode { parent.init(); qmlContext = nullptr; - incubator.reset(new QQmlComponentIncubator(this, m)); + incubator = new QQmlComponentIncubator(this, m); +} + +void QV4::Heap::QmlIncubatorObject::destroy() { + delete incubator; + parent.destroy(); } void QV4::QmlIncubatorObject::setInitialState(QObject *o) diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 13d708bc17..95ff7b866f 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -65,15 +65,16 @@ Heap::QmlContextWrapper::QmlContextWrapper(QQmlContextData *context, QObject *sc : readOnly(true) , ownsContext(ownsContext) , isNullWrapper(false) - , context(context) { + this->context = new QQmlGuardedContextData(context); this->scopeObject.init(scopeObject); } -Heap::QmlContextWrapper::~QmlContextWrapper() +void Heap::QmlContextWrapper::destroy() { - if (context && ownsContext) - context->destroy(); + if (*context && ownsContext) + (*context)->destroy(); + delete context; scopeObject.destroy(); } @@ -120,7 +121,7 @@ ReturnedValue QmlContextWrapper::get(const Managed *m, String *name, bool *hasPr if (resource->d()->isNullWrapper) return Object::get(m, name, hasProperty); - if (v4->callingQmlContext() != resource->d()->context) + if (v4->callingQmlContext() != *resource->d()->context) return Object::get(m, name, hasProperty); result = Object::get(m, name, &hasProp); diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h index 2b8c16f274..9e5ba4a10c 100644 --- a/src/qml/qml/qqmlcontextwrapper_p.h +++ b/src/qml/qml/qqmlcontextwrapper_p.h @@ -65,12 +65,12 @@ namespace Heap { struct QmlContextWrapper : Object { QmlContextWrapper(QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); - ~QmlContextWrapper(); + void destroy(); bool readOnly; bool ownsContext; bool isNullWrapper; - QQmlGuardedContextData context; + QQmlGuardedContextData *context; QQmlQPointer<QObject> scopeObject; }; @@ -89,7 +89,7 @@ struct Q_QML_EXPORT QmlContextWrapper : Object } inline QObject *getScopeObject() const { return d()->scopeObject; } - inline QQmlContextData *getContext() const { return d()->context; } + inline QQmlContextData *getContext() const { return *d()->context; } void setReadOnly(bool b) { d()->readOnly = b; } diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp index 425a720867..4bc0e11340 100644 --- a/src/qml/qml/qqmllistwrapper.cpp +++ b/src/qml/qml/qqmllistwrapper.cpp @@ -60,7 +60,7 @@ Heap::QmlListWrapper::QmlListWrapper() o->setArrayType(Heap::ArrayData::Custom); } -Heap::QmlListWrapper::~QmlListWrapper() +void Heap::QmlListWrapper::destroy() { object.destroy(); } diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h index 1107b957c9..18038d2a80 100644 --- a/src/qml/qml/qqmllistwrapper_p.h +++ b/src/qml/qml/qqmllistwrapper_p.h @@ -67,7 +67,7 @@ namespace Heap { struct QmlListWrapper : Object { QmlListWrapper(); - ~QmlListWrapper(); + void destroy(); QQmlQPointer<QObject> object; QQmlListProperty<QObject> property; int propertyType; diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 76752f509c..6f66475aa5 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -109,16 +109,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::CallContext *ct if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedDt = r->d()->locale.toString(dt, format); + formattedDt = r->d()->locale->toString(dt, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedDt = r->d()->locale.toString(dt, format); + formattedDt = r->d()->locale->toString(dt, format); } else { V4THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format"); } } else { - formattedDt = r->d()->locale.toString(dt, enumFormat); + formattedDt = r->d()->locale->toString(dt, enumFormat); } return ctx->d()->engine->newString(formattedDt)->asReturnedValue(); @@ -154,16 +154,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::CallContext if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedTime = r->d()->locale.toString(time, format); + formattedTime = r->d()->locale->toString(time, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedTime = r->d()->locale.toString(time, format); + formattedTime = r->d()->locale->toString(time, format); } else { V4THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format"); } } else { - formattedTime = r->d()->locale.toString(time, enumFormat); + formattedTime = r->d()->locale->toString(time, enumFormat); } return ctx->d()->engine->newString(formattedTime)->asReturnedValue(); @@ -199,16 +199,16 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::CallContext if (ctx->argc() == 2) { if (ctx->args()[1].isString()) { QString format = ctx->args()[1].stringValue()->toQString(); - formattedDate = r->d()->locale.toString(date, format); + formattedDate = r->d()->locale->toString(date, format); } else if (ctx->args()[1].isNumber()) { quint32 intFormat = ctx->args()[1].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - formattedDate = r->d()->locale.toString(date, format); + formattedDate = r->d()->locale->toString(date, format); } else { V4THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format"); } } else { - formattedDate = r->d()->locale.toString(date, enumFormat); + formattedDate = r->d()->locale->toString(date, enumFormat); } return ctx->d()->engine->newString(formattedDate)->asReturnedValue(); @@ -237,16 +237,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::CallContext * if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - dt = r->d()->locale.toDateTime(dateString, format); + dt = r->d()->locale->toDateTime(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - dt = r->d()->locale.toDateTime(dateString, format); + dt = r->d()->locale->toDateTime(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format"); } } else { - dt = r->d()->locale.toDateTime(dateString, enumFormat); + dt = r->d()->locale->toDateTime(dateString, enumFormat); } return QV4::Encode(engine->newDateObject(dt)); @@ -278,16 +278,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::CallConte if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - tm = r->d()->locale.toTime(dateString, format); + tm = r->d()->locale->toTime(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - tm = r->d()->locale.toTime(dateString, format); + tm = r->d()->locale->toTime(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format"); } } else { - tm = r->d()->locale.toTime(dateString, enumFormat); + tm = r->d()->locale->toTime(dateString, enumFormat); } QDateTime dt; @@ -323,16 +323,16 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::CallConte if (ctx->argc() == 3) { if (ctx->args()[2].isString()) { QString format = ctx->args()[2].stringValue()->toQString(); - dt = r->d()->locale.toDate(dateString, format); + dt = r->d()->locale->toDate(dateString, format); } else if (ctx->args()[2].isNumber()) { quint32 intFormat = ctx->args()[2].toNumber(); QLocale::FormatType format = QLocale::FormatType(intFormat); - dt = r->d()->locale.toDate(dateString, format); + dt = r->d()->locale->toDate(dateString, format); } else { V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format"); } } else { - dt = r->d()->locale.toDate(dateString, enumFormat); + dt = r->d()->locale->toDate(dateString, enumFormat); } return QV4::Encode(engine->newDateObject(QDateTime(dt))); @@ -393,7 +393,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext * prec = ctx->args()[2].toInt32(); } - return ctx->d()->engine->newString(r->d()->locale.toString(number, (char)format, prec))->asReturnedValue(); + return ctx->d()->engine->newString(r->d()->locale->toString(number, (char)format, prec))->asReturnedValue(); } QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallContext *ctx) @@ -423,7 +423,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::CallC symbol = ctx->args()[1].toQStringNoThrow(); } - return ctx->d()->engine->newString(r->d()->locale.toCurrencyString(number, symbol))->asReturnedValue(); + return ctx->d()->engine->newString(r->d()->locale->toCurrencyString(number, symbol))->asReturnedValue(); } QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext *ctx) @@ -441,7 +441,7 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); GET_LOCALE_DATA_RESOURCE(ctx->args()[0]); - locale = r->d()->locale; + locale = *r->d()->locale; numberIdx = 1; } @@ -813,7 +813,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale) QV4::Scope scope(v4); QV4LocaleDataDeletable *d = localeV4Data(scope.engine); QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>()); - wrapper->d()->locale = locale; + *wrapper->d()->locale = locale; QV4::ScopedObject p(scope, d->prototype.value()); wrapper->setPrototype(p); return wrapper.asReturnedValue(); diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h index 652a3ca0d4..4494fa9b53 100644 --- a/src/qml/qml/qqmllocale_p.h +++ b/src/qml/qml/qqmllocale_p.h @@ -143,8 +143,9 @@ namespace QV4 { namespace Heap { struct QQmlLocaleData : Object { - inline QQmlLocaleData() {} - QLocale locale; + inline QQmlLocaleData() { locale = new QLocale; } + void destroy() { delete locale; } + QLocale *locale; }; } @@ -161,7 +162,7 @@ struct QQmlLocaleData : public QV4::Object ctx->engine()->throwTypeError(); return 0; } - return &thisObject->d()->locale; + return thisObject->d()->locale; } static QV4::ReturnedValue method_currencySymbol(QV4::CallContext *ctx); diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 28c2588117..c8e2e5387c 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -61,7 +61,7 @@ Heap::QmlTypeWrapper::QmlTypeWrapper() object.init(); } -Heap::QmlTypeWrapper::~QmlTypeWrapper() +void Heap::QmlTypeWrapper::destroy() { if (typeNamespace) typeNamespace->release(); diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 7c5105b184..fe75aefca9 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -72,7 +72,7 @@ struct QmlTypeWrapper : Object { }; QmlTypeWrapper(); - ~QmlTypeWrapper(); + void destroy(); TypeNameMode mode; QQmlQPointer<QObject> object; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 85e17525a5..5128fc0f08 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -175,17 +175,24 @@ namespace Heap { struct NamedNodeMap : Object { NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list); - ~NamedNodeMap() { + void destroy() { + delete listPtr; if (d) d->release(); } - QList<NodeImpl *> list; // Only used in NamedNodeMap + QList<NodeImpl *> &list() { + if (listPtr == nullptr) + listPtr = new QList<NodeImpl *>; + return *listPtr; + } + + QList<NodeImpl *> *listPtr; // Only used in NamedNodeMap NodeImpl *d; }; struct NodeList : Object { NodeList(NodeImpl *data); - ~NodeList() { + void destroy() { if (d) d->release(); } @@ -198,7 +205,7 @@ struct NodePrototype : Object { struct Node : Object { Node(NodeImpl *data); - ~Node() { + void destroy() { if (d) d->release(); } @@ -222,9 +229,9 @@ public: }; Heap::NamedNodeMap::NamedNodeMap(NodeImpl *data, const QList<NodeImpl *> &list) - : list(list) - , d(data) + : d(data) { + this->list() = list; if (d) d->addref(); } @@ -877,10 +884,10 @@ ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasPr const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m); QV4::ExecutionEngine *v4 = r->engine(); - if ((int)index < r->d()->list.count()) { + if ((int)index < r->d()->list().count()) { if (hasProperty) *hasProperty = true; - return Node::create(v4, r->d()->list.at(index)); + return Node::create(v4, r->d()->list().at(index)); } if (hasProperty) *hasProperty = false; @@ -895,14 +902,14 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert name->makeIdentifier(v4); if (name->equals(v4->id_length())) - return Primitive::fromInt32(r->d()->list.count()).asReturnedValue(); + return Primitive::fromInt32(r->d()->list().count()).asReturnedValue(); QString str = name->toQString(); - for (int ii = 0; ii < r->d()->list.count(); ++ii) { - if (r->d()->list.at(ii)->name == str) { + for (int ii = 0; ii < r->d()->list().count(); ++ii) { + if (r->d()->list().at(ii)->name == str) { if (hasProperty) *hasProperty = true; - return Node::create(v4, r->d()->list.at(ii)); + return Node::create(v4, r->d()->list().at(ii)); } } @@ -1588,7 +1595,7 @@ namespace Heap { struct QQmlXMLHttpRequestWrapper : Object { QQmlXMLHttpRequestWrapper(QQmlXMLHttpRequest *request); - ~QQmlXMLHttpRequestWrapper() { + void destroy() { delete request; } QQmlXMLHttpRequest *request; diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 1ca51ea360..02a5514275 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -76,7 +76,8 @@ struct QQmlDelegateModelGroupChange : Object { struct QQmlDelegateModelGroupChangeArray : Object { QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes); - QVector<QQmlChangeSet::Change> changes; + void destroy() { delete changes; } + QVector<QQmlChangeSet::Change> *changes; }; @@ -1865,7 +1866,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject); -QV4::Heap::QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject() +void QV4::Heap::QQmlDelegateModelItemObject::destroy() { item->Dispose(); } @@ -3256,8 +3257,8 @@ public: return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes); } - quint32 count() const { return d()->changes.count(); } - const QQmlChangeSet::Change &at(int index) const { return d()->changes.at(index); } + quint32 count() const { return d()->changes->count(); } + const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); } static QV4::ReturnedValue getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) { @@ -3300,7 +3301,7 @@ public: }; QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(const QVector<QQmlChangeSet::Change> &changes) - : changes(changes) + : changes(new QVector<QQmlChangeSet::Change>(changes)) { QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h index bf9fd99f19..a34450ebd6 100644 --- a/src/qml/types/qqmldelegatemodel_p_p.h +++ b/src/qml/types/qqmldelegatemodel_p_p.h @@ -161,7 +161,7 @@ namespace QV4 { namespace Heap { struct QQmlDelegateModelItemObject : Object { inline QQmlDelegateModelItemObject(QQmlDelegateModelItem *item); - ~QQmlDelegateModelItemObject(); + void destroy(); QQmlDelegateModelItem *item; }; diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index c26f641754..e621bc9eed 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -500,19 +500,22 @@ struct QQuickJSContext2DPrototype : Object { struct QQuickContext2DStyle : Object { QQuickContext2DStyle() { + brush = new QBrush; patternRepeatX = false; patternRepeatY = false; } + void destroy() { delete brush; } - QBrush brush; + QBrush *brush; bool patternRepeatX:1; bool patternRepeatY:1; }; struct QQuickJSContext2DPixelData : Object { QQuickJSContext2DPixelData(); + void destroy() { delete image; } - QImage image; + QImage *image; }; struct QQuickJSContext2DImageData : Object { @@ -899,6 +902,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData() { + image = new QImage; QV4::Scope scope(internalClass->engine); QV4::ScopedObject o(scope, this); o->setArrayType(QV4::Heap::ArrayData::Custom); @@ -943,11 +947,11 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE pixelData->setPrototype(p); if (image.isNull()) { - pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32); - pixelData->d()->image.fill(0x00000000); + *pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32); + pixelData->d()->image->fill(0x00000000); } else { Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h)); - pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32); + *pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32); } QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, scope.engine->memoryManager->allocObject<QQuickJSContext2DImageData>()); @@ -1392,9 +1396,9 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx r->d()->context->m_fillStyle.set(scope.engine, value); } else { QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>()); - if (style && style->d()->brush != r->d()->context->state.fillStyle) { - r->d()->context->state.fillStyle = style->d()->brush; - r->d()->context->buffer()->setFillStyle(style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY); + if (style && *style->d()->brush != r->d()->context->state.fillStyle) { + r->d()->context->state.fillStyle = *style->d()->brush; + r->d()->context->buffer()->setFillStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY); r->d()->context->m_fillStyle.set(scope.engine, value); r->d()->context->state.fillPatternRepeatX = style->d()->patternRepeatX; r->d()->context->state.fillPatternRepeatY = style->d()->patternRepeatY; @@ -1501,9 +1505,9 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c r->d()->context->m_strokeStyle.set(scope.engine, value); } else { QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>()); - if (style && style->d()->brush != r->d()->context->state.strokeStyle) { - r->d()->context->state.strokeStyle = style->d()->brush; - r->d()->context->buffer()->setStrokeStyle(style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY); + if (style && *style->d()->brush != r->d()->context->state.strokeStyle) { + r->d()->context->state.strokeStyle = *style->d()->brush; + r->d()->context->buffer()->setStrokeStyle(*style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY); r->d()->context->m_strokeStyle.set(scope.engine, value); r->d()->context->state.strokePatternRepeatX = style->d()->patternRepeatX; r->d()->context->state.strokePatternRepeatY = style->d()->patternRepeatY; @@ -1561,7 +1565,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); - gradient->d()->brush = QLinearGradient(x0, y0, x1, y1); + *gradient->d()->brush = QLinearGradient(x0, y0, x1, y1); return gradient.asReturnedValue(); } @@ -1612,7 +1616,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); - gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); + *gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); return gradient.asReturnedValue(); } @@ -1655,7 +1659,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->allocObject<QQuickContext2DStyle>()); QV4::ScopedObject p(scope, ed->gradientProto.value()); gradient->setPrototype(p); - gradient->d()->brush = QConicalGradient(x, y, angle); + *gradient->d()->brush = QConicalGradient(x, y, angle); return gradient.asReturnedValue(); } @@ -1720,7 +1724,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon if (patternMode >= 0 && patternMode < Qt::LinearGradientPattern) { style = static_cast<Qt::BrushStyle>(patternMode); } - pattern->d()->brush = QBrush(color, style); + *pattern->d()->brush = QBrush(color, style); } else { QImage patternTexture; @@ -1728,14 +1732,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data"))); QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s)); if (!!pixelData) { - patternTexture = pixelData->d()->image; + patternTexture = *pixelData->d()->image; } } else { patternTexture = r->d()->context->createPixmap(QUrl(ctx->args()[0].toQStringNoThrow()))->image(); } if (!patternTexture.isNull()) { - pattern->d()->brush.setTextureImage(patternTexture); + pattern->d()->brush->setTextureImage(patternTexture); QString repetition = ctx->args()[1].toQStringNoThrow(); if (repetition == QLatin1String("repeat") || repetition.isEmpty()) { @@ -2925,8 +2929,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, arg); if (!!imageData) { QV4::Scoped<QQuickJSContext2DPixelData> pix(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>()); - if (pix && !pix->d()->image.isNull()) { - pixmap.adopt(new QQuickCanvasPixmap(pix->d()->image)); + if (pix && !pix->d()->image->isNull()) { + pixmap.adopt(new QQuickCanvasPixmap(*pix->d()->image)); } else { V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } @@ -3034,7 +3038,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::CallContext QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>()); if (!r) return QV4::Encode(0); - return QV4::Encode(r->d()->image.width()); + return QV4::Encode(r->d()->image->width()); } /*! @@ -3050,7 +3054,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::CallContex QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>()); if (!r) return QV4::Encode(0); - return QV4::Encode(r->d()->image.height()); + return QV4::Encode(r->d()->image->height()); } /*! @@ -3088,10 +3092,10 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext { QV4::Scope scope(ctx); QV4::Scoped<QQuickJSContext2DPixelData> r(scope, ctx->thisObject().as<QQuickJSContext2DPixelData>()); - if (!r || r->d()->image.isNull()) + if (!r || r->d()->image->isNull()) return QV4::Encode::undefined(); - return QV4::Encode(r->d()->image.width() * r->d()->image.height() * 4); + return QV4::Encode(r->d()->image->width() * r->d()->image->height() * 4); } QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, uint index, bool *hasProperty) @@ -3101,13 +3105,13 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(const QV4::Managed *m, QV4::Scope scope(v4); QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<const QQuickJSContext2DPixelData *>(m)); - if (index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4)) { + if (index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4)) { if (hasProperty) *hasProperty = true; - const quint32 w = r->d()->image.width(); + const quint32 w = r->d()->image->width(); const quint32 row = (index / 4) / w; const quint32 col = (index / 4) % w; - const QRgb* pixel = reinterpret_cast<const QRgb*>(r->d()->image.constScanLine(row)); + const QRgb* pixel = reinterpret_cast<const QRgb*>(r->d()->image->constScanLine(row)); pixel += col; switch (index % 4) { case 0: @@ -3136,12 +3140,12 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q QV4::Scoped<QQuickJSContext2DPixelData> r(scope, static_cast<QQuickJSContext2DPixelData *>(m)); const int v = value.toInt32(); - if (r && index < static_cast<quint32>(r->d()->image.width() * r->d()->image.height() * 4) && v >= 0 && v <= 255) { - const quint32 w = r->d()->image.width(); + if (r && index < static_cast<quint32>(r->d()->image->width() * r->d()->image->height() * 4) && v >= 0 && v <= 255) { + const quint32 w = r->d()->image->width(); const quint32 row = (index / 4) / w; const quint32 col = (index / 4) % w; - QRgb* pixel = reinterpret_cast<QRgb*>(r->d()->image.scanLine(row)); + QRgb* pixel = reinterpret_cast<QRgb*>(r->d()->image->scanLine(row)); pixel += col; switch (index % 4) { case 0: @@ -3192,8 +3196,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC if (!!imgData) { QV4::Scoped<QQuickJSContext2DPixelData> pa(scope, imgData->d()->pixelData.as<QQuickJSContext2DPixelData>()); if (pa) { - qreal w = pa->d()->image.width(); - qreal h = pa->d()->image.height(); + qreal w = pa->d()->image->width(); + qreal h = pa->d()->image->height(); return qt_create_image_data(w, h, scope.engine, QImage()); } } else if (arg0->isString()) { @@ -3271,8 +3275,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont QV4::Scoped<QQuickJSContext2DPixelData> pixelArray(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>()); if (pixelArray) { - w = pixelArray->d()->image.width(); - h = pixelArray->d()->image.height(); + w = pixelArray->d()->image->width(); + h = pixelArray->d()->image->height(); if (ctx->argc() == 7) { dirtyX = ctx->args()[3].toNumber(); @@ -3321,7 +3325,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont dirtyHeight = h; } - QImage image = pixelArray->d()->image.copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight); + QImage image = pixelArray->d()->image->copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight); r->d()->context->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight)); } return ctx->thisObject().asReturnedValue(); @@ -3356,9 +3360,9 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo if (ctx->argc() == 2) { - if (!style->d()->brush.gradient()) + if (!style->d()->brush->gradient()) V4THROW_ERROR("Not a valid CanvasGradient object, can't get the gradient information"); - QGradient gradient = *(style->d()->brush.gradient()); + QGradient gradient = *(style->d()->brush->gradient()); qreal pos = ctx->args()[0].toNumber(); QColor color; @@ -3376,7 +3380,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo } else { V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "CanvasGradient: parameter color is not a valid color string"); } - style->d()->brush = gradient; + *style->d()->brush = gradient; } return ctx->thisObject().asReturnedValue(); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index c734a0a011..ceb8d934da 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -7264,7 +7264,7 @@ struct WeakReferenceSentinel : public Object { } - ~WeakReferenceSentinel() { + void destroy() { *resultPtr = weakRef->isNullOrUndefined(); } |