| Index: src/full-codegen.cc
|
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc
|
| index aabf6ca9a9a6becba35a099509d4dc89052b6f9d..732a8fe7d0aadc3a0a9417efe3333a829431339a 100644
|
| --- a/src/full-codegen.cc
|
| +++ b/src/full-codegen.cc
|
| @@ -91,8 +91,7 @@ void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
|
| }
|
|
|
|
|
| -void BreakableStatementChecker::VisitEnterWithContextStatement(
|
| - EnterWithContextStatement* stmt) {
|
| +void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
|
| Visit(stmt->expression());
|
| }
|
|
|
| @@ -914,16 +913,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());
|
| @@ -935,16 +942,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());
|
| @@ -960,9 +975,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);
|
|
|
| @@ -970,9 +985,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());
|
| @@ -980,6 +994,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());
|
| }
|
|
|
|
|
| @@ -1138,7 +1161,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);
|
|
|
| @@ -1184,8 +1209,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
|
| @@ -1314,20 +1339,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_;
|
| }
|
|
|
|
|
|
|