aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-03-16 11:15:38 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2018-03-16 10:42:57 +0000
commitee89a8c052db0fa3dffe3e01c4c0309cf9ec80d0 (patch)
tree281e0baf0ae8f69408f438dac87952805f8504af
parentd7b361bc33992ed61310b709df476cc4fa9f67e5 (diff)
Fix lookup of enums declared in QML singletons
Given the following expression var x = MySingleton.MyEnumValue where MySingleton is a QML (composite) singleton and MyEnumValue comes from a QML declared enum, we had code in place up to (and including) 5.10 to attempt to optimize that expression to a enum constant at compile time. In 5.10 that optimization does not exist anymore. In <= 5.10 we would also skip the optimization under certain circumstances (too many statementes, etc.). The fallback that is in place for handling this at run-time tried to be smart by avoiding the QQmlContextWrapper::get lookup and return straight a reference to the singleton as QObject. That works for regular property lookups, but it fails when trying to look up something like an enum, that isn't a meta-object property. Change-Id: I1819b9d8ae06a3f595e067bf5b018c4065be76bb Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp6
-rw-r--r--src/qml/compiler/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h6
-rw-r--r--src/qml/jit/qv4jit.cpp11
-rw-r--r--src/qml/jit/qv4jit_p.h1
-rw-r--r--src/qml/jsruntime/qv4engine.cpp21
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp7
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp4
14 files changed, 12 insertions, 61 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 237cd9bf3b..a9d86b24f5 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2213,12 +2213,6 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n
Reference imports = Reference::fromStackSlot(this, _importedScriptsSlot);
return Reference::fromSubscript(imports, Reference::fromConst(this, QV4::Encode(r.scriptIndex)));
} else if (r.type.isValid()) {
- if (r.type.isCompositeSingleton()) {
- Instruction::LoadQmlSingleton load;
- load.name = registerString(name);
- bytecodeGenerator->addInstruction(load);
- return Reference::fromAccumulator(this);
- }
return Reference::fromName(this, name);
} else {
Q_ASSERT(r.importNamespace);
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 2c0320f7f1..f1776f5772 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x17
+#define QV4_DATA_STRUCTURE_VERSION 0x18
class QIODevice;
class QQmlPropertyCache;
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 34953d52ce..450fa50528 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -634,10 +634,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
d << dumpRegister(result, nFormals);
MOTH_END_INSTR(LoadQmlImportedScripts)
-
- MOTH_BEGIN_INSTR(LoadQmlSingleton)
- d << name;
- MOTH_END_INSTR(LoadQmlSingleton)
}
}
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 2d1428bd19..7dd639c94c 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -174,7 +174,6 @@ QT_BEGIN_NAMESPACE
#define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs)
#define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result)
#define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result)
-#define INSTR_LoadQmlSingleton(op) INSTRUCTION(op, LoadQmlSingleton, 1, name)
#define FOR_EACH_MOTH_INSTR(F) \
@@ -290,9 +289,8 @@ QT_BEGIN_NAMESPACE
F(Mod) \
F(Sub) \
F(LoadQmlContext) \
- F(LoadQmlImportedScripts) \
- F(LoadQmlSingleton)
-#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlSingleton) + 1)
+ F(LoadQmlImportedScripts)
+#define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::LoadQmlImportedScripts) + 1)
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
// icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the
diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp
index 5dc98a591a..bc46c0ca1d 100644
--- a/src/qml/jit/qv4jit.cpp
+++ b/src/qml/jit/qv4jit.cpp
@@ -917,14 +917,6 @@ void BaselineJIT::generate_LoadQmlImportedScripts(int result)
as->storeReg(result);
}
-void BaselineJIT::generate_LoadQmlSingleton(int name)
-{
- as->prepareCallWithArgCount(2);
- as->passInt32AsArg(name, 1);
- as->passEngineAsArg(0);
- JIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlSingleton, Assembler::ResultInAccumulator);
-}
-
void BaselineJIT::startInstruction(Instr::Type /*instr*/)
{
if (hasLabel())
@@ -1328,9 +1320,6 @@ void BaselineJIT::collectLabelsInBytecode()
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
MOTH_END_INSTR(LoadQmlImportedScripts)
-
- MOTH_BEGIN_INSTR(LoadQmlSingleton)
- MOTH_END_INSTR(LoadQmlSingleton)
}
}
#undef MOTH_BEGIN_INSTR
diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h
index c17ab4ff6e..5aebf78a8d 100644
--- a/src/qml/jit/qv4jit_p.h
+++ b/src/qml/jit/qv4jit_p.h
@@ -240,7 +240,6 @@ public:
void generate_Sub(int lhs) override;
void generate_LoadQmlContext(int result) override;
void generate_LoadQmlImportedScripts(int result) override;
- void generate_LoadQmlSingleton(int name) override;
void startInstruction(Moth::Instr::Type instr) override;
void endInstruction(Moth::Instr::Type instr) override;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 5f59e1e809..5521633db7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -758,27 +758,6 @@ QObject *ExecutionEngine::qmlScopeObject() const
return ctx->qml()->scopeObject;
}
-ReturnedValue ExecutionEngine::qmlSingletonWrapper(String *name)
-{
- QQmlContextData *ctx = callingQmlContext();
- if (!ctx->imports)
- return Encode::undefined();
- // Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = ctx->imports->query(name);
-
- Q_ASSERT(r.isValid());
- Q_ASSERT(r.type.isValid());
- Q_ASSERT(r.type.isSingleton());
-
- QQmlType::SingletonInstanceInfo *siinfo = r.type.singletonInstanceInfo();
- QQmlEngine *e = qmlEngine();
- siinfo->init(e);
-
- if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
- return QV4::QObjectWrapper::wrap(this, qobjectSingleton);
- return QJSValuePrivate::convertedToValue(this, siinfo->scriptApi(e));
-}
-
QQmlContextData *ExecutionEngine::callingQmlContext() const
{
Heap::QmlContext *ctx = qmlContext();
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 5edf89f720..c7fb743088 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -441,7 +441,6 @@ public:
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
- ReturnedValue qmlSingletonWrapper(String *name);
QQmlContextData *callingQmlContext() const;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 04cad8ddb7..2506777e76 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1326,13 +1326,6 @@ ReturnedValue Runtime::method_loadQmlImportedScripts(NoThrowEngine *engine)
return context->importedScripts.value();
}
-QV4::ReturnedValue Runtime::method_loadQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex)
-{
- Scope scope(engine);
- ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- return engine->qmlSingletonWrapper(name);
-}
-
ReturnedValue Runtime::method_uMinus(const Value &value)
{
TRACE1(value);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index 2956a4a463..91232256a9 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -184,7 +184,6 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
/* qml */ \
F(ReturnedValue, loadQmlContext, (NoThrowEngine *engine)) \
F(ReturnedValue, loadQmlImportedScripts, (NoThrowEngine *engine)) \
- F(ReturnedValue, loadQmlSingleton, (NoThrowEngine *engine, int nameIndex)) \
F(ReturnedValue, loadQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
F(ReturnedValue, loadQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired)) \
F(ReturnedValue, loadQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)) \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index feeeee527a..e73365e9b1 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -1369,10 +1369,6 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
- MOTH_BEGIN_INSTR(LoadQmlSingleton)
- acc = Runtime::method_loadQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), name);
- MOTH_END_INSTR(LoadQmlSingleton)
-
catchException:
Q_ASSERT(engine->hasException);
if (!exceptionHandler) {
diff --git a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml
index 7763c783f1..2913ceca08 100644
--- a/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml
+++ b/tests/auto/qml/qqmllanguage/data/lib/org/qtproject/MixedModule/SingletonType.qml
@@ -2,4 +2,7 @@ import QtQuick 2.0
pragma Singleton
Item {
+ enum EnumInSingleton {
+ EnumValue = 42
+ }
}
diff --git a/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml
index 2509fc0df1..43e54bbf1d 100644
--- a/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml
+++ b/tests/auto/qml/qqmllanguage/data/usingTypeWithEnum.qml
@@ -1,8 +1,10 @@
import QtQuick 2.0
+import org.qtproject.MixedModule 1.0
QtObject {
property int enumValue: TypeWithEnum.EnumValue2
property int enumValue2: -1
property int scopedEnumValue: TypeWithEnum.MyEnum.EnumValue3
+ property int enumValueFromSingleton: { var x = SingletonType.EnumValue; return x; }
Component.onCompleted: enumValue2 = TypeWithEnum.EnumValue1
}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 8bc631fbdd..f1f35f9fd4 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -3752,6 +3752,9 @@ void tst_qqmllanguage::scopedEnum()
void tst_qqmllanguage::qmlEnums()
{
+ QQmlEngine engine;
+ engine.setImportPathList(QStringList(defaultImportPathList) << testFile("lib"));
+
{
QQmlComponent component(&engine, testFileUrl("TypeWithEnum.qml"));
QScopedPointer<QObject> o(component.create());
@@ -3774,6 +3777,7 @@ void tst_qqmllanguage::qmlEnums()
QCOMPARE(o->property("enumValue").toInt(), 1);
QCOMPARE(o->property("enumValue2").toInt(), 0);
QCOMPARE(o->property("scopedEnumValue").toInt(), 2);
+ QCOMPARE(o->property("enumValueFromSingleton").toInt(), 42);
}
}