From a7fc82e2e95657e048e43fe438d07b63349c38cd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 28 Aug 2018 09:43:32 +0200 Subject: 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 --- src/qml/compiler/qv4compilerscanfunctions.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/qml/compiler/qv4compilerscanfunctions.cpp') diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index 06335b3aa0..5d3a7a6d8c 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -312,6 +312,10 @@ bool ScanFunctions::visit(PatternElement *ast) QStringList names; ast->boundNames(&names); + QQmlJS::AST::SourceLocation lastInitializerLocation = ast->lastSourceLocation(); + if (_context->lastBlockInitializerLocation.isValid()) + lastInitializerLocation = _context->lastBlockInitializerLocation; + for (const QString &name : qAsConst(names)) { if (_context->isStrict && (name == QLatin1String("eval") || name == QLatin1String("arguments"))) _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode")); @@ -322,7 +326,8 @@ bool ScanFunctions::visit(PatternElement *ast) _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration")); return false; } - if (!_context->addLocalVar(name, ast->initializer ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope)) { + if (!_context->addLocalVar(name, ast->initializer ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope, + /*function*/nullptr, lastInitializerLocation)) { _cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name)); return false; } @@ -485,6 +490,8 @@ void ScanFunctions::endVisit(ForStatement *) bool ScanFunctions::visit(ForEachStatement *ast) { enterEnvironment(ast, ContextType::Block, QStringLiteral("%Foreach")); + if (ast->expression) + _context->lastBlockInitializerLocation = ast->expression->lastSourceLocation(); Node::accept(ast->lhs, this); Node::accept(ast->expression, this); -- cgit v1.2.1