Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(737)

Unified Diff: runtime/vm/isolate.cc

Issue 881373002: Implemented more of the Isolate API (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/isolate.cc
===================================================================
--- runtime/vm/isolate.cc (revision 44200)
+++ runtime/vm/isolate.cc (working copy)
@@ -129,6 +129,11 @@
kResumeMsg = 2,
kPingMsg = 3,
kKillMsg = 4,
+ kAddExitMsg = 5,
+ kDelExitMsg = 6,
+ kAddErrorMsg = 7,
+ kDelErrorMsg = 8,
+ kErrorFatalMsg = 9,
kImmediateAction = 0,
kBeforeNextEventAction = 1,
@@ -164,8 +169,8 @@
if (message.Length() < 2) return true;
const Object& type = Object::Handle(I, message.At(1));
if (!type.IsSmi()) return true;
- const Smi& msg_type = Smi::Cast(type);
- switch (msg_type.Value()) {
+ const intptr_t msg_type = Smi::Cast(type).Value();
+ switch (msg_type) {
case kPauseMsg: {
// [ OOB, kPauseMsg, pause capability, resume capability ]
if (message.Length() != 4) return true;
@@ -252,6 +257,45 @@
}
break;
}
+ case kAddExitMsg:
+ case kDelExitMsg:
+ case kAddErrorMsg:
+ case kDelErrorMsg: {
+ // [ OOB, msg, listener port ]
+ if (message.Length() != 3) return true;
+ Object& obj = Object::Handle(I, message.At(2));
siva 2015/03/06 23:56:04 const Object& obj = ...;
Ivan Posva 2015/03/07 04:20:39 Done.
+ if (!obj.IsSendPort()) return true;
siva 2015/03/06 23:56:04 Did we change the C++ style here, we always used t
Ivan Posva 2015/03/07 04:20:39 There are 2628 places in the project that use the
+ const SendPort& listener = SendPort::Cast(obj);
+ switch (msg_type) {
+ case kAddExitMsg:
+ I->AddExitListener(listener);
+ break;
+ case kDelExitMsg:
+ I->RemoveExitListener(listener);
+ break;
+ case kAddErrorMsg:
+ I->AddErrorListener(listener);
+ break;
+ case kDelErrorMsg:
+ I->RemoveErrorListener(listener);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ }
+ case kErrorFatalMsg: {
+ // [ OOB, kErrorFatalMsg, terminate capability, val ]
+ if (message.Length() != 4) return true;
+ // Check that the terminate capability has been passed correctly.
+ Object& obj = Object::Handle(I, message.At(2));
+ if (!I->VerifyTerminateCapability(obj)) return true;
+ // Get the value to be set.
+ obj = message.At(3);
+ if (!obj.IsBool()) return true;
+ I->SetErrorsFatal(Bool::Cast(obj).value());
+ break;
+ }
#if defined(DEBUG)
// Malformed OOB messages are silently ignored in release builds.
default:
@@ -417,8 +461,35 @@
Dart_ExitScope();
}
- I->object_store()->set_sticky_error(result);
- return false;
+ // Generate the error and stacktrace strings for the error message.
+ String& exc_str = String::Handle(I);
+ String& stacktrace_str = String::Handle(I);
+ if (result.IsUnhandledException()) {
+ const UnhandledException& uhe = UnhandledException::Cast(result);
+ const Instance& exception = Instance::Handle(I, uhe.exception());
+ Object& tmp = Object::Handle(I);
+ tmp = DartLibraryCalls::ToString(exception);
+ if (!tmp.IsString()) {
+ tmp = String::New(exception.ToCString());
+ }
+ exc_str ^= tmp.raw();
+
+ const Instance& stacktrace = Instance::Handle(I, uhe.stacktrace());
+ tmp = DartLibraryCalls::ToString(stacktrace);
+ if (!tmp.IsString()) {
+ tmp = String::New(stacktrace.ToCString());
+ }
+ stacktrace_str ^= tmp.raw();;
+ } else {
+ exc_str = String::New(result.ToErrorCString());
+ }
+ I->NotifyErrorListeners(exc_str, stacktrace_str);
+
+ if (I->ErrorsFatal()) {
+ I->object_store()->set_sticky_error(result);
+ return false;
+ }
+ return true;
}
@@ -449,6 +520,7 @@
origin_id_(0),
pause_capability_(0),
terminate_capability_(0),
+ errors_fatal_(true),
heap_(NULL),
object_store_(NULL),
top_exit_frame_info_(0),
@@ -514,6 +586,7 @@
main_port_(0),
pause_capability_(0),
terminate_capability_(0),
+ errors_fatal_(true),
heap_(NULL),
object_store_(NULL),
top_exit_frame_info_(0),
@@ -917,6 +990,144 @@
}
+// TODO(iposva): Remove duplicated code and start using some hash based
+// structure instead of these linear lookups.
+void Isolate::AddExitListener(const SendPort& listener) {
+ // Ensure a limit for the number of listeners remembered.
+ static const intptr_t kMaxListeners = kSmiMax / (6*kWordSize);
siva 2015/03/06 23:56:04 spaces 6 * kWOrdSize
Ivan Posva 2015/03/07 04:20:39 Done.
+
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, object_store()->exit_listeners());
+ SendPort& current = SendPort::Handle(this);
+ intptr_t insertion_index = -1;
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ current ^= listeners.At(i);
+ if (current.IsNull()) {
+ if (insertion_index < 0) {
+ insertion_index = i;
+ }
+ } else if (current.Id() == listener.Id()) {
+ return;
+ }
+ }
+ if (insertion_index < 0) {
+ if (listeners.Length() >= kMaxListeners) {
+ // Cannot grow the array of listeners beyond its max. Additional
+ // listeners are ignored. In practice will never happen as we will
+ // run out of memory beforehand.
+ return;
+ }
+ listeners.Add(listener);
+ } else {
+ listeners.SetAt(insertion_index, listener);
+ }
+}
+
+
+void Isolate::RemoveExitListener(const SendPort& listener) {
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, object_store()->exit_listeners());
+ SendPort& current = SendPort::Handle(this);
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ current ^= listeners.At(i);
+ if (!current.IsNull() && (current.Id() == listener.Id())) {
+ // Remove the matching listener from the list.
+ current = SendPort::null();
+ listeners.SetAt(i, current);
+ return;
+ }
+ }
+}
+
+
+void Isolate::NotifyExitListeners() {
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, this->object_store()->exit_listeners());
+ SendPort& listener = SendPort::Handle(this);
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ listener ^= listeners.At(i);
+ if (!listener.IsNull()) {
+ Dart_Port port_id = listener.Id();
+ uint8_t* data = NULL;
+ intptr_t len = 0;
+ SerializeObject(Object::null_instance(), &data, &len, false);
+ Message* msg = new Message(port_id, data, len, Message::kNormalPriority);
+ PortMap::PostMessage(msg);
+ }
+ }
+}
+
+
+void Isolate::AddErrorListener(const SendPort& listener) {
+ // Ensure a limit for the number of listeners remembered.
+ static const intptr_t kMaxListeners = kSmiMax / (6*kWordSize);
+
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, object_store()->error_listeners());
+ SendPort& current = SendPort::Handle(this);
+ intptr_t insertion_index = -1;
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ current ^= listeners.At(i);
+ if (current.IsNull()) {
+ if (insertion_index < 0) {
+ insertion_index = i;
+ }
+ } else if (current.Id() == listener.Id()) {
+ return;
+ }
+ }
+ if (insertion_index < 0) {
+ if (listeners.Length() >= kMaxListeners) {
+ // Cannot grow the array of listeners beyond its max. Additional
+ // listeners are ignored. In practice will never happen as we will
+ // run out of memory beforehand.
+ return;
+ }
+ listeners.Add(listener);
+ } else {
+ listeners.SetAt(insertion_index, listener);
+ }
+}
+
+
+void Isolate::RemoveErrorListener(const SendPort& listener) {
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, object_store()->error_listeners());
+ SendPort& current = SendPort::Handle(this);
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ current ^= listeners.At(i);
+ if (!current.IsNull() && (current.Id() == listener.Id())) {
+ // Remove the matching listener from the list.
+ current = SendPort::null();
+ listeners.SetAt(i, current);
+ return;
+ }
+ }
+}
+
+
+void Isolate::NotifyErrorListeners(const String& msg,
+ const String& stacktrace) {
+ const Array& arr = Array::Handle(this, Array::New(2));
+ arr.SetAt(0, msg);
+ arr.SetAt(1, stacktrace);
+ const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
+ this, this->object_store()->error_listeners());
+ SendPort& listener = SendPort::Handle(this);
+ for (intptr_t i = 0; i < listeners.Length(); i++) {
+ listener ^= listeners.At(i);
+ if (!listener.IsNull()) {
+ Dart_Port port_id = listener.Id();
+ uint8_t* data = NULL;
+ intptr_t len = 0;
+ SerializeObject(arr, &data, &len, false);
+ Message* msg = new Message(port_id, data, len, Message::kNormalPriority);
+ PortMap::PostMessage(msg);
+ }
+ }
+}
+
+
static void StoreError(Isolate* isolate, const Object& obj) {
ASSERT(obj.IsError());
isolate->object_store()->set_sticky_error(Error::Cast(obj));
@@ -1149,6 +1360,9 @@
StackZone stack_zone(this);
HandleScope handle_scope(this);
+ // Notify exit listeners that this isolate is shutting down.
+ NotifyExitListeners();
+
// Clean up debugger resources.
debugger()->Shutdown();

Powered by Google App Engine
This is Rietveld 408576698