From 182c3ebb2d81875cc5af9c48b9016853b7a6a413 Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Fri, 6 Mar 2009 14:18:03 +0000 Subject: [PATCH] Reapply r1434 and port to ARM. Review URL: http://codereview.chromium.org/40220 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1441 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/codegen-arm.cc | 48 ++++++++++++++++------------- src/codegen-ia32.cc | 37 +++++++++++++--------- test/mjsunit/regress/regress-259.js | 33 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 36 deletions(-) create mode 100644 test/mjsunit/regress/regress-259.js diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc index 64c3d6194b..d4dc67eb3f 100644 --- a/src/codegen-arm.cc +++ b/src/codegen-arm.cc @@ -2214,28 +2214,34 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { } // Unlink from try chain; - unlink.Bind(); + if (unlink.is_linked()) { + unlink.Bind(); + } - // 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); // first field is code - // 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); + // 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(); diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc index b5ac20078f..649c9e5d45 100644 --- a/src/codegen-ia32.cc +++ b/src/codegen-ia32.cc @@ -2830,22 +2830,29 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { } // Unlink from try chain; be careful not to destroy the TOS. - unlink.Bind(); - // Reload sp from the top handler, because some statements that we - // break from (eg, for...in) may have left stuff on the stack. - // Preserve the TOS in a register across stack manipulation. - frame_->EmitPop(eax); - ExternalReference handler_address(Top::k_handler_address); - __ mov(edx, Operand::StaticVariable(handler_address)); - const int kNextOffset = StackHandlerConstants::kNextOffset + - StackHandlerConstants::kAddressDisplacement; - __ lea(esp, Operand(edx, kNextOffset)); - frame_->Forget(frame_->height() - handler_height); + if (unlink.is_linked()) { + unlink.Bind(); + } - frame_->EmitPop(Operand::StaticVariable(handler_address)); - frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); - // Next_sp popped. - frame_->EmitPush(eax); + // 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()) { + // Reload sp from the top handler, because some statements that we + // break from (eg, for...in) may have left stuff on the stack. + // Preserve the TOS in a register across stack manipulation. + frame_->EmitPop(eax); + ExternalReference handler_address(Top::k_handler_address); + __ mov(edx, Operand::StaticVariable(handler_address)); + const int kNextOffset = StackHandlerConstants::kNextOffset + + StackHandlerConstants::kAddressDisplacement; + __ lea(esp, Operand(edx, kNextOffset)); + frame_->Forget(frame_->height() - handler_height); + + frame_->EmitPop(Operand::StaticVariable(handler_address)); + frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); + // Next_sp popped. + frame_->EmitPush(eax); + } // --- Finally block --- finally_block.Bind(); diff --git a/test/mjsunit/regress/regress-259.js b/test/mjsunit/regress/regress-259.js new file mode 100644 index 0000000000..f0476ffc37 --- /dev/null +++ b/test/mjsunit/regress/regress-259.js @@ -0,0 +1,33 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Test that we do not crash when compiling a try/finally with an +// infinite loop (with no normal exits) in the try block. + +// See http://code.google.com/p/v8/issues/detail?id=259 + +assertThrows("try { while (true) { throw 0; }} finally {}");