Clean up the nesting stack in the full code generator.

Remove unused methods, introduce named constants, and attempt to add some
sanity to naming.

BUG=
TEST=

Review URL: http://codereview.chromium.org/7669018

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8972 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 025c05dc
......@@ -878,7 +878,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
__ b(nested_statement.break_target());
__ b(nested_statement.break_label());
} else {
__ b(default_clause->body_target());
}
......@@ -892,7 +892,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_target());
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
......@@ -1023,7 +1023,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Load the current count to r0, load the length to r1.
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
__ cmp(r0, r1); // Compare to the array length.
__ b(hs, loop_statement.break_target());
__ b(hs, loop_statement.break_label());
// Get the current entry of the array into register r3.
__ ldr(r2, MemOperand(sp, 2 * kPointerSize));
......@@ -1049,7 +1049,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(r3); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ mov(r3, Operand(r0), SetCC);
__ b(eq, loop_statement.continue_target());
__ b(eq, loop_statement.continue_label());
// Update the 'each' property or variable from the possibly filtered
// entry in register r3.
......@@ -1065,7 +1065,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for the going to the next element by incrementing
// the index (smi) stored on top of the stack.
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
__ pop(r0);
__ add(r0, r0, Operand(Smi::FromInt(1)));
__ push(r0);
......@@ -1074,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ b(&loop);
// Remove the pointers stored on the stack.
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
__ Drop(5);
// Exit and decrement the loop depth.
......
......@@ -862,7 +862,7 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
VisitStatements(stmt->statements());
scope_ = saved_scope;
__ bind(nested_statement.break_target());
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
......@@ -932,8 +932,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
context_register());
}
Iteration* loop = current->AsIteration();
__ jmp(loop->continue_target());
__ jmp(current->AsIteration()->continue_label());
}
......@@ -961,8 +960,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
context_register());
}
Breakable* target = current->AsBreakable();
__ jmp(target->break_target());
__ jmp(current->AsBreakable()->break_label());
}
......@@ -1030,12 +1028,12 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
// Record the position of the do while condition and make sure it is
// possible to break on the condition.
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
SetExpressionPosition(stmt->cond(), stmt->condition_position());
VisitForControl(stmt->cond(),
&stack_check,
loop_statement.break_target(),
loop_statement.break_label(),
&stack_check);
// Check stack before looping.
......@@ -1045,7 +1043,7 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
__ jmp(&body);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
......@@ -1066,7 +1064,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
// Emit the statement position here as this is where the while
// statement code starts.
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
SetStatementPosition(stmt);
// Check stack before looping.
......@@ -1075,11 +1073,11 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
__ bind(&test);
VisitForControl(stmt->cond(),
&body,
loop_statement.break_target(),
loop_statement.break_target());
loop_statement.break_label(),
loop_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
......@@ -1102,7 +1100,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
Visit(stmt->body());
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
SetStatementPosition(stmt);
if (stmt->next() != NULL) {
Visit(stmt->next());
......@@ -1119,14 +1117,14 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
if (stmt->cond() != NULL) {
VisitForControl(stmt->cond(),
&body,
loop_statement.break_target(),
loop_statement.break_target());
loop_statement.break_label(),
loop_statement.break_label());
} else {
__ jmp(&body);
}
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
......@@ -1144,7 +1142,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// to introduce a new scope to bind the catch variable and to remove
// that scope again afterwards.
Label try_handler_setup, catch_entry, done;
Label try_handler_setup, done;
__ Call(&try_handler_setup);
// Try handler code, exception in result register.
......@@ -1170,12 +1168,13 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Try block code. Sets up the exception handler chain.
__ bind(&try_handler_setup);
{
TryCatch try_block(this, &catch_entry);
const int delta = StackHandlerConstants::kSize / kPointerSize;
TryCatch try_block(this);
__ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
increment_stack_height(StackHandlerConstants::kSize / kPointerSize);
increment_stack_height(delta);
Visit(stmt->try_block());
__ PopTryHandler();
decrement_stack_height(StackHandlerConstants::kSize / kPointerSize);
decrement_stack_height(delta);
}
__ bind(&done);
}
......@@ -1208,9 +1207,6 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Label finally_entry;
Label try_handler_setup;
const int original_stack_height = stack_height();
const int finally_block_stack_height = original_stack_height + 2;
const int try_block_stack_height = original_stack_height + 5;
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
// Setup the try-handler chain. Use a call to
// Jump to try-handler setup and try-block code. Use call to put try-handler
......@@ -1219,9 +1215,9 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// Try handler code. Return address of call is pushed on handler stack.
{
// This code is only executed during stack-handler traversal when an
// exception is thrown. The execption is in the result register, which
// exception is thrown. The exception is in the result register, which
// is retained by the finally block.
// Call the finally block and then rethrow the exception.
// Call the finally block and then rethrow the exception if it returns.
__ Call(&finally_entry);
__ push(result_register());
__ CallRuntime(Runtime::kReThrow, 1);
......@@ -1232,7 +1228,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// Finally block implementation.
Finally finally_block(this);
EnterFinallyBlock();
set_stack_height(finally_block_stack_height);
set_stack_height(original_stack_height + Finally::kElementCount);
Visit(stmt->finally_block());
ExitFinallyBlock(); // Return to the calling code.
}
......@@ -1240,9 +1236,10 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
__ bind(&try_handler_setup);
{
// Setup try handler (stack pointer registers).
const int delta = StackHandlerConstants::kSize / kPointerSize;
TryFinally try_block(this, &finally_entry);
__ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
set_stack_height(try_block_stack_height);
set_stack_height(original_stack_height + delta);
Visit(stmt->try_block());
__ PopTryHandler();
set_stack_height(original_stack_height);
......
......@@ -111,10 +111,7 @@ class FullCodeGenerator: public AstVisitor {
private:
class Breakable;
class Iteration;
class TryCatch;
class TryFinally;
class Finally;
class ForIn;
class TestContext;
class NestedStatement BASE_EMBEDDED {
......@@ -132,10 +129,6 @@ class FullCodeGenerator: public AstVisitor {
virtual Breakable* AsBreakable() { return NULL; }
virtual Iteration* AsIteration() { return NULL; }
virtual TryCatch* AsTryCatch() { return NULL; }
virtual TryFinally* AsTryFinally() { return NULL; }
virtual Finally* AsFinally() { return NULL; }
virtual ForIn* AsForIn() { return NULL; }
virtual bool IsContinueTarget(Statement* target) { return false; }
virtual bool IsBreakTarget(Statement* target) { return false; }
......@@ -158,110 +151,102 @@ class FullCodeGenerator: public AstVisitor {
DISALLOW_COPY_AND_ASSIGN(NestedStatement);
};
// A breakable statement such as a block.
class Breakable : public NestedStatement {
public:
Breakable(FullCodeGenerator* codegen,
BreakableStatement* break_target)
: NestedStatement(codegen),
target_(break_target) {}
Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
: NestedStatement(codegen), statement_(statement) {
}
virtual ~Breakable() {}
virtual Breakable* AsBreakable() { return this; }
virtual bool IsBreakTarget(Statement* statement) {
return target_ == statement;
virtual bool IsBreakTarget(Statement* target) {
return statement() == target;
}
BreakableStatement* statement() { return target_; }
Label* break_target() { return &break_target_label_; }
BreakableStatement* statement() { return statement_; }
Label* break_label() { return &break_label_; }
private:
BreakableStatement* target_;
Label break_target_label_;
DISALLOW_COPY_AND_ASSIGN(Breakable);
BreakableStatement* statement_;
Label break_label_;
};
// An iteration statement such as a while, for, or do loop.
class Iteration : public Breakable {
public:
Iteration(FullCodeGenerator* codegen,
IterationStatement* iteration_statement)
: Breakable(codegen, iteration_statement) {}
Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
: Breakable(codegen, statement) {
}
virtual ~Iteration() {}
virtual Iteration* AsIteration() { return this; }
virtual bool IsContinueTarget(Statement* statement) {
return this->statement() == statement;
virtual bool IsContinueTarget(Statement* target) {
return statement() == target;
}
Label* continue_target() { return &continue_target_label_; }
Label* continue_label() { return &continue_label_; }
private:
Label continue_target_label_;
DISALLOW_COPY_AND_ASSIGN(Iteration);
Label continue_label_;
};
// The environment inside the try block of a try/catch statement.
// The try block of a try/catch statement.
class TryCatch : public NestedStatement {
public:
explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
: NestedStatement(codegen), catch_entry_(catch_entry) { }
explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
}
virtual ~TryCatch() {}
virtual TryCatch* AsTryCatch() { return this; }
Label* catch_entry() { return catch_entry_; }
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
private:
Label* catch_entry_;
DISALLOW_COPY_AND_ASSIGN(TryCatch);
};
// The environment inside the try block of a try/finally statement.
// The try block of a try/finally statement.
class TryFinally : public NestedStatement {
public:
explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
: NestedStatement(codegen), finally_entry_(finally_entry) { }
TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
: NestedStatement(codegen), finally_entry_(finally_entry) {
}
virtual ~TryFinally() {}
virtual TryFinally* AsTryFinally() { return this; }
Label* finally_entry() { return finally_entry_; }
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
private:
Label* finally_entry_;
DISALLOW_COPY_AND_ASSIGN(TryFinally);
};
// A FinallyEnvironment represents being inside a finally block.
// Abnormal termination of the finally block needs to clean up
// the block's parameters from the stack.
// The finally block of a try/finally statement.
class Finally : public NestedStatement {
public:
static const int kElementCount = 2;
explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
virtual ~Finally() {}
virtual Finally* AsFinally() { return this; }
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
*stack_depth += kFinallyStackElementCount;
*stack_depth += kElementCount;
return previous_;
}
private:
// Number of extra stack slots occupied during a finally block.
static const int kFinallyStackElementCount = 2;
DISALLOW_COPY_AND_ASSIGN(Finally);
};
// A ForInEnvironment represents being inside a for-in loop.
// Abnormal termination of the for-in block needs to clean up
// the block's temporary storage from the stack.
// The body of a for/in loop.
class ForIn : public Iteration {
public:
ForIn(FullCodeGenerator* codegen,
ForInStatement* statement)
: Iteration(codegen, statement) { }
static const int kElementCount = 5;
ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
: Iteration(codegen, statement) {
}
virtual ~ForIn() {}
virtual ForIn* AsForIn() { return this; }
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
*stack_depth += kForInStackElementCount;
*stack_depth += kElementCount;
return previous_;
}
private:
static const int kForInStackElementCount = 5;
DISALLOW_COPY_AND_ASSIGN(ForIn);
};
// A WithOrCatch represents being inside the body of a with or catch
// statement. Exiting the body needs to remove a link from the context
// chain.
// The body of a with or catch.
class WithOrCatch : public NestedStatement {
public:
explicit WithOrCatch(FullCodeGenerator* codegen)
......
......@@ -875,7 +875,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
__ jmp(nested_statement.break_target());
__ jmp(nested_statement.break_label());
} else {
__ jmp(default_clause->body_target());
}
......@@ -890,7 +890,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_target());
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
......@@ -1006,12 +1006,13 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(eax); // Fixed array length (as smi).
__ push(Immediate(Smi::FromInt(0))); // Initial index.
increment_stack_height(4);
// 1 ~ The object has already been pushed.
increment_stack_height(ForIn::kElementCount - 1);
// Generate code for doing the condition check.
__ bind(&loop);
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
__ j(above_equal, loop_statement.break_target());
__ j(above_equal, loop_statement.break_label());
// Get the current entry of the array into register ebx.
__ mov(ebx, Operand(esp, 2 * kPointerSize));
......@@ -1035,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(ebx); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ test(eax, Operand(eax));
__ j(equal, loop_statement.continue_target());
__ j(equal, loop_statement.continue_label());
__ mov(ebx, Operand(eax));
// Update the 'each' property or variable from the possibly filtered
......@@ -1052,17 +1053,17 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for going to the next element by incrementing the
// index (smi) stored on top of the stack.
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
__ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
EmitStackCheck(stmt);
__ jmp(&loop);
// Remove the pointers stored on the stack.
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
__ add(Operand(esp), Immediate(5 * kPointerSize));
decrement_stack_height(5);
decrement_stack_height(ForIn::kElementCount);
// Exit and decrement the loop depth.
__ bind(&exit);
decrement_loop_depth();
......
......@@ -842,7 +842,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ bind(&next_test);
__ Drop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
__ jmp(nested_statement.break_target());
__ jmp(nested_statement.break_label());
} else {
__ jmp(default_clause->body_target());
}
......@@ -856,7 +856,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_target());
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
......@@ -982,7 +982,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&loop);
__ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
__ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
__ j(above_equal, loop_statement.break_target());
__ j(above_equal, loop_statement.break_label());
// Get the current entry of the array into register rbx.
__ movq(rbx, Operand(rsp, 2 * kPointerSize));
......@@ -1010,7 +1010,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(rbx); // Current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ Cmp(rax, Smi::FromInt(0));
__ j(equal, loop_statement.continue_target());
__ j(equal, loop_statement.continue_label());
__ movq(rbx, rax);
// Update the 'each' property or variable from the possibly filtered
......@@ -1027,14 +1027,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for going to the next element by incrementing the
// index (smi) stored on top of the stack.
__ bind(loop_statement.continue_target());
__ bind(loop_statement.continue_label());
__ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
EmitStackCheck(stmt);
__ jmp(&loop);
// Remove the pointers stored on the stack.
__ bind(loop_statement.break_target());
__ bind(loop_statement.break_label());
__ addq(rsp, Immediate(5 * kPointerSize));
// Exit and decrement the loop depth.
......
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