OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/isolate.h" | 5 #include "vm/isolate.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "platform/json.h" | 9 #include "platform/json.h" |
10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 bool IsCurrentIsolate() const; | 122 bool IsCurrentIsolate() const; |
123 virtual Isolate* isolate() const { return isolate_; } | 123 virtual Isolate* isolate() const { return isolate_; } |
124 | 124 |
125 private: | 125 private: |
126 // Keep in sync with isolate_patch.dart. | 126 // Keep in sync with isolate_patch.dart. |
127 enum { | 127 enum { |
128 kPauseMsg = 1, | 128 kPauseMsg = 1, |
129 kResumeMsg = 2, | 129 kResumeMsg = 2, |
130 kPingMsg = 3, | 130 kPingMsg = 3, |
131 kKillMsg = 4, | 131 kKillMsg = 4, |
132 kAddExitMsg = 5, | |
133 kDelExitMsg = 6, | |
134 kAddErrorMsg = 7, | |
135 kDelErrorMsg = 8, | |
136 kErrorFatalMsg = 9, | |
132 | 137 |
133 kImmediateAction = 0, | 138 kImmediateAction = 0, |
134 kBeforeNextEventAction = 1, | 139 kBeforeNextEventAction = 1, |
135 kAsEventAction = 2 | 140 kAsEventAction = 2 |
siva
2015/03/06 23:56:04
can these be in two enum blocks seems confusing to
Ivan Posva
2015/03/07 04:20:39
Done.
| |
136 }; | 141 }; |
137 | 142 |
138 // A result of false indicates that the isolate should terminate the | 143 // A result of false indicates that the isolate should terminate the |
139 // processing of further events. | 144 // processing of further events. |
140 bool HandleLibMessage(const Array& message); | 145 bool HandleLibMessage(const Array& message); |
141 | 146 |
142 bool ProcessUnhandledException(const Error& result); | 147 bool ProcessUnhandledException(const Error& result); |
143 Isolate* isolate_; | 148 Isolate* isolate_; |
144 }; | 149 }; |
145 | 150 |
(...skipping 11 matching lines...) Expand all Loading... | |
157 } | 162 } |
158 | 163 |
159 | 164 |
160 // Isolate library OOB messages are fixed sized arrays which have the | 165 // Isolate library OOB messages are fixed sized arrays which have the |
161 // following format: | 166 // following format: |
162 // [ OOB dispatch, Isolate library dispatch, <message specific data> ] | 167 // [ OOB dispatch, Isolate library dispatch, <message specific data> ] |
163 bool IsolateMessageHandler::HandleLibMessage(const Array& message) { | 168 bool IsolateMessageHandler::HandleLibMessage(const Array& message) { |
164 if (message.Length() < 2) return true; | 169 if (message.Length() < 2) return true; |
165 const Object& type = Object::Handle(I, message.At(1)); | 170 const Object& type = Object::Handle(I, message.At(1)); |
166 if (!type.IsSmi()) return true; | 171 if (!type.IsSmi()) return true; |
167 const Smi& msg_type = Smi::Cast(type); | 172 const intptr_t msg_type = Smi::Cast(type).Value(); |
168 switch (msg_type.Value()) { | 173 switch (msg_type) { |
169 case kPauseMsg: { | 174 case kPauseMsg: { |
170 // [ OOB, kPauseMsg, pause capability, resume capability ] | 175 // [ OOB, kPauseMsg, pause capability, resume capability ] |
171 if (message.Length() != 4) return true; | 176 if (message.Length() != 4) return true; |
172 Object& obj = Object::Handle(I, message.At(2)); | 177 Object& obj = Object::Handle(I, message.At(2)); |
173 if (!I->VerifyPauseCapability(obj)) return true; | 178 if (!I->VerifyPauseCapability(obj)) return true; |
174 obj = message.At(3); | 179 obj = message.At(3); |
175 if (!obj.IsCapability()) return true; | 180 if (!obj.IsCapability()) return true; |
176 if (I->AddResumeCapability(Capability::Cast(obj))) { | 181 if (I->AddResumeCapability(Capability::Cast(obj))) { |
177 increment_paused(); | 182 increment_paused(); |
178 } | 183 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 uint8_t* data = NULL; | 250 uint8_t* data = NULL; |
246 intptr_t len = 0; | 251 intptr_t len = 0; |
247 SerializeObject(message, &data, &len, false); | 252 SerializeObject(message, &data, &len, false); |
248 this->PostMessage(new Message(Message::kIllegalPort, | 253 this->PostMessage(new Message(Message::kIllegalPort, |
249 data, len, | 254 data, len, |
250 Message::kNormalPriority), | 255 Message::kNormalPriority), |
251 priority == kBeforeNextEventAction /* at_head */); | 256 priority == kBeforeNextEventAction /* at_head */); |
252 } | 257 } |
253 break; | 258 break; |
254 } | 259 } |
260 case kAddExitMsg: | |
261 case kDelExitMsg: | |
262 case kAddErrorMsg: | |
263 case kDelErrorMsg: { | |
264 // [ OOB, msg, listener port ] | |
265 if (message.Length() != 3) return true; | |
266 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.
| |
267 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
| |
268 const SendPort& listener = SendPort::Cast(obj); | |
269 switch (msg_type) { | |
270 case kAddExitMsg: | |
271 I->AddExitListener(listener); | |
272 break; | |
273 case kDelExitMsg: | |
274 I->RemoveExitListener(listener); | |
275 break; | |
276 case kAddErrorMsg: | |
277 I->AddErrorListener(listener); | |
278 break; | |
279 case kDelErrorMsg: | |
280 I->RemoveErrorListener(listener); | |
281 break; | |
282 default: | |
283 UNREACHABLE(); | |
284 } | |
285 break; | |
286 } | |
287 case kErrorFatalMsg: { | |
288 // [ OOB, kErrorFatalMsg, terminate capability, val ] | |
289 if (message.Length() != 4) return true; | |
290 // Check that the terminate capability has been passed correctly. | |
291 Object& obj = Object::Handle(I, message.At(2)); | |
292 if (!I->VerifyTerminateCapability(obj)) return true; | |
293 // Get the value to be set. | |
294 obj = message.At(3); | |
295 if (!obj.IsBool()) return true; | |
296 I->SetErrorsFatal(Bool::Cast(obj).value()); | |
297 break; | |
298 } | |
255 #if defined(DEBUG) | 299 #if defined(DEBUG) |
256 // Malformed OOB messages are silently ignored in release builds. | 300 // Malformed OOB messages are silently ignored in release builds. |
257 default: | 301 default: |
258 UNREACHABLE(); | 302 UNREACHABLE(); |
259 break; | 303 break; |
260 #endif // defined(DEBUG) | 304 #endif // defined(DEBUG) |
261 } | 305 } |
262 return true; | 306 return true; |
263 } | 307 } |
264 | 308 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 } | 454 } |
411 | 455 |
412 // Invoke the isolate's unhandled exception callback if there is one. | 456 // Invoke the isolate's unhandled exception callback if there is one. |
413 if (Isolate::UnhandledExceptionCallback() != NULL) { | 457 if (Isolate::UnhandledExceptionCallback() != NULL) { |
414 Dart_EnterScope(); | 458 Dart_EnterScope(); |
415 Dart_Handle error = Api::NewHandle(I, result.raw()); | 459 Dart_Handle error = Api::NewHandle(I, result.raw()); |
416 (Isolate::UnhandledExceptionCallback())(error); | 460 (Isolate::UnhandledExceptionCallback())(error); |
417 Dart_ExitScope(); | 461 Dart_ExitScope(); |
418 } | 462 } |
419 | 463 |
420 I->object_store()->set_sticky_error(result); | 464 // Generate the error and stacktrace strings for the error message. |
421 return false; | 465 String& exc_str = String::Handle(I); |
466 String& stacktrace_str = String::Handle(I); | |
467 if (result.IsUnhandledException()) { | |
468 const UnhandledException& uhe = UnhandledException::Cast(result); | |
469 const Instance& exception = Instance::Handle(I, uhe.exception()); | |
470 Object& tmp = Object::Handle(I); | |
471 tmp = DartLibraryCalls::ToString(exception); | |
472 if (!tmp.IsString()) { | |
473 tmp = String::New(exception.ToCString()); | |
474 } | |
475 exc_str ^= tmp.raw(); | |
476 | |
477 const Instance& stacktrace = Instance::Handle(I, uhe.stacktrace()); | |
478 tmp = DartLibraryCalls::ToString(stacktrace); | |
479 if (!tmp.IsString()) { | |
480 tmp = String::New(stacktrace.ToCString()); | |
481 } | |
482 stacktrace_str ^= tmp.raw();; | |
483 } else { | |
484 exc_str = String::New(result.ToErrorCString()); | |
485 } | |
486 I->NotifyErrorListeners(exc_str, stacktrace_str); | |
487 | |
488 if (I->ErrorsFatal()) { | |
489 I->object_store()->set_sticky_error(result); | |
490 return false; | |
491 } | |
492 return true; | |
422 } | 493 } |
423 | 494 |
424 | 495 |
425 #if defined(DEBUG) | 496 #if defined(DEBUG) |
426 // static | 497 // static |
427 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) { | 498 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) { |
428 ASSERT(isolate == Isolate::Current()); | 499 ASSERT(isolate == Isolate::Current()); |
429 } | 500 } |
430 #endif // defined(DEBUG) | 501 #endif // defined(DEBUG) |
431 | 502 |
(...skipping 10 matching lines...) Expand all Loading... | |
442 Isolate::Isolate() | 513 Isolate::Isolate() |
443 : vm_tag_(0), | 514 : vm_tag_(0), |
444 store_buffer_(), | 515 store_buffer_(), |
445 message_notify_callback_(NULL), | 516 message_notify_callback_(NULL), |
446 name_(NULL), | 517 name_(NULL), |
447 start_time_(OS::GetCurrentTimeMicros()), | 518 start_time_(OS::GetCurrentTimeMicros()), |
448 main_port_(0), | 519 main_port_(0), |
449 origin_id_(0), | 520 origin_id_(0), |
450 pause_capability_(0), | 521 pause_capability_(0), |
451 terminate_capability_(0), | 522 terminate_capability_(0), |
523 errors_fatal_(true), | |
452 heap_(NULL), | 524 heap_(NULL), |
453 object_store_(NULL), | 525 object_store_(NULL), |
454 top_exit_frame_info_(0), | 526 top_exit_frame_info_(0), |
455 init_callback_data_(NULL), | 527 init_callback_data_(NULL), |
456 environment_callback_(NULL), | 528 environment_callback_(NULL), |
457 library_tag_handler_(NULL), | 529 library_tag_handler_(NULL), |
458 api_state_(NULL), | 530 api_state_(NULL), |
459 stub_code_(NULL), | 531 stub_code_(NULL), |
460 debugger_(NULL), | 532 debugger_(NULL), |
461 single_step_(false), | 533 single_step_(false), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
507 Isolate::Isolate(Isolate* original) | 579 Isolate::Isolate(Isolate* original) |
508 : vm_tag_(0), | 580 : vm_tag_(0), |
509 store_buffer_(true), | 581 store_buffer_(true), |
510 class_table_(original->class_table()), | 582 class_table_(original->class_table()), |
511 message_notify_callback_(NULL), | 583 message_notify_callback_(NULL), |
512 name_(NULL), | 584 name_(NULL), |
513 start_time_(OS::GetCurrentTimeMicros()), | 585 start_time_(OS::GetCurrentTimeMicros()), |
514 main_port_(0), | 586 main_port_(0), |
515 pause_capability_(0), | 587 pause_capability_(0), |
516 terminate_capability_(0), | 588 terminate_capability_(0), |
589 errors_fatal_(true), | |
517 heap_(NULL), | 590 heap_(NULL), |
518 object_store_(NULL), | 591 object_store_(NULL), |
519 top_exit_frame_info_(0), | 592 top_exit_frame_info_(0), |
520 init_callback_data_(NULL), | 593 init_callback_data_(NULL), |
521 environment_callback_(NULL), | 594 environment_callback_(NULL), |
522 library_tag_handler_(NULL), | 595 library_tag_handler_(NULL), |
523 api_state_(NULL), | 596 api_state_(NULL), |
524 stub_code_(NULL), | 597 stub_code_(NULL), |
525 debugger_(NULL), | 598 debugger_(NULL), |
526 single_step_(false), | 599 single_step_(false), |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
910 // Remove the matching capability from the list. | 983 // Remove the matching capability from the list. |
911 current = Capability::null(); | 984 current = Capability::null(); |
912 caps.SetAt(i, current); | 985 caps.SetAt(i, current); |
913 return true; | 986 return true; |
914 } | 987 } |
915 } | 988 } |
916 return false; | 989 return false; |
917 } | 990 } |
918 | 991 |
919 | 992 |
993 // TODO(iposva): Remove duplicated code and start using some hash based | |
994 // structure instead of these linear lookups. | |
995 void Isolate::AddExitListener(const SendPort& listener) { | |
996 // Ensure a limit for the number of listeners remembered. | |
997 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.
| |
998 | |
999 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1000 this, object_store()->exit_listeners()); | |
1001 SendPort& current = SendPort::Handle(this); | |
1002 intptr_t insertion_index = -1; | |
1003 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1004 current ^= listeners.At(i); | |
1005 if (current.IsNull()) { | |
1006 if (insertion_index < 0) { | |
1007 insertion_index = i; | |
1008 } | |
1009 } else if (current.Id() == listener.Id()) { | |
1010 return; | |
1011 } | |
1012 } | |
1013 if (insertion_index < 0) { | |
1014 if (listeners.Length() >= kMaxListeners) { | |
1015 // Cannot grow the array of listeners beyond its max. Additional | |
1016 // listeners are ignored. In practice will never happen as we will | |
1017 // run out of memory beforehand. | |
1018 return; | |
1019 } | |
1020 listeners.Add(listener); | |
1021 } else { | |
1022 listeners.SetAt(insertion_index, listener); | |
1023 } | |
1024 } | |
1025 | |
1026 | |
1027 void Isolate::RemoveExitListener(const SendPort& listener) { | |
1028 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1029 this, object_store()->exit_listeners()); | |
1030 SendPort& current = SendPort::Handle(this); | |
1031 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1032 current ^= listeners.At(i); | |
1033 if (!current.IsNull() && (current.Id() == listener.Id())) { | |
1034 // Remove the matching listener from the list. | |
1035 current = SendPort::null(); | |
1036 listeners.SetAt(i, current); | |
1037 return; | |
1038 } | |
1039 } | |
1040 } | |
1041 | |
1042 | |
1043 void Isolate::NotifyExitListeners() { | |
1044 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1045 this, this->object_store()->exit_listeners()); | |
1046 SendPort& listener = SendPort::Handle(this); | |
1047 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1048 listener ^= listeners.At(i); | |
1049 if (!listener.IsNull()) { | |
1050 Dart_Port port_id = listener.Id(); | |
1051 uint8_t* data = NULL; | |
1052 intptr_t len = 0; | |
1053 SerializeObject(Object::null_instance(), &data, &len, false); | |
1054 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); | |
1055 PortMap::PostMessage(msg); | |
1056 } | |
1057 } | |
1058 } | |
1059 | |
1060 | |
1061 void Isolate::AddErrorListener(const SendPort& listener) { | |
1062 // Ensure a limit for the number of listeners remembered. | |
1063 static const intptr_t kMaxListeners = kSmiMax / (6*kWordSize); | |
1064 | |
1065 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1066 this, object_store()->error_listeners()); | |
1067 SendPort& current = SendPort::Handle(this); | |
1068 intptr_t insertion_index = -1; | |
1069 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1070 current ^= listeners.At(i); | |
1071 if (current.IsNull()) { | |
1072 if (insertion_index < 0) { | |
1073 insertion_index = i; | |
1074 } | |
1075 } else if (current.Id() == listener.Id()) { | |
1076 return; | |
1077 } | |
1078 } | |
1079 if (insertion_index < 0) { | |
1080 if (listeners.Length() >= kMaxListeners) { | |
1081 // Cannot grow the array of listeners beyond its max. Additional | |
1082 // listeners are ignored. In practice will never happen as we will | |
1083 // run out of memory beforehand. | |
1084 return; | |
1085 } | |
1086 listeners.Add(listener); | |
1087 } else { | |
1088 listeners.SetAt(insertion_index, listener); | |
1089 } | |
1090 } | |
1091 | |
1092 | |
1093 void Isolate::RemoveErrorListener(const SendPort& listener) { | |
1094 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1095 this, object_store()->error_listeners()); | |
1096 SendPort& current = SendPort::Handle(this); | |
1097 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1098 current ^= listeners.At(i); | |
1099 if (!current.IsNull() && (current.Id() == listener.Id())) { | |
1100 // Remove the matching listener from the list. | |
1101 current = SendPort::null(); | |
1102 listeners.SetAt(i, current); | |
1103 return; | |
1104 } | |
1105 } | |
1106 } | |
1107 | |
1108 | |
1109 void Isolate::NotifyErrorListeners(const String& msg, | |
1110 const String& stacktrace) { | |
1111 const Array& arr = Array::Handle(this, Array::New(2)); | |
1112 arr.SetAt(0, msg); | |
1113 arr.SetAt(1, stacktrace); | |
1114 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | |
1115 this, this->object_store()->error_listeners()); | |
1116 SendPort& listener = SendPort::Handle(this); | |
1117 for (intptr_t i = 0; i < listeners.Length(); i++) { | |
1118 listener ^= listeners.At(i); | |
1119 if (!listener.IsNull()) { | |
1120 Dart_Port port_id = listener.Id(); | |
1121 uint8_t* data = NULL; | |
1122 intptr_t len = 0; | |
1123 SerializeObject(arr, &data, &len, false); | |
1124 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); | |
1125 PortMap::PostMessage(msg); | |
1126 } | |
1127 } | |
1128 } | |
1129 | |
1130 | |
920 static void StoreError(Isolate* isolate, const Object& obj) { | 1131 static void StoreError(Isolate* isolate, const Object& obj) { |
921 ASSERT(obj.IsError()); | 1132 ASSERT(obj.IsError()); |
922 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | 1133 isolate->object_store()->set_sticky_error(Error::Cast(obj)); |
923 } | 1134 } |
924 | 1135 |
925 | 1136 |
926 static bool RunIsolate(uword parameter) { | 1137 static bool RunIsolate(uword parameter) { |
927 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 1138 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
928 IsolateSpawnState* state = NULL; | 1139 IsolateSpawnState* state = NULL; |
929 { | 1140 { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1142 // Remove this isolate from the list *before* we start tearing it down, to | 1353 // Remove this isolate from the list *before* we start tearing it down, to |
1143 // avoid exposing it in a state of decay. | 1354 // avoid exposing it in a state of decay. |
1144 RemoveIsolateFromList(this); | 1355 RemoveIsolateFromList(this); |
1145 | 1356 |
1146 // Create an area where we do have a zone and a handle scope so that we can | 1357 // Create an area where we do have a zone and a handle scope so that we can |
1147 // call VM functions while tearing this isolate down. | 1358 // call VM functions while tearing this isolate down. |
1148 { | 1359 { |
1149 StackZone stack_zone(this); | 1360 StackZone stack_zone(this); |
1150 HandleScope handle_scope(this); | 1361 HandleScope handle_scope(this); |
1151 | 1362 |
1363 // Notify exit listeners that this isolate is shutting down. | |
1364 NotifyExitListeners(); | |
1365 | |
1152 // Clean up debugger resources. | 1366 // Clean up debugger resources. |
1153 debugger()->Shutdown(); | 1367 debugger()->Shutdown(); |
1154 | 1368 |
1155 // Close all the ports owned by this isolate. | 1369 // Close all the ports owned by this isolate. |
1156 PortMap::ClosePorts(message_handler()); | 1370 PortMap::ClosePorts(message_handler()); |
1157 | 1371 |
1158 // Fail fast if anybody tries to post any more messsages to this isolate. | 1372 // Fail fast if anybody tries to post any more messsages to this isolate. |
1159 delete message_handler(); | 1373 delete message_handler(); |
1160 set_message_handler(NULL); | 1374 set_message_handler(NULL); |
1161 | 1375 |
(...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1725 serialized_message_, serialized_message_len_); | 1939 serialized_message_, serialized_message_len_); |
1726 } | 1940 } |
1727 | 1941 |
1728 | 1942 |
1729 void IsolateSpawnState::Cleanup() { | 1943 void IsolateSpawnState::Cleanup() { |
1730 SwitchIsolateScope switch_scope(I); | 1944 SwitchIsolateScope switch_scope(I); |
1731 Dart::ShutdownIsolate(); | 1945 Dart::ShutdownIsolate(); |
1732 } | 1946 } |
1733 | 1947 |
1734 } // namespace dart | 1948 } // namespace dart |
OLD | NEW |