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
-~----------~----~----~----~------~----~------~--~---