Commit 68103cee authored by kasperl@chromium.org's avatar kasperl@chromium.org

Get rid of the local variable we use to keep the state

during the execution of a finally block by just pushing
the state on the execution stack instead.
Review URL: http://codereview.chromium.org/5626

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@402 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 22d604e5
......@@ -568,24 +568,15 @@ class TryCatch: public TryStatement {
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_;
};
......
......@@ -3182,37 +3182,22 @@ void ArmCodeGenerator::VisitTryFinally(TryFinally* node) {
// --- 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
......
......@@ -3558,38 +3558,22 @@ void Ia32CodeGenerator::VisitTryFinally(TryFinally* node) {
// --- 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
......
......@@ -1598,7 +1598,7 @@ Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
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;
......@@ -1793,12 +1793,10 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
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);
}
......@@ -1823,7 +1821,7 @@ TryStatement* Parser::ParseTryStatement(bool* 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));
......
......@@ -221,11 +221,6 @@ void UsageComputer::VisitTryCatch(TryCatch* node) {
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());
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment