Index: src/fast-codegen.h |
diff --git a/src/fast-codegen.h b/src/fast-codegen.h |
index 9b262a739315da71876300610abd25d21ef86130..5fa89c4759a80b17c1cd634fd5d598745ba96a2b 100644 |
--- a/src/fast-codegen.h |
+++ b/src/fast-codegen.h |
@@ -35,6 +35,8 @@ |
namespace v8 { |
namespace internal { |
+// ----------------------------------------------------------------------------- |
+// Fast code generator. |
class FastCodeGenerator: public AstVisitor { |
public: |
@@ -43,6 +45,7 @@ class FastCodeGenerator: public AstVisitor { |
function_(NULL), |
script_(script), |
is_eval_(is_eval), |
+ nesting_stack_(NULL), |
loop_depth_(0), |
true_label_(NULL), |
false_label_(NULL) { |
@@ -55,6 +58,164 @@ class FastCodeGenerator: public AstVisitor { |
void Generate(FunctionLiteral* fun); |
private: |
+ class Breakable; |
+ class Iteration; |
+ class TryCatch; |
+ class TryFinally; |
+ class Finally; |
+ class ForIn; |
+ |
+ class NestedStatement BASE_EMBEDDED { |
+ public: |
+ explicit NestedStatement(FastCodeGenerator* codegen) : codegen_(codegen) { |
+ // Link into codegen's nesting stack. |
+ previous_ = codegen->nesting_stack_; |
+ codegen->nesting_stack_ = this; |
+ } |
+ virtual ~NestedStatement() { |
+ // Unlink from codegen's nesting stack. |
+ ASSERT_EQ(this, codegen_->nesting_stack_); |
+ codegen_->nesting_stack_ = previous_; |
+ } |
+ |
+ 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; } |
+ |
+ // Generate code to leave the nested statement. This includes |
Kevin Millikin (Chromium)
2009/12/10 13:09:26
We should probably document (in several places) th
Lasse Reichstein
2009/12/10 13:55:32
It's documented here now, and I'll put it on the f
|
+ // cleaning up any stack elements in use and restoring the |
+ // stack to the expectations of the surrounding statements. |
+ // Takes a number of stack elements currently on top of the |
+ // nested statement's stack, and returns a number of stack |
+ // elements left on top of the surrounding statement's stack. |
+ virtual int Exit(int stack_depth) { |
+ // Default implementation for the case where there is |
+ // nothing to clean up. |
+ return stack_depth; |
+ } |
+ NestedStatement* outer() { return previous_; } |
+ protected: |
+ MacroAssembler* masm() { return codegen_->masm(); } |
+ private: |
+ FastCodeGenerator *codegen_; |
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Space after star.
Lasse Reichstein
2009/12/10 13:55:32
Fixed
|
+ NestedStatement *previous_; |
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Same.
Lasse Reichstein
2009/12/10 13:55:32
Fixed
|
+ DISALLOW_COPY_AND_ASSIGN(NestedStatement); |
+ }; |
+ |
+ class Breakable : public NestedStatement { |
+ public: |
+ Breakable(FastCodeGenerator* codegen, |
+ BreakableStatement* break_target, |
+ Label* target_label) |
+ : NestedStatement(codegen), |
+ target_(break_target), |
+ break_target_label_(target_label) {} |
+ virtual ~Breakable() {} |
+ virtual Breakable* AsBreakable() { return this; } |
+ virtual bool IsBreakTarget(Statement* statement) { |
+ return target_ == statement; |
+ } |
+ Statement* statement() { return target_; } |
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Might make return type BreakableStatement* in case
Lasse Reichstein
2009/12/10 13:55:32
Fixed.
|
+ Label* break_target() { return break_target_label_; } |
+ private: |
+ BreakableStatement* target_; |
+ Label* break_target_label_; |
Kevin Millikin (Chromium)
2009/12/10 13:09:26
Instead of passing a label pointer to the construc
|
+ DISALLOW_COPY_AND_ASSIGN(Breakable); |
+ }; |
+ |
+ class Iteration : public Breakable { |
+ public: |
+ Iteration(FastCodeGenerator* codegen, |
+ IterationStatement* iteration_statement, |
+ Label* break_target_label, |
+ Label* continue_target_label) |
+ : Breakable(codegen, iteration_statement, break_target_label), |
+ continue_target_label_(continue_target_label) {} |
+ virtual ~Iteration() {} |
+ virtual Iteration* AsIteration() { return this; } |
+ virtual bool IsContinueTarget(Statement* statement) { |
+ return this->statement() == statement; |
+ } |
+ Label* continue_target() { return continue_target_label_; } |
+ private: |
+ Label* continue_target_label_; |
+ DISALLOW_COPY_AND_ASSIGN(Iteration); |
+ }; |
+ |
+ // The environment inside the try block of a try/catch statement. |
+ class TryCatch : public NestedStatement { |
+ public: |
+ explicit TryCatch(FastCodeGenerator* codegen, Label* catch_entry) |
+ : NestedStatement(codegen), catch_entry_(catch_entry) { } |
+ virtual ~TryCatch() {} |
+ virtual TryCatch* AsTryCatch() { return this; } |
+ Label* catch_entry() { return catch_entry_; } |
+ virtual int Exit(int stack_depth); |
+ private: |
+ Label* catch_entry_; |
+ DISALLOW_COPY_AND_ASSIGN(TryCatch); |
+ }; |
+ |
+ // The environment inside the try block of a try/finally statement. |
+ class TryFinally : public NestedStatement { |
+ public: |
+ explicit TryFinally(FastCodeGenerator* codegen, Label* finally_entry) |
+ : NestedStatement(codegen), finally_entry_(finally_entry) { } |
+ virtual ~TryFinally() {} |
+ virtual TryFinally* AsTryFinally() { return this; } |
+ Label* finally_entry() { return finally_entry_; } |
+ virtual int Exit(int stack_depth); |
+ 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. |
+ class Finally : public NestedStatement { |
+ public: |
+ explicit Finally(FastCodeGenerator* codegen) : NestedStatement(codegen) { } |
+ virtual ~Finally() {} |
+ virtual Finally* AsFinally() { return this; } |
+ virtual int Exit(int stack_depth) { |
+ return stack_depth + kFinallyStackElementCount; |
+ } |
+ 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. |
+ class ForIn : public Iteration { |
+ public: |
+ ForIn(FastCodeGenerator* codegen, |
+ ForInStatement* statement, |
+ Label* break_target, |
+ Label* continue_target) |
+ : Iteration(codegen, statement, break_target, continue_target) { } |
+ virtual ~ForIn() {} |
+ virtual ForIn* AsForIn() { return this; } |
+ virtual int Exit(int stack_depth) { |
+ return stack_depth + kForInStackElementCount; |
+ } |
+ private: |
+ // TODO(lrn): Check that this value is correct when implementing |
+ // for-in. |
+ static const int kForInStackElementCount = 5; |
+ DISALLOW_COPY_AND_ASSIGN(ForIn); |
+ }; |
+ |
+ |
int SlotOffset(Slot* slot); |
void Move(Expression::Context destination, Register source); |
void Move(Expression::Context destination, Slot* source, Register scratch); |
@@ -112,11 +273,13 @@ class FastCodeGenerator: public AstVisitor { |
loop_depth_--; |
} |
+ MacroAssembler* masm() { return masm_; } |
+ static Register result_register(); |
+ |
// AST node visit functions. |
#define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
AST_NODE_LIST(DECLARE_VISIT) |
#undef DECLARE_VISIT |
- |
// Handles the shortcutted logical binary operations in VisitBinaryOperation. |
void EmitLogicalOperation(BinaryOperation* expr); |
@@ -125,11 +288,14 @@ class FastCodeGenerator: public AstVisitor { |
Handle<Script> script_; |
bool is_eval_; |
Label return_label_; |
+ NestedStatement* nesting_stack_; |
int loop_depth_; |
Label* true_label_; |
Label* false_label_; |
+ friend class NestedStatement; |
+ |
DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator); |
}; |