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 "lib/mirrors.h" | 10 #include "lib/mirrors.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 #if defined(DEBUG) | 76 #if defined(DEBUG) |
77 // Check that it is safe to access this handler. | 77 // Check that it is safe to access this handler. |
78 void CheckAccess(); | 78 void CheckAccess(); |
79 #endif | 79 #endif |
80 bool IsCurrentIsolate() const; | 80 bool IsCurrentIsolate() const; |
81 virtual Isolate* isolate() const { return isolate_; } | 81 virtual Isolate* isolate() const { return isolate_; } |
82 bool UnhandledExceptionCallbackHandler(const Object& message, | 82 bool UnhandledExceptionCallbackHandler(const Object& message, |
83 const UnhandledException& error); | 83 const UnhandledException& error); |
84 | 84 |
85 private: | 85 private: |
86 // Keep in sync with isolate_patch.dart. | |
87 enum { | |
88 kPauseMsg = 1, | |
89 kResumeMsg | |
90 }; | |
91 | |
92 void HandleLibMessage(const Array& message); | |
86 bool ProcessUnhandledException(const Object& message, const Error& result); | 93 bool ProcessUnhandledException(const Object& message, const Error& result); |
87 RawFunction* ResolveCallbackFunction(); | 94 RawFunction* ResolveCallbackFunction(); |
88 Isolate* isolate_; | 95 Isolate* isolate_; |
89 }; | 96 }; |
90 | 97 |
91 | 98 |
92 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | 99 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) |
93 : isolate_(isolate) { | 100 : isolate_(isolate) { |
94 } | 101 } |
95 | 102 |
96 | 103 |
97 IsolateMessageHandler::~IsolateMessageHandler() { | 104 IsolateMessageHandler::~IsolateMessageHandler() { |
98 } | 105 } |
99 | 106 |
100 const char* IsolateMessageHandler::name() const { | 107 const char* IsolateMessageHandler::name() const { |
101 return isolate_->name(); | 108 return isolate_->name(); |
102 } | 109 } |
103 | 110 |
104 | 111 |
112 void IsolateMessageHandler::HandleLibMessage(const Array& message) { | |
siva
2014/07/01 21:42:56
Would be good to document the message formats here
Ivan Posva
2014/07/03 12:51:16
Done.
| |
113 if (message.Length() < 2) return; | |
114 const Object& type = Object::Handle(I, message.At(1)); | |
115 if (!type.IsSmi()) return; | |
116 const Smi& msg_type = Smi::Cast(type); | |
117 switch (msg_type.Value()) { | |
118 case kPauseMsg: { | |
119 if (message.Length() != 4) return; | |
120 Object& obj = Object::Handle(I, message.At(2)); | |
121 if (!obj.IsCapability()) return; | |
122 if (!I->VerifyPauseCapability(Capability::Cast(obj))) return; | |
123 obj = message.At(3); | |
124 if (!obj.IsCapability()) return; | |
125 if (I->AddPauseCapability(Capability::Cast(obj))) { | |
126 increment_paused(); | |
127 } | |
128 break; | |
129 } | |
130 case kResumeMsg: { | |
131 if (message.Length() != 4) return; | |
132 Object& obj = Object::Handle(I, message.At(2)); | |
133 if (!obj.IsCapability()) return; | |
134 if (!I->VerifyPauseCapability(Capability::Cast(obj))) return; | |
135 obj = message.At(3); | |
136 if (!obj.IsCapability()) return; | |
137 if (I->RemovePauseCapability(Capability::Cast(obj))) { | |
138 decrement_paused(); | |
139 } | |
140 break; | |
141 } | |
142 #if DEBUG | |
siva
2014/07/01 21:42:56
#if defined(DEBUG) to be consistent.
Ivan Posva
2014/07/03 12:51:16
Done.
| |
143 // Malformed OOB messages are silently ignored in release builds. | |
144 default: | |
145 UNREACHABLE(); | |
146 break; | |
147 #endif // DEBUG | |
148 } | |
149 } | |
150 | |
151 | |
105 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { | 152 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { |
106 if (priority >= Message::kOOBPriority) { | 153 if (priority >= Message::kOOBPriority) { |
107 // Handle out of band messages even if the isolate is busy. | 154 // Handle out of band messages even if the isolate is busy. |
108 I->ScheduleInterrupts(Isolate::kMessageInterrupt); | 155 I->ScheduleInterrupts(Isolate::kMessageInterrupt); |
109 } | 156 } |
110 Dart_MessageNotifyCallback callback = I->message_notify_callback(); | 157 Dart_MessageNotifyCallback callback = I->message_notify_callback(); |
111 if (callback) { | 158 if (callback) { |
112 // Allow the embedder to handle message notification. | 159 // Allow the embedder to handle message notification. |
113 (*callback)(Api::CastIsolate(I)); | 160 (*callback)(Api::CastIsolate(I)); |
114 } | 161 } |
115 } | 162 } |
116 | 163 |
117 | 164 |
118 bool IsolateMessageHandler::HandleMessage(Message* message) { | 165 bool IsolateMessageHandler::HandleMessage(Message* message) { |
119 StartIsolateScope start_scope(I); | 166 StartIsolateScope start_scope(I); |
120 StackZone zone(I); | 167 StackZone zone(I); |
121 HandleScope handle_scope(I); | 168 HandleScope handle_scope(I); |
122 // TODO(turnidge): Rework collection total dart execution. This can | 169 // TODO(turnidge): Rework collection total dart execution. This can |
123 // overcount when other things (gc, compilation) are active. | 170 // overcount when other things (gc, compilation) are active. |
124 TIMERSCOPE(isolate_, time_dart_execution); | 171 TIMERSCOPE(isolate_, time_dart_execution); |
125 | 172 |
126 // If the message is in band we lookup the handler to dispatch to. If the | 173 // If the message is in band we lookup the handler to dispatch to. If the |
127 // receive port was closed, we drop the message without deserializing it. | 174 // receive port was closed, we drop the message without deserializing it. |
128 Object& msg_handler = Object::Handle(I); | 175 Object& msg_handler = Object::Handle(I); |
129 if (!message->IsOOB()) { | 176 if (!message->IsOOB()) { |
130 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); | 177 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); |
131 if (msg_handler.IsError()) { | 178 if (msg_handler.IsError()) { |
179 delete message; | |
132 return ProcessUnhandledException(Object::null_instance(), | 180 return ProcessUnhandledException(Object::null_instance(), |
133 Error::Cast(msg_handler)); | 181 Error::Cast(msg_handler)); |
134 } | 182 } |
135 if (msg_handler.IsNull()) { | 183 if (msg_handler.IsNull()) { |
136 // If the port has been closed then the message will be dropped at this | 184 // If the port has been closed then the message will be dropped at this |
137 // point. Make sure to post to the delivery failure port in that case. | 185 // point. Make sure to post to the delivery failure port in that case. |
138 if (message->RedirectToDeliveryFailurePort()) { | 186 if (message->RedirectToDeliveryFailurePort()) { |
139 PortMap::PostMessage(message); | 187 PortMap::PostMessage(message); |
140 } else { | 188 } else { |
141 delete message; | 189 delete message; |
142 } | 190 } |
143 return true; | 191 return true; |
144 } | 192 } |
145 } | 193 } |
146 | 194 |
147 // Parse the message. | 195 // Parse the message. |
148 SnapshotReader reader(message->data(), message->len(), Snapshot::kMessage, I); | 196 SnapshotReader reader(message->data(), message->len(), Snapshot::kMessage, I); |
149 const Object& msg_obj = Object::Handle(I, reader.ReadObject()); | 197 const Object& msg_obj = Object::Handle(I, reader.ReadObject()); |
150 if (msg_obj.IsError()) { | 198 if (msg_obj.IsError()) { |
151 // An error occurred while reading the message. | 199 // An error occurred while reading the message. |
200 delete message; | |
152 return ProcessUnhandledException(Object::null_instance(), | 201 return ProcessUnhandledException(Object::null_instance(), |
153 Error::Cast(msg_obj)); | 202 Error::Cast(msg_obj)); |
154 } | 203 } |
155 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { | 204 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { |
156 // TODO(turnidge): We need to decide what an isolate does with | 205 // TODO(turnidge): We need to decide what an isolate does with |
157 // malformed messages. If they (eventually) come from a remote | 206 // malformed messages. If they (eventually) come from a remote |
158 // machine, then it might make sense to drop the message entirely. | 207 // machine, then it might make sense to drop the message entirely. |
159 // In the case that the message originated locally, which is | 208 // In the case that the message originated locally, which is |
160 // always true for now, then this should never occur. | 209 // always true for now, then this should never occur. |
161 UNREACHABLE(); | 210 UNREACHABLE(); |
162 } | 211 } |
163 | 212 |
164 Instance& msg = Instance::Handle(I); | 213 Instance& msg = Instance::Handle(I); |
165 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. | 214 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. |
166 | 215 |
167 bool success = true; | 216 bool success = true; |
168 if (message->IsOOB()) { | 217 if (message->IsOOB()) { |
169 ASSERT(msg.IsArray()); | 218 // OOB messages are expected to be fixed length arrays where the first |
170 const Object& oob_tag = Object::Handle(I, Array::Cast(msg).At(0)); | 219 // element is a Smi describing the OOB destination. Messages that do not |
171 ASSERT(oob_tag.IsSmi()); | 220 // confirm to this layout are silently ignored. |
172 switch (Smi::Cast(oob_tag).Value()) { | 221 if (msg.IsArray()) { |
173 case Message::kServiceOOBMsg: { | 222 const Array& oob_msg = Array::Cast(msg); |
174 Service::HandleIsolateMessage(I, msg); | 223 if (oob_msg.Length() > 0) { |
175 break; | 224 const Object& oob_tag = Object::Handle(I, oob_msg.At(0)); |
176 } | 225 if (oob_tag.IsSmi()) { |
177 default: { | 226 switch (Smi::Cast(oob_tag).Value()) { |
178 UNREACHABLE(); | 227 case Message::kServiceOOBMsg: { |
179 break; | 228 Service::HandleIsolateMessage(I, oob_msg); |
229 break; | |
230 } | |
231 case Message::kIsolateLibOOBMsg: { | |
232 HandleLibMessage(oob_msg); | |
233 break; | |
234 } | |
235 #if DEBUG | |
siva
2014/07/01 21:42:56
Ditto.
Ivan Posva
2014/07/03 12:51:16
Done.
| |
236 // Malformed OOB messages are silently ignored in release builds. | |
237 default: { | |
238 UNREACHABLE(); | |
239 break; | |
240 } | |
241 #endif // DEBUG | |
242 } | |
243 } | |
180 } | 244 } |
181 } | 245 } |
182 } else { | 246 } else { |
183 const Object& result = Object::Handle(I, | 247 const Object& result = Object::Handle(I, |
184 DartLibraryCalls::HandleMessage(msg_handler, msg)); | 248 DartLibraryCalls::HandleMessage(msg_handler, msg)); |
185 if (result.IsError()) { | 249 if (result.IsError()) { |
186 success = ProcessUnhandledException(msg, Error::Cast(result)); | 250 success = ProcessUnhandledException(msg, Error::Cast(result)); |
187 } else { | 251 } else { |
188 ASSERT(result.IsNull()); | 252 ASSERT(result.IsNull()); |
189 } | 253 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 | 377 |
314 #define REUSABLE_HANDLE_INITIALIZERS(object) \ | 378 #define REUSABLE_HANDLE_INITIALIZERS(object) \ |
315 object##_handle_(NULL), | 379 object##_handle_(NULL), |
316 | 380 |
317 Isolate::Isolate() | 381 Isolate::Isolate() |
318 : store_buffer_(), | 382 : store_buffer_(), |
319 message_notify_callback_(NULL), | 383 message_notify_callback_(NULL), |
320 name_(NULL), | 384 name_(NULL), |
321 start_time_(OS::GetCurrentTimeMicros()), | 385 start_time_(OS::GetCurrentTimeMicros()), |
322 main_port_(0), | 386 main_port_(0), |
387 pause_capability_(0), | |
388 terminate_capability_(0), | |
323 heap_(NULL), | 389 heap_(NULL), |
324 object_store_(NULL), | 390 object_store_(NULL), |
325 top_context_(Context::null()), | 391 top_context_(Context::null()), |
326 top_exit_frame_info_(0), | 392 top_exit_frame_info_(0), |
327 init_callback_data_(NULL), | 393 init_callback_data_(NULL), |
328 environment_callback_(NULL), | 394 environment_callback_(NULL), |
329 library_tag_handler_(NULL), | 395 library_tag_handler_(NULL), |
330 api_state_(NULL), | 396 api_state_(NULL), |
331 stub_code_(NULL), | 397 stub_code_(NULL), |
332 debugger_(NULL), | 398 debugger_(NULL), |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
456 ApiState* state = new ApiState(); | 522 ApiState* state = new ApiState(); |
457 ASSERT(state != NULL); | 523 ASSERT(state != NULL); |
458 result->set_api_state(state); | 524 result->set_api_state(state); |
459 | 525 |
460 // Initialize stack top and limit in case we are running the isolate in the | 526 // Initialize stack top and limit in case we are running the isolate in the |
461 // main thread. | 527 // main thread. |
462 // TODO(5411455): Need to figure out how to set the stack limit for the | 528 // TODO(5411455): Need to figure out how to set the stack limit for the |
463 // main thread. | 529 // main thread. |
464 result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result)); | 530 result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result)); |
465 result->set_main_port(PortMap::CreatePort(result->message_handler())); | 531 result->set_main_port(PortMap::CreatePort(result->message_handler())); |
532 result->set_pause_capability(result->random()->NextUInt64()); | |
533 result->set_terminate_capability(result->random()->NextUInt64()); | |
534 | |
466 result->BuildName(name_prefix); | 535 result->BuildName(name_prefix); |
467 | 536 |
468 result->debugger_ = new Debugger(); | 537 result->debugger_ = new Debugger(); |
469 result->debugger_->Initialize(result); | 538 result->debugger_->Initialize(result); |
470 if (FLAG_trace_isolates) { | 539 if (FLAG_trace_isolates) { |
471 if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) { | 540 if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) { |
472 OS::Print("[+] Starting isolate:\n" | 541 OS::Print("[+] Starting isolate:\n" |
473 "\tisolate: %s\n", result->name()); | 542 "\tisolate: %s\n", result->name()); |
474 } | 543 } |
475 } | 544 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
586 IsolateSpawnState* state = spawn_state(); | 655 IsolateSpawnState* state = spawn_state(); |
587 if (state != NULL) { | 656 if (state != NULL) { |
588 ASSERT(this == state->isolate()); | 657 ASSERT(this == state->isolate()); |
589 Run(); | 658 Run(); |
590 } | 659 } |
591 mutex_->Unlock(); | 660 mutex_->Unlock(); |
592 return true; | 661 return true; |
593 } | 662 } |
594 | 663 |
595 | 664 |
665 bool Isolate::VerifyPauseCapability(const Capability& capability) { | |
666 return !capability.IsNull() && (pause_capability() == capability.Id()); | |
667 } | |
668 | |
669 | |
670 bool Isolate::AddPauseCapability(const Capability& capability) { | |
671 const GrowableObjectArray& caps = GrowableObjectArray::Handle( | |
672 this, object_store()->pause_capabilities()); | |
673 Capability& current = Capability::Handle(this); | |
674 intptr_t insertion_index = -1; | |
675 for (intptr_t i = 0; i < caps.Length(); i++) { | |
676 current ^= caps.At(i); | |
677 if (current.IsNull()) { | |
678 if (insertion_index < 0) { | |
679 insertion_index = i; | |
680 } | |
681 } else if (current.Id() == capability.Id()) { | |
682 return false; | |
683 } | |
684 } | |
685 if (insertion_index < 0) { | |
686 caps.Add(capability); | |
687 } else { | |
688 caps.SetAt(insertion_index, capability); | |
689 } | |
690 return true; | |
691 } | |
692 | |
693 | |
694 bool Isolate::RemovePauseCapability(const Capability& capability) { | |
695 const GrowableObjectArray& caps = GrowableObjectArray::Handle( | |
696 this, object_store()->pause_capabilities()); | |
697 Capability& current = Capability::Handle(this); | |
698 for (intptr_t i = 0; i < caps.Length(); i++) { | |
699 current ^= caps.At(i); | |
700 if (!current.IsNull() && (current.Id() == capability.Id())) { | |
701 // Remove the matching capability from the list. | |
702 current = Capability::null(); | |
703 caps.SetAt(i, current); | |
704 return true; | |
705 } | |
706 } | |
707 return false; | |
708 } | |
709 | |
710 | |
596 static void StoreError(Isolate* isolate, const Object& obj) { | 711 static void StoreError(Isolate* isolate, const Object& obj) { |
597 ASSERT(obj.IsError()); | 712 ASSERT(obj.IsError()); |
598 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | 713 isolate->object_store()->set_sticky_error(Error::Cast(obj)); |
599 } | 714 } |
600 | 715 |
601 | 716 |
602 static bool RunIsolate(uword parameter) { | 717 static bool RunIsolate(uword parameter) { |
603 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 718 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
604 IsolateSpawnState* state = NULL; | 719 IsolateSpawnState* state = NULL; |
605 { | 720 { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
765 | 880 |
766 | 881 |
767 class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor { | 882 class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor { |
768 public: | 883 public: |
769 FinalizeWeakPersistentHandlesVisitor() : HandleVisitor(Isolate::Current()) { | 884 FinalizeWeakPersistentHandlesVisitor() : HandleVisitor(Isolate::Current()) { |
770 } | 885 } |
771 | 886 |
772 void VisitHandle(uword addr) { | 887 void VisitHandle(uword addr) { |
773 FinalizablePersistentHandle* handle = | 888 FinalizablePersistentHandle* handle = |
774 reinterpret_cast<FinalizablePersistentHandle*>(addr); | 889 reinterpret_cast<FinalizablePersistentHandle*>(addr); |
775 handle->UpdateUnreachable(isolate()); | 890 handle->UpdateUnreachable(I); |
776 } | 891 } |
777 | 892 |
778 private: | 893 private: |
779 DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor); | 894 DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor); |
780 }; | 895 }; |
781 | 896 |
782 | 897 |
783 void Isolate::Shutdown() { | 898 void Isolate::Shutdown() { |
784 ASSERT(this == Isolate::Current()); | 899 ASSERT(this == Isolate::Current()); |
785 ASSERT(top_resource() == NULL); | 900 ASSERT(top_resource() == NULL); |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1205 Library& lib = Library::Handle(); | 1320 Library& lib = Library::Handle(); |
1206 if (library_url()) { | 1321 if (library_url()) { |
1207 const String& lib_url = String::Handle(String::New(library_url())); | 1322 const String& lib_url = String::Handle(String::New(library_url())); |
1208 lib = Library::LookupLibrary(lib_url); | 1323 lib = Library::LookupLibrary(lib_url); |
1209 if (lib.IsNull() || lib.IsError()) { | 1324 if (lib.IsNull() || lib.IsError()) { |
1210 const String& msg = String::Handle(String::NewFormatted( | 1325 const String& msg = String::Handle(String::NewFormatted( |
1211 "Unable to find library '%s'.", library_url())); | 1326 "Unable to find library '%s'.", library_url())); |
1212 return LanguageError::New(msg); | 1327 return LanguageError::New(msg); |
1213 } | 1328 } |
1214 } else { | 1329 } else { |
1215 lib = isolate()->object_store()->root_library(); | 1330 lib = I->object_store()->root_library(); |
1216 } | 1331 } |
1217 ASSERT(!lib.IsNull()); | 1332 ASSERT(!lib.IsNull()); |
1218 | 1333 |
1219 // Resolve the function. | 1334 // Resolve the function. |
1220 const String& func_name = String::Handle(String::New(function_name())); | 1335 const String& func_name = String::Handle(String::New(function_name())); |
1221 | 1336 |
1222 if (class_name() == NULL) { | 1337 if (class_name() == NULL) { |
1223 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); | 1338 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); |
1224 if (func.IsNull()) { | 1339 if (func.IsNull()) { |
1225 const String& msg = String::Handle(String::NewFormatted( | 1340 const String& msg = String::Handle(String::NewFormatted( |
(...skipping 21 matching lines...) Expand all Loading... | |
1247 "Unable to resolve static method '%s.%s' in library '%s'.", | 1362 "Unable to resolve static method '%s.%s' in library '%s'.", |
1248 class_name(), function_name(), | 1363 class_name(), function_name(), |
1249 (library_url() != NULL ? library_url() : script_url()))); | 1364 (library_url() != NULL ? library_url() : script_url()))); |
1250 return LanguageError::New(msg); | 1365 return LanguageError::New(msg); |
1251 } | 1366 } |
1252 return func.raw(); | 1367 return func.raw(); |
1253 } | 1368 } |
1254 | 1369 |
1255 | 1370 |
1256 void IsolateSpawnState::Cleanup() { | 1371 void IsolateSpawnState::Cleanup() { |
1257 SwitchIsolateScope switch_scope(isolate()); | 1372 SwitchIsolateScope switch_scope(I); |
1258 Dart::ShutdownIsolate(); | 1373 Dart::ShutdownIsolate(); |
1259 } | 1374 } |
1260 | 1375 |
1261 } // namespace dart | 1376 } // namespace dart |
OLD | NEW |