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

Side by Side Diff: runtime/lib/isolate_patch.dart

Issue 456983002: Refactor isolate startup code in preparation for making isolate spawning more truly non-blocking. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 4 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
« no previous file with comments | « runtime/lib/isolate.cc ('k') | runtime/vm/bootstrap_natives.h » ('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) 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 import "dart:collection" show HashMap; 5 import "dart:collection" show HashMap;
6 6
7 patch class ReceivePort { 7 patch class ReceivePort {
8 /* patch */ factory ReceivePort() = _ReceivePortImpl; 8 /* patch */ factory ReceivePort() = _ReceivePortImpl;
9 9
10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) = 10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 /// The callback that has been registered through `scheduleImmediate`. 70 /// The callback that has been registered through `scheduleImmediate`.
71 ImmediateCallback _pendingImmediateCallback; 71 ImmediateCallback _pendingImmediateCallback;
72 72
73 /// The closure that should be used as scheduleImmediateClosure, when the VM 73 /// The closure that should be used as scheduleImmediateClosure, when the VM
74 /// is responsible for the event loop. 74 /// is responsible for the event loop.
75 void _isolateScheduleImmediate(void callback()) { 75 void _isolateScheduleImmediate(void callback()) {
76 assert(_pendingImmediateCallback == null); 76 assert(_pendingImmediateCallback == null);
77 _pendingImmediateCallback = callback; 77 _pendingImmediateCallback = callback;
78 } 78 }
79 79
80 void _runPendingImmediateCallback() {
81 if (_pendingImmediateCallback != null) {
82 var callback = _pendingImmediateCallback;
83 _pendingImmediateCallback = null;
84 callback();
85 }
86 }
87
80 /// The embedder can execute this function to get hold of 88 /// The embedder can execute this function to get hold of
81 /// [_isolateScheduleImmediate] above. 89 /// [_isolateScheduleImmediate] above.
82 Function _getIsolateScheduleImmediateClosure() { 90 Function _getIsolateScheduleImmediateClosure() {
83 return _isolateScheduleImmediate; 91 return _isolateScheduleImmediate;
84 } 92 }
85 93
86 class _RawReceivePortImpl implements RawReceivePort { 94 class _RawReceivePortImpl implements RawReceivePort {
87 factory _RawReceivePortImpl() native "RawReceivePortImpl_factory"; 95 factory _RawReceivePortImpl() native "RawReceivePortImpl_factory";
88 96
89 close() { 97 close() {
(...skipping 23 matching lines...) Expand all
113 var result = _handlerMap[id]; 121 var result = _handlerMap[id];
114 return result; 122 return result;
115 } 123 }
116 124
117 // Called from the VM to dispatch to the handler. 125 // Called from the VM to dispatch to the handler.
118 static void _handleMessage(Function handler, var message) { 126 static void _handleMessage(Function handler, var message) {
119 // TODO(floitsch): this relies on the fact that any exception aborts the 127 // TODO(floitsch): this relies on the fact that any exception aborts the
120 // VM. Once we have non-fatal global exceptions we need to catch errors 128 // VM. Once we have non-fatal global exceptions we need to catch errors
121 // so that we can run the immediate callbacks. 129 // so that we can run the immediate callbacks.
122 handler(message); 130 handler(message);
123 if (_pendingImmediateCallback != null) { 131 _runPendingImmediateCallback();
124 var callback = _pendingImmediateCallback;
125 _pendingImmediateCallback = null;
126 callback();
127 }
128 } 132 }
129 133
130 // Call into the VM to close the VM maintained mappings. 134 // Call into the VM to close the VM maintained mappings.
131 _closeInternal() native "RawReceivePortImpl_closeInternal"; 135 _closeInternal() native "RawReceivePortImpl_closeInternal";
132 136
133 void set handler(Function value) { 137 void set handler(Function value) {
134 _handlerMap[this._get_id()] = value; 138 _handlerMap[this._get_id()] = value;
135 } 139 }
136 140
137 // TODO(iposva): Ideally keep this map in the VM. 141 // TODO(iposva): Ideally keep this map in the VM.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 typedef _MainFunction(); 178 typedef _MainFunction();
175 typedef _MainFunctionArgs(args); 179 typedef _MainFunctionArgs(args);
176 typedef _MainFunctionArgsMessage(args, message); 180 typedef _MainFunctionArgsMessage(args, message);
177 181
178 /** 182 /**
179 * Takes the real entry point as argument and invokes it with the initial 183 * Takes the real entry point as argument and invokes it with the initial
180 * message. 184 * message.
181 * 185 *
182 * The initial startup message is received through the control port. 186 * The initial startup message is received through the control port.
183 */ 187 */
184 void _startIsolate(Function entryPoint, bool isSpawnUri) { 188 void _startIsolate(SendPort parentPort,
185 // This port keeps the isolate alive until the initial startup message has 189 Function entryPoint,
186 // been received. 190 List<String> args,
187 var keepAlivePort = new RawReceivePort(); 191 var message,
192 bool isSpawnUri,
193 RawReceivePort controlPort,
194 List capabilities) {
195 if (controlPort != null) {
196 controlPort.handler = (_) {}; // Nobody home on the control port.
197 }
198 if (parentPort != null) {
199 // Build a message to our parent isolate providing access to the
200 // current isolate's control port and capabilities.
201 //
202 // TODO(floitsch): Send an error message if we can't find the entry point.
203 var readyMessage = new List(2);
204 readyMessage[0] = controlPort.sendPort;
205 readyMessage[1] = capabilities;
188 206
189 ignoreHandler(message) { 207 // Out of an excess of paranoia we clear the capabilities from the
190 // Messages on the current Isolate's control port are dropped after the 208 // stack. Not really necessary.
191 // initial startup message has been received. 209 capabilities = null;
210 parentPort.send(readyMessage);
192 } 211 }
212 assert(capabilities == null);
193 213
194 isolateStartHandler(message) { 214 if (isSpawnUri) {
195 // We received the initial startup message. Ignore all further messages and 215 if (entryPoint is _MainFunctionArgsMessage) {
196 // close the port which kept this isolate alive. 216 entryPoint(args, message);
197 Isolate._self.handler = ignoreHandler; 217 } else if (entryPoint is _MainFunctionArgs) {
198 keepAlivePort.close(); 218 entryPoint(args);
199 219 } else {
200 SendPort replyTo = message[0]; 220 entryPoint();
201 if (replyTo != null) {
202 // TODO(floitsch): don't send ok-message if we can't find the entry point.
203 replyTo.send("started");
204 } 221 }
205 if (isSpawnUri) { 222 } else {
206 assert(message.length == 3); 223 entryPoint(message);
207 List<String> args = message[1];
208 var isolateMessage = message[2];
209 if (entryPoint is _MainFunctionArgsMessage) {
210 entryPoint(args, isolateMessage);
211 } else if (entryPoint is _MainFunctionArgs) {
212 entryPoint(args);
213 } else {
214 entryPoint();
215 }
216 } else {
217 assert(message.length == 2);
218 var entryMessage = message[1];
219 entryPoint(entryMessage);
220 }
221 } 224 }
222 225 _runPendingImmediateCallback();
223 Isolate._self.handler = isolateStartHandler;
224 } 226 }
225 227
226 patch class Isolate { 228 patch class Isolate {
227 /* patch */ static Future<Isolate> spawn( 229 /* patch */ static Future<Isolate> spawn(
228 void entryPoint(message), var message, { bool paused: false }) { 230 void entryPoint(message), var message, { bool paused: false }) {
229 // `paused` isn't handled yet. 231 // `paused` isn't handled yet.
232 RawReceivePort readyPort;
230 try { 233 try {
231 // The VM will invoke [_startIsolate] with entryPoint as argument. 234 // The VM will invoke [_startIsolate] with entryPoint as argument.
232 List spawnData = _spawnFunction(entryPoint); 235 readyPort = new RawReceivePort();
233 assert(spawnData.length == 3); 236 _spawnFunction(readyPort.sendPort, entryPoint, message);
234 SendPort controlPort = spawnData[0];
235 RawReceivePort readyPort = new RawReceivePort();
236 controlPort.send([readyPort.sendPort, message]);
237 Completer completer = new Completer<Isolate>.sync(); 237 Completer completer = new Completer<Isolate>.sync();
238 readyPort.handler = (readyMessage) { 238 readyPort.handler = (readyMessage) {
239 assert(readyMessage == 'started');
240 readyPort.close(); 239 readyPort.close();
240 assert(readyMessage is List);
241 assert(readyMessage.length == 2);
242 SendPort controlPort = readyMessage[0];
243 List capabilities = readyMessage[1];
241 completer.complete(new Isolate(controlPort, 244 completer.complete(new Isolate(controlPort,
242 pauseCapability: spawnData[1], 245 pauseCapability: capabilities[0],
243 terminateCapability: spawnData[2])); 246 terminateCapability: capabilities[1]));
244 }; 247 };
245 return completer.future; 248 return completer.future;
246 } catch (e, st) { 249 } catch (e, st) {
250 if (readyPort != null) {
251 readyPort.close();
252 }
247 return new Future<Isolate>.error(e, st); 253 return new Future<Isolate>.error(e, st);
248 }; 254 };
249 } 255 }
250 256
251 /* patch */ static Future<Isolate> spawnUri( 257 /* patch */ static Future<Isolate> spawnUri(
252 Uri uri, List<String> args, var message, { bool paused: false }) { 258 Uri uri, List<String> args, var message, { bool paused: false }) {
253 // `paused` isn't handled yet. 259 // `paused` isn't handled yet.
260 RawReceivePort readyPort;
254 try { 261 try {
255 // The VM will invoke [_startIsolate] and not `main`. 262 // The VM will invoke [_startIsolate] and not `main`.
256 List spawnData = _spawnUri(uri.toString()); 263 readyPort = new RawReceivePort();
257 assert(spawnData.length == 3); 264 _spawnUri(readyPort.sendPort, uri.toString(), args, message);
258 SendPort controlPort = spawnData[0];
259 RawReceivePort readyPort = new RawReceivePort();
260 controlPort.send([readyPort.sendPort, args, message]);
261 Completer completer = new Completer<Isolate>.sync(); 265 Completer completer = new Completer<Isolate>.sync();
262 readyPort.handler = (readyMessage) { 266 readyPort.handler = (readyMessage) {
263 assert(readyMessage == 'started');
264 readyPort.close(); 267 readyPort.close();
268 assert(readyMessage is List);
269 assert(readyMessage.length == 2);
270 SendPort controlPort = readyMessage[0];
271 List capabilities = readyMessage[1];
265 completer.complete(new Isolate(controlPort, 272 completer.complete(new Isolate(controlPort,
266 pauseCapability: spawnData[1], 273 pauseCapability: capabilities[0],
267 terminateCapability: spawnData[2])); 274 terminateCapability: capabilities[1]));
268 }; 275 };
269 return completer.future; 276 return completer.future;
270 } catch (e, st) { 277 } catch (e, st) {
278 if (readyPort != null) {
279 readyPort.close();
280 }
271 return new Future<Isolate>.error(e, st); 281 return new Future<Isolate>.error(e, st);
272 }; 282 };
273 return completer.future; 283 return completer.future;
274 } 284 }
275 285
276 static final RawReceivePort _self = _mainPort;
277 static RawReceivePort get _mainPort native "Isolate_mainPort";
278
279 // TODO(iposva): Cleanup to have only one definition. 286 // TODO(iposva): Cleanup to have only one definition.
280 // These values need to be kept in sync with the class IsolateMessageHandler 287 // These values need to be kept in sync with the class IsolateMessageHandler
281 // in vm/isolate.cc. 288 // in vm/isolate.cc.
282 static const _PAUSE = 1; 289 static const _PAUSE = 1;
283 static const _RESUME = 2; 290 static const _RESUME = 2;
284 291
285 static List _spawnFunction(Function topLevelFunction) 292 static SendPort _spawnFunction(SendPort readyPort, Function topLevelFunction,
293 var message)
286 native "Isolate_spawnFunction"; 294 native "Isolate_spawnFunction";
287 295
288 static List _spawnUri(String uri) native "Isolate_spawnUri"; 296 static SendPort _spawnUri(SendPort readyPort, String uri,
297 List<String> args, var message)
298 native "Isolate_spawnUri";
289 299
290 static void _sendOOB(port, msg) native "Isolate_sendOOB"; 300 static void _sendOOB(port, msg) native "Isolate_sendOOB";
291 301
292 /* patch */ void _pause(Capability resumeCapability) { 302 /* patch */ void _pause(Capability resumeCapability) {
293 var msg = new List(4) 303 var msg = new List(4)
294 ..[0] = 0 // Make room for OOM message type. 304 ..[0] = 0 // Make room for OOM message type.
295 ..[1] = _PAUSE 305 ..[1] = _PAUSE
296 ..[2] = pauseCapability 306 ..[2] = pauseCapability
297 ..[3] = resumeCapability; 307 ..[3] = resumeCapability;
298 _sendOOB(controlPort, msg); 308 _sendOOB(controlPort, msg);
(...skipping 29 matching lines...) Expand all
328 } 338 }
329 339
330 /* patch */ void addErrorListener(SendPort port) { 340 /* patch */ void addErrorListener(SendPort port) {
331 throw new UnsupportedError("addErrorListener"); 341 throw new UnsupportedError("addErrorListener");
332 } 342 }
333 343
334 /* patch */ void removeErrorListener(SendPort port) { 344 /* patch */ void removeErrorListener(SendPort port) {
335 throw new UnsupportedError("removeErrorListener"); 345 throw new UnsupportedError("removeErrorListener");
336 } 346 }
337 } 347 }
OLDNEW
« no previous file with comments | « runtime/lib/isolate.cc ('k') | runtime/vm/bootstrap_natives.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698