aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compilerscanfunctions.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-28 10:58:58 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:21 +0000
commit851c28d140c398990513640047a20aab36ccc655 (patch)
treedd9391f74c6a98a234cf2b5ac09bc41b7b7d3b98 /src/qml/compiler/qv4compilerscanfunctions.cpp
parent13cc936859518b5fa378c7b8242d56ebf49ebce9 (diff)
Refactor variable resolving
Move variable resolving into the context, and avoid creating ExecutionContext's whereever we can. This prepares things for block scoping, where this becomes rather important to be able to achieve decent performance. Change-Id: Idf3d3c12cf348a2c3da01989c26c8529ceb36c12 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp')
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index b779e37946..0feba7bb61 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -474,13 +474,17 @@ void ScanFunctions::calcEscapingVariables()
while (c) {
Context::MemberMap::const_iterator it = c->members.find(var);
if (it != c->members.end()) {
- if (c != inner)
+ if (c != inner) {
it->canEscape = true;
+ c->requiresExecutionContext = true;
+ }
break;
}
if (c->findArgument(var) != -1) {
- if (c != inner)
+ if (c != inner) {
c->argumentsCanEscape = true;
+ c->requiresExecutionContext = true;
+ }
break;
}
c = c->parent;
@@ -489,16 +493,44 @@ void ScanFunctions::calcEscapingVariables()
Context *c = inner->parent;
while (c) {
c->hasDirectEval |= inner->hasDirectEval;
+ c->hasWith |= inner->hasWith;
c = c->parent;
}
}
+ for (Context *c : qAsConst(m->contextMap)) {
+ bool allVarsEscape = c->hasWith || c->hasTry || c->hasDirectEval || m->debugMode;
+ if (allVarsEscape) {
+ c->requiresExecutionContext = true;
+ c->argumentsCanEscape = true;
+ for (auto &m : c->members) {
+ m.canEscape = true;
+ }
+ }
+ // ### for now until we have lexically scoped vars that'll require it
+ if (c->type == ContextType::Global)
+ c->requiresExecutionContext = false;
+ // ### Shouldn't be required, we could probably rather change the ContextType to FunctionCode for strict eval
+ if (c->type == ContextType::Eval && c->isStrict)
+ c->requiresExecutionContext = true;
+ if (!c->parent || c->usesArgumentsObject == Context::ArgumentsObjectUnknown)
+ c->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
+ if (c->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ QString arguments = QStringLiteral("arguments");
+ c->addLocalVar(arguments, Context::VariableDeclaration, AST::VariableScope::Var);
+ if (!c->isStrict) {
+ c->argumentsCanEscape = true;
+ c->requiresExecutionContext = true;
+ }
+ }
+ }
static const bool showEscapingVars = qEnvironmentVariableIsSet("QV4_SHOW_ESCAPING_VARS");
if (showEscapingVars) {
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
qDebug() << "Context" << c->name << ":";
- qDebug() << " Arguments escape" << c->argumentsCanEscape;
+ if (c->argumentsCanEscape)
+ qDebug() << " Arguments escape";
for (auto it = c->members.constBegin(); it != c->members.constEnd(); ++it) {
qDebug() << " " << it.key() << it.value().canEscape;
}