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" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 | 52 |
53 | 53 |
54 static void StoreError(Isolate* isolate, const Object& obj) { | 54 static void StoreError(Isolate* isolate, const Object& obj) { |
55 ASSERT(obj.IsError()); | 55 ASSERT(obj.IsError()); |
56 Error& error = Error::Handle(); | 56 Error& error = Error::Handle(); |
57 error ^= obj.raw(); | 57 error ^= obj.raw(); |
58 isolate->object_store()->set_sticky_error(error); | 58 isolate->object_store()->set_sticky_error(error); |
59 } | 59 } |
60 | 60 |
61 | 61 |
62 static void ThrowErrorException(Exceptions::ExceptionType type, | |
63 const char* error_msg, | |
64 const char* library_url, | |
65 const char* class_name) { | |
66 String& str = String::Handle(); | |
67 String& name = String::Handle(); | |
68 str ^= String::New(error_msg); | |
69 name ^= Symbols::New(library_url); | |
70 str ^= String::Concat(str, name); | |
71 name ^= String::New(":"); | |
72 str ^= String::Concat(str, name); | |
73 name ^= Symbols::New(class_name); | |
74 str ^= String::Concat(str, name); | |
75 GrowableArray<const Object*> arguments(1); | |
76 arguments.Add(&str); | |
77 Exceptions::ThrowByType(type, arguments); | |
78 } | |
79 | |
80 | |
81 // TODO(turnidge): Move to DartLibraryCalls. | 62 // TODO(turnidge): Move to DartLibraryCalls. |
82 RawObject* ReceivePortCreate(intptr_t port_id) { | 63 RawObject* ReceivePortCreate(intptr_t port_id) { |
83 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); | 64 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); |
84 ASSERT(!isolate_lib.IsNull()); | 65 ASSERT(!isolate_lib.IsNull()); |
85 const String& public_class_name = | 66 const String& public_class_name = |
86 String::Handle(Symbols::New("_ReceivePortImpl")); | 67 String::Handle(Symbols::New("_ReceivePortImpl")); |
87 const String& class_name = | 68 const String& class_name = |
88 String::Handle(isolate_lib.PrivateName(public_class_name)); | 69 String::Handle(isolate_lib.PrivateName(public_class_name)); |
89 const String& function_name = | 70 const String& function_name = |
90 String::Handle(Symbols::New("_get_or_create")); | 71 String::Handle(Symbols::New("_get_or_create")); |
(...skipping 10 matching lines...) Expand all Loading... |
101 arguments.Add(&Integer::Handle(Integer::New(port_id))); | 82 arguments.Add(&Integer::Handle(Integer::New(port_id))); |
102 const Object& result = Object::Handle( | 83 const Object& result = Object::Handle( |
103 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); | 84 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
104 if (!result.IsError()) { | 85 if (!result.IsError()) { |
105 PortMap::SetLive(port_id); | 86 PortMap::SetLive(port_id); |
106 } | 87 } |
107 return result.raw(); | 88 return result.raw(); |
108 } | 89 } |
109 | 90 |
110 | 91 |
111 static bool RunIsolate(uword parameter) { | |
112 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
113 IsolateStartData* data = | |
114 reinterpret_cast<IsolateStartData*>(isolate->spawn_data()); | |
115 isolate->set_spawn_data(NULL); | |
116 char* library_url = data->library_url_; | |
117 char* class_name = data->class_name_; | |
118 intptr_t port_id = data->port_id_; | |
119 delete data; | |
120 | |
121 { | |
122 StartIsolateScope start_scope(isolate); | |
123 Zone zone(isolate); | |
124 HandleScope handle_scope(isolate); | |
125 ASSERT(ClassFinalizer::AllClassesFinalized()); | |
126 // Lookup the target class by name, create an instance and call the run | |
127 // method. | |
128 const String& lib_name = String::Handle(Symbols::New(library_url)); | |
129 free(library_url); | |
130 const Library& lib = Library::Handle(Library::LookupLibrary(lib_name)); | |
131 ASSERT(!lib.IsNull()); | |
132 const String& cls_name = String::Handle(Symbols::New(class_name)); | |
133 free(class_name); | |
134 const Class& target_class = Class::Handle(lib.LookupClass(cls_name)); | |
135 // TODO(iposva): Deserialize or call the constructor after allocating. | |
136 // For now, we only support a non-parameterized or raw target class. | |
137 const Instance& target = Instance::Handle(Instance::New(target_class)); | |
138 Object& result = Object::Handle(); | |
139 | |
140 // Invoke the default constructor. | |
141 const String& period = String::Handle(String::New(".")); | |
142 String& constructor_name = String::Handle(String::Concat(cls_name, period)); | |
143 const Function& default_constructor = | |
144 Function::Handle(target_class.LookupConstructor(constructor_name)); | |
145 if (!default_constructor.IsNull()) { | |
146 GrowableArray<const Object*> arguments(1); | |
147 arguments.Add(&target); | |
148 arguments.Add(&Smi::Handle(Smi::New(Function::kCtorPhaseAll))); | |
149 const Array& kNoArgumentNames = Array::Handle(); | |
150 result = DartEntry::InvokeStatic(default_constructor, | |
151 arguments, | |
152 kNoArgumentNames); | |
153 if (result.IsError()) { | |
154 StoreError(isolate, result); | |
155 return false; | |
156 } | |
157 ASSERT(result.IsNull()); | |
158 } | |
159 | |
160 // Invoke the "_run" method. | |
161 const Function& target_function = Function::Handle(Resolver::ResolveDynamic( | |
162 target, String::Handle(Symbols::New("_run")), 2, 0)); | |
163 // TODO(iposva): Proper error checking here. | |
164 ASSERT(!target_function.IsNull()); | |
165 // TODO(iposva): Allocate the proper port number here. | |
166 const Object& local_port = Object::Handle(ReceivePortCreate(port_id)); | |
167 if (local_port.IsError()) { | |
168 StoreError(isolate, local_port); | |
169 return false; | |
170 } | |
171 GrowableArray<const Object*> arguments(1); | |
172 arguments.Add(&local_port); | |
173 const Array& kNoArgumentNames = Array::Handle(); | |
174 result = DartEntry::InvokeDynamic(target, | |
175 target_function, | |
176 arguments, | |
177 kNoArgumentNames); | |
178 if (result.IsError()) { | |
179 StoreError(isolate, result); | |
180 return false; | |
181 } | |
182 ASSERT(result.IsNull()); | |
183 } | |
184 return true; | |
185 } | |
186 | |
187 | |
188 static void ShutdownIsolate(uword parameter) { | 92 static void ShutdownIsolate(uword parameter) { |
189 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 93 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
190 { | 94 { |
191 // Print the error if there is one. This may execute dart code to | 95 // Print the error if there is one. This may execute dart code to |
192 // print the exception object, so we need to use a StartIsolateScope. | 96 // print the exception object, so we need to use a StartIsolateScope. |
193 StartIsolateScope start_scope(isolate); | 97 StartIsolateScope start_scope(isolate); |
194 Zone zone(isolate); | 98 Zone zone(isolate); |
195 HandleScope handle_scope(isolate); | 99 HandleScope handle_scope(isolate); |
196 Error& error = Error::Handle(); | 100 Error& error = Error::Handle(); |
197 error = isolate->object_store()->sticky_error(); | 101 error = isolate->object_store()->sticky_error(); |
198 if (!error.IsNull()) { | 102 if (!error.IsNull()) { |
199 OS::PrintErr("%s\n", error.ToErrorCString()); | 103 OS::PrintErr("%s\n", error.ToErrorCString()); |
200 exit(255); | 104 exit(255); |
201 } | 105 } |
202 } | 106 } |
203 { | 107 { |
204 // Shut the isolate down. | 108 // Shut the isolate down. |
205 SwitchIsolateScope switch_scope(isolate); | 109 SwitchIsolateScope switch_scope(isolate); |
206 Dart::ShutdownIsolate(); | 110 Dart::ShutdownIsolate(); |
207 } | 111 } |
208 } | 112 } |
209 | 113 |
210 | 114 |
211 static bool CheckArguments(const char* library_url, const char* class_name) { | |
212 Isolate* isolate = Isolate::Current(); | |
213 Zone zone(isolate); | |
214 HandleScope handle_scope(isolate); | |
215 String& name = String::Handle(); | |
216 if (!ClassFinalizer::FinalizePendingClasses()) { | |
217 return false; | |
218 } | |
219 // Lookup the target class by name, create an instance and call the run | |
220 // method. | |
221 name ^= Symbols::New(library_url); | |
222 const Library& lib = Library::Handle(Library::LookupLibrary(name)); | |
223 if (lib.IsNull()) { | |
224 const String& error_str = String::Handle( | |
225 String::New("Error starting Isolate, library not loaded : ")); | |
226 const Error& error = Error::Handle(LanguageError::New(error_str)); | |
227 Isolate::Current()->object_store()->set_sticky_error(error); | |
228 return false; | |
229 } | |
230 name ^= Symbols::New(class_name); | |
231 const Class& target_class = Class::Handle(lib.LookupClass(name)); | |
232 if (target_class.IsNull()) { | |
233 const String& error_str = String::Handle( | |
234 String::New("Error starting Isolate, class not loaded : ")); | |
235 const Error& error = Error::Handle(LanguageError::New(error_str)); | |
236 Isolate::Current()->object_store()->set_sticky_error(error); | |
237 return false; | |
238 } | |
239 return true; // No errors. | |
240 } | |
241 | |
242 | |
243 static char* GetRootScriptUri(Isolate* isolate) { | 115 static char* GetRootScriptUri(Isolate* isolate) { |
244 const Library& library = | 116 const Library& library = |
245 Library::Handle(isolate->object_store()->root_library()); | 117 Library::Handle(isolate->object_store()->root_library()); |
246 ASSERT(!library.IsNull()); | 118 ASSERT(!library.IsNull()); |
247 const String& script_name = String::Handle(library.url()); | 119 const String& script_name = String::Handle(library.url()); |
248 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | 120 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); |
249 } | 121 } |
250 | 122 |
251 | 123 |
252 static char* BuildMainName(const char* class_name) { | |
253 intptr_t len = OS::SNPrint(NULL, 0, "%s.main", class_name) + 1; | |
254 char* chars = reinterpret_cast<char*>( | |
255 Isolate::Current()->current_zone()->Allocate(len)); | |
256 OS::SNPrint(chars, len, "%s.main", class_name); | |
257 return chars; | |
258 } | |
259 | |
260 | |
261 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) { | |
262 Isolate* preserved_isolate = Isolate::Current(); | |
263 GET_NATIVE_ARGUMENT(Instance, runnable, arguments->At(0)); | |
264 // arguments->At(1) unused. | |
265 const Class& runnable_class = Class::Handle(runnable.clazz()); | |
266 const char* class_name = String::Handle(runnable_class.Name()).ToCString(); | |
267 const Library& library = Library::Handle(runnable_class.library()); | |
268 ASSERT(!library.IsNull()); | |
269 const char* library_url = String::Handle(library.url()).ToCString(); | |
270 intptr_t port_id = 0; | |
271 LongJump jump; | |
272 bool init_successful = true; | |
273 Isolate* spawned_isolate = NULL; | |
274 void* callback_data = preserved_isolate->init_callback_data(); | |
275 char* error = NULL; | |
276 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | |
277 const char* root_script_uri = GetRootScriptUri(preserved_isolate); | |
278 const char* main = BuildMainName(class_name); | |
279 if (callback == NULL) { | |
280 error = strdup("Null callback specified for isolate creation\n"); | |
281 } else if (callback(root_script_uri, main, callback_data, &error)) { | |
282 spawned_isolate = Isolate::Current(); | |
283 ASSERT(spawned_isolate != NULL); | |
284 // Check arguments to see if the specified library and classes are | |
285 // loaded, this check will throw an exception if they are not loaded. | |
286 if (init_successful && CheckArguments(library_url, class_name)) { | |
287 port_id = spawned_isolate->main_port(); | |
288 spawned_isolate->set_spawn_data( | |
289 reinterpret_cast<uword>( | |
290 new IsolateStartData(strdup(library_url), | |
291 strdup(class_name), | |
292 port_id))); | |
293 Isolate::SetCurrent(NULL); | |
294 spawned_isolate->message_handler()->Run( | |
295 Dart::thread_pool(), RunIsolate, ShutdownIsolate, | |
296 reinterpret_cast<uword>(spawned_isolate)); | |
297 } else { | |
298 // Error spawning the isolate, maybe due to initialization errors or | |
299 // errors while loading the application into spawned isolate, shut | |
300 // it down and report error. | |
301 // Make sure to grab the error message out of the isolate before it has | |
302 // been shutdown and to allocate it in the preserved isolates zone. | |
303 { | |
304 Zone zone(spawned_isolate); | |
305 HandleScope scope(spawned_isolate); | |
306 const Error& err_obj = Error::Handle( | |
307 spawned_isolate->object_store()->sticky_error()); | |
308 error = strdup(err_obj.ToErrorCString()); | |
309 } | |
310 Dart::ShutdownIsolate(); | |
311 spawned_isolate = NULL; | |
312 } | |
313 } | |
314 | |
315 // Switch back to the original isolate and return. | |
316 Isolate::SetCurrent(preserved_isolate); | |
317 if (spawned_isolate == NULL) { | |
318 // Unable to spawn isolate correctly, throw exception. | |
319 ThrowErrorException(Exceptions::kIllegalArgument, | |
320 error, | |
321 library_url, | |
322 class_name); | |
323 } | |
324 | |
325 // TODO(turnidge): Move this code up before we launch the new | |
326 // thread. That way we won't have a thread hanging around that we | |
327 // can't talk to. | |
328 const Object& port = Object::Handle(DartLibraryCalls::NewSendPort(port_id)); | |
329 if (port.IsError()) { | |
330 Exceptions::PropagateError(Error::Cast(port)); | |
331 } | |
332 arguments->SetReturn(port); | |
333 } | |
334 | |
335 | |
336 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { | 124 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { |
337 ASSERT(AbstractTypeArguments::CheckedHandle(arguments->At(0)).IsNull()); | 125 ASSERT(AbstractTypeArguments::CheckedHandle(arguments->At(0)).IsNull()); |
338 intptr_t port_id = | 126 intptr_t port_id = |
339 PortMap::CreatePort(arguments->isolate()->message_handler()); | 127 PortMap::CreatePort(arguments->isolate()->message_handler()); |
340 const Object& port = Object::Handle(ReceivePortCreate(port_id)); | 128 const Object& port = Object::Handle(ReceivePortCreate(port_id)); |
341 if (port.IsError()) { | 129 if (port.IsError()) { |
342 Exceptions::PropagateError(Error::Cast(port)); | 130 Exceptions::PropagateError(Error::Cast(port)); |
343 } | 131 } |
344 arguments->SetReturn(port); | 132 arguments->SetReturn(port); |
345 } | 133 } |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 char* script_url_; | 281 char* script_url_; |
494 char* library_url_; | 282 char* library_url_; |
495 char* function_name_; | 283 char* function_name_; |
496 }; | 284 }; |
497 | 285 |
498 | 286 |
499 static bool CreateIsolate(SpawnState* state, char** error) { | 287 static bool CreateIsolate(SpawnState* state, char** error) { |
500 Isolate* parent_isolate = Isolate::Current(); | 288 Isolate* parent_isolate = Isolate::Current(); |
501 | 289 |
502 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 290 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
503 ASSERT(callback != NULL); | 291 if (callback == NULL) { |
| 292 *error = strdup("Null callback specified for isolate creation\n"); |
| 293 Isolate::SetCurrent(parent_isolate); |
| 294 return false; |
| 295 } |
| 296 |
504 void* init_data = parent_isolate->init_callback_data(); | 297 void* init_data = parent_isolate->init_callback_data(); |
505 bool retval = (callback)(state->script_url(), | 298 bool retval = (callback)(state->script_url(), |
506 state->function_name(), | 299 state->function_name(), |
507 init_data, | 300 init_data, |
508 error); | 301 error); |
509 if (!retval) { | 302 if (!retval) { |
510 Isolate::SetCurrent(parent_isolate); | 303 Isolate::SetCurrent(parent_isolate); |
511 return false; | 304 return false; |
512 } | 305 } |
513 | 306 |
(...skipping 21 matching lines...) Expand all Loading... |
535 Dart::ShutdownIsolate(); | 328 Dart::ShutdownIsolate(); |
536 Isolate::SetCurrent(parent_isolate); | 329 Isolate::SetCurrent(parent_isolate); |
537 return false; | 330 return false; |
538 } | 331 } |
539 | 332 |
540 Isolate::SetCurrent(parent_isolate); | 333 Isolate::SetCurrent(parent_isolate); |
541 return true; | 334 return true; |
542 } | 335 } |
543 | 336 |
544 | 337 |
545 static bool RunIsolate2(uword parameter) { | 338 static bool RunIsolate(uword parameter) { |
546 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 339 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
547 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); | 340 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); |
548 isolate->set_spawn_data(NULL); | 341 isolate->set_spawn_data(NULL); |
549 { | 342 { |
550 StartIsolateScope start_scope(isolate); | 343 StartIsolateScope start_scope(isolate); |
551 Zone zone(isolate); | 344 Zone zone(isolate); |
552 HandleScope handle_scope(isolate); | 345 HandleScope handle_scope(isolate); |
553 if (!ClassFinalizer::FinalizePendingClasses()) { | 346 if (!ClassFinalizer::FinalizePendingClasses()) { |
554 // Error is in sticky error already. | 347 // Error is in sticky error already. |
555 return false; | 348 return false; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 386 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
594 if (port.IsError()) { | 387 if (port.IsError()) { |
595 state->Cleanup(); | 388 state->Cleanup(); |
596 delete state; | 389 delete state; |
597 Exceptions::PropagateError(Error::Cast(port)); | 390 Exceptions::PropagateError(Error::Cast(port)); |
598 } | 391 } |
599 | 392 |
600 // Start the new isolate. | 393 // Start the new isolate. |
601 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); | 394 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); |
602 state->isolate()->message_handler()->Run( | 395 state->isolate()->message_handler()->Run( |
603 Dart::thread_pool(), RunIsolate2, ShutdownIsolate, | 396 Dart::thread_pool(), RunIsolate, ShutdownIsolate, |
604 reinterpret_cast<uword>(state->isolate())); | 397 reinterpret_cast<uword>(state->isolate())); |
605 | 398 |
606 arguments->SetReturn(port); | 399 arguments->SetReturn(port); |
607 } | 400 } |
608 | 401 |
609 | 402 |
610 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { | 403 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { |
611 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); | 404 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); |
612 const Function& func = Function::Handle(closure.function()); | 405 const Function& func = Function::Handle(closure.function()); |
613 const Class& cls = Class::Handle(func.owner()); | 406 const Class& cls = Class::Handle(func.owner()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 | 441 |
649 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 442 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
650 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 443 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
651 if (port.IsError()) { | 444 if (port.IsError()) { |
652 Exceptions::PropagateError(Error::Cast(port)); | 445 Exceptions::PropagateError(Error::Cast(port)); |
653 } | 446 } |
654 arguments->SetReturn(port); | 447 arguments->SetReturn(port); |
655 } | 448 } |
656 | 449 |
657 } // namespace dart | 450 } // namespace dart |
OLD | NEW |