From ee89a8c052db0fa3dffe3e01c4c0309cf9ec80d0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 16 Mar 2018 11:15:38 +0100 Subject: 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 --- src/qml/compiler/qqmlirbuilder.cpp | 6 ------ src/qml/compiler/qv4compileddata_p.h | 2 +- src/qml/compiler/qv4instr_moth.cpp | 4 ---- src/qml/compiler/qv4instr_moth_p.h | 6 ++---- src/qml/jit/qv4jit.cpp | 11 ----------- src/qml/jit/qv4jit_p.h | 1 - src/qml/jsruntime/qv4engine.cpp | 21 --------------------- src/qml/jsruntime/qv4engine_p.h | 1 - src/qml/jsruntime/qv4runtime.cpp | 7 ------- src/qml/jsruntime/qv4runtimeapi_p.h | 1 - src/qml/jsruntime/qv4vme_moth.cpp | 4 ---- .../lib/org/qtproject/MixedModule/SingletonType.qml | 3 +++ .../qml/qqmllanguage/data/usingTypeWithEnum.qml | 2 ++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 4 ++++ 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(Moth::Instr::Type::LoadQmlSingleton) + 1) + F(LoadQmlImportedScripts) +#define MOTH_NUM_INSTRUCTIONS() (static_cast(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 { /* 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(engine)); MOTH_END_INSTR(LoadQmlImportedScripts) - MOTH_BEGIN_INSTR(LoadQmlSingleton) - acc = Runtime::method_loadQmlSingleton(static_cast(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 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); } } -- cgit v1.2.3