| Index: src/full-codegen/full-codegen.cc
|
| diff --git a/src/full-codegen/full-codegen.cc b/src/full-codegen/full-codegen.cc
|
| index 8255089f7ef0ede6f612983fb70bdefb73a9f631..4d292be5018481426691b9f69396272dc74226dd 100644
|
| --- a/src/full-codegen/full-codegen.cc
|
| +++ b/src/full-codegen/full-codegen.cc
|
| @@ -913,7 +913,6 @@ void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
|
|
|
| void FullCodeGenerator::EmitContinue(Statement* target) {
|
| 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
|
| @@ -923,15 +922,17 @@ void FullCodeGenerator::EmitContinue(Statement* target) {
|
| while (!current->IsContinueTarget(target)) {
|
| if (current->IsTryFinally()) {
|
| Comment cmnt(masm(), "[ Deferred continue through finally");
|
| - current->Exit(&stack_depth, &context_length);
|
| - DCHECK_EQ(0, stack_depth);
|
| - DCHECK_EQ(0, context_length);
|
| + current->Exit(&context_length);
|
| + DCHECK_EQ(-1, context_length);
|
| current->AsTryFinally()->deferred_commands()->RecordContinue(target);
|
| return;
|
| }
|
| - current = current->Exit(&stack_depth, &context_length);
|
| + current = current->Exit(&context_length);
|
| }
|
| - __ Drop(stack_depth);
|
| + int stack_depth = current->GetStackDepthAtTarget();
|
| + int stack_drop = operand_stack_depth_ - stack_depth;
|
| + DCHECK_GE(stack_drop, 0);
|
| + __ Drop(stack_drop);
|
| if (context_length > 0) {
|
| while (context_length > 0) {
|
| LoadContextField(context_register(), Context::PREVIOUS_INDEX);
|
| @@ -952,7 +953,6 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
|
|
| void FullCodeGenerator::EmitBreak(Statement* target) {
|
| 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
|
| @@ -962,15 +962,17 @@ void FullCodeGenerator::EmitBreak(Statement* target) {
|
| while (!current->IsBreakTarget(target)) {
|
| if (current->IsTryFinally()) {
|
| Comment cmnt(masm(), "[ Deferred break through finally");
|
| - current->Exit(&stack_depth, &context_length);
|
| - DCHECK_EQ(0, stack_depth);
|
| - DCHECK_EQ(0, context_length);
|
| + current->Exit(&context_length);
|
| + DCHECK_EQ(-1, context_length);
|
| current->AsTryFinally()->deferred_commands()->RecordBreak(target);
|
| return;
|
| }
|
| - current = current->Exit(&stack_depth, &context_length);
|
| + current = current->Exit(&context_length);
|
| }
|
| - __ Drop(stack_depth);
|
| + int stack_depth = current->GetStackDepthAtTarget();
|
| + int stack_drop = operand_stack_depth_ - stack_depth;
|
| + DCHECK_GE(stack_drop, 0);
|
| + __ Drop(stack_drop);
|
| if (context_length > 0) {
|
| while (context_length > 0) {
|
| LoadContextField(context_register(), Context::PREVIOUS_INDEX);
|
| @@ -991,20 +993,17 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
|
|
| void FullCodeGenerator::EmitUnwindAndReturn() {
|
| NestedStatement* current = nesting_stack_;
|
| - int stack_depth = 0;
|
| int context_length = 0;
|
| while (current != NULL) {
|
| if (current->IsTryFinally()) {
|
| Comment cmnt(masm(), "[ Deferred return through finally");
|
| - current->Exit(&stack_depth, &context_length);
|
| - DCHECK_EQ(0, stack_depth);
|
| - DCHECK_EQ(0, context_length);
|
| + current->Exit(&context_length);
|
| + DCHECK_EQ(-1, context_length);
|
| current->AsTryFinally()->deferred_commands()->RecordReturn();
|
| return;
|
| }
|
| - current = current->Exit(&stack_depth, &context_length);
|
| + current = current->Exit(&context_length);
|
| }
|
| - __ Drop(stack_depth);
|
| EmitReturnSequence();
|
| }
|
|
|
| @@ -1281,7 +1280,8 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
| try_catch_depth_++;
|
| int handler_index = NewHandlerTableEntry();
|
| EnterTryBlock(handler_index, &handler_entry);
|
| - { TryCatch try_body(this);
|
| + {
|
| + Comment cmnt_try(masm(), "[ Try block");
|
| Visit(stmt->try_block());
|
| }
|
| ExitTryBlock(handler_index);
|
| @@ -1322,7 +1322,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| // Exception handler code. This code is only executed when an exception
|
| // is thrown. Record the continuation and jump to the finally block.
|
| {
|
| - Comment cmt_handler(masm(), "[ Finally handler");
|
| + Comment cmnt_handler(masm(), "[ Finally handler");
|
| deferred.RecordThrow();
|
| }
|
|
|
| @@ -1331,6 +1331,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| int handler_index = NewHandlerTableEntry();
|
| EnterTryBlock(handler_index, &handler_entry);
|
| {
|
| + Comment cmnt_try(masm(), "[ Try block");
|
| TryFinally try_body(this, &deferred);
|
| Visit(stmt->try_block());
|
| }
|
| @@ -1345,15 +1346,14 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
|
|
| // Finally block implementation.
|
| __ bind(&finally_entry);
|
| - Comment cmnt_finally(masm(), "[ Finally block");
|
| - OperandStackDepthIncrement(2); // Token and accumulator are on stack.
|
| - EnterFinallyBlock();
|
| {
|
| - Finally finally_body(this);
|
| + Comment cmnt_finally(masm(), "[ Finally block");
|
| + OperandStackDepthIncrement(2); // Token and accumulator are on stack.
|
| + EnterFinallyBlock();
|
| Visit(stmt->finally_block());
|
| + ExitFinallyBlock();
|
| + OperandStackDepthDecrement(2); // Token and accumulator were on stack.
|
| }
|
| - ExitFinallyBlock();
|
| - OperandStackDepthDecrement(2); // Token and accumulator were on stack.
|
|
|
| {
|
| Comment cmnt_deferred(masm(), "[ Post-finally dispatch");
|
| @@ -1599,28 +1599,32 @@ void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
|
| Visit(expr->expression());
|
| }
|
|
|
| -
|
| FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
|
| - int* stack_depth, int* context_length) {
|
| + int* context_length) {
|
| // The macros used here must preserve the result register.
|
|
|
| + // Calculate how many operands to drop to get down to handler block.
|
| + int stack_drop = codegen_->operand_stack_depth_ - GetStackDepthAtTarget();
|
| + DCHECK_GE(stack_drop, 0);
|
| +
|
| // Because the handler block contains the context of the finally
|
| // code, we can restore it directly from there for the finally code
|
| // rather than iteratively unwinding contexts via their previous
|
| // links.
|
| if (*context_length > 0) {
|
| - __ Drop(*stack_depth); // Down to the handler block.
|
| + __ Drop(stack_drop); // Down to the handler block.
|
| // Restore the context to its dedicated register and the stack.
|
| - STATIC_ASSERT(TryFinally::kElementCount == 1);
|
| + STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
|
| __ Pop(codegen_->context_register());
|
| codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
|
| codegen_->context_register());
|
| } else {
|
| // Down to the handler block and also drop context.
|
| - __ Drop(*stack_depth + kElementCount);
|
| + __ Drop(stack_drop + TryBlockConstant::kElementCount);
|
| }
|
| - *stack_depth = 0;
|
| - *context_length = 0;
|
| +
|
| + // The caller will ignore outputs.
|
| + *context_length = -1;
|
| return previous_;
|
| }
|
|
|
|
|