Posponed the setting of "external_caught_exception" to when leaving JavaScript
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 Oct 2008 12:54:13 +0000 (12:54 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 Oct 2008 12:54:13 +0000 (12:54 +0000)
execution. This is achieved by storing a pointer to the C++ TryCatch when the
exception is thrown and checking that this is the handler active when leaving
JavaScript.
Review URL: http://codereview.chromium.org/8101

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

src/execution.cc
src/top.cc
src/top.h
test/mjsunit/api-call-after-overridden-exception.js [new file with mode: 0644]

index d10a3ab..0598ad7 100644 (file)
@@ -94,6 +94,9 @@ static Handle<Object> Invoke(bool construct,
   // Update the pending exception flag and return the value.
   *has_pending_exception = value->IsException();
   ASSERT(*has_pending_exception == Top::has_pending_exception());
+  if (*has_pending_exception) {
+    Top::setup_external_caught();
+  }
 
   // If the pending exception is OutOfMemoryException set out_of_memory in
   // the global context.  Note: We have to mark the global context here
index 3ed93d6..a78ba32 100644 (file)
@@ -101,6 +101,7 @@ void Top::InitializeThreadLocal() {
   clear_pending_exception();
   clear_scheduled_exception();
   thread_local_.save_context_ = NULL;
+  thread_local_.catcher_ = NULL;
 }
 
 
@@ -606,11 +607,6 @@ Failure* Top::Throw(Object* exception, MessageLocation* location) {
 
 
 Failure* Top::ReThrow(Object* exception, MessageLocation* location) {
-  // Check is this exception is externally caught.
-  bool is_caught_externally = false;
-  ShouldReportException(&is_caught_externally);
-  thread_local_.external_caught_exception_ = is_caught_externally;
-
   // Set the exception beeing re-thrown.
   set_pending_exception(exception);
   return Failure::Exception();
@@ -793,7 +789,9 @@ void Top::DoThrow(Object* exception,
   // If the exception is caught externally, we store it in the
   // try/catch handler. The C code can find it later and process it if
   // necessary.
+  thread_local_.catcher_ = NULL;
   if (is_caught_externally) {
+    thread_local_.catcher_ = thread_local_.try_catch_handler_;
     thread_local_.try_catch_handler_->exception_ =
       reinterpret_cast<void*>(*exception_handle);
     if (!message_obj.is_null()) {
@@ -812,7 +810,6 @@ void Top::DoThrow(Object* exception,
       MessageHandler::ReportMessage(location, message_obj);
     }
   }
-  thread_local_.external_caught_exception_ = is_caught_externally;
 
   // NOTE: Notifying the debugger or reporting the exception may have caused
   // new exceptions. For now, we just ignore that and set the pending exception
index e2639f8..f7595b1 100644 (file)
--- a/src/top.h
+++ b/src/top.h
@@ -53,6 +53,7 @@ class ThreadLocalTop BASE_EMBEDDED {
   bool external_caught_exception_;
   v8::TryCatch* try_catch_handler_;
   SaveContext* save_context_;
+  v8::TryCatch* catcher_;
 
   // Stack.
   Address c_entry_fp_;  // the frame pointer of the top c entry frame
@@ -143,6 +144,12 @@ class Top {
     thread_local_.scheduled_exception_ = Heap::the_hole_value();
   }
 
+  static void setup_external_caught() {
+    thread_local_.external_caught_exception_ =
+        (thread_local_.catcher_ != NULL) &&
+        (Top::thread_local_.try_catch_handler_ == Top::thread_local_.catcher_);
+  }
+
   // Tells whether the current context has experienced an out of memory
   // exception.
   static bool is_out_of_memory();
diff --git a/test/mjsunit/api-call-after-overridden-exception.js b/test/mjsunit/api-call-after-overridden-exception.js
new file mode 100644 (file)
index 0000000..78a2aed
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2008 the V8 project authors. All rights reserved.\r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions are\r
+// met:\r
+//\r
+//     * Redistributions of source code must retain the above copyright\r
+//       notice, this list of conditions and the following disclaimer.\r
+//     * Redistributions in binary form must reproduce the above\r
+//       copyright notice, this list of conditions and the following\r
+//       disclaimer in the documentation and/or other materials provided\r
+//       with the distribution.\r
+//     * Neither the name of Google Inc. nor the names of its\r
+//       contributors may be used to endorse or promote products derived\r
+//       from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+
+// This is a test of making an API call after an exception thrown in JavaScript
+// has been swallowed by a return in the finally block.
+function foo()
+{
+  try {
+    throw "bar";
+  }
+  finally {
+    return "baz";
+  }
+}
+
+foo();
+print({});