| Index: src/full-codegen.cc | 
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc | 
| index dbf58b19576e5b18b659d764094993591a9e4c22..336f580caa2fe6bcbebde3ff7abc6490b79d7597 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()); | 
| } | 
|  | 
| @@ -898,16 +897,24 @@ 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); | 
| +  if (context_length > 0) { | 
| +    while (context_length > 0) { | 
| +      LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 
| +      --context_length; | 
| +    } | 
| +    StoreToFrameField(StandardFrameConstants::kContextOffset, | 
| +                      context_register()); | 
| +  } | 
|  | 
| Iteration* loop = current->AsIteration(); | 
| __ jmp(loop->continue_target()); | 
| @@ -919,16 +926,24 @@ 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); | 
| +  if (context_length > 0) { | 
| +    while (context_length > 0) { | 
| +      LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 
| +      --context_length; | 
| +    } | 
| +    StoreToFrameField(StandardFrameConstants::kContextOffset, | 
| +                      context_register()); | 
| +  } | 
|  | 
| Breakable* target = current->AsBreakable(); | 
| __ jmp(target->break_target()); | 
| @@ -944,9 +959,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); | 
|  | 
| @@ -954,9 +969,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()); | 
| @@ -964,6 +978,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()); | 
| } | 
|  | 
|  | 
| @@ -1122,7 +1145,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); | 
|  | 
| @@ -1168,8 +1193,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 | 
| @@ -1298,20 +1323,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_; | 
| } | 
|  | 
|  | 
|  |