aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-01-02 16:09:56 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2019-03-20 09:16:02 +0000
commitc9e6251cc8dfcf002f64b07e48dd68b7edd3f630 (patch)
treecf366b381c614be175d10e393b02b0c0c7779957 /src/qml/compiler
parentd4076f5ae93e7994e5ce5edcf35a090978613e98 (diff)
Implement dummy QML lookups for "global" variables
When resolving names in the context of QML bindings, we now direct runtime access to QQmlContextWrapper::resolveQmlPropertyLookupGetter. At the moment this does basically the same as Runtime::method_loadName, which we called earlier. However this now provides the opportunity to optimize lookups in the QML context in a central place. When performing a call on a scope or context object property, we also did not use a CallName() instruction - which would have gotten the thisObject wrong - but instead we use a dedicated CallScopeObjectProperty and CallContextObjectProperty instruction. These rely on identifying these properties at compile time, which goes away with lookups (and also doesn't work when using ahead-of-time compilation). Therefore the qml context property lookup is using a getPropertyAndBase style signature and Runtime::method_callQmlContextPropertyLookup uses that. For the tests to pass, some error expectations need adjusting. In particular the compile-time detection of write attempts to id objects is now delayed to the run-time. The old code path is still there and will be removed separately in the next commit (as it is massive). Task-number: QTBUG-69898 Change-Id: Iad1ff93d3758c4db984a7c2d003beee21ed2275c Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp3
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp6
-rw-r--r--src/qml/compiler/qv4codegen.cpp35
-rw-r--r--src/qml/compiler/qv4codegen_p.h5
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata_p.h7
-rw-r--r--src/qml/compiler/qv4compiler.cpp12
-rw-r--r--src/qml/compiler/qv4compiler_p.h2
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp7
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp8
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h4
12 files changed, 70 insertions, 22 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 59b9968bf6..4b4d3c27e8 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2228,7 +2228,8 @@ void JSCodeGen::beginFunctionBodyHook()
QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &name)
{
#ifndef V4_BOOTSTRAP
- if (_disableAcceleratedLookups)
+ // FIXME: Remove this function.
+ if (_disableAcceleratedLookups || true)
return Reference();
// Implement QML lookup semantics in the current file context.
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index af86b70014..a34472010b 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -192,6 +192,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(LoadGlobalLookup)
COLLECTOR_END_INSTR(LoadGlobalLookup)
+ COLLECTOR_BEGIN_INSTR(LoadQmlContextPropertyLookup)
+ COLLECTOR_END_INSTR(LoadQmlContextPropertyLookup)
+
COLLECTOR_BEGIN_INSTR(StoreNameSloppy)
COLLECTOR_END_INSTR(StoreNameSloppy)
@@ -270,6 +273,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(CallGlobalLookup)
COLLECTOR_END_INSTR(CallGlobalLookup)
+ COLLECTOR_BEGIN_INSTR(CallQmlContextPropertyLookup)
+ COLLECTOR_END_INSTR(CallQmlContextPropertyLookup)
+
COLLECTOR_BEGIN_INSTR(CallScopeObjectProperty)
COLLECTOR_END_INSTR(CallScopeObjectProperty)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 66c334d197..de87d6d48c 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1982,11 +1982,19 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.argv = calldata.argv;
bytecodeGenerator->addInstruction(call);
} else if (!disable_lookups && useFastLookups && base.global) {
- Instruction::CallGlobalLookup call;
- call.index = registerGlobalGetterLookup(base.nameAsIndex());
- call.argc = calldata.argc;
- call.argv = calldata.argv;
- bytecodeGenerator->addInstruction(call);
+ if (base.qmlGlobal) {
+ Instruction::CallQmlContextPropertyLookup call;
+ call.index = registerQmlContextPropertyGetterLookup(base.nameAsIndex());
+ call.argc = calldata.argc;
+ call.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(call);
+ } else {
+ Instruction::CallGlobalLookup call;
+ call.index = registerGlobalGetterLookup(base.nameAsIndex());
+ call.argc = calldata.argc;
+ call.argv = calldata.argv;
+ bytecodeGenerator->addInstruction(call);
+ }
} else {
Instruction::CallName call;
call.name = base.nameAsIndex();
@@ -2361,8 +2369,9 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co
return fallback;
Reference r = Reference::fromName(this, name);
- r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global);
- if (!r.global && canAccelerateGlobalLookups() && m_globalNames.contains(name))
+ r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global || resolved.type == Context::ResolvedName::QmlGlobal);
+ r.qmlGlobal = resolved.type == Context::ResolvedName::QmlGlobal;
+ if (!r.global && !r.qmlGlobal && m_globalNames.contains(name))
r.global = true;
return r;
}
@@ -4385,9 +4394,15 @@ QT_WARNING_POP
}
}
if (!disable_lookups && global) {
- Instruction::LoadGlobalLookup load;
- load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
- codegen->bytecodeGenerator->addInstruction(load);
+ if (qmlGlobal) {
+ Instruction::LoadQmlContextPropertyLookup load;
+ load.index = codegen->registerQmlContextPropertyGetterLookup(nameAsIndex());
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else {
+ Instruction::LoadGlobalLookup load;
+ load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
+ codegen->bytecodeGenerator->addInstruction(load);
+ }
} else {
Instruction::LoadName load;
load.name = nameAsIndex();
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 0b25d9c53d..b1cc4c090a 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -207,7 +207,8 @@ public:
subscriptRequiresTDZCheck(false),
stackSlotIsLocalOrArgument(false),
isVolatile(false),
- global(false)
+ global(false),
+ qmlGlobal(false)
{}
Reference(const Reference &) = default;
@@ -421,6 +422,7 @@ public:
quint32 stackSlotIsLocalOrArgument:1;
quint32 isVolatile:1;
quint32 global:1;
+ quint32 qmlGlobal:1;
private:
void storeAccumulator() const;
@@ -553,6 +555,7 @@ public:
int registerGetterLookup(int nameIndex) { return jsUnitGenerator->registerGetterLookup(nameIndex); }
int registerSetterLookup(int nameIndex) { return jsUnitGenerator->registerSetterLookup(nameIndex); }
int registerGlobalGetterLookup(int nameIndex) { return jsUnitGenerator->registerGlobalGetterLookup(nameIndex); }
+ int registerQmlContextPropertyGetterLookup(int nameIndex) { return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex); }
// Returns index in _module->functions
virtual int defineFunction(const QString &name, AST::Node *ast,
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index e428340f62..6701443971 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -170,6 +170,8 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
l->setter = QV4::Lookup::setterGeneric;
else if (type == CompiledData::Lookup::Type_GlobalGetter)
l->globalGetter = QV4::Lookup::globalGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
+ l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
l->nameIndex = compiledLookups[i].nameIndex;
}
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index c4821daa86..d63b1fd2b9 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -160,9 +160,10 @@ static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected
struct Lookup
{
enum Type : unsigned int {
- Type_Getter = 0x0,
- Type_Setter = 0x1,
- Type_GlobalGetter = 2
+ Type_Getter = 0,
+ Type_Setter = 1,
+ Type_GlobalGetter = 2,
+ Type_QmlContextPropertyGetter = 3
};
union {
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 3076c6b526..a3c9347c67 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -154,15 +154,19 @@ int QV4::Compiler::JSUnitGenerator::registerSetterLookup(int nameIndex)
return lookups.size() - 1;
}
-int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &name)
+int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(int nameIndex)
{
- return registerGlobalGetterLookup(registerString(name));
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter;
+ l.nameIndex = nameIndex;
+ lookups << l;
+ return lookups.size() - 1;
}
-int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(int nameIndex)
+int QV4::Compiler::JSUnitGenerator::registerQmlContextPropertyGetterLookup(int nameIndex)
{
CompiledData::Lookup l;
- l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter;
+ l.type_and_flags = CompiledData::Lookup::Type_QmlContextPropertyGetter;
l.nameIndex = nameIndex;
lookups << l;
return lookups.size() - 1;
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 2f5889ab53..49e334bb81 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -118,8 +118,8 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
int registerGetterLookup(int nameIndex);
int registerSetterLookup(const QString &name);
int registerSetterLookup(int nameIndex);
- int registerGlobalGetterLookup(const QString &name);
int registerGlobalGetterLookup(int nameIndex);
+ int registerQmlContextPropertyGetterLookup(int nameIndex);
int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp);
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 5772bff7bf..84c5d67e8d 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -187,10 +187,13 @@ Context::ResolvedName Context::resolveName(const QString &name, const QQmlJS::AS
}
// ### can we relax the restrictions here?
- if (c->contextType == ContextType::Eval || c->contextType == ContextType::Binding)
+ if (c->contextType == ContextType::Eval)
return result;
- result.type = ResolvedName::Global;
+ if (c->contextType == ContextType::Binding)
+ result.type = ResolvedName::QmlGlobal;
+ else
+ result.type = ResolvedName::Global;
return result;
}
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 328715da07..c9e54c0d1b 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -336,6 +336,7 @@ struct Context {
struct ResolvedName {
enum Type {
Unresolved,
+ QmlGlobal,
Global,
Local,
Stack,
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 83aca3a02c..d2e95b83c4 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -286,6 +286,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << index;
MOTH_END_INSTR(LoadGlobalLookup)
+ MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup)
+ d << index;
+ MOTH_END_INSTR(LoadQmlContextPropertyLookup)
+
MOTH_BEGIN_INSTR(StoreNameSloppy)
d << name;
MOTH_END_INSTR(StoreNameSloppy)
@@ -388,6 +392,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << index << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallGlobalLookup)
+ MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup)
+ d << index << dumpArguments(argc, argv, nFormals);
+ MOTH_END_INSTR(CallQmlContextPropertyLookup)
+
MOTH_BEGIN_INSTR(CallScopeObjectProperty)
d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals);
MOTH_END_INSTR(CallScopeObjectProperty)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 2ca8f692b8..1c77e6050c 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -86,6 +86,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value)
#define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name)
#define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index)
+#define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index)
#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
@@ -113,6 +114,7 @@ QT_BEGIN_NAMESPACE
#define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv)
#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv)
#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv)
+#define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv)
#define INSTR_CallScopeObjectProperty(op) INSTRUCTION(op, CallScopeObjectProperty, 4, name, base, argc, argv)
#define INSTR_CallContextObjectProperty(op) INSTRUCTION(op, CallContextObjectProperty, 4, name, base, argc, argv)
#define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv)
@@ -228,6 +230,7 @@ QT_BEGIN_NAMESPACE
F(LoadClosure) \
F(LoadName) \
F(LoadGlobalLookup) \
+ F(LoadQmlContextPropertyLookup) \
F(StoreNameSloppy) \
F(StoreNameStrict) \
F(LoadElement) \
@@ -296,6 +299,7 @@ QT_BEGIN_NAMESPACE
F(CallName) \
F(CallPossiblyDirectEval) \
F(CallGlobalLookup) \
+ F(CallQmlContextPropertyLookup) \
F(CallScopeObjectProperty) \
F(CallContextObjectProperty) \
F(CallWithSpread) \