Revision: 11753
Author:   [email protected]
Date:     Mon Jun 11 03:51:09 2012
Log:      Preserve error message during finally block in try..finally.

[email protected]
BUG=129171
TEST=test-api/TryFinallyMessage

Review URL: https://chromiumcodereview.appspot.com/10537078
http://code.google.com/p/v8/source/detail?r=11753

Modified:
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/assembler.cc
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/full-codegen.h
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed May 23 07:24:29 2012 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Jun 11 03:51:09 2012
@@ -4506,6 +4506,52 @@
   __ mov(r1, Operand(r1, ASR, 1));  // Un-smi-tag value.
   __ add(pc, r1, Operand(masm_->CodeObject()));
 }
+
+
+void FullCodeGenerator::SavePendingMessage() {
+  ASSERT(!result_register().is(r1));
+  // Store pending message while executing finally block upon exception.
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(ip, Operand(pending_message_obj));
+  __ ldr(r1, MemOperand(ip));
+  __ push(r1);
+
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(ip, Operand(has_pending_message));
+  __ ldr(r1, MemOperand(ip));
+  __ push(r1);
+
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(ip, Operand(pending_message_script));
+  __ ldr(r1, MemOperand(ip));
+  __ push(r1);
+}
+
+
+void FullCodeGenerator::RestorePendingMessage() {
+  ASSERT(!result_register().is(r1));
+  // Restore pending message.
+  __ pop(r1);
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(ip, Operand(pending_message_script));
+  __ str(r1, MemOperand(ip));
+
+  __ pop(r1);
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(ip, Operand(has_pending_message));
+  __ str(r1, MemOperand(ip));
+
+  __ pop(r1);
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(ip, Operand(pending_message_obj));
+  __ str(r1, MemOperand(ip));
+}


 #undef __
=======================================
--- /branches/bleeding_edge/src/assembler.cc    Wed Jun  6 04:05:28 2012
+++ /branches/bleeding_edge/src/assembler.cc    Mon Jun 11 03:51:09 2012
@@ -953,6 +953,24 @@
     Isolate* isolate) {
   return ExternalReference(isolate->scheduled_exception_address());
 }
+
+
+ExternalReference ExternalReference::address_of_pending_message_obj(
+    Isolate* isolate) {
+  return ExternalReference(isolate->pending_message_obj_address());
+}
+
+
+ExternalReference ExternalReference::address_of_has_pending_message(
+    Isolate* isolate) {
+  return ExternalReference(isolate->has_pending_message_address());
+}
+
+
+ExternalReference ExternalReference::address_of_pending_message_script(
+    Isolate* isolate) {
+  return ExternalReference(isolate->pending_message_script_address());
+}


 ExternalReference ExternalReference::address_of_min_int() {
=======================================
--- /branches/bleeding_edge/src/assembler.h     Wed Jun  6 04:05:28 2012
+++ /branches/bleeding_edge/src/assembler.h     Mon Jun 11 03:51:09 2012
@@ -640,6 +640,9 @@
   static ExternalReference handle_scope_level_address();

   static ExternalReference scheduled_exception_address(Isolate* isolate);
+ static ExternalReference address_of_pending_message_obj(Isolate* isolate); + static ExternalReference address_of_has_pending_message(Isolate* isolate); + static ExternalReference address_of_pending_message_script(Isolate* isolate);

   // Static variables containing common double constants.
   static ExternalReference address_of_min_int();
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Fri May 18 06:06:16 2012
+++ /branches/bleeding_edge/src/full-codegen.cc Mon Jun 11 03:51:09 2012
@@ -1287,7 +1287,11 @@
   // is thrown.  The exception is in the result register, and must be
   // preserved by the finally block.  Call the finally block and then
   // rethrow the exception if it returns.
+ // Also preserve the pending message corresponding to the thrown error when
+  // executing the finally block.
+  SavePendingMessage();
   __ Call(&finally_entry);
+  RestorePendingMessage();
   __ push(result_register());
   __ CallRuntime(Runtime::kReThrow, 1);

=======================================
--- /branches/bleeding_edge/src/full-codegen.h  Mon Jun  4 07:42:58 2012
+++ /branches/bleeding_edge/src/full-codegen.h  Mon Jun 11 03:51:09 2012
@@ -527,6 +527,8 @@
   // Non-local control flow support.
   void EnterFinallyBlock();
   void ExitFinallyBlock();
+  void SavePendingMessage();
+  void RestorePendingMessage();

   // Loop nesting counter.
   int loop_depth() { return loop_depth_; }
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed May 23 07:24:29 2012 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Jun 11 03:51:09 2012
@@ -4490,6 +4490,46 @@
   __ add(edx, Immediate(masm_->CodeObject()));
   __ jmp(edx);
 }
+
+
+void FullCodeGenerator::SavePendingMessage() {
+  ASSERT(!result_register().is(edx));
+  // Store pending message while executing finally block upon exception.
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(edx, Operand::StaticVariable(pending_message_obj));
+  __ push(edx);
+
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(edx, Operand::StaticVariable(has_pending_message));
+  __ push(edx);
+
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(edx, Operand::StaticVariable(pending_message_script));
+  __ push(edx);
+}
+
+
+void FullCodeGenerator::RestorePendingMessage() {
+  ASSERT(!result_register().is(edx));
+  // Restore pending message.
+  __ pop(edx);
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ mov(Operand::StaticVariable(pending_message_script), edx);
+
+  __ pop(edx);
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ mov(Operand::StaticVariable(has_pending_message), edx);
+
+  __ pop(edx);
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ mov(Operand::StaticVariable(pending_message_obj), edx);
+}


 #undef __
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Mon Jun  4 07:42:58 2012
+++ /branches/bleeding_edge/src/isolate.cc      Mon Jun 11 03:51:09 2012
@@ -921,7 +921,7 @@
 }


-Failure* Isolate::ReThrow(MaybeObject* exception, MessageLocation* location) {
+Failure* Isolate::ReThrow(MaybeObject* exception) {
   bool can_be_caught_externally = false;
   bool catchable_by_javascript = is_catchable_by_javascript(exception);
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
=======================================
--- /branches/bleeding_edge/src/isolate.h       Mon Jun  4 07:42:58 2012
+++ /branches/bleeding_edge/src/isolate.h       Mon Jun 11 03:51:09 2012
@@ -578,6 +578,20 @@
   MaybeObject** scheduled_exception_address() {
     return &thread_local_top_.scheduled_exception_;
   }
+
+  Address pending_message_obj_address() {
+ return reinterpret_cast<Address>(&thread_local_top_.pending_message_obj_);
+  }
+
+  Address has_pending_message_address() {
+ return reinterpret_cast<Address>(&thread_local_top_.has_pending_message_);
+  }
+
+  Address pending_message_script_address() {
+    return reinterpret_cast<Address>(
+        &thread_local_top_.pending_message_script_);
+  }
+
   MaybeObject* scheduled_exception() {
     ASSERT(has_scheduled_exception());
     return thread_local_top_.scheduled_exception_;
@@ -708,7 +722,7 @@
   // Re-throw an exception.  This involves no error reporting since
   // error reporting was handled when the exception was thrown
   // originally.
- Failure* ReThrow(MaybeObject* exception, MessageLocation* location = NULL);
+  Failure* ReThrow(MaybeObject* exception);
   void ScheduleThrow(Object* exception);
   void ReportPendingMessages();
   Failure* ThrowIllegalOperation();
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed May 23 07:24:29 2012 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Jun 11 03:51:09 2012
@@ -4475,6 +4475,46 @@
   __ addq(rdx, rcx);
   __ jmp(rdx);
 }
+
+
+void FullCodeGenerator::SavePendingMessage() {
+  ASSERT(!result_register().is(rdx));
+  // Store pending message while executing finally block upon exception.
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ Load(rdx, pending_message_obj);
+  __ push(rdx);
+
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ Load(rdx, has_pending_message);
+  __ push(rdx);
+
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ Load(rdx, pending_message_script);
+  __ push(rdx);
+}
+
+
+void FullCodeGenerator::RestorePendingMessage() {
+  ASSERT(!result_register().is(rdx));
+  // Restore pending message.
+  __ pop(rdx);
+  ExternalReference pending_message_script =
+      ExternalReference::address_of_pending_message_script(isolate());
+  __ Store(pending_message_script, rdx);
+
+  __ pop(rdx);
+  ExternalReference has_pending_message =
+      ExternalReference::address_of_has_pending_message(isolate());
+  __ Store(has_pending_message, rdx);
+
+  __ pop(rdx);
+  ExternalReference pending_message_obj =
+      ExternalReference::address_of_pending_message_obj(isolate());
+  __ Store(pending_message_obj, rdx);
+}


 #undef __
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Fri Jun  8 00:45:11 2012
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Mon Jun 11 03:51:09 2012
@@ -16768,3 +16768,46 @@
   CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
   CheckInstanceCheckedAccessors(true);
 }
+
+
+TEST(TryFinallyMessage) {
+  v8::HandleScope scope;
+  LocalContext context;
+  {
+    // Test that the original error message is not lost if there is a
+    // recursive call into Javascript is done in the finally block, e.g. to
+    // initialize an IC. (crbug.com/129171)
+    TryCatch try_catch;
+    const char* trigger_ic =
+        "try {                      \n"
+        "  throw new Error('test'); \n"
+        "} finally {                \n"
+        "  var x = 0;               \n"
+ " x++; \n" // Trigger an IC initialization here.
+        "}                          \n";
+    Local<Value> result = CompileRun(trigger_ic);
+    CHECK(try_catch.HasCaught());
+    Local<Message> message = try_catch.Message();
+    CHECK(!message.IsEmpty());
+    CHECK_EQ(2, message->GetLineNumber());
+  }
+
+  {
+    // Test that the original exception message is indeed overwritten if
+    // a new error is thrown in the finally block.
+    TryCatch try_catch;
+    const char* throw_again =
+        "try {                       \n"
+        "  throw new Error('test');  \n"
+        "} finally {                 \n"
+        "  var x = 0;                \n"
+        "  x++;                      \n"
+ " throw new Error('again'); \n" // This is the new uncaught error.
+        "}                           \n";
+    Local<Value> result = CompileRun(throw_again);
+    CHECK(try_catch.HasCaught());
+    Local<Message> message = try_catch.Message();
+    CHECK(!message.IsEmpty());
+    CHECK_EQ(6, message->GetLineNumber());
+  }
+}

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to