| Index: runtime/lib/isolate_patch.dart
|
| diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
|
| index 00b26e079357383ad958fd47f83c2eee0cf1448a..82e306fd007fcacce54c62f74235a8b67ecb0d7f 100644
|
| --- a/runtime/lib/isolate_patch.dart
|
| +++ b/runtime/lib/isolate_patch.dart
|
| @@ -77,6 +77,14 @@ void _isolateScheduleImmediate(void callback()) {
|
| _pendingImmediateCallback = callback;
|
| }
|
|
|
| +void _runPendingImmediateCallback() {
|
| + if (_pendingImmediateCallback != null) {
|
| + var callback = _pendingImmediateCallback;
|
| + _pendingImmediateCallback = null;
|
| + callback();
|
| + }
|
| +}
|
| +
|
| /// The embedder can execute this function to get hold of
|
| /// [_isolateScheduleImmediate] above.
|
| Function _getIsolateScheduleImmediateClosure() {
|
| @@ -120,11 +128,7 @@ class _RawReceivePortImpl implements RawReceivePort {
|
| // VM. Once we have non-fatal global exceptions we need to catch errors
|
| // so that we can run the immediate callbacks.
|
| handler(message);
|
| - if (_pendingImmediateCallback != null) {
|
| - var callback = _pendingImmediateCallback;
|
| - _pendingImmediateCallback = null;
|
| - callback();
|
| - }
|
| + _runPendingImmediateCallback();
|
| }
|
|
|
| // Call into the VM to close the VM maintained mappings.
|
| @@ -181,69 +185,71 @@ typedef _MainFunctionArgsMessage(args, message);
|
| *
|
| * The initial startup message is received through the control port.
|
| */
|
| -void _startIsolate(Function entryPoint, bool isSpawnUri) {
|
| - // This port keeps the isolate alive until the initial startup message has
|
| - // been received.
|
| - var keepAlivePort = new RawReceivePort();
|
| -
|
| - ignoreHandler(message) {
|
| - // Messages on the current Isolate's control port are dropped after the
|
| - // initial startup message has been received.
|
| +void _startIsolate(SendPort parentPort,
|
| + Function entryPoint,
|
| + List<String> args,
|
| + var message,
|
| + bool isSpawnUri,
|
| + RawReceivePort controlPort,
|
| + List capabilities) {
|
| + if (controlPort != null) {
|
| + controlPort.handler = (_) {}; // Nobody home on the control port.
|
| }
|
| + if (parentPort != null) {
|
| + // Build a message to our parent isolate providing access to the
|
| + // current isolate's control port and capabilities.
|
| + //
|
| + // TODO(floitsch): Send an error message if we can't find the entry point.
|
| + var readyMessage = new List(2);
|
| + readyMessage[0] = controlPort.sendPort;
|
| + readyMessage[1] = capabilities;
|
| +
|
| + // Out of an excess of paranoia we clear the capabilities from the
|
| + // stack. Not really necessary.
|
| + capabilities = null;
|
| + parentPort.send(readyMessage);
|
| + }
|
| + assert(capabilities == null);
|
|
|
| - isolateStartHandler(message) {
|
| - // We received the initial startup message. Ignore all further messages and
|
| - // close the port which kept this isolate alive.
|
| - Isolate._self.handler = ignoreHandler;
|
| - keepAlivePort.close();
|
| -
|
| - SendPort replyTo = message[0];
|
| - if (replyTo != null) {
|
| - // TODO(floitsch): don't send ok-message if we can't find the entry point.
|
| - replyTo.send("started");
|
| - }
|
| - if (isSpawnUri) {
|
| - assert(message.length == 3);
|
| - List<String> args = message[1];
|
| - var isolateMessage = message[2];
|
| - if (entryPoint is _MainFunctionArgsMessage) {
|
| - entryPoint(args, isolateMessage);
|
| - } else if (entryPoint is _MainFunctionArgs) {
|
| - entryPoint(args);
|
| - } else {
|
| - entryPoint();
|
| - }
|
| + if (isSpawnUri) {
|
| + if (entryPoint is _MainFunctionArgsMessage) {
|
| + entryPoint(args, message);
|
| + } else if (entryPoint is _MainFunctionArgs) {
|
| + entryPoint(args);
|
| } else {
|
| - assert(message.length == 2);
|
| - var entryMessage = message[1];
|
| - entryPoint(entryMessage);
|
| + entryPoint();
|
| }
|
| + } else {
|
| + entryPoint(message);
|
| }
|
| -
|
| - Isolate._self.handler = isolateStartHandler;
|
| + _runPendingImmediateCallback();
|
| }
|
|
|
| patch class Isolate {
|
| /* patch */ static Future<Isolate> spawn(
|
| void entryPoint(message), var message, { bool paused: false }) {
|
| // `paused` isn't handled yet.
|
| + RawReceivePort readyPort;
|
| try {
|
| // The VM will invoke [_startIsolate] with entryPoint as argument.
|
| - List spawnData = _spawnFunction(entryPoint);
|
| - assert(spawnData.length == 3);
|
| - SendPort controlPort = spawnData[0];
|
| - RawReceivePort readyPort = new RawReceivePort();
|
| - controlPort.send([readyPort.sendPort, message]);
|
| + readyPort = new RawReceivePort();
|
| + _spawnFunction(readyPort.sendPort, entryPoint, message);
|
| Completer completer = new Completer<Isolate>.sync();
|
| readyPort.handler = (readyMessage) {
|
| - assert(readyMessage == 'started');
|
| readyPort.close();
|
| + assert(readyMessage is List);
|
| + assert(readyMessage.length == 2);
|
| + SendPort controlPort = readyMessage[0];
|
| + List capabilities = readyMessage[1];
|
| completer.complete(new Isolate(controlPort,
|
| - pauseCapability: spawnData[1],
|
| - terminateCapability: spawnData[2]));
|
| + pauseCapability: capabilities[0],
|
| + terminateCapability: capabilities[1]));
|
| };
|
| return completer.future;
|
| } catch (e, st) {
|
| + if (readyPort != null) {
|
| + readyPort.close();
|
| + }
|
| return new Future<Isolate>.error(e, st);
|
| };
|
| }
|
| @@ -251,41 +257,45 @@ patch class Isolate {
|
| /* patch */ static Future<Isolate> spawnUri(
|
| Uri uri, List<String> args, var message, { bool paused: false }) {
|
| // `paused` isn't handled yet.
|
| + RawReceivePort readyPort;
|
| try {
|
| // The VM will invoke [_startIsolate] and not `main`.
|
| - List spawnData = _spawnUri(uri.toString());
|
| - assert(spawnData.length == 3);
|
| - SendPort controlPort = spawnData[0];
|
| - RawReceivePort readyPort = new RawReceivePort();
|
| - controlPort.send([readyPort.sendPort, args, message]);
|
| + readyPort = new RawReceivePort();
|
| + _spawnUri(readyPort.sendPort, uri.toString(), args, message);
|
| Completer completer = new Completer<Isolate>.sync();
|
| readyPort.handler = (readyMessage) {
|
| - assert(readyMessage == 'started');
|
| readyPort.close();
|
| + assert(readyMessage is List);
|
| + assert(readyMessage.length == 2);
|
| + SendPort controlPort = readyMessage[0];
|
| + List capabilities = readyMessage[1];
|
| completer.complete(new Isolate(controlPort,
|
| - pauseCapability: spawnData[1],
|
| - terminateCapability: spawnData[2]));
|
| + pauseCapability: capabilities[0],
|
| + terminateCapability: capabilities[1]));
|
| };
|
| return completer.future;
|
| } catch (e, st) {
|
| + if (readyPort != null) {
|
| + readyPort.close();
|
| + }
|
| return new Future<Isolate>.error(e, st);
|
| };
|
| return completer.future;
|
| }
|
|
|
| - static final RawReceivePort _self = _mainPort;
|
| - static RawReceivePort get _mainPort native "Isolate_mainPort";
|
| -
|
| // TODO(iposva): Cleanup to have only one definition.
|
| // These values need to be kept in sync with the class IsolateMessageHandler
|
| // in vm/isolate.cc.
|
| static const _PAUSE = 1;
|
| static const _RESUME = 2;
|
|
|
| - static List _spawnFunction(Function topLevelFunction)
|
| + static SendPort _spawnFunction(SendPort readyPort, Function topLevelFunction,
|
| + var message)
|
| native "Isolate_spawnFunction";
|
|
|
| - static List _spawnUri(String uri) native "Isolate_spawnUri";
|
| + static SendPort _spawnUri(SendPort readyPort, String uri,
|
| + List<String> args, var message)
|
| + native "Isolate_spawnUri";
|
|
|
| static void _sendOOB(port, msg) native "Isolate_sendOOB";
|
|
|
|
|