aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-06-20 12:00:28 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-06-20 10:12:58 +0000
commit1658f5b7492161a883058cbaaaf276ccd8588688 (patch)
tree1fbe726ebd59115c0945cdb85494fe54945bbe99 /src/qml/compiler
parentf66599936e8d9ed3a67263b8ae64acfda605ada7 (diff)
Port JSCodeGen in qqmlirbuilder over to new parser
Implement QML support in Reference. Implement the fallbackNameLookup() method for QML, and emit bytecode to load the qml context and imported script temps in beginFunctionBodyHook() Change-Id: I7e052f10ec064097ab1c1f51d776622a4176ce99 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp80
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/compiler/qv4codegen.cpp52
-rw-r--r--src/qml/compiler/qv4codegen_p.h28
4 files changed, 118 insertions, 44 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 9cc8346160..fade4148c5 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1927,29 +1927,34 @@ static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver,
void JSCodeGen::beginFunctionBodyHook()
{
- _qmlContextTemp = _block->newTemp();
- _importedScriptsTemp = _block->newTemp();
+ _qmlContextTemp = bytecodeGenerator->newTemp();
+ _importedScriptsTemp = bytecodeGenerator->newTemp();
#ifndef V4_BOOTSTRAP
- QV4::IR::Temp *temp = _block->TEMP(_qmlContextTemp);
+ Instruction::LoadQmlContext load;
+ load.result = Reference::fromTemp(this, _qmlContextTemp).asLValue();
+ bytecodeGenerator->addInstruction(load);
+
+#if 0
temp->type = QV4::IR::QObjectType;
temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
initMetaObjectResolver(temp->memberResolver, _scopeObject);
auto name = _block->NAME(QV4::IR::Name::builtin_qml_context, 0, 0);
name->type = temp->type;
- move(temp, name);
+#endif
- move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
+ Instruction::LoadQmlImportedScripts loadScripts;
+ loadScripts.result = Reference::fromTemp(this, _importedScriptsTemp).asLValue();
+ bytecodeGenerator->addInstruction(loadScripts);
#endif
}
-QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col)
+QQmlJS::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &name)
{
- Q_UNUSED(line)
- Q_UNUSED(col)
#ifndef V4_BOOTSTRAP
if (_disableAcceleratedLookups)
- return 0;
+ return Reference();
+
// Implement QML lookup semantics in the current file context.
//
// Note: We do not check if properties of the qml scope object or context object
@@ -1967,10 +1972,14 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
if (_function->isQmlBinding)
_function->idObjectDependencies.insert(mapping.idIndex);
- QV4::IR::Expr *s = _block->MEMBER(_block->TEMP(_qmlContextTemp), _function->newString(name), 0, QV4::IR::Member::MemberOfIdObjectsArray, mapping.idIndex);
- QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
- _block->MOVE(result, s);
- result = _block->TEMP(result->index);
+ Reference result = Reference::fromTemp(this);
+ Instruction::LoadIdObject load;
+ load.base = Reference::fromTemp(this, _qmlContextTemp).asRValue();
+ load.index = registerString(name);
+ load.result = result.asLValue();
+ bytecodeGenerator->addInstruction(load);
+
+#if 0
if (mapping.type) {
result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
result->memberResolver->owner = _function;
@@ -1978,6 +1987,7 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
result->memberResolver->flags |= AllPropertiesAreFinal;
}
result->isReadOnly = true; // don't allow use as lvalue
+#endif
return result;
}
}
@@ -1986,32 +1996,39 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
QQmlTypeNameCache::Result r = imports->query(name);
if (r.isValid()) {
if (r.scriptIndex != -1) {
- return _block->SUBSCRIPT(_block->TEMP(_importedScriptsTemp),
- _block->CONST(QV4::IR::SInt32Type, r.scriptIndex));
+ Reference imports = Reference::fromTemp(this, _importedScriptsTemp);
+ return Reference::fromSubscript(imports, Reference::fromConst(this, QV4::Encode(r.scriptIndex)));
} else if (r.type) {
- QV4::IR::Name *typeName = _block->NAME(name, line, col);
- // Make sure the run-time loads this through the more efficient singleton getter.
- typeName->qmlSingleton = r.type->isCompositeSingleton();
+#if 0
typeName->freeOfSideEffects = true;
- QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
- _block->MOVE(result, typeName);
-
result = _block->TEMP(result->index);
result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
result->memberResolver->owner = _function;
initQmlTypeResolver(result->memberResolver, r.type);
+#endif
+ if (r.type->isCompositeSingleton()) {
+ Reference result = Reference::fromTemp(this);
+ Instruction::LoadQmlSingleton load;
+ load.result = result.asRValue();
+ load.name = registerString(name);
+ bytecodeGenerator->addInstruction(load);
+ return result;
+ }
+ Reference result = Reference::fromName(this, name);
return result;
} else {
Q_ASSERT(r.importNamespace);
+ Reference result = Reference::fromName(this, name);
+#if 0
QV4::IR::Name *namespaceName = _block->NAME(name, line, col);
namespaceName->freeOfSideEffects = true;
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
result->memberResolver->owner = _function;
initImportNamespaceResolver(result->memberResolver, imports, r.importNamespace);
-
_block->MOVE(result, namespaceName);
- return _block->TEMP(result->index);
+#endif
+ return result;
}
}
}
@@ -2020,13 +2037,16 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
bool propertyExistsButForceNameLookup = false;
QQmlPropertyData *pd = lookupQmlCompliantProperty(_scopeObject, name, &propertyExistsButForceNameLookup);
if (propertyExistsButForceNameLookup)
- return 0;
+ return Reference::fromName(this, name);
if (pd) {
+#if 0
QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
base->memberResolver->owner = _function;
initMetaObjectResolver(base->memberResolver, _scopeObject);
- return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
+#endif
+ Reference base = Reference::fromTemp(this, _qmlContextTemp);
+ return Reference::fromQmlScopeObject(base, pd->coreIndex());
}
}
@@ -2034,21 +2054,23 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
bool propertyExistsButForceNameLookup = false;
QQmlPropertyData *pd = lookupQmlCompliantProperty(_contextObject, name, &propertyExistsButForceNameLookup);
if (propertyExistsButForceNameLookup)
- return 0;
+ return Reference::fromName(this, name);
if (pd) {
+#if 0
QV4::IR::Temp *base = _block->TEMP(_qmlContextTemp);
base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
base->memberResolver->owner = _function;
initMetaObjectResolver(base->memberResolver, _contextObject);
- return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
+#endif
+ Reference base = Reference::fromTemp(this, _qmlContextTemp);
+ return Reference::fromQmlContextObject(base, pd->coreIndex());
}
}
-
#else
Q_UNUSED(name)
#endif // V4_BOOTSTRAP
// fall back to name lookup at run-time.
- return 0;
+ return Reference();
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 2bdf61ddde..e8a2ba3b5a 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -603,7 +603,7 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QQmlJS::Codegen
protected:
void beginFunctionBodyHook() override;
- QV4::IR::Expr *fallbackNameLookup(const QString &name, int line, int col) override;
+ Reference fallbackNameLookup(const QString &name) override;
private:
QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name, bool *propertyExistsButForceNameLookup = 0);
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 5384272bda..2b3c065fae 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1856,10 +1856,12 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
f = f->outer;
}
- // This hook allows implementing QML lookup semantics
-// ####
-// if (IR::Expr *fallback = fallbackNameLookup(name, line, col))
-// return fallback;
+ {
+ // This hook allows implementing QML lookup semantics
+ Reference fallback = fallbackNameLookup(name);
+ if (fallback.type != Reference::Invalid)
+ return fallback;
+ }
// ###
// if (!e->parent && (!f || !f->insideWithOrCatch) && _variableEnvironment->compilationMode != EvalCode && e->compilationMode != QmlBinding)
@@ -1870,12 +1872,10 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
return Reference::fromName(this, name);
}
-IR::Expr *Codegen::fallbackNameLookup(const QString &name, int line, int col)
+Codegen::Reference Codegen::fallbackNameLookup(const QString &name)
{
Q_UNUSED(name)
- Q_UNUSED(line)
- Q_UNUSED(col)
- return 0;
+ return Reference();
}
bool Codegen::visit(IdentifierExpression *ast)
@@ -2234,7 +2234,7 @@ bool Codegen::visit(StringLiteral *ast)
Instruction::LoadRuntimeString instr;
instr.result = _expr.result.asLValue();
- instr.stringId = jsUnitGenerator->registerString(ast->value.toString());
+ instr.stringId = registerString(ast->value.toString());
bytecodeGenerator->addInstruction(instr);
return false;
}
@@ -2408,7 +2408,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
Instruction::CallBuiltinDeclareVar declareVar;
declareVar.isDeletable = false;
- declareVar.varName = jsUnitGenerator->registerString(local);
+ declareVar.varName = registerString(local);
bytecodeGenerator->addInstruction(declareVar);
}
}
@@ -3210,6 +3210,9 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
break;
case Closure:
closureId = other.closureId;
+ case QmlScopeObject:
+ case QmlContextObject:
+ closureId = other.qmlIndex;
break;
}
@@ -3246,6 +3249,9 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const
return constant == other.constant;
case Closure:
return closureId == other.closureId;
+ case QmlScopeObject:
+ case QmlContextObject:
+ return qmlIndex == other.qmlIndex;
}
return true;
}
@@ -3368,6 +3374,18 @@ void Codegen::Reference::writeBack() const
store.index = subscript;
store.source = temp;
codegen->bytecodeGenerator->addInstruction(store);
+ } else if (type == QmlScopeObject) {
+ Instruction::StoreScopeObjectProperty store;
+ store.base = base;
+ store.propertyIndex = qmlIndex;
+ store.source = temp;
+ codegen->bytecodeGenerator->addInstruction(store);
+ } else if (type == QmlContextObject) {
+ Instruction::StoreContextObjectProperty store;
+ store.base = base;
+ store.propertyIndex = qmlIndex;
+ store.source = temp;
+ codegen->bytecodeGenerator->addInstruction(store);
} else {
Q_ASSERT(false);
Q_UNREACHABLE();
@@ -3412,6 +3430,20 @@ void Codegen::Reference::load(uint tmp) const
load.value = closureId;
load.result = temp;
codegen->bytecodeGenerator->addInstruction(load);
+ } else if (type == QmlScopeObject) {
+ Instruction::LoadScopeObjectProperty load;
+ load.base = base;
+ load.propertyIndex = qmlIndex;
+ load.captureRequired = true; // ### captureRequired;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else if (type == QmlContextObject) {
+ Instruction::LoadContextObjectProperty load;
+ load.base = base;
+ load.propertyIndex = qmlIndex;
+ load.captureRequired = true; // ### captureRequired;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
} else {
Q_ASSERT(false);
Q_UNREACHABLE();
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 109f8ca294..7eefd296a2 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -86,6 +86,7 @@ class UiParameterList;
class Q_QML_PRIVATE_EXPORT Codegen: protected AST::Visitor
{
+protected:
using BytecodeGenerator = QV4::Moth::BytecodeGenerator;
using Instruction = QV4::Moth::Instruction;
public:
@@ -123,7 +124,9 @@ public:
Member,
Subscript,
Closure,
- LastLValue = Closure,
+ QmlScopeObject,
+ QmlContextObject,
+ LastLValue = QmlContextObject,
Const
} type = Invalid;
@@ -164,13 +167,13 @@ public:
}
static Reference fromName(Codegen *cg, const QString &name) {
Reference r(cg, Name);
- r.nameIndex = cg->jsUnitGenerator->registerString(name);
+ r.nameIndex = cg->registerString(name);
return r;
}
static Reference fromMember(const Reference &baseRef, const QString &name) {
Reference r(baseRef.codegen, Member);
r.base = baseRef.asRValue();
- r.nameIndex = r.codegen->jsUnitGenerator->registerString(name);
+ r.nameIndex = r.codegen->registerString(name);
return r;
}
static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) {
@@ -189,6 +192,18 @@ public:
r.closureId = functionId;
return r;
}
+ static Reference fromQmlScopeObject(const Reference &base, int index) {
+ Reference r(base.codegen, QmlScopeObject);
+ r.base = base.asRValue();
+ r.qmlIndex = index;
+ return r;
+ }
+ static Reference fromQmlContextObject(const Reference &base, int index) {
+ Reference r(base.codegen, QmlContextObject);
+ r.base = base.asRValue();
+ r.qmlIndex = index;
+ return r;
+ }
bool isSimple() const {
switch (type) {
@@ -217,6 +232,7 @@ public:
QV4::Moth::Param subscript;
QV4::ReturnedValue constant;
int closureId;
+ int qmlIndex;
};
mutable int tempIndex = -1;
mutable bool needsWriteBack = false;
@@ -451,6 +467,10 @@ protected:
Reference unop(UnaryOperation op, const Reference &expr);
QV4::IR::Stmt *move(QV4::IR::Expr *target, QV4::IR::Expr *source);
+ int registerString(const QString &name) {
+ return jsUnitGenerator->registerString(name);
+ }
+
// Returns index in _module->functions
int defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
@@ -477,7 +497,7 @@ protected:
Reference referenceForName(const QString &name, bool lhs);
// Hook provided to implement QML lookup semantics
- virtual QV4::IR::Expr *fallbackNameLookup(const QString &name, int line, int col);
+ virtual Reference fallbackNameLookup(const QString &name);
virtual void beginFunctionBodyHook() {}
// nodes