| Index: src/full-codegen.cc
|
| diff --git a/src/full-codegen.cc b/src/full-codegen.cc
|
| index a2e3e8c74ac526422549d4f19f6d33d550c90d15..ba41d05559b81fe3c5bb94e8a6779eb55219d28a 100644
|
| --- a/src/full-codegen.cc
|
| +++ b/src/full-codegen.cc
|
| @@ -1380,7 +1380,6 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
| Label try_entry, handler_entry, exit;
|
| __ jmp(&try_entry);
|
| __ bind(&handler_entry);
|
| - handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
|
| // Exception handler code, the exception is in the result register.
|
| // Extend the context before executing the catch block.
|
| { Comment cmnt(masm_, "[ Extend catch context");
|
| @@ -1406,11 +1405,11 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
|
|
| // Try block code. Sets up the exception handler chain.
|
| __ bind(&try_entry);
|
| - __ PushTryHandler(StackHandler::CATCH, stmt->index());
|
| + EnterTryBlock(stmt->index(), &handler_entry);
|
| { TryCatch try_body(this);
|
| Visit(stmt->try_block());
|
| }
|
| - __ PopTryHandler();
|
| + ExitTryBlock(stmt->index());
|
| __ bind(&exit);
|
| }
|
|
|
| @@ -1444,7 +1443,6 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| // Jump to try-handler setup and try-block code.
|
| __ jmp(&try_entry);
|
| __ bind(&handler_entry);
|
| - handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
|
| // Exception handler code. This code is only executed when an exception
|
| // is thrown. The exception is in the result register, and must be
|
| // preserved by the finally block. Call the finally block and then
|
| @@ -1463,11 +1461,11 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
|
|
| // Set up try handler.
|
| __ bind(&try_entry);
|
| - __ PushTryHandler(StackHandler::FINALLY, stmt->index());
|
| + EnterTryBlock(stmt->index(), &handler_entry);
|
| { TryFinally try_body(this, &finally_entry);
|
| Visit(stmt->try_block());
|
| }
|
| - __ PopTryHandler();
|
| + ExitTryBlock(stmt->index());
|
| // Execute the finally block on the way out. Clobber the unpredictable
|
| // value in the result register with one that's safe for GC because the
|
| // finally block will unconditionally preserve the result register on the
|
| @@ -1622,13 +1620,54 @@ void FullCodeGenerator::VisitThrow(Throw* expr) {
|
| }
|
|
|
|
|
| -FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
|
| - int* stack_depth,
|
| - int* context_length) {
|
| +void FullCodeGenerator::EnterTryBlock(int index, Label* handler) {
|
| + handler_table()->SetRangeStart(index, masm()->pc_offset());
|
| + handler_table()->SetRangeHandler(index, handler->pos());
|
| +
|
| + // Determine expression stack depth of try statement.
|
| + int stack_depth = info_->scope()->num_stack_slots(); // Include stack locals.
|
| + for (NestedStatement* current = nesting_stack_; current != NULL; /*nop*/) {
|
| + current = current->AccumulateDepth(&stack_depth);
|
| + }
|
| + handler_table()->SetRangeDepth(index, stack_depth);
|
| +
|
| + // Push context onto operand stack.
|
| + STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
|
| + __ Push(context_register());
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::ExitTryBlock(int index) {
|
| + handler_table()->SetRangeEnd(index, masm()->pc_offset());
|
| +
|
| + // Drop context from operand stack.
|
| + __ Drop(TryBlockConstant::kElementCount);
|
| +}
|
| +
|
| +
|
| +FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
|
| + int* stack_depth, int* context_length) {
|
| // The macros used here must preserve the result register.
|
| - __ Drop(*stack_depth);
|
| - __ PopTryHandler();
|
| +
|
| + // 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.
|
| + // Restore the context to its dedicated register and the stack.
|
| + STATIC_ASSERT(TryFinally::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);
|
| + }
|
| + __ Call(finally_entry_);
|
| +
|
| *stack_depth = 0;
|
| + *context_length = 0;
|
| return previous_;
|
| }
|
|
|
|
|