OLD | NEW |
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 Loading... |
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 |
OLD | NEW |