Revision: 2796
Author: [email protected]
Date: Tue Sep  1 06:55:45 2009
Log: Fix the handling of termination exceptions thrown when creating error
objects in the runtime system.
Review URL: http://codereview.chromium.org/179062
http://code.google.com/p/v8/source/detail?r=2796

Modified:
  /branches/bleeding_edge/src/api.cc
  /branches/bleeding_edge/src/debug.cc
  /branches/bleeding_edge/src/execution.cc
  /branches/bleeding_edge/src/messages.js
  /branches/bleeding_edge/src/top.cc
  /branches/bleeding_edge/src/top.h
  /branches/bleeding_edge/test/cctest/test-thread-termination.cc

=======================================
--- /branches/bleeding_edge/src/api.cc  Wed Aug 26 03:33:11 2009
+++ /branches/bleeding_edge/src/api.cc  Tue Sep  1 06:55:45 2009
@@ -75,7 +75,7 @@
             
i::V8::FatalProcessOutOfMemory(NULL);                                \
         
}                                                                        \
        bool call_depth_is_zero =  
thread_local.CallDepthIsZero();                \
-      i::Top::OptionalRescheduleException(call_depth_is_zero,  
false);        \
+       
i::Top::OptionalRescheduleException(call_depth_is_zero);                 \
        return  
value;                                                            \
       
}                                                                          \
    } while (false)
=======================================
--- /branches/bleeding_edge/src/debug.cc        Mon Aug 24 19:54:39 2009
+++ /branches/bleeding_edge/src/debug.cc        Tue Sep  1 06:55:45 2009
@@ -661,7 +661,7 @@
    // Check for caught exceptions.
    if (caught_exception) {
      Handle<Object> message = MessageHandler::MakeMessageObject(
-        "error_loading_debugger", NULL, HandleVector<Object>(&result, 1),
+        "error_loading_debugger", NULL, Vector<Handle<Object> >::empty(),
          Handle<String>());
      MessageHandler::ReportMessage(NULL, message);
      return false;
@@ -2001,9 +2001,7 @@
                                event_listener_data_.location() };
        Handle<Object> result = Execution::TryCall(fun, Top::global(),
                                                   argc, argv,  
&caught_exception);
-      if (caught_exception) {
-        // Silently ignore exceptions from debug event listeners.
-      }
+      // Silently ignore exceptions from debug event listeners.
      }
    }
  }
=======================================
--- /branches/bleeding_edge/src/execution.cc    Wed Aug 26 03:27:32 2009
+++ /branches/bleeding_edge/src/execution.cc    Tue Sep  1 06:55:45 2009
@@ -156,9 +156,12 @@
      ASSERT(catcher.HasCaught());
      ASSERT(Top::has_pending_exception());
      ASSERT(Top::external_caught_exception());
-    bool is_bottom_call =  
HandleScopeImplementer::instance()->CallDepthIsZero();
-    Top::OptionalRescheduleException(is_bottom_call, true);
-    result = v8::Utils::OpenHandle(*catcher.Exception());
+    if (Top::pending_exception() == Heap::termination_exception()) {
+      result = Factory::termination_exception();
+    } else {
+      result = v8::Utils::OpenHandle(*catcher.Exception());
+    }
+    Top::OptionalRescheduleException(true);
    }

    ASSERT(!Top::has_pending_exception());
=======================================
--- /branches/bleeding_edge/src/messages.js     Thu Aug 13 00:36:28 2009
+++ /branches/bleeding_edge/src/messages.js     Tue Sep  1 06:55:45 2009
@@ -163,7 +163,7 @@
        illegal_break:                "Illegal break statement",
        illegal_continue:             "Illegal continue statement",
        illegal_return:               "Illegal return statement",
-      error_loading_debugger:       "Error loading debugger %0",
+      error_loading_debugger:       "Error loading debugger",
        no_input_to_regexp:           "No input to %0",
        result_not_primitive:         "Result of %0 must be a primitive,  
was %1",
        invalid_json:                 "String '%0' is not valid JSON",
=======================================
--- /branches/bleeding_edge/src/top.cc  Wed Aug 19 08:14:11 2009
+++ /branches/bleeding_edge/src/top.cc  Tue Sep  1 06:55:45 2009
@@ -855,23 +855,18 @@
  }


-bool Top::OptionalRescheduleException(bool is_bottom_call,
-                                      bool force_clear_catchable) {
+bool Top::OptionalRescheduleException(bool is_bottom_call) {
    // Allways reschedule out of memory exceptions.
    if (!is_out_of_memory()) {
      bool is_termination_exception =
          pending_exception() == Heap::termination_exception();

-    // Do not reschedule the exception if this is the bottom call or
-    // if we are asked to clear catchable exceptions.  Termination
-    // exceptions are not catchable and are only cleared if this is
-    // the bottom call.
-    bool clear_exception = is_bottom_call ||
-        (force_clear_catchable && !is_termination_exception);
+    // Do not reschedule the exception if this is the bottom call.
+    bool clear_exception = is_bottom_call;

      if (is_termination_exception) {
-      thread_local_.external_caught_exception_ = false;
        if (is_bottom_call) {
+        thread_local_.external_caught_exception_ = false;
          clear_pending_exception();
          return false;
        }
=======================================
--- /branches/bleeding_edge/src/top.h   Wed Aug 19 08:14:11 2009
+++ /branches/bleeding_edge/src/top.h   Tue Sep  1 06:55:45 2009
@@ -157,8 +157,8 @@
    // exceptions.  If an exception was thrown and not handled by an external
    // handler the exception is scheduled to be rethrown when we return to  
running
    // JavaScript code.  If an exception is scheduled true is returned.
-  static bool OptionalRescheduleException(bool is_bottom_call,
-                                          bool force_clear_catchable);
+  static bool OptionalRescheduleException(bool is_bottom_call);
+

    static bool* external_caught_exception_address() {
      return &thread_local_.external_caught_exception_;
=======================================
--- /branches/bleeding_edge/test/cctest/test-thread-termination.cc      Wed Aug 
 
19 08:14:11 2009
+++ /branches/bleeding_edge/test/cctest/test-thread-termination.cc      Tue Sep 
  
1 06:55:45 2009
@@ -193,3 +193,63 @@
    delete semaphore;
    semaphore = NULL;
  }
+
+
+int call_count = 0;
+
+
+v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) {
+  if (++call_count == 10) {
+    v8::V8::TerminateExecution();
+    return v8::Undefined();
+  }
+  v8::Local<v8::Object> result = v8::Object::New();
+  result->Set(v8::String::New("x"), v8::Integer::New(42));
+  return result;
+}
+
+
+v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) {
+  v8::TryCatch try_catch;
+  v8::Script::Compile(v8::String::New("function f() {"
+                                      "  try {"
+                                      "    while(true) {"
+                                      "       
terminate_or_return_object().x;"
+                                      "    }"
+                                      "    fail();"
+                                      "  } catch(e) {"
+                                      "    fail();"
+                                      "  }"
+                                      "}"
+                                      "f()"))->Run();
+  CHECK(try_catch.HasCaught());
+  CHECK(try_catch.Exception()->IsNull());
+  CHECK(try_catch.Message().IsEmpty());
+  CHECK(!try_catch.CanContinue());
+  return v8::Undefined();
+}
+
+
+// Test that we correctly handle termination exceptions if they are
+// triggered by the creation of error objects in connection with ICs.
+TEST(TerminateLoadICException) {
+  v8::HandleScope scope;
+  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
+  global->Set(v8::String::New("terminate_or_return_object"),
+              v8::FunctionTemplate::New(TerminateOrReturnObject));
+  global->Set(v8::String::New("fail"), v8::FunctionTemplate::New(Fail));
+  global->Set(v8::String::New("loop"),
+              v8::FunctionTemplate::New(LoopGetProperty));
+
+  v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
+  v8::Context::Scope context_scope(context);
+  // Run a loop that will be infinite if thread termination does not work.
+  v8::Handle<v8::String> source =
+      v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
+  call_count = 0;
+  v8::Script::Compile(source)->Run();
+  // Test that we can run the code again after thread termination.
+  call_count = 0;
+  v8::Script::Compile(source)->Run();
+  context.Dispose();
+}

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

Reply via email to