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

Side by Side Diff: runtime/vm/isolate.cc

Issue 354763004: - Implement Isolate.pause and Isolate.resume. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698