, _env(0)
, _loop(0)
, _labelledStatement(0)
- , _tryCleanup(0)
+ , _scopeAndFinally(0)
, _context(context)
, _strictMode(strict)
, _debugger(context->engine->debugger)
, _env(0)
, _loop(0)
, _labelledStatement(0)
- , _tryCleanup(0)
+ , _scopeAndFinally(0)
, _context(0)
, _strictMode(strictMode)
, _debugger(0)
{
_loop = new Loop(node, breakBlock, continueBlock, _loop);
_loop->labelledStatement = _labelledStatement; // consume the enclosing labelled statement
- _loop->tryCleanup = _tryCleanup;
+ _loop->scopeAndFinally = _scopeAndFinally;
_labelledStatement = 0;
}
{
qSwap(_mode, mode); // enter function code.
- TryCleanup *tryCleanup = 0;
+ ScopeAndFinally *scopeAndFinally = 0;
enterEnvironment(ast);
IR::Function *function = _module->newFunction(name, _function);
qSwap(_exitBlock, exitBlock);
qSwap(_throwBlock, throwBlock);
qSwap(_returnAddress, returnAddress);
- qSwap(_tryCleanup, tryCleanup);
+ qSwap(_scopeAndFinally, scopeAndFinally);
qSwap(_loop, loop);
for (FormalParameterList *it = formals; it; it = it->next) {
qSwap(_exitBlock, exitBlock);
qSwap(_throwBlock, throwBlock);
qSwap(_returnAddress, returnAddress);
- qSwap(_tryCleanup, tryCleanup);
+ qSwap(_scopeAndFinally, scopeAndFinally);
qSwap(_loop, loop);
leaveEnvironment();
if (!loop)
throwSyntaxError(ast->lastSourceLocation(), QCoreApplication::translate("qv4codegen", "Undefined label '%1'").arg(ast->label.toString()));
}
- unwindException(loop->tryCleanup);
+ unwindException(loop->scopeAndFinally);
_block->JUMP(loop->breakBlock);
return false;
}
}
if (!loop)
throwSyntaxError(ast->lastSourceLocation(), QCoreApplication::translate("qv4codegen", "continue outside of loop"));
- unwindException(loop->tryCleanup);
+ unwindException(loop->scopeAndFinally);
_block->JUMP(loop->continueBlock);
return false;
}
deleteExceptionArgs->next->init(_block->TEMP(inCatch));
}
- TryCleanup tcf(_tryCleanup, ast->finallyExpression, deleteExceptionArgs);
- _tryCleanup = &tcf;
+ ScopeAndFinally tcf(_scopeAndFinally, ast->finallyExpression, deleteExceptionArgs);
+ _scopeAndFinally = &tcf;
_block->CJUMP(_block->TEMP(hasException), catchBody ? catchBody : finallyBody, tryBody);
_block->JUMP(finallyBody);
}
- _tryCleanup = tcf.parent;
+ _scopeAndFinally = tcf.parent;
IR::BasicBlock *after = _function->newBasicBlock();
_block = finallyBody;
return false;
}
-void Codegen::unwindException(Codegen::TryCleanup *outest)
+void Codegen::unwindException(Codegen::ScopeAndFinally *outest)
{
- TryCleanup *tryCleanup = _tryCleanup;
- qSwap(_tryCleanup, tryCleanup);
- while (_tryCleanup != outest) {
- _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_delete_exception_handler, 0, 0), _tryCleanup->deleteExceptionArgs));
- TryCleanup *tc = _tryCleanup;
- _tryCleanup = tc->parent;
- if (tc->finally && tc->finally->statement)
- statement(tc->finally->statement);
+ ScopeAndFinally *scopeAndFinally = _scopeAndFinally;
+ qSwap(_scopeAndFinally, scopeAndFinally);
+ while (_scopeAndFinally != outest) {
+ if (_scopeAndFinally->popScope) {
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0)));
+ _scopeAndFinally = _scopeAndFinally->parent;
+ } else {
+ _block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_delete_exception_handler, 0, 0), _scopeAndFinally->deleteExceptionArgs));
+ ScopeAndFinally *tc = _scopeAndFinally;
+ _scopeAndFinally = tc->parent;
+ if (tc->finally && tc->finally->statement)
+ statement(tc->finally->statement);
+ }
}
- qSwap(_tryCleanup, tryCleanup);
+ qSwap(_scopeAndFinally, scopeAndFinally);
}
bool Codegen::visit(VariableStatement *ast)
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(withObject));
_block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_push_with_scope, 0, 0), args));
+
++_function->insideWith;
- statement(ast->statement);
+ {
+ ScopeAndFinally scope(_scopeAndFinally);
+ _scopeAndFinally = &scope;
+ statement(ast->statement);
+ _scopeAndFinally = scope.parent;
+ }
--_function->insideWith;
_block->EXP(_block->CALL(_block->NAME(IR::Name::builtin_pop_scope, 0, 0), 0));
struct UiMember {
};
- struct TryCleanup {
- TryCleanup *parent;
+ struct ScopeAndFinally {
+ ScopeAndFinally *parent;
AST::Finally *finally;
IR::ExprList *deleteExceptionArgs;
+ bool popScope;
- TryCleanup(TryCleanup *parent, AST::Finally *finally, IR::ExprList *deleteExceptionArgs)
- : parent(parent), finally(finally), deleteExceptionArgs(deleteExceptionArgs)
+ ScopeAndFinally(ScopeAndFinally *parent) : parent(parent), finally(0), deleteExceptionArgs(0), popScope(true) {}
+ ScopeAndFinally(ScopeAndFinally *parent, AST::Finally *finally, IR::ExprList *deleteExceptionArgs)
+ : parent(parent), finally(finally), deleteExceptionArgs(deleteExceptionArgs), popScope(false)
{}
};
IR::BasicBlock *breakBlock;
IR::BasicBlock *continueBlock;
Loop *parent;
- TryCleanup *tryCleanup;
+ ScopeAndFinally *scopeAndFinally;
Loop(AST::Statement *node, IR::BasicBlock *breakBlock, IR::BasicBlock *continueBlock, Loop *parent)
: labelledStatement(0), node(node), breakBlock(breakBlock), continueBlock(continueBlock), parent(parent) {}
const QStringList &inheritedLocals = QStringList());
int indexOfArgument(const QStringRef &string) const;
- void unwindException(TryCleanup *outest);
+ void unwindException(ScopeAndFinally *outest);
void statement(AST::Statement *ast);
void statement(AST::ExpressionNode *ast);
Environment *_env;
Loop *_loop;
AST::LabelledStatement *_labelledStatement;
- TryCleanup *_tryCleanup;
+ ScopeAndFinally *_scopeAndFinally;
QHash<AST::Node *, Environment *> _envMap;
QHash<AST::FunctionExpression *, int> _functionMap;
VM::ExecutionContext *_context;