aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/animations/qabstractanimationjob.cpp41
-rw-r--r--src/qml/animations/qabstractanimationjob_p.h3
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp6
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h7
-rw-r--r--src/qml/jit/qv4assemblercommon.cpp4
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h4
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp4
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h4
-rw-r--r--src/qml/jit/qv4baselinejit.cpp5
-rw-r--r--src/qml/jit/qv4baselinejit_p.h4
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp20
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp113
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h48
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp13
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp19
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/qml/qqmlproperty.cpp8
-rw-r--r--src/qml/qml/qqmltypedata.cpp8
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp7
-rw-r--r--src/qml/qtqmlglobal_p.h22
20 files changed, 237 insertions, 105 deletions
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index f3c12bce3f..e15771531a 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -65,6 +65,30 @@ QQmlAnimationTimer::QQmlAnimationTimer() :
{
}
+void QQmlAnimationTimer::unsetJobTimer(QAbstractAnimationJob *animation)
+{
+ if (!animation)
+ return;
+ if (animation->m_timer == this)
+ animation->m_timer = nullptr;
+
+ if (animation->isGroup()) {
+ QAnimationGroupJob *group = static_cast<QAnimationGroupJob *>(animation);
+ for (auto *child = group->firstChild(); child; child = child->nextSibling())
+ unsetJobTimer(child);
+ }
+}
+
+QQmlAnimationTimer::~QQmlAnimationTimer()
+{
+ for (const auto &animation : qAsConst(animations))
+ unsetJobTimer(animation);
+ for (const auto &animation : qAsConst(animationsToStart))
+ unsetJobTimer(animation);
+ for (const auto &animation : qAsConst(runningPauseAnimations))
+ unsetJobTimer(animation);
+}
+
QQmlAnimationTimer *QQmlAnimationTimer::instance(bool create)
{
QQmlAnimationTimer *inst;
@@ -216,6 +240,7 @@ void QQmlAnimationTimer::registerRunningAnimation(QAbstractAnimationJob *animati
void QQmlAnimationTimer::unregisterRunningAnimation(QAbstractAnimationJob *animation)
{
+ unsetJobTimer(animation);
if (animation->userControlDisabled())
return;
@@ -282,8 +307,10 @@ QAbstractAnimationJob::~QAbstractAnimationJob()
Q_ASSERT(m_state == Stopped);
if (oldState == Running) {
- Q_ASSERT(QQmlAnimationTimer::instance() == m_timer);
- m_timer->unregisterAnimation(this);
+ if (m_timer) {
+ Q_ASSERT(QQmlAnimationTimer::instance(false) == m_timer);
+ m_timer->unregisterAnimation(this);
+ }
}
Q_ASSERT(!m_hasRegisteredTimer);
}
@@ -308,8 +335,9 @@ void QAbstractAnimationJob::setState(QAbstractAnimationJob::State newState)
if (m_loopCount == 0)
return;
- if (!m_timer)
- m_timer = QQmlAnimationTimer::instance();
+ if (!m_timer) // don't create a timer just to stop the animation
+ m_timer = QQmlAnimationTimer::instance(newState != Stopped);
+ Q_ASSERT(m_timer || newState == Stopped);
State oldState = m_state;
int oldCurrentTime = m_currentTime;
@@ -337,8 +365,9 @@ void QAbstractAnimationJob::setState(QAbstractAnimationJob::State newState)
if (oldState == Running) {
if (newState == Paused && m_hasRegisteredTimer)
m_timer->ensureTimerUpdate();
- //the animation, is not running any more
- m_timer->unregisterAnimation(this);
+ // the animation is not running any more
+ if (m_timer)
+ m_timer->unregisterAnimation(this);
} else if (newState == Running) {
m_timer->registerAnimation(this, isTopLevel);
}
diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h
index 9490070246..1010f0f392 100644
--- a/src/qml/animations/qabstractanimationjob_p.h
+++ b/src/qml/animations/qabstractanimationjob_p.h
@@ -207,6 +207,8 @@ private:
QQmlAnimationTimer();
public:
+ ~QQmlAnimationTimer(); // must be destructible by QThreadStorage
+
static QQmlAnimationTimer *instance();
static QQmlAnimationTimer *instance(bool create);
@@ -252,6 +254,7 @@ private:
void registerRunningAnimation(QAbstractAnimationJob *animation);
void unregisterRunningAnimation(QAbstractAnimationJob *animation);
+ void unsetJobTimer(QAbstractAnimationJob *animation);
int closestPauseAnimationTimeToFinish();
};
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 2ad85ab910..36b7f68de9 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1901,6 +1901,12 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
scan.enterEnvironment(f.parentNode, QV4::Compiler::ContextType::Binding, qmlName(f));
}
+ /* We do not want to visit the whole function, as we already called enterQmlFunction
+ However, there might be a function defined as a default argument of the function.
+ That needs to be considered, too, so we call handleTopLevelFunctionFormals to
+ deal with them.
+ */
+ scan.handleTopLevelFunctionFormals(function);
scan(function ? function->body : f.node);
scan.leaveEnvironment();
}
diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h
index e39aa2454e..56172e2ea5 100644
--- a/src/qml/compiler/qv4compilerscanfunctions_p.h
+++ b/src/qml/compiler/qv4compilerscanfunctions_p.h
@@ -83,6 +83,13 @@ public:
ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType);
void operator()(QQmlJS::AST::Node *node);
+ // see comment at its call site in generateJSCodeForFunctionsAndBindings
+ // for why this function is necessary
+ void handleTopLevelFunctionFormals(QQmlJS::AST::FunctionExpression *node) {
+ if (node && node->formals)
+ node->formals->accept(this);
+ }
+
void enterGlobalEnvironment(ContextType compilationMode);
void enterEnvironment(QQmlJS::AST::Node *node, ContextType compilationMode,
const QString &name);
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp
index 95070fbb96..b090fc7597 100644
--- a/src/qml/jit/qv4assemblercommon.cpp
+++ b/src/qml/jit/qv4assemblercommon.cpp
@@ -51,6 +51,8 @@
#include <assembler/LinkBuffer.h>
#include <WTFStubs.h>
+#if QT_CONFIG(qml_jit)
+
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
QT_BEGIN_NAMESPACE
@@ -370,3 +372,5 @@ void PlatformAssemblerCommon::storeInt32AsValue(int srcInt, Address destAddr)
} // QV4 namepsace
QT_END_NAMESPACE
+
+#endif // QT_CONFIG(qml_jit)
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index ead1e757de..c3b1eb34eb 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -58,7 +58,7 @@
#include <wtf/Vector.h>
#include <assembler/MacroAssembler.h>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -740,4 +740,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4PLATFORMASSEMBLER_P_H
diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp
index dd6a40afe0..7ad131335e 100644
--- a/src/qml/jit/qv4baselineassembler.cpp
+++ b/src/qml/jit/qv4baselineassembler.cpp
@@ -55,6 +55,8 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
+#if QT_CONFIG(qml_jit)
+
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace JIT {
@@ -1619,3 +1621,5 @@ void BaselineAssembler::ret()
} // QV4 namepsace
QT_END_NAMESPACE
+
+#endif // QT_CONFIG(qml_jit)
diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h
index c2c735282b..c6fdab51c5 100644
--- a/src/qml/jit/qv4baselineassembler_p.h
+++ b/src/qml/jit/qv4baselineassembler_p.h
@@ -55,7 +55,7 @@
#include <private/qv4function_p.h>
#include <QHash>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -182,4 +182,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4BASELINEASSEMBLER_P_H
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index d329a5afec..45150cfffd 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -42,6 +42,8 @@
#include <private/qv4lookup_p.h>
#include <private/qv4generatorobject_p.h>
+#if QT_CONFIG(qml_jit)
+
QT_USE_NAMESPACE
using namespace QV4;
using namespace QV4::JIT;
@@ -930,3 +932,6 @@ void BaselineJIT::endInstruction(Instr::Type instr)
{
Q_UNUSED(instr);
}
+
+#endif // QT_CONFIG(qml_jit)
+
diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 284faf0ff0..2b0913169e 100644
--- a/src/qml/jit/qv4baselinejit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -56,7 +56,7 @@
#include <private/qv4instr_moth_p.h>
#include <private/qv4bytecodehandler_p.h>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -220,4 +220,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4JIT_P_H
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 2c54388100..5eb0e889b0 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -296,24 +296,8 @@ void ExecutableCompilationUnit::unlink()
propertyCaches.clear();
if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup &l = runtimeLookups[i];
- if (l.getter == QV4::QObjectWrapper::lookupGetter
- || l.getter == QQmlTypeWrapper::lookupSingletonProperty) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- } else if (l.getter == QQmlValueTypeWrapper::lookupGetter
- || l.getter == QQmlTypeWrapper::lookupSingletonProperty) {
- if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
- pc->release();
- }
-
- if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty
- || l.qmlContextPropertyGetter == QQmlContextWrapper::lookupContextObjectProperty) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- }
- }
+ for (uint i = 0; i < data->lookupTableSize; ++i)
+ runtimeLookups[i].releasePropertyCache();
}
dependentScripts.clear();
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index d3ea50867a..db6fb39695 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -41,6 +41,7 @@
#include "qv4jscall_p.h"
#include "qv4string_p.h"
#include <private/qv4identifiertable_p.h>
+#include <private/qv4qobjectwrapper_p.h>
QT_BEGIN_NAMESPACE
@@ -144,47 +145,76 @@ ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Va
return l->resolvePrimitiveGetter(engine, object);
}
+static inline void setupObjectLookupTwoClasses(Lookup *l, const Lookup &first, const Lookup &second)
+{
+ Heap::InternalClass *ic1 = first.objectLookup.ic;
+ const uint offset1 = first.objectLookup.offset;
+ Heap::InternalClass *ic2 = second.objectLookup.ic;
+ const uint offset2 = second.objectLookup.offset;
+
+ l->objectLookupTwoClasses.ic = ic1;
+ l->objectLookupTwoClasses.ic2 = ic2;
+ l->objectLookupTwoClasses.offset = offset1;
+ l->objectLookupTwoClasses.offset2 = offset2;
+}
+
+static inline void setupProtoLookupTwoClasses(Lookup *l, const Lookup &first, const Lookup &second)
+{
+ const quintptr protoId1 = first.protoLookup.protoId;
+ const Value *data1 = first.protoLookup.data;
+ const quintptr protoId2 = second.protoLookup.protoId;
+ const Value *data2 = second.protoLookup.data;
+
+ l->protoLookupTwoClasses.protoId = protoId1;
+ l->protoLookupTwoClasses.protoId2 = protoId2;
+ l->protoLookupTwoClasses.data = data1;
+ l->protoLookupTwoClasses.data2 = data2;
+}
+
ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
{
if (const Object *o = object.as<Object>()) {
- Lookup first = *l;
- Lookup second = *l;
- ReturnedValue result = second.resolveGetter(engine, o);
-
- if (first.getter == getter0Inline && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
- l->objectLookupTwoClasses.ic = first.objectLookup.ic;
- l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
- l->objectLookupTwoClasses.offset = first.objectLookup.offset;
- l->objectLookupTwoClasses.offset2 = second.objectLookup.offset;
- l->getter = second.getter == getter0Inline ? getter0Inlinegetter0Inline : getter0Inlinegetter0MemberData;
+ // Do the resolution on a second lookup, then merge.
+ Lookup second;
+ memset(&second, 0, sizeof(Lookup));
+ second.nameIndex = l->nameIndex;
+ second.getter = getterGeneric;
+ const ReturnedValue result = second.resolveGetter(engine, o);
+
+ if (l->getter == getter0Inline
+ && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
+ setupObjectLookupTwoClasses(l, *l, second);
+ l->getter = (second.getter == getter0Inline)
+ ? getter0Inlinegetter0Inline
+ : getter0Inlinegetter0MemberData;
return result;
}
- if (first.getter == getter0MemberData && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
- l->objectLookupTwoClasses.ic = second.objectLookup.ic;
- l->objectLookupTwoClasses.ic2 = first.objectLookup.ic;
- l->objectLookupTwoClasses.offset = second.objectLookup.offset;
- l->objectLookupTwoClasses.offset2 = first.objectLookup.offset;
- l->getter = second.getter == getter0Inline ? getter0Inlinegetter0MemberData : getter0MemberDatagetter0MemberData;
+
+ if (l->getter == getter0MemberData
+ && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
+ setupObjectLookupTwoClasses(l, second, *l);
+ l->getter = (second.getter == getter0Inline)
+ ? getter0Inlinegetter0MemberData
+ : getter0MemberDatagetter0MemberData;
return result;
}
- if (first.getter == getterProto && second.getter == getterProto) {
- l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
- l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
- l->protoLookupTwoClasses.data = first.protoLookup.data;
- l->protoLookupTwoClasses.data2 = second.protoLookup.data;
+
+
+ if (l->getter == getterProto && second.getter == getterProto) {
+ setupProtoLookupTwoClasses(l, *l, second);
l->getter = getterProtoTwoClasses;
return result;
}
- if (first.getter == getterProtoAccessor && second.getter == getterProtoAccessor) {
- l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
- l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
- l->protoLookupTwoClasses.data = first.protoLookup.data;
- l->protoLookupTwoClasses.data2 = second.protoLookup.data;
+
+ if (l->getter == getterProtoAccessor && second.getter == getterProtoAccessor) {
+ setupProtoLookupTwoClasses(l, *l, second);
l->getter = getterProtoAccessorTwoClasses;
return result;
}
+ // If any of the above options were true, the propertyCache was inactive.
+ second.releasePropertyCache();
}
l->getter = getterFallback;
@@ -371,7 +401,19 @@ ReturnedValue Lookup::getterIndexed(Lookup *l, ExecutionEngine *engine, const Va
}
l->getter = getterFallback;
return getterFallback(l, engine, object);
+}
+ReturnedValue Lookup::getterQObject(Lookup *lookup, ExecutionEngine *engine, const Value &object)
+{
+ const auto revertLookup = [lookup, engine, &object]() {
+ lookup->qobjectLookup.propertyCache->release();
+ lookup->qobjectLookup.propertyCache = nullptr;
+ lookup->getter = Lookup::getterGeneric;
+ return Lookup::getterGeneric(lookup, engine, object);
+ };
+
+ return QObjectWrapper::lookupGetterImpl(
+ lookup, engine, object, /*useOriginalProperty*/ false, revertLookup);
}
ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
@@ -463,23 +505,30 @@ bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, co
bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
- Lookup first = *l;
- Lookup second = *l;
+ // A precondition of this method is that l->objectLookup is the active variant of the union.
+ Q_ASSERT(l->setter == setter0MemberData || l->setter == setter0Inline);
if (object.isObject()) {
+
+ // As l->objectLookup is active, we can stash some members here, before resolving.
+ Heap::InternalClass *ic = l->objectLookup.ic;
+ const uint index = l->objectLookup.index;
+
if (!l->resolveSetter(engine, static_cast<Object *>(&object), value)) {
l->setter = setterFallback;
return false;
}
if (l->setter == Lookup::setter0MemberData || l->setter == Lookup::setter0Inline) {
- l->objectLookupTwoClasses.ic = first.objectLookup.ic;
- l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
- l->objectLookupTwoClasses.offset = first.objectLookup.index;
- l->objectLookupTwoClasses.offset2 = second.objectLookup.index;
+ l->objectLookupTwoClasses.ic = ic;
+ l->objectLookupTwoClasses.ic2 = ic;
+ l->objectLookupTwoClasses.offset = index;
+ l->objectLookupTwoClasses.offset2 = index;
l->setter = setter0setter0;
return true;
}
+
+ l->releasePropertyCache();
}
l->setter = setterFallback;
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 31c90b31f6..6241a81850 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -56,11 +56,17 @@
#include "qv4context_p.h"
#include "qv4object_p.h"
#include "qv4internalclass_p.h"
+#include "qv4qmlcontext_p.h"
+#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
+// Note: We cannot hide the copy ctor and assignment operator of this class because it needs to
+// be trivially copyable. But you should never ever copy it. There are refcounted members
+// in there.
struct Q_QML_PRIVATE_EXPORT Lookup {
union {
ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
@@ -187,6 +193,7 @@ struct Q_QML_PRIVATE_EXPORT Lookup {
static ReturnedValue getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object);
+ static ReturnedValue getterQObject(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
static ReturnedValue primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
@@ -216,6 +223,20 @@ struct Q_QML_PRIVATE_EXPORT Lookup {
void clear() {
memset(&markDef, 0, sizeof(markDef));
}
+
+ void releasePropertyCache()
+ {
+ if (getter == getterQObject
+ || getter == QQmlTypeWrapper::lookupSingletonProperty
+ || qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty
+ || qmlContextPropertyGetter == QQmlContextWrapper::lookupContextObjectProperty) {
+ if (QQmlPropertyCache *pc = qobjectLookup.propertyCache)
+ pc->release();
+ } else if (getter == QQmlValueTypeWrapper::lookupGetter) {
+ if (QQmlPropertyCache *pc = qgadgetLookup.propertyCache)
+ pc->release();
+ }
+ }
};
Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
@@ -223,6 +244,33 @@ Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
// across 32-bit and 64-bit (matters when cross-compiling).
Q_STATIC_ASSERT(offsetof(Lookup, getter) == 0);
+inline void setupQObjectLookup(
+ Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData)
+{
+ lookup->releasePropertyCache();
+ Q_ASSERT(ddata->propertyCache != nullptr);
+ lookup->qobjectLookup.propertyCache = ddata->propertyCache;
+ lookup->qobjectLookup.propertyCache->addref();
+ lookup->qobjectLookup.propertyData = propertyData;
+}
+
+inline void setupQObjectLookup(
+ Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData,
+ const Object *self)
+{
+ lookup->qobjectLookup.ic = self->internalClass();
+ setupQObjectLookup(lookup, ddata, propertyData);
+}
+
+
+inline void setupQObjectLookup(
+ Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData,
+ const Object *self, const Object *qmlType)
+{
+ lookup->qobjectLookup.qmlTypeIc = qmlType->internalClass();
+ setupQObjectLookup(lookup, ddata, propertyData, self);
+}
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 6eece147a6..be6c614eda 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -294,11 +294,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
QQmlData *ddata = QQmlData::get(scopeObject, false);
if (ddata && ddata->propertyCache) {
ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, scopeObject)));
- const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
- lookup->qobjectLookup.ic = That->internalClass();
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = propertyData;
+ QV4::setupQObjectLookup(lookup, ddata, propertyData, val->objectValue());
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupScopeObjectProperty;
}
}
@@ -326,11 +322,8 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
QQmlData *ddata = QQmlData::get(context->contextObject, false);
if (ddata && ddata->propertyCache) {
ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, context->contextObject)));
- const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
- lookup->qobjectLookup.ic = That->internalClass();
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = propertyData;
+ QV4::setupQObjectLookup(lookup, ddata, propertyData,
+ val->objectValue());
lookup->qmlContextPropertyGetter = contextGetterFunction;
}
} else if (originalLookup) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 9899c9274e..e57cdd8278 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -875,26 +875,11 @@ ReturnedValue QObjectWrapper::virtualResolveLookupGetter(const Object *object, E
return QV4::Object::virtualResolveLookupGetter(object, engine, lookup);
}
- lookup->qobjectLookup.ic = This->internalClass();
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = property;
- lookup->getter = QV4::QObjectWrapper::lookupGetter;
+ QV4::setupQObjectLookup(lookup, ddata, property, This);
+ lookup->getter = QV4::Lookup::getterQObject;
return lookup->getter(lookup, engine, *object);
}
-ReturnedValue QObjectWrapper::lookupGetter(Lookup *lookup, ExecutionEngine *engine, const Value &object)
-{
- const auto revertLookup = [lookup, engine, &object]() {
- lookup->qobjectLookup.propertyCache->release();
- lookup->qobjectLookup.propertyCache = nullptr;
- lookup->getter = Lookup::getterGeneric;
- return Lookup::getterGeneric(lookup, engine, object);
- };
-
- return lookupGetterImpl(lookup, engine, object, /*useOriginalProperty*/ false, revertLookup);
-}
-
bool QObjectWrapper::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup,
const Value &value)
{
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index ac9cad2bdb..10ba79a5e9 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -183,7 +183,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
static ReturnedValue getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property);
static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
- static ReturnedValue lookupGetter(Lookup *l, ExecutionEngine *engine, const Value &object);
+
template <typename ReversalFunctor> static ReturnedValue lookupGetterImpl(Lookup *l, ExecutionEngine *engine, const Value &object, bool useOriginalProperty, ReversalFunctor revert);
static bool virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 9eb81e566e..92bd369ccc 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -598,12 +598,8 @@ QObject *QQmlProperty::object() const
*/
QQmlProperty &QQmlProperty::operator=(const QQmlProperty &other)
{
- if (d)
- d->release();
- d = other.d;
- if (d)
- d->addref();
-
+ QQmlProperty copied(other);
+ qSwap(d, copied.d);
return *this;
}
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index 92a90ea677..ebd139b6a9 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -211,18 +211,12 @@ bool QQmlTypeData::tryLoadFromDiskCache()
}
}
- QQmlType containingType;
- auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first();
- int major = -1, minor = -1;
- QQmlImportNamespace *ns = nullptr;
- m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns);
for (auto&& ic: ics) {
QString const nameString = m_compiledData->stringAt(ic.nameIndex);
- QByteArray const name = nameString.toUtf8();
auto importUrl = finalUrl();
importUrl.setFragment(QString::number(ic.objectIndex));
auto import = new QQmlImportInstance();
- m_importCache.addInlineComponentImport(import, nameString, importUrl, containingType);
+ m_importCache.addInlineComponentImport(import, nameString, importUrl, QQmlType());
}
return true;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index fa5d36503d..175de8b936 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -458,11 +458,8 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
if (property) {
ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
- lookup->qobjectLookup.qmlTypeIc = This->internalClass();
- lookup->qobjectLookup.ic = val->objectValue()->internalClass();
- lookup->qobjectLookup.propertyCache = ddata->propertyCache;
- lookup->qobjectLookup.propertyCache->addref();
- lookup->qobjectLookup.propertyData = property;
+ setupQObjectLookup(lookup, ddata, property,
+ val->objectValue(), This);
lookup->getter = QQmlTypeWrapper::lookupSingletonProperty;
return lookup->getter(lookup, engine, *object);
}
diff --git a/src/qml/qtqmlglobal_p.h b/src/qml/qtqmlglobal_p.h
index 7b0910fa13..76479431dc 100644
--- a/src/qml/qtqmlglobal_p.h
+++ b/src/qml/qtqmlglobal_p.h
@@ -70,4 +70,26 @@ GHS_KEEP_REFERENCE(qml_register_types_QtQml);
# define Q_QML_AUTOTEST_EXPORT
#endif
+// When doing macOS universal builds, JIT needs to be disabled for the ARM slice.
+// Because both arm and x86_64 slices are built in one clang frontend invocation
+// we need this hack to ensure each backend invocation sees the correct value
+// of the feature definition.
+
+// Unset dummy value
+#undef QT_QML_JIT_SUPPORTED_IMPL
+// Compute per-arch value and save in extra define
+#if QT_CONFIG(qml_jit) && !(defined(Q_OS_MACOS) && defined(Q_PROCESSOR_ARM))
+# define QT_QML_JIT_SUPPORTED_IMPL 1
+#else
+# define QT_QML_JIT_SUPPORTED_IMPL 0
+#endif
+// Unset original feature value
+#undef QT_FEATURE_qml_jit
+// Set new value based on previous computation
+#if QT_QML_JIT_SUPPORTED_IMPL
+# define QT_FEATURE_qml_jit 1
+#else
+# define QT_FEATURE_qml_jit -1
+#endif
+
#endif // QTQMLGLOBAL_P_H