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

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

Issue 2651633002: VM: [Kernel] Fix bootstraping when Kernel isolate is used. (Closed)
Patch Set: Landing issue Created 3 years, 10 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
« no previous file with comments | « runtime/vm/kernel_isolate.h ('k') | runtime/vm/native_api_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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/kernel_isolate.h" 5 #include "vm/kernel_isolate.h"
6 6
7 #include "vm/compiler.h" 7 #include "vm/compiler.h"
8 #include "include/dart_native_api.h"
8 #include "vm/dart_api_impl.h" 9 #include "vm/dart_api_impl.h"
9 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
10 #include "vm/isolate.h" 11 #include "vm/isolate.h"
11 #include "vm/lockers.h" 12 #include "vm/lockers.h"
12 #include "vm/message.h" 13 #include "vm/message.h"
13 #include "vm/message_handler.h" 14 #include "vm/message_handler.h"
14 #include "vm/native_entry.h" 15 #include "vm/native_entry.h"
15 #include "vm/native_arguments.h" 16 #include "vm/native_arguments.h"
16 #include "vm/object.h" 17 #include "vm/object.h"
17 #include "vm/object_store.h" 18 #include "vm/object_store.h"
18 #include "vm/port.h" 19 #include "vm/port.h"
19 #include "vm/service.h" 20 #include "vm/service.h"
20 #include "vm/symbols.h" 21 #include "vm/symbols.h"
21 #include "vm/thread_pool.h" 22 #include "vm/thread_pool.h"
22 #include "vm/timeline.h" 23 #include "vm/timeline.h"
23 24
24 namespace dart { 25 namespace dart {
25 26
26 #if !defined(DART_PRECOMPILED_RUNTIME) 27 #if !defined(DART_PRECOMPILED_RUNTIME)
27 28
28 #define Z (T->zone()) 29 #define Z (T->zone())
29 30
30 DEFINE_FLAG(bool, trace_kernel, false, "Trace Kernel service requests."); 31 DEFINE_FLAG(bool, trace_kernel, false, "Trace Kernel service requests.");
31 DEFINE_FLAG(bool, 32 DEFINE_FLAG(bool,
32 use_dart_frontend, 33 use_dart_frontend,
33 false, 34 false,
34 "Parse scripts with Dart-to-Kernel parser"); 35 "Parse scripts with Dart-to-Kernel parser");
35 36
36 const char* KernelIsolate::kName = "kernel-service"; 37 const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME;
37 Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL; 38 Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
38 Monitor* KernelIsolate::monitor_ = new Monitor(); 39 Monitor* KernelIsolate::monitor_ = new Monitor();
39 Isolate* KernelIsolate::isolate_ = NULL; 40 Isolate* KernelIsolate::isolate_ = NULL;
40 bool KernelIsolate::initializing_ = true; 41 bool KernelIsolate::initializing_ = true;
41 Dart_Port KernelIsolate::kernel_port_ = ILLEGAL_PORT; 42 Dart_Port KernelIsolate::kernel_port_ = ILLEGAL_PORT;
42 43
43 44
44 class RunKernelTask : public ThreadPool::Task { 45 class RunKernelTask : public ThreadPool::Task {
45 public: 46 public:
46 virtual void Run() { 47 virtual void Run() {
(...skipping 20 matching lines...) Expand all
67 return; 68 return;
68 } 69 }
69 70
70 Dart_IsolateFlags api_flags; 71 Dart_IsolateFlags api_flags;
71 Isolate::FlagsInitialize(&api_flags); 72 Isolate::FlagsInitialize(&api_flags);
72 73
73 isolate = reinterpret_cast<Isolate*>(create_callback( 74 isolate = reinterpret_cast<Isolate*>(create_callback(
74 KernelIsolate::kName, NULL, NULL, NULL, &api_flags, NULL, &error)); 75 KernelIsolate::kName, NULL, NULL, NULL, &api_flags, NULL, &error));
75 if (isolate == NULL) { 76 if (isolate == NULL) {
76 if (FLAG_trace_kernel) { 77 if (FLAG_trace_kernel) {
77 OS::PrintErr("kernel-service: Isolate creation error: %s\n", error); 78 OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n",
79 error);
78 } 80 }
79 KernelIsolate::SetKernelIsolate(NULL); 81 KernelIsolate::SetKernelIsolate(NULL);
80 KernelIsolate::FinishedInitializing(); 82 KernelIsolate::FinishedInitializing();
81 return; 83 return;
82 } 84 }
83 85
84 bool init_success = false; 86 bool init_success = false;
85 { 87 {
86 ASSERT(Isolate::Current() == NULL); 88 ASSERT(Isolate::Current() == NULL);
87 StartIsolateScope start_scope(isolate); 89 StartIsolateScope start_scope(isolate);
88 init_success = RunMain(isolate); 90 init_success = RunMain(isolate);
89 } 91 }
90 KernelIsolate::FinishedInitializing(); 92 KernelIsolate::FinishedInitializing();
91 93
92 if (!init_success) { 94 if (!init_success) {
93 ShutdownIsolate(reinterpret_cast<uword>(isolate)); 95 ShutdownIsolate(reinterpret_cast<uword>(isolate));
94 return; 96 return;
95 } 97 }
96 98
97 // isolate_ was set as side effect of create callback. 99 // isolate_ was set as side effect of create callback.
98 ASSERT(KernelIsolate::IsKernelIsolate(isolate)); 100 ASSERT(KernelIsolate::IsKernelIsolate(isolate));
99 101
100 isolate->message_handler()->Run(Dart::thread_pool(), NULL, ShutdownIsolate, 102 isolate->message_handler()->Run(Dart::thread_pool(), NULL, ShutdownIsolate,
101 reinterpret_cast<uword>(isolate)); 103 reinterpret_cast<uword>(isolate));
102 } 104 }
103 105
104 protected: 106 protected:
105 static void ShutdownIsolate(uword parameter) { 107 static void ShutdownIsolate(uword parameter) {
106 if (FLAG_trace_kernel) { 108 if (FLAG_trace_kernel) {
107 OS::Print("kernel-service: ShutdownIsolate\n"); 109 OS::Print(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n");
108 } 110 }
109 Isolate* I = reinterpret_cast<Isolate*>(parameter); 111 Isolate* I = reinterpret_cast<Isolate*>(parameter);
110 ASSERT(KernelIsolate::IsKernelIsolate(I)); 112 ASSERT(KernelIsolate::IsKernelIsolate(I));
111 KernelIsolate::SetKernelIsolate(NULL); 113 KernelIsolate::SetKernelIsolate(NULL);
112 KernelIsolate::SetLoadPort(ILLEGAL_PORT); 114 KernelIsolate::SetLoadPort(ILLEGAL_PORT);
113 I->WaitForOutstandingSpawns(); 115 I->WaitForOutstandingSpawns();
114 { 116 {
115 // Print the error if there is one. This may execute dart code to 117 // Print the error if there is one. This may execute dart code to
116 // print the exception object, so we need to use a StartIsolateScope. 118 // print the exception object, so we need to use a StartIsolateScope.
117 ASSERT(Isolate::Current() == NULL); 119 ASSERT(Isolate::Current() == NULL);
118 StartIsolateScope start_scope(I); 120 StartIsolateScope start_scope(I);
119 Thread* T = Thread::Current(); 121 Thread* T = Thread::Current();
120 ASSERT(I == T->isolate()); 122 ASSERT(I == T->isolate());
121 StackZone zone(T); 123 StackZone zone(T);
122 HandleScope handle_scope(T); 124 HandleScope handle_scope(T);
123 Error& error = Error::Handle(Z); 125 Error& error = Error::Handle(Z);
124 error = T->sticky_error(); 126 error = T->sticky_error();
125 if (!error.IsNull() && !error.IsUnwindError()) { 127 if (!error.IsNull() && !error.IsUnwindError()) {
126 OS::PrintErr("kernel-service: Error: %s\n", error.ToErrorCString()); 128 OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
129 error.ToErrorCString());
127 } 130 }
128 error = I->sticky_error(); 131 error = I->sticky_error();
129 if (!error.IsNull() && !error.IsUnwindError()) { 132 if (!error.IsNull() && !error.IsUnwindError()) {
130 OS::PrintErr("kernel-service: Error: %s\n", error.ToErrorCString()); 133 OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
134 error.ToErrorCString());
131 } 135 }
132 Dart::RunShutdownCallback(); 136 Dart::RunShutdownCallback();
133 } 137 }
134 // Shut the isolate down. 138 // Shut the isolate down.
135 Dart::ShutdownIsolate(I); 139 Dart::ShutdownIsolate(I);
136 if (FLAG_trace_kernel) { 140 if (FLAG_trace_kernel) {
137 OS::Print("kernel-service: Shutdown.\n"); 141 OS::Print(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n");
138 } 142 }
139 } 143 }
140 144
141 bool RunMain(Isolate* I) { 145 bool RunMain(Isolate* I) {
142 Thread* T = Thread::Current(); 146 Thread* T = Thread::Current();
143 ASSERT(I == T->isolate()); 147 ASSERT(I == T->isolate());
144 StackZone zone(T); 148 StackZone zone(T);
145 HANDLESCOPE(T); 149 HANDLESCOPE(T);
146 // Invoke main which will return the port to which load requests are sent. 150 // Invoke main which will return the port to which load requests are sent.
147 const Library& root_library = 151 const Library& root_library =
148 Library::Handle(Z, I->object_store()->root_library()); 152 Library::Handle(Z, I->object_store()->root_library());
149 if (root_library.IsNull()) { 153 if (root_library.IsNull()) {
150 if (FLAG_trace_kernel) { 154 if (FLAG_trace_kernel) {
151 OS::Print("kernel-service: Embedder did not install a script."); 155 OS::Print(DART_KERNEL_ISOLATE_NAME
156 ": Embedder did not install a script.");
152 } 157 }
153 // Kernel isolate is not supported by embedder. 158 // Kernel isolate is not supported by embedder.
154 return false; 159 return false;
155 } 160 }
156 ASSERT(!root_library.IsNull()); 161 ASSERT(!root_library.IsNull());
157 const String& entry_name = String::Handle(Z, String::New("main")); 162 const String& entry_name = String::Handle(Z, String::New("main"));
158 ASSERT(!entry_name.IsNull()); 163 ASSERT(!entry_name.IsNull());
159 const Function& entry = Function::Handle( 164 const Function& entry = Function::Handle(
160 Z, root_library.LookupFunctionAllowPrivate(entry_name)); 165 Z, root_library.LookupFunctionAllowPrivate(entry_name));
161 if (entry.IsNull()) { 166 if (entry.IsNull()) {
162 // Kernel isolate is not supported by embedder. 167 // Kernel isolate is not supported by embedder.
163 if (FLAG_trace_kernel) { 168 if (FLAG_trace_kernel) {
164 OS::Print("kernel-service: Embedder did not provide a main function."); 169 OS::Print(DART_KERNEL_ISOLATE_NAME
170 ": Embedder did not provide a main function.");
165 } 171 }
166 return false; 172 return false;
167 } 173 }
168 ASSERT(!entry.IsNull()); 174 ASSERT(!entry.IsNull());
169 const Object& result = Object::Handle( 175 const Object& result = Object::Handle(
170 Z, DartEntry::InvokeFunction(entry, Object::empty_array())); 176 Z, DartEntry::InvokeFunction(entry, Object::empty_array()));
171 ASSERT(!result.IsNull()); 177 ASSERT(!result.IsNull());
172 if (result.IsError()) { 178 if (result.IsError()) {
173 // Kernel isolate did not initialize properly. 179 // Kernel isolate did not initialize properly.
174 if (FLAG_trace_kernel) { 180 if (FLAG_trace_kernel) {
175 const Error& error = Error::Cast(result); 181 const Error& error = Error::Cast(result);
176 OS::Print("kernel-service: Calling main resulted in an error: %s", 182 OS::Print(DART_KERNEL_ISOLATE_NAME
183 ": Calling main resulted in an error: %s",
177 error.ToErrorCString()); 184 error.ToErrorCString());
178 } 185 }
179 return false; 186 return false;
180 } 187 }
181 ASSERT(result.IsReceivePort()); 188 ASSERT(result.IsReceivePort());
182 const ReceivePort& rp = ReceivePort::Cast(result); 189 const ReceivePort& rp = ReceivePort::Cast(result);
183 KernelIsolate::SetLoadPort(rp.Id()); 190 KernelIsolate::SetLoadPort(rp.Id());
184 return true; 191 return true;
185 } 192 }
186 }; 193 };
187 194
188 195
189 void KernelIsolate::Run() { 196 void KernelIsolate::Run() {
190 if (!FLAG_use_dart_frontend) { 197 if (!FLAG_use_dart_frontend) {
191 return; 198 return;
192 } 199 }
193 // Grab the isolate create callback here to avoid race conditions with tests 200 // Grab the isolate create callback here to avoid race conditions with tests
194 // that change this after Dart_Initialize returns. 201 // that change this after Dart_Initialize returns.
195 create_callback_ = Isolate::CreateCallback(); 202 create_callback_ = Isolate::CreateCallback();
196 Dart::thread_pool()->Run(new RunKernelTask()); 203 Dart::thread_pool()->Run(new RunKernelTask());
197 } 204 }
198 205
199 206
200 void KernelIsolate::InitCallback(Isolate* I) { 207 void KernelIsolate::InitCallback(Isolate* I) {
201 Thread* T = Thread::Current(); 208 Thread* T = Thread::Current();
202 ASSERT(I == T->isolate()); 209 ASSERT(I == T->isolate());
203 ASSERT(I != NULL); 210 ASSERT(I != NULL);
204 ASSERT(I->name() != NULL); 211 ASSERT(I->name() != NULL);
205 if (!FLAG_use_dart_frontend || 212 if (!FLAG_use_dart_frontend ||
206 (strstr(I->name(), "kernel-service") == NULL)) { 213 (strstr(I->name(), DART_KERNEL_ISOLATE_NAME) == NULL)) {
207 // Not kernel isolate. 214 // Not kernel isolate.
208 return; 215 return;
209 } 216 }
210 ASSERT(!Exists()); 217 ASSERT(!Exists());
211 if (FLAG_trace_kernel) { 218 if (FLAG_trace_kernel) {
212 OS::Print("kernel-service: InitCallback for %s.\n", I->name()); 219 OS::Print(DART_KERNEL_ISOLATE_NAME ": InitCallback for %s.\n", I->name());
213 } 220 }
214 SetKernelIsolate(I); 221 SetKernelIsolate(I);
215 } 222 }
216 223
217 224
218 bool KernelIsolate::IsKernelIsolate(const Isolate* isolate) { 225 bool KernelIsolate::IsKernelIsolate(const Isolate* isolate) {
219 MonitorLocker ml(monitor_); 226 MonitorLocker ml(monitor_);
220 return isolate == isolate_; 227 return isolate == isolate_;
221 } 228 }
222 229
223 230
224 bool KernelIsolate::IsRunning() { 231 bool KernelIsolate::IsRunning() {
225 MonitorLocker ml(monitor_); 232 MonitorLocker ml(monitor_);
226 return (kernel_port_ != ILLEGAL_PORT) && (isolate_ != NULL); 233 return (kernel_port_ != ILLEGAL_PORT) && (isolate_ != NULL);
227 } 234 }
228 235
229 236
230 bool KernelIsolate::Exists() { 237 bool KernelIsolate::Exists() {
231 MonitorLocker ml(monitor_); 238 MonitorLocker ml(monitor_);
232 return isolate_ != NULL; 239 return isolate_ != NULL;
233 } 240 }
234 241
235 242
236 void KernelIsolate::SetKernelIsolate(Isolate* isolate) { 243 void KernelIsolate::SetKernelIsolate(Isolate* isolate) {
237 MonitorLocker ml(monitor_); 244 MonitorLocker ml(monitor_);
238 isolate_ = isolate; 245 isolate_ = isolate;
239 } 246 }
240 247
248
241 void KernelIsolate::SetLoadPort(Dart_Port port) { 249 void KernelIsolate::SetLoadPort(Dart_Port port) {
242 MonitorLocker ml(monitor_); 250 MonitorLocker ml(monitor_);
243 kernel_port_ = port; 251 kernel_port_ = port;
244 } 252 }
245 253
254
246 void KernelIsolate::FinishedInitializing() { 255 void KernelIsolate::FinishedInitializing() {
247 MonitorLocker ml(monitor_); 256 MonitorLocker ml(monitor_);
248 initializing_ = false; 257 initializing_ = false;
249 ml.NotifyAll(); 258 ml.NotifyAll();
250 } 259 }
251 260
252 261
253 Dart_Port KernelIsolate::WaitForKernelPort() { 262 Dart_Port KernelIsolate::WaitForKernelPort() {
254 if (!FLAG_use_dart_frontend) { 263 if (!FLAG_use_dart_frontend) {
255 return ILLEGAL_PORT; 264 return ILLEGAL_PORT;
256 } 265 }
257 MonitorLocker ml(monitor_); 266 MonitorLocker ml(monitor_);
258 while (initializing_ && (kernel_port_ == ILLEGAL_PORT)) { 267 while (initializing_ && (kernel_port_ == ILLEGAL_PORT)) {
259 ml.Wait(); 268 ml.Wait();
260 } 269 }
261 return kernel_port_; 270 return kernel_port_;
262 } 271 }
263 272
273
274 class KernelCompilationRequest : public ValueObject {
275 public:
276 KernelCompilationRequest()
277 : monitor_(new Monitor()),
278 port_(Dart_NewNativePort("kernel-compilation-port",
279 &HandleResponse,
280 false,
281 this)) {
282 result_.status = Dart_KernelCompilationStatus_Unknown;
283 result_.error = NULL;
284 result_.kernel = NULL;
285 result_.kernel_size = 0;
286 }
287
288 ~KernelCompilationRequest() {
289 Dart_CloseNativePort(port_);
290 delete monitor_;
291 }
292
293 Dart_KernelCompilationResult SendAndWaitForResponse(Dart_Port kernel_port,
294 const char* script_uri) {
295 // Build the [null, send_port, script_uri] message for the Kernel isolate:
296 // null tag tells it that request came from this code, instead of Loader
297 // so that it can given a more informative response.
298 Dart_CObject tag;
299 tag.type = Dart_CObject_kNull;
300
301 Dart_CObject send_port;
302 send_port.type = Dart_CObject_kSendPort;
303 send_port.value.as_send_port.id = port_;
304 send_port.value.as_send_port.origin_id = ILLEGAL_PORT;
305
306 Dart_CObject uri;
307 uri.type = Dart_CObject_kString;
308 uri.value.as_string = const_cast<char*>(script_uri);
309
310 static const intptr_t kMessageLen = 3;
311 Dart_CObject* message_arr[kMessageLen] = {&tag, &send_port, &uri};
312
313 Dart_CObject message;
314 message.type = Dart_CObject_kArray;
315 message.value.as_array.length = kMessageLen;
316 message.value.as_array.values = message_arr;
317
318 // Send the message.
319 Dart_PostCObject(kernel_port, &message);
320
321 // Wait for reply to arrive.
322 MonitorLocker ml(monitor_);
323 while (result_.status == Dart_KernelCompilationStatus_Unknown) {
324 ml.Wait();
325 }
326
327 return result_;
328 }
329
330 private:
331 // Possible responses from the Kernel isolate:
332 //
333 // [Ok, Uint8List KernelBinary]
334 // [Error, String error]
335 // [Crash, String error]
336 //
337 void HandleResponseImpl(Dart_CObject* message) {
338 ASSERT(message->type == Dart_CObject_kArray);
339 ASSERT(message->value.as_array.length >= 1);
340
341 Dart_CObject** response = message->value.as_array.values;
342
343 MonitorLocker ml(monitor_);
344
345 ASSERT(response[0]->type == Dart_CObject_kInt32);
346 result_.status = static_cast<Dart_KernelCompilationStatus>(
347 message->value.as_array.values[0]->value.as_int32);
348
349 if (result_.status == Dart_KernelCompilationStatus_Ok) {
350 ASSERT(response[1]->type == Dart_CObject_kTypedData);
351 ASSERT(response[1]->value.as_typed_data.type == Dart_TypedData_kUint8);
352
353 result_.kernel_size = response[1]->value.as_typed_data.length;
354 result_.kernel = static_cast<uint8_t*>(malloc(result_.kernel_size));
355 memmove(result_.kernel, response[1]->value.as_typed_data.values,
356 result_.kernel_size);
357 } else {
358 ASSERT(result_.status == Dart_KernelCompilationStatus_Crash ||
359 result_.status == Dart_KernelCompilationStatus_Error);
360 // This is an error.
361 ASSERT(response[1]->type == Dart_CObject_kString);
362 result_.error = strdup(response[1]->value.as_string);
363 }
364 ml.Notify();
365 }
366
367 static void HandleResponse(Dart_Port dest_port_id,
368 Dart_CObject* message,
369 void* peer) {
370 static_cast<KernelCompilationRequest*>(peer)->HandleResponseImpl(message);
371 }
372
373 Monitor* monitor_;
374 Dart_Port port_;
375
376 Dart_KernelCompilationResult result_;
377 };
378
379
380 Dart_KernelCompilationResult KernelIsolate::CompileToKernel(
381 const char* script_uri) {
382 // This must be the main script to be loaded. Wait for Kernel isolate
383 // to finish initialization.
384 Dart_Port kernel_port = WaitForKernelPort();
385 if (kernel_port == ILLEGAL_PORT) {
386 Dart_KernelCompilationResult result;
387 result.status = Dart_KernelCompilationStatus_Unknown;
388 result.error = strdup("Error while initializing Kernel isolate");
389 return result;
390 }
391
392 KernelCompilationRequest request;
393 return request.SendAndWaitForResponse(kernel_port, script_uri);
394 }
395
396
264 #endif // DART_PRECOMPILED_RUNTIME 397 #endif // DART_PRECOMPILED_RUNTIME
265 398
266 } // namespace dart 399 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/kernel_isolate.h ('k') | runtime/vm/native_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698