diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-08-28 09:43:32 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-08-29 06:54:02 +0000 |
commit | a7fc82e2e95657e048e43fe438d07b63349c38cd (patch) | |
tree | 48dfcfc88fb60cdb89efaabed53fcc6b82634e1a /src/qml/compiler/qv4compilercontext.cpp | |
parent | 2d1a50228571a82ab7a098a64ef04b4ccfe7ee15 (diff) | |
download | qtdeclarative-a7fc82e2e95657e048e43fe438d07b63349c38cd.tar.gz |
Optimize access to lexically scoped variables
If we access a lexically scoped variable after the initializer, then we
know it's either initialized or at least undefined, so we don't need to
do the TDZ check anymore.
The ES tests ensure that we don't optimize too much and the newly
revived tst_v4misc test ensures that we do not generate the TDZ check
instruction for certain scenarios.
Change-Id: I6706d1feb22217f323124ee698ebadb70324693b
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compilercontext.cpp')
-rw-r--r-- | src/qml/compiler/qv4compilercontext.cpp | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp index ac0c2e0ecc..ba9b270601 100644 --- a/src/qml/compiler/qv4compilercontext.cpp +++ b/src/qml/compiler/qv4compilercontext.cpp @@ -71,7 +71,22 @@ Context *Module::newContext(Node *node, Context *parent, ContextType contextType return c; } -bool Context::addLocalVar(const QString &name, Context::MemberType type, VariableScope scope, FunctionExpression *function) +bool Context::Member::requiresTDZCheck(const SourceLocation &accessLocation, bool accessAcrossContextBoundaries) const +{ + if (!isLexicallyScoped()) + return false; + + if (accessAcrossContextBoundaries) + return true; + + if (!accessLocation.isValid() || !endOfInitializerLocation.isValid()) + return true; + + return accessLocation.begin() < endOfInitializerLocation.end(); +} + +bool Context::addLocalVar(const QString &name, Context::MemberType type, VariableScope scope, FunctionExpression *function, + const QQmlJS::AST::SourceLocation &endOfInitializer) { // ### can this happen? if (name.isEmpty()) @@ -96,17 +111,18 @@ bool Context::addLocalVar(const QString &name, Context::MemberType type, Variabl // hoist var declarations to the function level if (contextType == ContextType::Block && (scope == VariableScope::Var && type != MemberType::FunctionDefinition)) - return parent->addLocalVar(name, type, scope, function); + return parent->addLocalVar(name, type, scope, function, endOfInitializer); Member m; m.type = type; m.function = function; m.scope = scope; + m.endOfInitializerLocation = endOfInitializer; members.insert(name, m); return true; } -Context::ResolvedName Context::resolveName(const QString &name) +Context::ResolvedName Context::resolveName(const QString &name, const QQmlJS::AST::SourceLocation &accessLocation) { int scope = 0; Context *c = this; @@ -126,7 +142,7 @@ Context::ResolvedName Context::resolveName(const QString &name) result.scope = scope; result.index = m.index; result.isConst = (m.scope == VariableScope::Const); - result.requiresTDZCheck = m.isLexicallyScoped(); + result.requiresTDZCheck = m.requiresTDZCheck(accessLocation, c != this); if (c->isStrict && (name == QLatin1String("arguments") || name == QLatin1String("eval"))) result.isArgOrEval = true; return result; |