Index: src/full-codegen.h |
diff --git a/src/full-codegen.h b/src/full-codegen.h |
index 9bd6e5e4dc873f4cb5479cc291eae24dc2b1b1be..2fc055366100eddeb89eedb0e7b44321e89a84ad 100644 |
--- a/src/full-codegen.h |
+++ b/src/full-codegen.h |
@@ -140,25 +140,19 @@ class FullCodeGenerator: public AstVisitor { |
virtual bool IsContinueTarget(Statement* target) { return false; } |
virtual bool IsBreakTarget(Statement* target) { return false; } |
- // Generate code to leave the nested statement. This includes |
- // 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. |
- // The generated code must preserve the result register (which |
- // contains the value in case of a return). |
- virtual int Exit(int stack_depth) { |
- // Default implementation for the case where there is |
- // nothing to clean up. |
- return stack_depth; |
+ // Notify the statement that we are exiting it via break, continue, or |
+ // return and give it a chance to generate cleanup code. Return the |
+ // next outer statement in the nesting stack. We accumulate in |
+ // *stack_depth the amount to drop the stack and in *context_length the |
+ // number of context chain links to unwind as we traverse the nesting |
+ // stack from an exit to its target. |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
+ return previous_; |
} |
- NestedStatement* outer() { return previous_; } |
protected: |
MacroAssembler* masm() { return codegen_->masm(); } |
- private: |
FullCodeGenerator* codegen_; |
NestedStatement* previous_; |
DISALLOW_COPY_AND_ASSIGN(NestedStatement); |
@@ -207,7 +201,7 @@ class FullCodeGenerator: public AstVisitor { |
virtual ~TryCatch() {} |
virtual TryCatch* AsTryCatch() { return this; } |
Label* catch_entry() { return catch_entry_; } |
- virtual int Exit(int stack_depth); |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length); |
private: |
Label* catch_entry_; |
DISALLOW_COPY_AND_ASSIGN(TryCatch); |
@@ -221,7 +215,7 @@ class FullCodeGenerator: public AstVisitor { |
virtual ~TryFinally() {} |
virtual TryFinally* AsTryFinally() { return this; } |
Label* finally_entry() { return finally_entry_; } |
- virtual int Exit(int stack_depth); |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length); |
private: |
Label* finally_entry_; |
DISALLOW_COPY_AND_ASSIGN(TryFinally); |
@@ -235,8 +229,9 @@ class FullCodeGenerator: public AstVisitor { |
explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { } |
virtual ~Finally() {} |
virtual Finally* AsFinally() { return this; } |
- virtual int Exit(int stack_depth) { |
- return stack_depth + kFinallyStackElementCount; |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
+ *stack_depth += kFinallyStackElementCount; |
+ return previous_; |
} |
private: |
// Number of extra stack slots occupied during a finally block. |
@@ -254,14 +249,32 @@ class FullCodeGenerator: public AstVisitor { |
: Iteration(codegen, statement) { } |
virtual ~ForIn() {} |
virtual ForIn* AsForIn() { return this; } |
- virtual int Exit(int stack_depth) { |
- return stack_depth + kForInStackElementCount; |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
+ *stack_depth += kForInStackElementCount; |
+ 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. |
+ class WithOrCatch : public NestedStatement { |
+ public: |
+ explicit WithOrCatch(FullCodeGenerator* codegen) |
+ : NestedStatement(codegen) { |
+ } |
+ virtual ~WithOrCatch() {} |
+ |
+ virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
+ ++(*context_length); |
+ return previous_; |
+ } |
+ }; |
+ |
// The forward bailout stack keeps track of the expressions that can |
// bail out to just before the control flow is split in a child |
// node. The stack elements are linked together through the parent |