Tighten the code for MacroAssembler::ThrowUncatchable.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 8 Nov 2011 11:09:00 +0000 (11:09 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 8 Nov 2011 11:09:00 +0000 (11:09 +0000)
Test at the bottom in the unwind loop.  Eliminate the possibility of a
useless move to the eax/rax/r0 register (currently impossible because
this function has two call sites).  Do not explicitly zero the context
because we've already saved 0 as the context in the handler.

R=fschneider@chromium.org
BUG=
TEST=

Review URL: http://codereview.chromium.org/8493008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9909 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/macro-assembler-arm.cc
src/ia32/macro-assembler-ia32.cc
src/x64/macro-assembler-x64.cc

index 90bad75..ee484d9 100644 (file)
@@ -1258,37 +1258,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 3 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
-  // r0 is expected to hold the exception.
-  if (!value.is(r0)) {
-    mov(r0, value);
-  }
-
-  // Drop sp to the top stack handler.
-  mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
-  ldr(sp, MemOperand(r3));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  Label loop, done;
-  bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  ldr(r2, MemOperand(sp, kStateOffset));
-  cmp(r2, Operand(StackHandler::ENTRY));
-  b(eq, &done);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  ldr(sp, MemOperand(sp, kNextOffset));
-  jmp(&loop);
-  bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  pop(r2);
-  str(r2, MemOperand(r3));
 
+  // The exception is expected in r0.
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(
-        Isolate::kExternalCaughtExceptionAddress, isolate());
+    ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
+                                      isolate());
     mov(r0, Operand(false, RelocInfo::NONE));
     mov(r2, Operand(external_caught));
     str(r0, MemOperand(r2));
@@ -1299,21 +1274,33 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
     mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
                                       isolate())));
     str(r0, MemOperand(r2));
+  } else if (!value.is(r0)) {
+    mov(r0, value);
   }
 
-  // Stack layout at this point. See also StackHandlerConstants.
-  // sp ->   state (ENTRY)
-  //         cp
-  //         fp
-  //         lr
+  // Drop the stack pointer to the top of the top stack handler.
+  mov(r3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+  ldr(sp, MemOperand(r3));
+
+  // Unwind the handlers until the top ENTRY handler is found.
+  Label fetch_next, check_kind;
+  jmp(&check_kind);
+  bind(&fetch_next);
+  ldr(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
 
-  // Restore context and frame pointer, discard state (r2).
+  bind(&check_kind);
+  ldr(r2, MemOperand(sp, StackHandlerConstants::kStateOffset));
+  cmp(r2, Operand(StackHandler::ENTRY));
+  b(ne, &fetch_next);
+
+  // Set the top handler address to next handler past the top ENTRY handler.
+  pop(r2);
+  str(r2, MemOperand(r3));
+
+  // Clear the context and frame pointer (0 was saved in the handler), and
+  // discard the state (r2).
   ldm(ia_w, sp, r2.bit() | cp.bit() | fp.bit());
-#ifdef DEBUG
-  if (emit_debug_code()) {
-    mov(lr, Operand(pc));
-  }
-#endif
+
   pop(pc);
 }
 
index 1676a70..f035354 100644 (file)
@@ -816,52 +816,43 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
 
-  // eax must hold the exception.
-  if (!value.is(eax)) {
-    mov(eax, value);
-  }
-
-  // Drop sp to the top stack handler.
-  ExternalReference handler_address(Isolate::kHandlerAddress,
-                                    isolate());
-  mov(esp, Operand::StaticVariable(handler_address));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  Label loop, done;
-  bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY));
-  j(equal, &done, Label::kNear);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  mov(esp, Operand(esp, kNextOffset));
-  jmp(&loop);
-  bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  pop(Operand::StaticVariable(handler_address));
-
+  // The exception is expected in eax.
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(
-        Isolate::kExternalCaughtExceptionAddress,
-        isolate());
-    mov(eax, false);
-    mov(Operand::StaticVariable(external_caught), eax);
+    ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
+                                      isolate());
+    mov(Operand::StaticVariable(external_caught), Immediate(false));
 
     // Set pending exception and eax to out of memory exception.
     ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
                                         isolate());
     mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
     mov(Operand::StaticVariable(pending_exception), eax);
+  } else if (!value.is(eax)) {
+    mov(eax, value);
   }
 
-  // Discard the context saved in the handler and clear the context pointer.
-  pop(edx);
-  Set(esi, Immediate(0));
+  // Drop the stack pointer to the top of the top stack handler.
+  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
+  mov(esp, Operand::StaticVariable(handler_address));
+
+  // Unwind the handlers until the top ENTRY handler is found.
+  Label fetch_next, check_kind;
+  jmp(&check_kind, Label::kNear);
+  bind(&fetch_next);
+  mov(esp, Operand(esp, StackHandlerConstants::kNextOffset));
+
+  bind(&check_kind);
+  cmp(Operand(esp, StackHandlerConstants::kStateOffset),
+      Immediate(StackHandler::ENTRY));
+  j(not_equal, &fetch_next);
+
+  // Set the top handler address to next handler past the top ENTRY handler.
+  pop(Operand::StaticVariable(handler_address));
 
-  // Restore fp from handler and discard handler state.
+  // Clear the context and frame pointer (0 was saved in the handler), and
+  // discard the state.
+  pop(esi);
   pop(ebp);
   pop(edx);  // State.
 
index 5b81fa6..39670cc 100644 (file)
@@ -2509,35 +2509,12 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kStateOffset == 3 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kPCOffset == 4 * kPointerSize);
-  // Keep thrown value in rax.
-  if (!value.is(rax)) {
-    movq(rax, value);
-  }
-  // Fetch top stack handler.
-  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
-  Load(rsp, handler_address);
-
-  // Unwind the handlers until the ENTRY handler is found.
-  Label loop, done;
-  bind(&loop);
-  // Load the type of the current stack handler.
-  const int kStateOffset = StackHandlerConstants::kStateOffset;
-  cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
-  j(equal, &done, Label::kNear);
-  // Fetch the next handler in the list.
-  const int kNextOffset = StackHandlerConstants::kNextOffset;
-  movq(rsp, Operand(rsp, kNextOffset));
-  jmp(&loop);
-  bind(&done);
-
-  // Set the top handler address to next handler past the current ENTRY handler.
-  Operand handler_operand = ExternalOperand(handler_address);
-  pop(handler_operand);
 
+  // The exception is expected in rax.
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(
-        Isolate::kExternalCaughtExceptionAddress, isolate());
+    ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
+                                      isolate());
     Set(rax, static_cast<int64_t>(false));
     Store(external_caught, rax);
 
@@ -2546,14 +2523,33 @@ void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type,
                                         isolate());
     movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
     Store(pending_exception, rax);
+  } else if (!value.is(rax)) {
+    movq(rax, value);
   }
 
-  // Discard the context saved in the handler and clear the context pointer.
-  pop(rdx);
-  Set(rsi, 0);
+  // Drop the stack pointer to the top of the top stack handler.
+  ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
+  Load(rsp, handler_address);
+
+  // Unwind the handlers until the top ENTRY handler is found.
+  Label fetch_next, check_kind;
+  jmp(&check_kind, Label::kNear);
+  bind(&fetch_next);
+  movq(rsp, Operand(rsp, StackHandlerConstants::kNextOffset));
 
-  pop(rbp);  // Restore frame pointer.
-  pop(rdx);  // Discard state.
+  bind(&check_kind);
+  cmpq(Operand(rsp, StackHandlerConstants::kStateOffset),
+       Immediate(StackHandler::ENTRY));
+  j(not_equal, &fetch_next);
+
+  // Set the top handler address to next handler past the top ENTRY handler.
+  pop(ExternalOperand(handler_address));
+
+  // Clear the context and frame pointer (0 was saved in the handler), and
+  // discard the state.
+  pop(rsi);
+  pop(rbp);
+  pop(rdx);  // State.
 
   ret(0);
 }