| Index: src/codegen-arm.cc
|
| ===================================================================
|
| --- src/codegen-arm.cc (revision 1443)
|
| +++ src/codegen-arm.cc (working copy)
|
| @@ -2058,22 +2058,25 @@
|
| // Stop the introduced shadowing and count the number of required unlinks.
|
| // After shadowing stops, the original labels are unshadowed and the
|
| // LabelShadows represent the formerly shadowing labels.
|
| - int nof_unlinks = 0;
|
| + bool has_unlinks = false;
|
| for (int i = 0; i <= nof_escapes; i++) {
|
| shadows[i]->StopShadowing();
|
| - if (shadows[i]->is_linked()) nof_unlinks++;
|
| + has_unlinks = has_unlinks || shadows[i]->is_linked();
|
| }
|
| function_return_is_shadowed_ = function_return_was_shadowed;
|
|
|
| + // Get an external reference to the handler address.
|
| + ExternalReference handler_address(Top::k_handler_address);
|
| +
|
| + // The next handler address is at kNextIndex in the stack.
|
| const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
|
| // If we can fall off the end of the try block, unlink from try chain.
|
| if (has_valid_frame()) {
|
| - // The next handler address is at kNextIndex in the stack.
|
| __ ldr(r1, frame_->ElementAt(kNextIndex));
|
| - __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
|
| + __ mov(r3, Operand(handler_address));
|
| __ str(r1, MemOperand(r3));
|
| frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
|
| - if (nof_unlinks > 0) {
|
| + if (has_unlinks) {
|
| exit.Jump();
|
| }
|
| }
|
| @@ -2090,7 +2093,7 @@
|
|
|
| // Reload sp from the top handler, because some statements that we
|
| // break from (eg, for...in) may have left stuff on the stack.
|
| - __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
|
| + __ mov(r3, Operand(handler_address));
|
| __ ldr(sp, MemOperand(r3));
|
| // The stack pointer was restored to just below the code slot
|
| // (the topmost slot) in the handler.
|
| @@ -2128,7 +2131,6 @@
|
| // break/continue from within the try block.
|
| enum { FALLING, THROWING, JUMPING };
|
|
|
| - JumpTarget unlink(this);
|
| JumpTarget try_block(this);
|
| JumpTarget finally_block(this);
|
|
|
| @@ -2179,26 +2181,60 @@
|
| }
|
| function_return_is_shadowed_ = function_return_was_shadowed;
|
|
|
| - // If we can fall off the end of the try block, set the state on the stack
|
| - // to FALLING.
|
| + // Get an external reference to the handler address.
|
| + ExternalReference handler_address(Top::k_handler_address);
|
| +
|
| + // The next handler address is at kNextIndex in the stack.
|
| + const int kNextIndex = StackHandlerConstants::kNextOffset / kPointerSize;
|
| + // If we can fall off the end of the try block, unlink from the try
|
| + // chain and set the state on the frame to FALLING.
|
| if (has_valid_frame()) {
|
| - __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
|
| + __ ldr(r1, frame_->ElementAt(kNextIndex));
|
| + __ mov(r3, Operand(handler_address));
|
| + __ str(r1, MemOperand(r3));
|
| + frame_->Drop(StackHandlerConstants::kSize / kPointerSize);
|
| +
|
| + // Fake a top of stack value (unneeded when FALLING) and set the
|
| + // state in r2, then jump around the unlink blocks if any.
|
| + __ mov(r0, Operand(Factory::undefined_value()));
|
| frame_->EmitPush(r0);
|
| __ mov(r2, Operand(Smi::FromInt(FALLING)));
|
| if (nof_unlinks > 0) {
|
| - unlink.Jump();
|
| + finally_block.Jump();
|
| }
|
| }
|
|
|
| - // Generate code to set the state for the (formerly) shadowing labels that
|
| - // have been jumped to.
|
| + // Generate code to unlink and set the state for the (formerly)
|
| + // shadowing labels that have been jumped to.
|
| for (int i = 0; i <= nof_escapes; i++) {
|
| if (shadows[i]->is_linked()) {
|
| + // If we have come from the shadowed return, the return value is
|
| + // in (a non-refcounted reference to) r0. We must preserve it
|
| + // until it is pushed.
|
| + //
|
| // Because we can be jumping here (to spilled code) from
|
| // unspilled code, we need to reestablish a spilled frame at
|
| // this block.
|
| shadows[i]->Bind();
|
| frame_->SpillAll();
|
| +
|
| + // Reload sp from the top handler, because some statements that
|
| + // we break from (eg, for...in) may have left stuff on the
|
| + // stack.
|
| + __ mov(r3, Operand(handler_address));
|
| + __ ldr(sp, MemOperand(r3));
|
| + // The stack pointer was restored to the address slot in the handler.
|
| + ASSERT(StackHandlerConstants::kNextOffset == 1 * kPointerSize);
|
| + frame_->Forget(frame_->height() - handler_height + 1);
|
| +
|
| + // Unlink this handler and drop it from the frame. The next
|
| + // handler address is now on top of the frame.
|
| + frame_->EmitPop(r1);
|
| + __ str(r1, MemOperand(r3));
|
| + // The top (code) and the second (handler) slot have both been
|
| + // dropped already.
|
| + frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 2);
|
| +
|
| if (i == kReturnShadowIndex) {
|
| // If this label shadowed the function return, materialize the
|
| // return value on the stack.
|
| @@ -2209,40 +2245,13 @@
|
| frame_->EmitPush(r0);
|
| }
|
| __ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
|
| - unlink.Jump();
|
| + if (--nof_unlinks > 0) {
|
| + // If this is not the last unlink block, jump around the next.
|
| + finally_block.Jump();
|
| + }
|
| }
|
| }
|
|
|
| - // Unlink from try chain;
|
| - if (unlink.is_linked()) {
|
| - unlink.Bind();
|
| - }
|
| -
|
| - // Control can reach here via a jump to unlink or by falling off the
|
| - // end of the try block (with no unlinks).
|
| - if (has_valid_frame()) {
|
| - // Preserve TOS result in r0 across stack manipulation.
|
| - frame_->EmitPop(r0);
|
| - // Reload sp from the top handler, because some statements that we
|
| - // break from (eg, for...in) may have left stuff on the stack.
|
| - __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
|
| - __ ldr(sp, MemOperand(r3));
|
| - // The stack pointer was restored to just below the code slot (the
|
| - // topmost slot) in the handler.
|
| - frame_->Forget(frame_->height() - handler_height + 1);
|
| - const int kNextIndex = (StackHandlerConstants::kNextOffset
|
| - + StackHandlerConstants::kAddressDisplacement)
|
| - / kPointerSize;
|
| - __ ldr(r1, frame_->ElementAt(kNextIndex));
|
| - __ str(r1, MemOperand(r3));
|
| - ASSERT(StackHandlerConstants::kCodeOffset == 0);
|
| - // Drop the rest of the handler (not including the already dropped
|
| - // code slot).
|
| - frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
|
| - // Restore the result to TOS.
|
| - frame_->EmitPush(r0);
|
| - }
|
| -
|
| // --- Finally block ---
|
| finally_block.Bind();
|
|
|
|
|