Chromium Code Reviews| Index: src/full-codegen.cc | 
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc | 
| index e5375fc3ae8b4750b6c47a45346f08abb9c5c2bc..e9461835c041ef976ebe9252e53d906700da0519 100644 | 
| --- a/src/full-codegen.cc | 
| +++ b/src/full-codegen.cc | 
| @@ -90,8 +90,7 @@ void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { | 
| } | 
| -void BreakableStatementChecker::VisitEnterWithContextStatement( | 
| - EnterWithContextStatement* stmt) { | 
| +void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) { | 
| Visit(stmt->expression()); | 
| 
 
Kevin Millikin (Chromium)
2011/08/11 10:37:18
I'm not sure this is right, I'll check with Soeren
 
 | 
| } | 
| @@ -900,16 +899,20 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 
| SetStatementPosition(stmt); | 
| NestedStatement* current = nesting_stack_; | 
| int stack_depth = 0; | 
| + int context_length = 0; | 
| // When continuing, we clobber the unpredictable value in the accumulator | 
| // with one that's safe for GC. If we hit an exit from the try block of | 
| // try...finally on our way out, we will unconditionally preserve the | 
| // accumulator on the stack. | 
| ClearAccumulator(); | 
| while (!current->IsContinueTarget(stmt->target())) { | 
| - stack_depth = current->Exit(stack_depth); | 
| - current = current->outer(); | 
| + current = current->Exit(&stack_depth, &context_length); | 
| } | 
| __ Drop(stack_depth); | 
| + while (context_length > 0) { | 
| + LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 
| + --context_length; | 
| + } | 
| Iteration* loop = current->AsIteration(); | 
| __ jmp(loop->continue_target()); | 
| @@ -921,16 +924,20 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 
| SetStatementPosition(stmt); | 
| NestedStatement* current = nesting_stack_; | 
| int stack_depth = 0; | 
| + int context_length = 0; | 
| // When breaking, we clobber the unpredictable value in the accumulator | 
| // with one that's safe for GC. If we hit an exit from the try block of | 
| // try...finally on our way out, we will unconditionally preserve the | 
| // accumulator on the stack. | 
| ClearAccumulator(); | 
| while (!current->IsBreakTarget(stmt->target())) { | 
| - stack_depth = current->Exit(stack_depth); | 
| - current = current->outer(); | 
| + current = current->Exit(&stack_depth, &context_length); | 
| } | 
| __ Drop(stack_depth); | 
| + while (context_length > 0) { | 
| + LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 
| + --context_length; | 
| + } | 
| 
 
Vyacheslav Egorov (Chromium)
2011/08/11 11:21:55
Break should also patch context in the stack slot:
 
Kevin Millikin (Chromium)
2011/08/11 11:30:50
Oops, yes.  Good catch.
 
 | 
| Breakable* target = current->AsBreakable(); | 
| __ jmp(target->break_target()); | 
| @@ -946,9 +953,9 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 
| // Exit all nested statements. | 
| NestedStatement* current = nesting_stack_; | 
| int stack_depth = 0; | 
| + int context_length = 0; | 
| while (current != NULL) { | 
| - stack_depth = current->Exit(stack_depth); | 
| - current = current->outer(); | 
| + current = current->Exit(&stack_depth, &context_length); | 
| } | 
| __ Drop(stack_depth); | 
| @@ -956,9 +963,8 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 
| } | 
| -void FullCodeGenerator::VisitEnterWithContextStatement( | 
| - EnterWithContextStatement* stmt) { | 
| - Comment cmnt(masm_, "[ EnterWithContextStatement"); | 
| +void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) { | 
| + Comment cmnt(masm_, "[ WithStatement"); | 
| SetStatementPosition(stmt); | 
| VisitForStackValue(stmt->expression()); | 
| @@ -966,6 +972,15 @@ void FullCodeGenerator::VisitEnterWithContextStatement( | 
| __ CallRuntime(Runtime::kPushWithContext, 2); | 
| decrement_stack_height(); | 
| StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 
| + | 
| + { WithOrCatch body(this); | 
| + Visit(stmt->statement()); | 
| + } | 
| + | 
| + // Pop context. | 
| + LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 
| + // Update local stack frame context field. | 
| + StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 
| } | 
| @@ -1124,7 +1139,9 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 
| Scope* saved_scope = scope(); | 
| scope_ = stmt->scope(); | 
| ASSERT(scope_->declarations()->is_empty()); | 
| - Visit(stmt->catch_block()); | 
| + { WithOrCatch body(this); | 
| + Visit(stmt->catch_block()); | 
| + } | 
| scope_ = saved_scope; | 
| __ jmp(&done); | 
| @@ -1170,8 +1187,8 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 
| 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 + 4; | 
| - STATIC_ASSERT(StackHandlerConstants::kSize / kPointerSize == 4); | 
| + 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 | 
| @@ -1300,20 +1317,33 @@ void FullCodeGenerator::VisitThrow(Throw* expr) { | 
| } | 
| -int FullCodeGenerator::TryFinally::Exit(int stack_depth) { | 
| +FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( | 
| + int* stack_depth, | 
| + int* context_length) { | 
| // The macros used here must preserve the result register. | 
| - __ Drop(stack_depth); | 
| + __ Drop(*stack_depth); | 
| __ PopTryHandler(); | 
| + *stack_depth = 0; | 
| + | 
| + Register context = FullCodeGenerator::context_register(); | 
| + while (*context_length > 0) { | 
| + codegen_->LoadContextField(context, Context::PREVIOUS_INDEX); | 
| + --(*context_length); | 
| + } | 
| + | 
| __ Call(finally_entry_); | 
| - return 0; | 
| + return previous_; | 
| } | 
| -int FullCodeGenerator::TryCatch::Exit(int stack_depth) { | 
| +FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit( | 
| + int* stack_depth, | 
| + int* context_length) { | 
| // The macros used here must preserve the result register. | 
| - __ Drop(stack_depth); | 
| + __ Drop(*stack_depth); | 
| __ PopTryHandler(); | 
| - return 0; | 
| + *stack_depth = 0; | 
| + return previous_; | 
| } |