From 6adb0693a2e408c388a0939e0a3d711da7b651df Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 11 Oct 2013 13:50:23 +0200 Subject: Fix determination of lookup mode in V4 code generator In order to determine the type of lookup we need (name or directly in environment members), we used Codegen::_mode, which is set to the currently suitable mode depending on the function (parameter to defineFunction). However that's not quite correct, the look-up mode depends on the function itself, not where it was called from. This patch corrects that by moving the compilation mode into the Environment itself. This is needed by follow-up patches. Additionally the "bool deletable" parameter to the builtin_declare_vars was always set to false, because it used mode instead of _mode, which was never set to Eval or QmlBinding. This will be cleaned up in a future patch. Change-Id: I878f187945e5de091689ab5d70a0f33eb5a9e38f Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlcodegenerator.cpp | 12 ++++----- src/qml/compiler/qqmlcodegenerator_p.h | 4 +-- src/qml/compiler/qv4codegen.cpp | 46 +++++++++++++++------------------- src/qml/compiler/qv4codegen_p.h | 20 ++++++++------- 4 files changed, 39 insertions(+), 43 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp index fb2ca7c14e..83f3dfe84a 100644 --- a/src/qml/compiler/qqmlcodegenerator.cpp +++ b/src/qml/compiler/qqmlcodegenerator.cpp @@ -1161,20 +1161,20 @@ void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, P _module->setFileName(fileName); QmlScanner scan(this, output->code); - scan.begin(output->program); + scan.begin(output->program, QmlBinding); foreach (AST::Node *node, output->functions) { if (node == output->program) continue; AST::FunctionDeclaration *function = AST::cast(node); - scan.enterEnvironment(node); + scan.enterEnvironment(node, function ? FunctionCode : QmlBinding); scan(function ? function->body : node); scan.leaveEnvironment(); } scan.end(); _env = 0; - _function = defineFunction(QString("context scope"), output->program, 0, 0, QmlBinding); + _function = defineFunction(QString("context scope"), output->program, 0, 0); foreach (AST::Node *node, output->functions) { if (node == output->program) @@ -1201,7 +1201,7 @@ void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, P defineFunction(name, node, function ? function->formals : 0, - body, function ? FunctionCode : QmlBinding); + body); } @@ -1210,9 +1210,9 @@ void JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fileName, P } -void JSCodeGen::QmlScanner::begin(AST::Node *rootNode) +void JSCodeGen::QmlScanner::begin(AST::Node *rootNode, CompilationMode compilationMode) { - enterEnvironment(0); + enterEnvironment(0, compilationMode); enterFunction(rootNode, "context scope", 0, 0, 0, /*isExpression*/false); } diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h index ec75c38160..09faec2374 100644 --- a/src/qml/compiler/qqmlcodegenerator_p.h +++ b/src/qml/compiler/qqmlcodegenerator_p.h @@ -341,11 +341,11 @@ private: struct QmlScanner : public ScanFunctions { QmlScanner(JSCodeGen *cg, const QString &sourceCode) - : ScanFunctions(cg, sourceCode) + : ScanFunctions(cg, sourceCode, /*default program mode*/GlobalCode) , codeGen(cg) {} - void begin(AST::Node *rootNode); + void begin(AST::Node *rootNode, CompilationMode compilationMode); void end(); JSCodeGen *codeGen; diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 94562ead7f..1f1ed42530 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -64,11 +64,12 @@ using namespace QQmlJS; using namespace AST; -Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode) +Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode) : _cg(cg) , _sourceCode(sourceCode) , _env(0) , _allowFuncDecls(true) + , defaultProgramMode(defaultProgramMode) { } @@ -78,9 +79,9 @@ void Codegen::ScanFunctions::operator()(Node *node) node->accept(this); } -void Codegen::ScanFunctions::enterEnvironment(Node *node) +void Codegen::ScanFunctions::enterEnvironment(Node *node, CompilationMode compilationMode) { - Environment *e = _cg->newEnvironment(node, _env); + Environment *e = _cg->newEnvironment(node, _env, compilationMode); if (!e->isStrict) e->isStrict = _cg->_strictMode; _envStack.append(e); @@ -146,7 +147,7 @@ void Codegen::ScanFunctions::checkForArguments(AST::FormalParameterList *paramet bool Codegen::ScanFunctions::visit(Program *ast) { - enterEnvironment(ast); + enterEnvironment(ast, defaultProgramMode); checkDirectivePrologue(ast->elements); return true; } @@ -374,7 +375,7 @@ void Codegen::ScanFunctions::enterFunction(Node *ast, const QString &name, Forma wasStrict = _env->isStrict; } - enterEnvironment(ast); + enterEnvironment(ast, FunctionCode); checkForArguments(formals); _env->isNamedFunctionExpression = isExpression && !name.isEmpty(); @@ -404,7 +405,6 @@ Codegen::Codegen(bool strict) , _exitBlock(0) , _throwBlock(0) , _returnAddress(0) - , _mode(GlobalCode) , _env(0) , _loop(0) , _labelledStatement(0) @@ -417,7 +417,7 @@ V4IR::Function *Codegen::generateFromProgram(const QString &fileName, const QString &sourceCode, Program *node, V4IR::Module *module, - Mode mode, + CompilationMode mode, const QStringList &inheritedLocals) { assert(node); @@ -427,11 +427,11 @@ V4IR::Function *Codegen::generateFromProgram(const QString &fileName, _module->setFileName(fileName); - ScanFunctions scan(this, sourceCode); + ScanFunctions scan(this, sourceCode, mode); scan(node); V4IR::Function *globalCode = defineFunction(QStringLiteral("%entry"), node, 0, - node->elements, mode, inheritedLocals); + node->elements, inheritedLocals); qDeleteAll(_envMap); _envMap.clear(); @@ -447,9 +447,9 @@ V4IR::Function *Codegen::generateFromFunctionExpression(const QString &fileName, _module->setFileName(fileName); _env = 0; - ScanFunctions scan(this, sourceCode); + ScanFunctions scan(this, sourceCode, GlobalCode); // fake a global environment - scan.enterEnvironment(0); + scan.enterEnvironment(0, FunctionCode); scan(ast); scan.leaveEnvironment(); @@ -804,7 +804,7 @@ void Codegen::variableDeclaration(VariableDeclaration *ast) assert(expr.code); initializer = *expr; - if (! _env->parent || _function->insideWithOrCatch || _mode == QmlBinding) { + if (! _env->parent || _function->insideWithOrCatch || _env->compilationMode == QmlBinding) { // it's global code. move(_block->NAME(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), initializer); } else { @@ -1355,10 +1355,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col) Environment *e = _env; V4IR::Function *f = _function; - if (_mode == QmlBinding) - return _block->NAME(name, line, col); - - while (f && e->parent) { + while (f && e->parent && e->compilationMode != QmlBinding) { if (f->insideWithOrCatch || (f->isNamedExpression && f->name == name)) return _block->NAME(name, line, col); @@ -1382,7 +1379,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col) f = f->outer; } - if (!e->parent && (!f || !f->insideWithOrCatch) && _mode != EvalCode && _mode != QmlBinding) + if (!e->parent && (!f || !f->insideWithOrCatch) && e->compilationMode != EvalCode && e->compilationMode != QmlBinding) return _block->GLOBALNAME(name, line, col); // global context or with. Lookup by name @@ -1752,7 +1749,7 @@ bool Codegen::visit(VoidExpression *ast) bool Codegen::visit(FunctionDeclaration * ast) { - if (_mode == QmlBinding) + if (_env->compilationMode == QmlBinding) move(_block->TEMP(_returnAddress), _block->NAME(ast->name.toString(), 0, 0)); _expr.accept(nx); return false; @@ -1760,10 +1757,9 @@ bool Codegen::visit(FunctionDeclaration * ast) V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, - AST::SourceElements *body, Mode mode, + AST::SourceElements *body, const QStringList &inheritedLocals) { - qSwap(_mode, mode); // enter function code. Loop *loop = 0; qSwap(_loop, loop); @@ -1789,7 +1785,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, _env->enter("arguments", Environment::VariableDeclaration); // variables in global code are properties of the global context object, not locals as with other functions. - if (_mode == FunctionCode) { + if (_env->compilationMode == FunctionCode) { unsigned t = 0; for (Environment::MemberMap::iterator it = _env->members.begin(); it != _env->members.end(); ++it) { const QString &local = it.key(); @@ -1819,7 +1815,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, } if (args) { V4IR::ExprList *next = function->New(); - next->expr = entryBlock->CONST(V4IR::BoolType, (mode == EvalCode || mode == QmlBinding)); + next->expr = entryBlock->CONST(V4IR::BoolType, false); // ### Investigate removal of bool deletable next->next = args; args = next; @@ -1882,8 +1878,6 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast, leaveEnvironment(); - qSwap(_mode, mode); - return function; } @@ -2008,7 +2002,7 @@ bool Codegen::visit(EmptyStatement *) bool Codegen::visit(ExpressionStatement *ast) { - if (_mode == EvalCode || _mode == QmlBinding) { + if (_env->compilationMode == EvalCode || _env->compilationMode == QmlBinding) { Result e = expression(ast->expression); if (*e) move(_block->TEMP(_returnAddress), *e); @@ -2217,7 +2211,7 @@ bool Codegen::visit(LocalForStatement *ast) bool Codegen::visit(ReturnStatement *ast) { - if (_mode != FunctionCode && _mode != QmlBinding) + if (_env->compilationMode != FunctionCode && _env->compilationMode != QmlBinding) throwSyntaxError(ast->returnToken, QCoreApplication::translate("qv4codegen", "Return statement outside of function")); if (ast->expression) { Result expr = expression(ast->expression); diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index ea32b5b349..2da65fae79 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -68,7 +68,7 @@ class Q_QML_EXPORT Codegen: protected AST::Visitor public: Codegen(bool strict); - enum Mode { + enum CompilationMode { GlobalCode, EvalCode, FunctionCode, @@ -79,7 +79,7 @@ public: const QString &sourceCode, AST::Program *ast, V4IR::Module *module, - Mode mode = GlobalCode, + CompilationMode mode = GlobalCode, const QStringList &inheritedLocals = QStringList()); V4IR::Function *generateFromFunctionExpression(const QString &fileName, const QString &sourceCode, @@ -153,7 +153,9 @@ protected: UsesArgumentsObject usesArgumentsObject; - Environment(Environment *parent) + CompilationMode compilationMode; + + Environment(Environment *parent, CompilationMode mode) : parent(parent) , formals(0) , maxNumberOfArguments(0) @@ -162,6 +164,7 @@ protected: , isStrict(false) , isNamedFunctionExpression(false) , usesArgumentsObject(ArgumentsObjectUnknown) + , compilationMode(mode) { if (parent && parent->isStrict) isStrict = true; @@ -216,9 +219,9 @@ protected: } }; - Environment *newEnvironment(AST::Node *node, Environment *parent) + Environment *newEnvironment(AST::Node *node, Environment *parent, CompilationMode compilationMode) { - Environment *env = new Environment(parent); + Environment *env = new Environment(parent, compilationMode); _envMap.insert(node, env); return env; } @@ -283,7 +286,6 @@ protected: V4IR::Function *defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::SourceElements *body, - Mode mode = FunctionCode, const QStringList &inheritedLocals = QStringList()); void unwindException(ScopeAndFinally *outest); @@ -427,7 +429,6 @@ protected: V4IR::BasicBlock *_exitBlock; V4IR::BasicBlock *_throwBlock; unsigned _returnAddress; - Mode _mode; Environment *_env; Loop *_loop; AST::LabelledStatement *_labelledStatement; @@ -442,10 +443,10 @@ protected: { typedef QV4::TemporaryAssignment TemporaryBoolAssignment; public: - ScanFunctions(Codegen *cg, const QString &sourceCode); + ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode); void operator()(AST::Node *node); - void enterEnvironment(AST::Node *node); + void enterEnvironment(AST::Node *node, CompilationMode compilationMode); void leaveEnvironment(); protected: @@ -500,6 +501,7 @@ protected: QStack _envStack; bool _allowFuncDecls; + CompilationMode defaultProgramMode; }; }; -- cgit v1.2.3