diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2016-01-29 13:01:21 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2016-01-29 13:01:22 +0100 |
commit | 1e421097f08876f5e2242be6f7a20db2aeb51692 (patch) | |
tree | c45b9323368cfdede67facd43c076a85322f12f6 /src/qml | |
parent | f4788a13e98aa4e5438327094524d7b8239893ec (diff) | |
parent | 666bc731a0ba930ca0cfda18daf836913fd91361 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Change-Id: Iec1b2de53c275996364c4bab0123ccb3e6e9895e
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 12 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 9 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4include.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4persistent.cpp | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4persistent_p.h | 8 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 17 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 10 | ||||
-rw-r--r-- | src/qml/types/qqmllistmodel.cpp | 3 |
11 files changed, 71 insertions, 20 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index e6c64c520a..9fcfe53b05 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1882,17 +1882,17 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int #ifndef V4_BOOTSTRAP -QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context) +QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) { if (notInRevision) *notInRevision = false; - QQmlPropertyData *d = cache->property(name, object, context); + QQmlPropertyData *d = cache->property(name, 0, 0); // Find the first property while (d && d->isFunction()) d = cache->overrideData(d); - if (d && !cache->isAllowedInRevision(d)) { + if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) { if (notInRevision) *notInRevision = true; return 0; } else { @@ -1901,11 +1901,11 @@ QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRev } -QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision, QObject *object, QQmlContextData *context) +QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) { if (notInRevision) *notInRevision = false; - QQmlPropertyData *d = cache->property(name, object, context); + QQmlPropertyData *d = cache->property(name, 0, 0); if (notInRevision) *notInRevision = false; while (d && !(d->isFunction())) @@ -1921,7 +1921,7 @@ QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevis if (name.endsWith(QStringLiteral("Changed"))) { QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed"))); - d = property(propName, notInRevision, object, context); + d = property(propName, notInRevision); if (d) return cache->signal(d->notifyIndex); } diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 3a92659dda..057ed1be9f 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -466,10 +466,15 @@ struct Q_QML_EXPORT PropertyResolver return cache->property(index); } - QQmlPropertyData *property(const QString &name, bool *notInRevision = 0, QObject *object = 0, QQmlContextData *context = 0); + enum RevisionCheck { + CheckRevision, + IgnoreRevision + }; + + QQmlPropertyData *property(const QString &name, bool *notInRevision = 0, RevisionCheck check = CheckRevision); // This code must match the semantics of QQmlPropertyPrivate::findSignalByName - QQmlPropertyData *signal(const QString &name, bool *notInRevision, QObject *object = 0, QQmlContextData *context = 0); + QQmlPropertyData *signal(const QString &name, bool *notInRevision); QQmlPropertyCache *cache; }; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index f5bfe3c896..2b3cd93052 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -1865,6 +1865,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD } bool bindingToDefaultProperty = false; + bool isGroupProperty = instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty; bool notInRevision = false; QQmlPropertyData *pd = 0; @@ -1873,7 +1874,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) pd = propertyResolver.signal(name, ¬InRevision); else - pd = propertyResolver.property(name, ¬InRevision); + pd = propertyResolver.property(name, ¬InRevision, isGroupProperty ? QmlIR::PropertyResolver::IgnoreRevision : QmlIR::PropertyResolver::CheckRevision); if (notInRevision) { QString typeName = stringAt(obj->inheritedTypeNameIndex); @@ -1885,7 +1886,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD } } } else { - if (instantiatingBinding && instantiatingBinding->type == QV4::CompiledData::Binding::Type_GroupProperty) + if (isGroupProperty) COMPILE_EXCEPTION(binding, tr("Cannot assign a value directly to a grouped property")); pd = defaultProperty; diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 606ba07adf..29f83da522 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -189,6 +189,8 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); 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); QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>()) diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 2a7a9a6ee7..f6d4046ec4 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -40,6 +40,7 @@ #include "qv4persistent_p.h" #include <private/qv4mm_p.h> #include "qv4object_p.h" +#include "qv4qobjectwrapper_p.h" #include "PageAllocation.h" using namespace QV4; @@ -387,7 +388,7 @@ WeakValue &WeakValue::operator=(const WeakValue &other) WeakValue::~WeakValue() { - PersistentValueStorage::free(val); + free(); } void WeakValue::set(ExecutionEngine *engine, const Value &value) @@ -418,3 +419,21 @@ void WeakValue::markOnce(ExecutionEngine *e) val->mark(e); } +void WeakValue::free() +{ + if (!val) + return; + + ExecutionEngine *e = engine(); + if (e && val->as<QObjectWrapper>()) { + // Some QV4::QObjectWrapper Value will be freed in WeakValue::~WeakValue() before MemoryManager::sweep() is being called, + // in this case we will never have a chance to call detroyObject() on those QV4::QObjectWrapper objects. + // Here we don't free these Value immediately, instead we keep track of them to free them later in MemoryManager::sweep() + e->memoryManager->m_pendingFreedObjectWrapperValue.push_back(val); + } else { + PersistentValueStorage::free(val); + } + + val = 0; +} + diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index b8f179c9eb..5b1926468a 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -184,15 +184,15 @@ public: bool isUndefined() const { return !val || val->isUndefined(); } bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); } - void clear() { - PersistentValueStorage::free(val); - val = 0; - } + void clear() { free(); } void markOnce(ExecutionEngine *e); private: Value *val; + +private: + void free(); }; } // namespace QV4 diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 18676ec8e6..fe94a11082 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -47,8 +47,6 @@ #include "StdLibExtras.h" #include <QTime> -#include <QVector> -#include <QVector> #include <QMap> #include <iostream> @@ -443,6 +441,21 @@ void MemoryManager::sweep(bool lastSweep) (*it) = Primitive::undefinedValue(); } + // Now it is time to free QV4::QObjectWrapper Value, we must check the Value's tag to make sure its object has been destroyed + const int pendingCount = m_pendingFreedObjectWrapperValue.count(); + if (pendingCount) { + QVector<Value *> remainingWeakQObjectWrappers; + remainingWeakQObjectWrappers.reserve(pendingCount); + for (int i = 0; i < pendingCount; ++i) { + Value *v = m_pendingFreedObjectWrapperValue.at(i); + if (v->tag() == Value::Undefined_Type) + PersistentValueStorage::free(v); + else + remainingWeakQObjectWrappers.append(v); + } + m_pendingFreedObjectWrapperValue = remainingWeakQObjectWrappers; + } + if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) { for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) { if (!it.value().isNullOrUndefined()) diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index b1503ad963..e169675f7d 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -55,6 +55,7 @@ #include <private/qv4value_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4object_p.h> +#include <QVector> //#define DETAILED_MM_STATS @@ -333,6 +334,7 @@ public: QScopedPointer<Data> m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; + QVector<Value *> m_pendingFreedObjectWrapperValue; }; } diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index a5173e9efb..576478b729 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -250,7 +250,7 @@ void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e) QObject *o = qobjectApis.take(e); if (o) { QQmlData *ddata = QQmlData::get(o, false); - if (ddata && ddata->indestructible) + if (url.isEmpty() && ddata && ddata->indestructible && ddata->explicitIndestructibleSet) return; delete o; } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 486feca7cb..d313557e98 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -363,8 +363,14 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString); VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool); - QVariant v(result->propType, (void *)0); - void *args[] = { v.data(), 0 }; + QVariant v; + void *args[] = { Q_NULLPTR, Q_NULLPTR }; + if (result->propType == QMetaType::QVariant) { + args[0] = &v; + } else { + v = QVariant(result->propType, static_cast<void *>(Q_NULLPTR)); + args[0] = v.data(); + } metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); return v4->fromVariant(v); #undef VALUE_TYPE_ACCESSOR diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index b2507fb99e..91eef2d982 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -2276,6 +2276,9 @@ QQmlV4Handle QQmlListModel::get(int index) const } else { QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index); result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index); + // Keep track of the QObjectWrapper in persistent value storage + QV4::Value *val = scope.engine->memoryManager->m_weakValues->allocate(); + *val = result; } } |