OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/bootstrap_natives.h" | 6 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
8 #include "vm/dart.h" | 8 #include "vm/dart.h" |
9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
11 #include "vm/exceptions.h" | 11 #include "vm/exceptions.h" |
12 #include "vm/longjump.h" | 12 #include "vm/longjump.h" |
13 #include "vm/message.h" | 13 #include "vm/message_handler.h" |
14 #include "vm/object.h" | 14 #include "vm/object.h" |
15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
16 #include "vm/port.h" | 16 #include "vm/port.h" |
17 #include "vm/resolver.h" | 17 #include "vm/resolver.h" |
18 #include "vm/snapshot.h" | 18 #include "vm/snapshot.h" |
19 #include "vm/thread.h" | 19 #include "vm/thread.h" |
20 | 20 |
21 namespace dart { | 21 namespace dart { |
22 | 22 |
23 class IsolateStartData { | 23 class IsolateStartData { |
(...skipping 22 matching lines...) Expand all Loading... | |
46 | 46 |
47 static uint8_t* SerializeObject(const Instance& obj) { | 47 static uint8_t* SerializeObject(const Instance& obj) { |
48 uint8_t* result = NULL; | 48 uint8_t* result = NULL; |
49 SnapshotWriter writer(Snapshot::kMessage, &result, &allocator); | 49 SnapshotWriter writer(Snapshot::kMessage, &result, &allocator); |
50 writer.WriteObject(obj.raw()); | 50 writer.WriteObject(obj.raw()); |
51 writer.FinalizeBuffer(); | 51 writer.FinalizeBuffer(); |
52 return result; | 52 return result; |
53 } | 53 } |
54 | 54 |
55 | 55 |
56 // TODO(turnidge): Taking down the whole vm when an isolate fails is | 56 static void StoreError(Isolate* isolate, const Object& obj) { |
57 // bad. Change this. | |
58 static void ProcessError(const Object& obj) { | |
59 ASSERT(obj.IsError()); | 57 ASSERT(obj.IsError()); |
60 Error& error = Error::Handle(); | 58 Error& error = Error::Handle(); |
61 error ^= obj.raw(); | 59 error ^= obj.raw(); |
62 OS::PrintErr("%s\n", error.ToErrorCString()); | 60 isolate->object_store()->set_sticky_error(error); |
63 exit(255); | |
64 } | 61 } |
65 | 62 |
66 | 63 |
67 static void ThrowErrorException(Exceptions::ExceptionType type, | 64 static void ThrowErrorException(Exceptions::ExceptionType type, |
68 const char* error_msg, | 65 const char* error_msg, |
69 const char* library_url, | 66 const char* library_url, |
70 const char* class_name) { | 67 const char* class_name) { |
71 String& str = String::Handle(); | 68 String& str = String::Handle(); |
72 String& name = String::Handle(); | 69 String& name = String::Handle(); |
73 str ^= String::New(error_msg); | 70 str ^= String::New(error_msg); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 arguments.Add(&Integer::Handle(Integer::New(port_id))); | 103 arguments.Add(&Integer::Handle(Integer::New(port_id))); |
107 const Object& result = Object::Handle( | 104 const Object& result = Object::Handle( |
108 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); | 105 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
109 if (!result.IsError()) { | 106 if (!result.IsError()) { |
110 PortMap::SetLive(port_id); | 107 PortMap::SetLive(port_id); |
111 } | 108 } |
112 return result.raw(); | 109 return result.raw(); |
113 } | 110 } |
114 | 111 |
115 | 112 |
116 static void RunIsolate(uword parameter) { | 113 static bool RunIsolate(uword parameter) { |
117 IsolateStartData* data = reinterpret_cast<IsolateStartData*>(parameter); | 114 IsolateStartData* data = reinterpret_cast<IsolateStartData*>(parameter); |
118 Isolate* isolate = data->isolate_; | 115 Isolate* isolate = data->isolate_; |
119 char* library_url = data->library_url_; | 116 char* library_url = data->library_url_; |
120 char* class_name = data->class_name_; | 117 char* class_name = data->class_name_; |
121 intptr_t port_id = data->port_id_; | 118 intptr_t port_id = data->port_id_; |
122 delete data; | 119 delete data; |
123 | 120 |
124 Isolate::SetCurrent(isolate); | 121 { |
125 // Intialize stack limit in case we are running isolate in a | 122 SetIsolateScope set_scope(isolate); |
126 // different thread than in which it was initialized. | |
127 isolate->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&isolate)); | |
128 LongJump* base = isolate->long_jump_base(); | |
129 LongJump jump; | |
130 isolate->set_long_jump_base(&jump); | |
131 if (setjmp(*jump.Set()) == 0) { | |
132 Zone zone(isolate); | 123 Zone zone(isolate); |
133 HandleScope handle_scope(isolate); | 124 HandleScope handle_scope(isolate); |
134 ASSERT(ClassFinalizer::FinalizePendingClasses()); | 125 ASSERT(ClassFinalizer::FinalizePendingClasses()); |
135 // Lookup the target class by name, create an instance and call the run | 126 // Lookup the target class by name, create an instance and call the run |
136 // method. | 127 // method. |
137 const String& lib_name = String::Handle(String::NewSymbol(library_url)); | 128 const String& lib_name = String::Handle(String::NewSymbol(library_url)); |
129 free(library_url); | |
138 const Library& lib = Library::Handle(Library::LookupLibrary(lib_name)); | 130 const Library& lib = Library::Handle(Library::LookupLibrary(lib_name)); |
139 ASSERT(!lib.IsNull()); | 131 ASSERT(!lib.IsNull()); |
140 const String& cls_name = String::Handle(String::NewSymbol(class_name)); | 132 const String& cls_name = String::Handle(String::NewSymbol(class_name)); |
133 free(class_name); | |
141 const Class& target_class = Class::Handle(lib.LookupClass(cls_name)); | 134 const Class& target_class = Class::Handle(lib.LookupClass(cls_name)); |
142 // TODO(iposva): Deserialize or call the constructor after allocating. | 135 // TODO(iposva): Deserialize or call the constructor after allocating. |
143 // For now, we only support a non-parameterized or raw target class. | 136 // For now, we only support a non-parameterized or raw target class. |
siva
2012/04/14 00:29:53
Is this comment still valid considering the new is
turnidge
2012/04/17 23:46:55
RunIsolate implements the old isolate api. The ne
| |
144 const Instance& target = Instance::Handle(Instance::New(target_class)); | 137 const Instance& target = Instance::Handle(Instance::New(target_class)); |
145 Object& result = Object::Handle(); | 138 Object& result = Object::Handle(); |
146 | 139 |
147 // Invoke the default constructor. | 140 // Invoke the default constructor. |
148 const String& period = String::Handle(String::New(".")); | 141 const String& period = String::Handle(String::New(".")); |
149 String& constructor_name = String::Handle(String::Concat(cls_name, period)); | 142 String& constructor_name = String::Handle(String::Concat(cls_name, period)); |
150 const Function& default_constructor = | 143 const Function& default_constructor = |
151 Function::Handle(target_class.LookupConstructor(constructor_name)); | 144 Function::Handle(target_class.LookupConstructor(constructor_name)); |
152 if (!default_constructor.IsNull()) { | 145 if (!default_constructor.IsNull()) { |
153 GrowableArray<const Object*> arguments(1); | 146 GrowableArray<const Object*> arguments(1); |
154 arguments.Add(&target); | 147 arguments.Add(&target); |
155 arguments.Add(&Smi::Handle(Smi::New(Function::kCtorPhaseAll))); | 148 arguments.Add(&Smi::Handle(Smi::New(Function::kCtorPhaseAll))); |
156 const Array& kNoArgumentNames = Array::Handle(); | 149 const Array& kNoArgumentNames = Array::Handle(); |
157 result = DartEntry::InvokeStatic(default_constructor, | 150 result = DartEntry::InvokeStatic(default_constructor, |
158 arguments, | 151 arguments, |
159 kNoArgumentNames); | 152 kNoArgumentNames); |
160 if (result.IsError()) { | 153 if (result.IsError()) { |
161 ProcessError(result); | 154 StoreError(isolate, result); |
155 return false; | |
162 } | 156 } |
163 ASSERT(result.IsNull()); | 157 ASSERT(result.IsNull()); |
164 } | 158 } |
165 | 159 |
166 // Invoke the "_run" method. | 160 // Invoke the "_run" method. |
167 const Function& target_function = Function::Handle(Resolver::ResolveDynamic( | 161 const Function& target_function = Function::Handle(Resolver::ResolveDynamic( |
168 target, String::Handle(String::NewSymbol("_run")), 2, 0)); | 162 target, String::Handle(String::NewSymbol("_run")), 2, 0)); |
169 // TODO(iposva): Proper error checking here. | 163 // TODO(iposva): Proper error checking here. |
170 ASSERT(!target_function.IsNull()); | 164 ASSERT(!target_function.IsNull()); |
171 // TODO(iposva): Allocate the proper port number here. | 165 // TODO(iposva): Allocate the proper port number here. |
172 const Object& local_port = Object::Handle(ReceivePortCreate(port_id)); | 166 const Object& local_port = Object::Handle(ReceivePortCreate(port_id)); |
173 if (local_port.IsError()) { | 167 if (local_port.IsError()) { |
174 ProcessError(local_port); | 168 StoreError(isolate, local_port); |
siva
2012/04/14 00:29:53
need a "return false"; here?
We don't want to invo
turnidge
2012/04/17 23:46:55
Done.
| |
175 } | 169 } |
176 GrowableArray<const Object*> arguments(1); | 170 GrowableArray<const Object*> arguments(1); |
177 arguments.Add(&local_port); | 171 arguments.Add(&local_port); |
178 const Array& kNoArgumentNames = Array::Handle(); | 172 const Array& kNoArgumentNames = Array::Handle(); |
179 result = DartEntry::InvokeDynamic(target, | 173 result = DartEntry::InvokeDynamic(target, |
180 target_function, | 174 target_function, |
181 arguments, | 175 arguments, |
182 kNoArgumentNames); | 176 kNoArgumentNames); |
183 if (result.IsError()) { | 177 if (result.IsError()) { |
184 ProcessError(result); | 178 StoreError(isolate, result); |
179 return false; | |
185 } | 180 } |
186 ASSERT(result.IsNull()); | 181 ASSERT(result.IsNull()); |
187 free(class_name); | |
188 free(library_url); | |
189 result = isolate->StandardRunLoop(); | |
190 if (result.IsError()) { | |
191 ProcessError(result); | |
192 } | |
193 ASSERT(result.IsNull()); | |
194 | |
195 } else { | |
196 Zone zone(isolate); | |
197 HandleScope handle_scope(isolate); | |
198 const Error& error = Error::Handle( | |
199 Isolate::Current()->object_store()->sticky_error()); | |
200 const char* errmsg = error.ToErrorCString(); | |
201 OS::PrintErr("%s\n", errmsg); | |
202 exit(255); | |
203 } | 182 } |
204 isolate->set_long_jump_base(base); | 183 return true; |
siva
2012/04/14 00:29:53
In the old code if the new isolate had some errors
turnidge
2012/04/17 23:46:55
Okay. Thanks, I had that all wrong. I made some
| |
205 Dart::ShutdownIsolate(); | |
206 } | 184 } |
207 | 185 |
208 | 186 |
209 static bool CheckArguments(const char* library_url, const char* class_name) { | 187 static bool CheckArguments(const char* library_url, const char* class_name) { |
210 Isolate* isolate = Isolate::Current(); | 188 Isolate* isolate = Isolate::Current(); |
211 Zone zone(isolate); | 189 Zone zone(isolate); |
212 HandleScope handle_scope(isolate); | 190 HandleScope handle_scope(isolate); |
213 String& name = String::Handle(); | 191 String& name = String::Handle(); |
214 if (!ClassFinalizer::FinalizePendingClasses()) { | 192 if (!ClassFinalizer::FinalizePendingClasses()) { |
215 return false; | 193 return false; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 ASSERT(spawned_isolate != NULL); | 268 ASSERT(spawned_isolate != NULL); |
291 // Check arguments to see if the specified library and classes are | 269 // Check arguments to see if the specified library and classes are |
292 // loaded, this check will throw an exception if they are not loaded. | 270 // loaded, this check will throw an exception if they are not loaded. |
293 if (init_successful && CheckArguments(library_url, class_name)) { | 271 if (init_successful && CheckArguments(library_url, class_name)) { |
294 port_id = spawned_isolate->main_port(); | 272 port_id = spawned_isolate->main_port(); |
295 uword data = reinterpret_cast<uword>( | 273 uword data = reinterpret_cast<uword>( |
296 new IsolateStartData(spawned_isolate, | 274 new IsolateStartData(spawned_isolate, |
297 strdup(library_url), | 275 strdup(library_url), |
298 strdup(class_name), | 276 strdup(class_name), |
299 port_id)); | 277 port_id)); |
300 int result = Thread::Start(RunIsolate, data); | 278 Isolate::SetCurrent(NULL); |
301 if (result != 0) { | 279 spawned_isolate->message_handler()->Run( |
302 FATAL1("Failed to start isolate thread %d", result); | 280 Dart::thread_pool(), RunIsolate, data); |
303 } | |
304 } else { | 281 } else { |
305 // Error spawning the isolate, maybe due to initialization errors or | 282 // Error spawning the isolate, maybe due to initialization errors or |
306 // errors while loading the application into spawned isolate, shut | 283 // errors while loading the application into spawned isolate, shut |
307 // it down and report error. | 284 // it down and report error. |
308 // Make sure to grab the error message out of the isolate before it has | 285 // Make sure to grab the error message out of the isolate before it has |
309 // been shutdown and to allocate it in the preserved isolates zone. | 286 // been shutdown and to allocate it in the preserved isolates zone. |
310 { | 287 { |
311 Zone zone(spawned_isolate); | 288 Zone zone(spawned_isolate); |
312 HandleScope scope(spawned_isolate); | 289 HandleScope scope(spawned_isolate); |
313 const Error& err_obj = Error::Handle( | 290 const Error& err_obj = Error::Handle( |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 String::Handle(String::NewSymbol(function_name())); | 395 String::Handle(String::NewSymbol(function_name())); |
419 | 396 |
420 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url)); | 397 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url)); |
421 if (lib.IsNull() || lib.IsError()) { | 398 if (lib.IsNull() || lib.IsError()) { |
422 return Function::null(); | 399 return Function::null(); |
423 } | 400 } |
424 return lib.LookupLocalFunction(func_name); | 401 return lib.LookupLocalFunction(func_name); |
425 } | 402 } |
426 | 403 |
427 void Cleanup() { | 404 void Cleanup() { |
428 Isolate* saved = Isolate::Current(); | 405 SetIsolateScope set_scope(isolate()); |
429 Isolate::SetCurrent(isolate()); | |
430 Dart::ShutdownIsolate(); | 406 Dart::ShutdownIsolate(); |
431 Isolate::SetCurrent(saved); | |
432 } | 407 } |
433 | 408 |
434 private: | 409 private: |
435 Isolate* isolate_; | 410 Isolate* isolate_; |
436 char* library_url_; | 411 char* library_url_; |
437 char* function_name_; | 412 char* function_name_; |
438 }; | 413 }; |
439 | 414 |
440 | 415 |
441 static bool CreateIsolate(SpawnState* state, char** error) { | 416 static bool CreateIsolate(SpawnState* state, char** error) { |
(...skipping 30 matching lines...) Expand all Loading... | |
472 } | 447 } |
473 } | 448 } |
474 if (!retval) { | 449 if (!retval) { |
475 Dart::ShutdownIsolate(); | 450 Dart::ShutdownIsolate(); |
476 } | 451 } |
477 Isolate::SetCurrent(parent_isolate); | 452 Isolate::SetCurrent(parent_isolate); |
478 return retval; | 453 return retval; |
479 } | 454 } |
480 | 455 |
481 | 456 |
482 static void RunIsolate2(uword parameter) { | 457 static bool RunIsolate2(uword parameter) { |
483 SpawnState* state = reinterpret_cast<SpawnState*>(parameter); | 458 SpawnState* state = reinterpret_cast<SpawnState*>(parameter); |
484 Isolate* isolate = state->isolate(); | 459 Isolate* isolate = state->isolate(); |
485 | |
486 Isolate::SetCurrent(isolate); | |
487 // Intialize stack limit in case we are running isolate in a | |
488 // different thread than in which it was initialized. | |
489 isolate->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&isolate)); | |
490 | |
491 { | 460 { |
461 SetIsolateScope set_scope(isolate); | |
492 Zone zone(isolate); | 462 Zone zone(isolate); |
493 HandleScope handle_scope(isolate); | 463 HandleScope handle_scope(isolate); |
494 ASSERT(ClassFinalizer::FinalizePendingClasses()); | 464 ASSERT(ClassFinalizer::FinalizePendingClasses()); |
495 Object& result = Object::Handle(); | 465 Object& result = Object::Handle(); |
496 | 466 |
497 const Function& func = Function::Handle(state->ResolveFunction()); | 467 const Function& func = Function::Handle(state->ResolveFunction()); |
498 delete state; | 468 delete state; |
499 state = NULL; | 469 state = NULL; |
500 ASSERT(!func.IsNull()); | 470 ASSERT(!func.IsNull()); |
501 | 471 |
502 GrowableArray<const Object*> args(0); | 472 GrowableArray<const Object*> args(0); |
503 const Array& kNoArgNames = Array::Handle(); | 473 const Array& kNoArgNames = Array::Handle(); |
504 result = DartEntry::InvokeStatic(func, args, kNoArgNames); | 474 result = DartEntry::InvokeStatic(func, args, kNoArgNames); |
505 if (result.IsError()) { | 475 if (result.IsError()) { |
506 ProcessError(result); | 476 StoreError(isolate, result); |
477 return false; | |
507 } | 478 } |
508 | |
509 result = isolate->StandardRunLoop(); | |
510 if (result.IsError()) { | |
511 ProcessError(result); | |
512 } | |
513 ASSERT(result.IsNull()); | |
514 } | 479 } |
515 Dart::ShutdownIsolate(); | 480 return true; |
516 } | 481 } |
517 | 482 |
518 | 483 |
519 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { | 484 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { |
520 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); | 485 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); |
521 const Function& func = Function::Handle(closure.function()); | 486 const Function& func = Function::Handle(closure.function()); |
522 const Class& cls = Class::Handle(func.owner()); | 487 const Class& cls = Class::Handle(func.owner()); |
523 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) { | 488 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) { |
524 const String& msg = String::Handle(String::New( | 489 const String& msg = String::Handle(String::New( |
525 "spawnFunction expects to be passed a closure to a top-level static " | 490 "spawnFunction expects to be passed a closure to a top-level static " |
(...skipping 18 matching lines...) Expand all Loading... | |
544 // Try to create a SendPort for the new isolate. | 509 // Try to create a SendPort for the new isolate. |
545 const Object& port = Object::Handle( | 510 const Object& port = Object::Handle( |
546 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 511 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
547 if (port.IsError()) { | 512 if (port.IsError()) { |
548 state->Cleanup(); | 513 state->Cleanup(); |
549 delete state; | 514 delete state; |
550 Exceptions::PropagateError(port); | 515 Exceptions::PropagateError(port); |
551 } | 516 } |
552 | 517 |
553 // Start the new isolate. | 518 // Start the new isolate. |
554 int result = Thread::Start(RunIsolate2, reinterpret_cast<uword>(state)); | 519 // int result = Thread::Start(RunIsolate2, reinterpret_cast<uword>(state)); |
520 state->isolate()->message_handler()->Run( | |
521 Dart::thread_pool(), RunIsolate2, reinterpret_cast<uword>(state)); | |
522 int result = 0; | |
555 if (result != 0) { | 523 if (result != 0) { |
siva
2012/04/14 00:29:53
result has just been initialized to 0, how can it
turnidge
2012/04/17 23:46:55
The check is no longer needed. It is now a FATAL
siva
2012/04/18 22:05:00
FATAL is fine for now, we could revisit once the n
| |
556 const String& msg = String::Handle(String::NewFormatted( | 524 const String& msg = String::Handle(String::NewFormatted( |
557 "Failed to start thread for isolate '%s'. Error code '%d'.", | 525 "Failed to start thread for isolate '%s'. Error code '%d'.", |
558 state->isolate()->name(), result)); | 526 state->isolate()->name(), result)); |
559 state->Cleanup(); | 527 state->Cleanup(); |
560 delete state; | 528 delete state; |
561 ThrowIsolateSpawnException(msg); | 529 ThrowIsolateSpawnException(msg); |
562 } | 530 } |
563 | 531 |
564 arguments->SetReturn(port); | 532 arguments->SetReturn(port); |
565 } | 533 } |
566 | 534 |
567 | 535 |
568 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 536 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
569 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 537 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
570 if (port.IsError()) { | 538 if (port.IsError()) { |
571 Exceptions::PropagateError(port); | 539 Exceptions::PropagateError(port); |
572 } | 540 } |
573 arguments->SetReturn(port); | 541 arguments->SetReturn(port); |
574 } | 542 } |
575 | 543 |
576 } // namespace dart | 544 } // namespace dart |
OLD | NEW |