class TryFinally: public TryStatement {
public:
- TryFinally(Block* try_block, Expression* finally_var, Block* finally_block)
+ TryFinally(Block* try_block, Block* finally_block)
: TryStatement(try_block),
- finally_var_(finally_var),
finally_block_(finally_block) { }
virtual void Accept(Visitor* v);
- // If the finally block is non-trivial it may be problematic to have
- // extra stuff on the expression stack while evaluating it. The
- // finally variable is used to hold the state instead of storing it
- // on the stack. It may be NULL in which case the state is stored on
- // the stack.
- Expression* finally_var() const { return finally_var_; }
-
Block* finally_block() const { return finally_block_; }
private:
- Expression* finally_var_;
Block* finally_block_;
};
// --- Finally block ---
__ bind(&finally_block);
- // We keep a single element on the stack - the (possibly faked)
- // result - while evaluating the finally block. Record it, so that a
- // break/continue crossing this statement can restore the stack.
- const int kFinallyStackSize = 1 * kPointerSize;
- break_stack_height_ += kFinallyStackSize;
-
- // Push the state on the stack. If necessary move the state to a
- // local variable to avoid having extra values on the stack while
- // evaluating the finally block.
+ // Push the state on the stack.
__ push(r2);
- if (node->finally_var() != NULL) {
- Reference target(this, node->finally_var());
- SetValue(&target);
- ASSERT(target.size() == 0); // no extra stuff on the stack
- __ pop(); // remove the extra avalue that was pushed above
- }
+
+ // We keep two elements on the stack - the (possibly faked) result
+ // and the state - while evaluating the finally block. Record it, so
+ // that a break/continue crossing this statement can restore the
+ // stack.
+ const int kFinallyStackSize = 2 * kPointerSize;
+ break_stack_height_ += kFinallyStackSize;
// Generate code for the statements in the finally block.
VisitStatements(node->finally_block()->statements());
- // Get the state from the stack - or the local variable.
- if (node->finally_var() != NULL) {
- Reference target(this, node->finally_var());
- GetValue(&target);
- }
+ // Restore state and return value or faked TOS.
__ pop(r2);
-
- // Restore return value or faked TOS.
__ pop(r0);
-
- // Record the fact that the result has been removed from the stack.
break_stack_height_ -= kFinallyStackSize;
// Generate code that jumps to the right destination for all used
// --- Finally block ---
__ bind(&finally_block);
- // We keep a single element on the stack - the (possibly faked)
- // result - while evaluating the finally block. Record it, so that a
- // break/continue crossing this statement can restore the stack.
- const int kFinallyStackSize = 1 * kPointerSize;
- break_stack_height_ += kFinallyStackSize;
-
- // Push the state on the stack. If necessary move the state to a
- // local variable to avoid having extra values on the stack while
- // evaluating the finally block.
+ // Push the state on the stack.
__ push(ecx);
- if (node->finally_var() != NULL) {
- Reference target(this, node->finally_var());
- SetValue(&target);
- ASSERT(target.size() == 0); // no extra stuff on the stack
- __ pop(edx); // remove the extra value that was pushed above
- }
+
+ // We keep two elements on the stack - the (possibly faked) result
+ // and the state - while evaluating the finally block. Record it, so
+ // that a break/continue crossing this statement can restore the
+ // stack.
+ const int kFinallyStackSize = 2 * kPointerSize;
+ break_stack_height_ += kFinallyStackSize;
// Generate code for the statements in the finally block.
VisitStatements(node->finally_block()->statements());
- // Get the state from the stack - or the local variable - and
- // restore the TOS register.
- if (node->finally_var() != NULL) {
- Reference target(this, node->finally_var());
- GetValue(&target);
- }
+ // Restore state and return value or faked TOS.
__ pop(ecx);
-
- // Restore return value or faked TOS.
__ pop(eax);
-
- // Record the fact that the result has been removed from the stack.
break_stack_height_ -= kFinallyStackSize;
// Generate code that jumps to the right destination for all used
exit->AddStatement(NEW(WithExitStatement()));
// Return a try-finally statement.
- TryFinally* wrapper = NEW(TryFinally(body, NULL, exit));
+ TryFinally* wrapper = NEW(TryFinally(body, exit));
wrapper->set_escaping_labels(collector.labels());
result->AddStatement(wrapper);
return result;
tok = peek();
}
- VariableProxy* finally_var = NULL;
if (tok == Token::FINALLY || !has_catch) {
Consume(Token::FINALLY);
// Declare a variable for holding the finally state while
// executing the finally block.
- finally_var = top_scope_->NewTemporary(Factory::finally_state_symbol());
finally_block = ParseBlock(NULL, CHECK_OK);
}
result->set_escaping_labels(collector.labels());
} else {
ASSERT(finally_block != NULL);
- result = NEW(TryFinally(try_block, finally_var, finally_block));
+ result = NEW(TryFinally(try_block, finally_block));
// Add the labels of the try block and the catch block.
for (int i = 0; i < collector.labels()->length(); i++) {
catch_collector.labels()->Add(collector.labels()->at(i));
void UsageComputer::VisitTryFinally(TryFinally* node) {
Visit(node->try_block());
- Expression* var = node->finally_var();
- if (var != NULL) {
- Write(var);
- Read(var);
- }
Visit(node->finally_block());
}