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

Side by Side Diff: frog/lib/isolate.dart

Issue 8591033: Support globals in frog isolates. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: john comments Created 9 years, 1 month 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 | « frog/gen.dart ('k') | frog/member.dart » ('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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** 5 /**
6 * A native object that is shared across isolates. This object is visible to all 6 * A native object that is shared across isolates. This object is visible to all
7 * isolates running on the same worker (either UI or background web worker). 7 * isolates running on the same worker (either UI or background web worker).
8 * 8 *
9 * This is code that is intended to 'escape' the isolate boundaries in order to 9 * This is code that is intended to 'escape' the isolate boundaries in order to
10 * implement the semantics of friendly isolates in JavaScript. Without this we 10 * implement the semantics of friendly isolates in JavaScript. Without this we
11 * would have been forced to implement more code (including the top-level event 11 * would have been forced to implement more code (including the top-level event
12 * loop) in JavaScript itself. 12 * loop) in JavaScript itself.
13 */ 13 */
14 GlobalState get _globalState() native "return \$globalState;"; 14 GlobalState get _globalState() native "return \$globalState;";
15 set _globalState(GlobalState val) native "\$globalState = val;"; 15 set _globalState(GlobalState val) native "\$globalState = val;";
16 16
17 /** 17 /**
18 * Wrapper that takes the dart entry point and runs it within an isolate. The 18 * Wrapper that takes the dart entry point and runs it within an isolate. The
19 * frog compiler will inject a call of the form [: startAsIsolate(main); :] when 19 * frog compiler will inject a call of the form [: startRootIsolate(main); :]
20 * it determines that this wrapping is needed. For single-isolate applications 20 * when it determines that this wrapping is needed. For single-isolate
21 * (e.g. hello world), this call is not emited. 21 * applications (e.g. hello world), this call is not emitted.
22 */ 22 */
23 void startAsIsolate(entry) { 23 void startRootIsolate(entry) {
24 _globalState = new GlobalState(); 24 _globalState = new GlobalState();
25 25
26 // Don't start the main loop again, if we are in a worker. 26 // Don't start the main loop again, if we are in a worker.
27 if (_globalState.inWorker) return; 27 if (_globalState.isWorker) return;
28 final entryIsolate = new IsolateContext(); 28 final rootContext = new IsolateContext();
29 _globalState.rootIsolate = entryIsolate; 29 _globalState.rootContext = rootContext;
30 _fillStatics(rootContext);
30 31
31 // BUG(5151491): Setting _thisISolate should not be necessary, but because 32 // BUG(5151491): Setting currentContext should not be necessary, but
32 // closures passed to the DOM as event handlers do not bind their isolate 33 // because closures passed to the DOM as event handlers do not bind their
33 // automatically we try to give them a reasonable context to live in by having 34 // isolate automatically we try to give them a reasonable context to live in
34 // a "default" isolate (the first one created). 35 // by having a "default" isolate (the first one created).
35 _globalState.currentIsolate = entryIsolate; 36 _globalState.currentContext = rootContext;
36 37
37 entryIsolate.eval(entry); 38 rootContext.eval(entry);
38 _globalState.topEventLoop.run(); 39 _globalState.topEventLoop.run();
39 } 40 }
40 41
42 void _fillStatics(context) native @"""
43 $globals = context.isolateStatics;
44 $static_init();
45 """;
46
41 /** Global state associated with the current worker. See [_globalState]. */ 47 /** Global state associated with the current worker. See [_globalState]. */
48 // TODO(sigmund): split in multiple classes: global, thread, main-worker states?
42 class GlobalState { 49 class GlobalState {
43 50
44 /** Next available isolate id. */ 51 /** Next available isolate id. */
45 int nextIsolateId = 0; 52 int nextIsolateId = 0;
46 53
47 /** Worker id associated with this worker. */ 54 /** Worker id associated with this worker. */
48 int currentWorkerId = 0; 55 int currentWorkerId = 0;
49 56
50 /** 57 /**
51 * Next available worker id. Only used by the main worker to assign a unique 58 * Next available worker id. Only used by the main worker to assign a unique
52 * id to each worker created by it. 59 * id to each worker created by it.
53 */ 60 */
54 int nextWorkerId = 1; 61 int nextWorkerId = 1;
55 62
56 /** Context for the currently running [Isolate]. */ 63 /** Context for the currently running [Isolate]. */
57 IsolateContext currentIsolate = null; 64 IsolateContext currentContext = null;
58 65
59 /** Context for the root [Isolate] that first run in this worker. */ 66 /** Context for the root [Isolate] that first run in this worker. */
60 IsolateContext rootIsolate = null; 67 IsolateContext rootContext = null;
61 68
62 /** The top-level event loop. */ 69 /** The top-level event loop. */
63 EventLoop topEventLoop; 70 EventLoop topEventLoop;
64 71
65 /** Whether this program is running in a background worker. */ 72 /** Whether this program is running in a background worker. */
66 bool inWorker; 73 bool isWorker;
67 74
68 /** Whether this program is running in a UI worker. */ 75 /** Whether this program is running in a UI worker. */
69 bool inWindow; 76 bool inWindow;
70 77
71 /** Whether we support spawning workers. */ 78 /** Whether we support spawning workers. */
72 bool supportsWorkers; 79 bool supportsWorkers;
73 80
74 /** 81 /**
75 * Whether to use web workers when implementing isolates. Set to false for 82 * Whether to use web workers when implementing isolates. Set to false for
76 * debugging/testing. 83 * debugging/testing.
77 */ 84 */
78 bool get useWorkers() => supportsWorkers; 85 bool get useWorkers() => supportsWorkers;
79 86
80 /** 87 /**
81 * Whether to use the web-worker JSON-based message serialization protocol, 88 * Whether to use the web-worker JSON-based message serialization protocol. By
82 * even if not using web workers. Set to true to always use the web-worker 89 * default this is only used with web workers. For debugging, you can force
83 * JSON-based message serialization protocol, e.g. for testing purposes. 90 * using this protocol by changing this field value to [true].
84 */ 91 */
85 bool get useWorkerSerializationProtocol() => useWorkers; 92 bool get needSerialization() => useWorkers;
86 93
87 /** 94 /**
88 * Registry of isolates. Isolates must be registered if, and only if, receive 95 * Registry of isolates. Isolates must be registered if, and only if, receive
89 * ports are alive. Normally no open receive-ports means that the isolate is 96 * ports are alive. Normally no open receive-ports means that the isolate is
90 * dead, but DOM callbacks could resurrect it. 97 * dead, but DOM callbacks could resurrect it.
91 */ 98 */
92 Map<int, IsolateContext> isolates; 99 Map<int, IsolateContext> isolates;
93 100
94 /** Reference to the main worker. */ 101 /** Reference to the main worker. */
95 MainWorker mainWorker; 102 MainWorker mainWorker;
96 103
97 /** Registry of active workers. Only used in the main worker. */ 104 /** Registry of active workers. Only used in the main worker. */
98 Map<int, var> workers; 105 Map<int, var> workers;
99 106
100 GlobalState() { 107 GlobalState() {
101 topEventLoop = new EventLoop(); 108 topEventLoop = new EventLoop();
102 isolates = {}; 109 isolates = {};
103 workers = {}; 110 workers = {};
104 mainWorker = new MainWorker(); 111 mainWorker = new MainWorker();
105 _nativeInit(); 112 _nativeInit();
106 } 113 }
107 114
108 void _nativeInit() native @""" 115 void _nativeInit() native @"""
109 this.inWorker = typeof ($globalThis['importScripts']) != 'undefined'; 116 this.isWorker = typeof ($globalThis['importScripts']) != 'undefined';
110 this.inWindow = typeof(window) !== 'undefined'; 117 this.inWindow = typeof(window) !== 'undefined';
111 this.supportsWorkers = this.inWorker || 118 this.supportsWorkers = this.isWorker ||
112 ((typeof $globalThis['Worker']) != 'undefined'); 119 ((typeof $globalThis['Worker']) != 'undefined');
113 120
114 // if workers are supported, treat this as a main worker: 121 // if workers are supported, treat this as a main worker:
115 if (this.supportsWorkers) { 122 if (this.supportsWorkers) {
116 $globalThis.onmessage = function(e) { 123 $globalThis.onmessage = function(e) {
117 IsolateNatives._processWorkerMessage(this.mainWorker, e); 124 IsolateNatives._processWorkerMessage(this.mainWorker, e);
118 }; 125 };
119 } 126 }
120 """; 127 """;
121 128
122 /** 129 /**
123 * Close the worker running this code, called when there is nothing else to 130 * Close the worker running this code, called when there is nothing else to
124 * run. 131 * run.
125 */ 132 */
126 void closeWorker() { 133 void closeWorker() {
127 if (inWorker) { 134 if (isWorker) {
128 if (!isolates.isEmpty()) return; 135 if (!isolates.isEmpty()) return;
129 mainWorker.postMessage( 136 mainWorker.postMessage(
130 _serializeMessage({'command': 'close'})); 137 _serializeMessage({'command': 'close'}));
131 } else if (isolates.containsKey(rootIsolate.id) && workers.isEmpty() && 138 } else if (isolates.containsKey(rootContext.id) && workers.isEmpty() &&
132 !supportsWorkers && !inWindow) { 139 !supportsWorkers && !inWindow) {
133 // This should only trigger when running on the command-line. 140 // This should only trigger when running on the command-line.
134 // We don't want this check to execute in the browser where the isolate 141 // We don't want this check to execute in the browser where the isolate
135 // might still be alive due to DOM callbacks. 142 // might still be alive due to DOM callbacks.
136 throw new Exception("Program exited with open ReceivePorts."); 143 throw new Exception("Program exited with open ReceivePorts.");
137 } 144 }
138 } 145 }
139 } 146 }
140 147
141 _serializeMessage(message) { 148 _serializeMessage(message) {
142 if (_globalState.useWorkerSerializationProtocol) { 149 if (_globalState.needSerialization) {
143 return new Serializer().traverse(message); 150 return new Serializer().traverse(message);
144 } else { 151 } else {
145 return new Copier().traverse(message); 152 return new Copier().traverse(message);
146 } 153 }
147 } 154 }
148 155
149 _deserializeMessage(message) { 156 _deserializeMessage(message) {
150 if (_globalState.useWorkerSerializationProtocol) { 157 if (_globalState.needSerialization) {
151 return new Deserializer().deserialize(message); 158 return new Deserializer().deserialize(message);
152 } else { 159 } else {
153 // Nothing more to do. 160 // Nothing more to do.
154 return message; 161 return message;
155 } 162 }
156 } 163 }
157 164
158 /** Default worker. */ 165 /** Default worker. */
159 class MainWorker { 166 class MainWorker {
160 int id = 0; 167 int id = 0;
(...skipping 10 matching lines...) Expand all
171 178
172 /** Holds isolate globals (statics and top-level properties). */ 179 /** Holds isolate globals (statics and top-level properties). */
173 var isolateStatics; // native object containing all globals of an isolate. 180 var isolateStatics; // native object containing all globals of an isolate.
174 181
175 IsolateContext() { 182 IsolateContext() {
176 id = _globalState.nextIsolateId++; 183 id = _globalState.nextIsolateId++;
177 ports = {}; 184 ports = {};
178 initGlobals(); 185 initGlobals();
179 } 186 }
180 187
181 // TODO(sigmund): actually do the initialization too. 188 // these are filled lazily the first time the isolate starts running.
182 void initGlobals() native "this.isolateStatics = {};"; 189 void initGlobals() native 'this.isolateStatics = {};';
183 190
184 /** 191 /**
185 * Run [code] in the context of the isolate represented by [this]. Note this 192 * Run [code] in the context of the isolate represented by [this]. Note this
186 * is marked as native because it is called from JavaScript (see $wrap_call in 193 * is marked as native because it is called from JavaScript (see $wrap_call in
187 * corejs.dart). 194 * corejs.dart).
188 */ 195 */
189 void eval(Function code) native { 196 void eval(Function code) native {
190 var old = _globalState.currentIsolate; 197 var old = _globalState.currentContext;
191 _globalState.currentIsolate = this; 198 _globalState.currentContext = this;
199 this._setGlobals();
192 var result = null; 200 var result = null;
193 try { 201 try {
194 result = code(); 202 result = code();
195 } finally { 203 } finally {
196 _globalState.currentIsolate = old; 204 _globalState.currentContext = old;
205 old._setGlobals();
197 } 206 }
198 return result; 207 return result;
199 } 208 }
200 209
210 void _setGlobals() native @'$globals = this.isolateStatics;';
211
201 /** Lookup a port registered for this isolate. */ 212 /** Lookup a port registered for this isolate. */
202 ReceivePort lookup(int id) => ports[id]; 213 ReceivePort lookup(int id) => ports[id];
203 214
204 /** Register a port on this isolate. */ 215 /** Register a port on this isolate. */
205 void register(int portId, ReceivePort port) { 216 void register(int portId, ReceivePort port) {
206 if (ports.containsKey(portId)) { 217 if (ports.containsKey(portId)) {
207 throw new Exception("Registry: ports must be registered only once."); 218 throw new Exception("Registry: ports must be registered only once.");
208 } 219 }
209 ports[portId] = port; 220 ports[portId] = port;
210 _globalState.isolates[id] = this; // indicate this isolate is active 221 _globalState.isolates[id] = this; // indicate this isolate is active
(...skipping 28 matching lines...) Expand all
239 final event = dequeue(); 250 final event = dequeue();
240 if (event == null) { 251 if (event == null) {
241 _globalState.closeWorker(); 252 _globalState.closeWorker();
242 return false; 253 return false;
243 } 254 }
244 event.process(); 255 event.process();
245 return true; 256 return true;
246 } 257 }
247 258
248 /** Function equivalent to [:window.setTimeout:] when available, or null. */ 259 /** Function equivalent to [:window.setTimeout:] when available, or null. */
249 static Function _platformDefer() native """ 260 static Function _wrapSetTimeout() native """
250 return typeof window != 'undefined' ? 261 return typeof window != 'undefined' ?
251 function(a, b) { window.setTimeout(a, b); } : undefined; 262 function(a, b) { window.setTimeout(a, b); } : undefined;
252 """; 263 """;
253 264
254 /** 265 /**
255 * Runs multiple iterations of the run-loop. If possible, each iteration is 266 * Runs multiple iterations of the run-loop. If possible, each iteration is
256 * run asynchronously. 267 * run asynchronously.
257 */ 268 */
258 void _runHelper() { 269 void _runHelper() {
259 final setTimeout = _platformDefer(); 270 final setTimeout = _wrapSetTimeout();
260 if (setTimeout != null) { 271 if (setTimeout != null) {
261 // Run each iteration from the browser's top event loop. 272 // Run each iteration from the browser's top event loop.
262 void next() { 273 void next() {
263 if (!runIteration()) return; 274 if (!runIteration()) return;
264 setTimeout(next, 0); 275 setTimeout(next, 0);
265 } 276 }
266 next(); 277 next();
267 } else { 278 } else {
268 // Run synchronously until no more iterations are available. 279 // Run synchronously until no more iterations are available.
269 while (runIteration()) {} 280 while (runIteration()) {}
270 } 281 }
271 } 282 }
272 283
273 /** 284 /**
274 * Call [_runHelper] but ensure that worker exceptions are propragated. Note 285 * Call [_runHelper] but ensure that worker exceptions are propragated. Note
275 * this is marked as native because it is called from JavaScript (see 286 * this is marked as native because it is called from JavaScript (see
276 * $wrap_call in corejs.dart). 287 * $wrap_call in corejs.dart).
277 */ 288 */
278 void run() native { 289 void run() native {
279 if (!_globalState.inWorker) { 290 if (!_globalState.isWorker) {
280 _runHelper(); 291 _runHelper();
281 } else { 292 } else {
282 try { 293 try {
283 _runHelper(); 294 _runHelper();
284 } catch(e) { 295 } catch(e) {
285 // TODO(floitsch): try to send stack-trace to the other side. 296 // TODO(floitsch): try to send stack-trace to the other side.
286 _globalState.mainWorker.postMessage(_serializeMessage( 297 _globalState.mainWorker.postMessage(_serializeMessage(
287 {'command': 'error', 'msg': "" + e })); 298 {'command': 'error', 'msg': "" + e }));
288 } 299 }
289 } 300 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 367
357 factory ReceivePort.singleShot() { 368 factory ReceivePort.singleShot() {
358 return new ReceivePortSingleShotImpl(); 369 return new ReceivePortSingleShotImpl();
359 } 370 }
360 } 371 }
361 372
362 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */ 373 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
363 class ReceivePortImpl implements ReceivePort { 374 class ReceivePortImpl implements ReceivePort {
364 ReceivePortImpl() 375 ReceivePortImpl()
365 : _id = _nextFreeId++ { 376 : _id = _nextFreeId++ {
366 _globalState.currentIsolate.register(_id, this); 377 _globalState.currentContext.register(_id, this);
367 } 378 }
368 379
369 void receive(void onMessage(var message, SendPort replyTo)) { 380 void receive(void onMessage(var message, SendPort replyTo)) {
370 _callback = onMessage; 381 _callback = onMessage;
371 } 382 }
372 383
373 void close() { 384 void close() {
374 _callback = null; 385 _callback = null;
375 _globalState.currentIsolate.unregister(_id); 386 _globalState.currentContext.unregister(_id);
376 } 387 }
377 388
378 /** 389 /**
379 * Returns a fresh [SendPort]. The implementation is not allowed to cache 390 * Returns a fresh [SendPort]. The implementation is not allowed to cache
380 * existing ports. 391 * existing ports.
381 */ 392 */
382 SendPort toSendPort() { 393 SendPort toSendPort() {
383 return new SendPortImpl( 394 return new SendPortImpl(
384 _globalState.currentWorkerId, _globalState.currentIsolate.id, _id); 395 _globalState.currentWorkerId, _globalState.currentContext.id, _id);
385 } 396 }
386 397
387 int _id; 398 int _id;
388 Function _callback; 399 Function _callback;
389 400
390 static int _nextFreeId = 1; 401 static int _nextFreeId = 1;
391 } 402 }
392 403
393 /** Implementation of a single-shot [ReceivePort]. */ 404 /** Implementation of a single-shot [ReceivePort]. */
394 class ReceivePortSingleShotImpl implements ReceivePort { 405 class ReceivePortSingleShotImpl implements ReceivePort {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 _startWorker(isolate, port.toSendPort()); 441 _startWorker(isolate, port.toSendPort());
431 } else { 442 } else {
432 _startNonWorker(isolate, port.toSendPort()); 443 _startNonWorker(isolate, port.toSendPort());
433 } 444 }
434 445
435 return completer.future; 446 return completer.future;
436 } 447 }
437 448
438 static SendPort _startWorker(Isolate runnable, SendPort replyPort) { 449 static SendPort _startWorker(Isolate runnable, SendPort replyPort) {
439 var factoryName = _getJSConstructorName(runnable); 450 var factoryName = _getJSConstructorName(runnable);
440 if (_globalState.inWorker) { 451 if (_globalState.isWorker) {
441 _globalState.mainWorker.postMessage(_serializeMessage({ 452 _globalState.mainWorker.postMessage(_serializeMessage({
442 'command': 'spawn-worker', 453 'command': 'spawn-worker',
443 'factoryName': factoryName, 454 'factoryName': factoryName,
444 'replyPort': replyPort})); 455 'replyPort': replyPort}));
445 } else { 456 } else {
446 _spawnWorker(factoryName, _serializeMessage(replyPort)); 457 _spawnWorker(factoryName, _serializeMessage(replyPort));
447 } 458 }
448 } 459 }
449 460
450 461
451 /** 462 /**
452 * The src url for the script tag that loaded this code. Used to create 463 * The src url for the script tag that loaded this code. Used to create
453 * JavaScript workers. 464 * JavaScript workers.
454 */ 465 */
455 static String get _thisScript() => 466 static String get _thisScript() =>
456 _thisScriptCache != null ? _thisScriptCache : _computeThisScript(); 467 _thisScriptCache != null ? _thisScriptCache : _computeThisScript();
457 468
458 static String _thisScriptCache; 469 static String _thisScriptCache;
459 470
460 // TODO(sigmund): fix - this code should be run synchronously when loading the 471 // TODO(sigmund): fix - this code should be run synchronously when loading the
461 // script. Running lazily on DOMContentLoaded will yield incorrect results. 472 // script. Running lazily on DOMContentLoaded will yield incorrect results.
462 static String _computeThisScript() native @""" 473 static String _computeThisScript() native @"""
463 if (!$globalState.supportsWorkers || $globalState.inWorker) return null; 474 if (!$globalState.supportsWorkers || $globalState.isWorker) return null;
464 475
465 // TODO(5334778): Find a cross-platform non-brittle way of getting the 476 // TODO(5334778): Find a cross-platform non-brittle way of getting the
466 // currently running script. 477 // currently running script.
467 var scripts = document.getElementsByTagName('script'); 478 var scripts = document.getElementsByTagName('script');
468 // The scripts variable only contains the scripts that have already been 479 // The scripts variable only contains the scripts that have already been
469 // executed. The last one is the currently running script. 480 // executed. The last one is the currently running script.
470 var script = scripts[scripts.length - 1]; 481 var script = scripts[scripts.length - 1];
471 var src = script.src; 482 var src = script && script.src;
472 if (!src) { 483 if (!src) {
473 // TODO() 484 // TODO()
474 src = "FIXME:5407062" + "_" + Math.random().toString(); 485 src = "FIXME:5407062" + "_" + Math.random().toString();
475 script.src = src; 486 if (script) script.src = src;
476 } 487 }
477 IsolateNatives._thisScriptCache = src; 488 IsolateNatives._thisScriptCache = src;
478 return src; 489 return src;
479 """; 490 """;
480 491
481 /** Starts a new worker with the given URL. */ 492 /** Starts a new worker with the given URL. */
482 static void _newWorker(url) native "return new Worker(url)"; 493 static void _newWorker(url) native "return new Worker(url)";
483 494
484 /** 495 /**
485 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor 496 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 case 'close': 543 case 'close':
533 _log("Closing Worker"); 544 _log("Closing Worker");
534 _globalState.workers.remove(sender.id); 545 _globalState.workers.remove(sender.id);
535 sender.terminate(); 546 sender.terminate();
536 _globalState.topEventLoop.run(); 547 _globalState.topEventLoop.run();
537 break; 548 break;
538 case 'log': 549 case 'log':
539 _log(msg['msg']); 550 _log(msg['msg']);
540 break; 551 break;
541 case 'print': 552 case 'print':
542 if (_globalState.inWorker) { 553 if (_globalState.isWorker) {
543 _globalState.mainWorker.postMessage( 554 _globalState.mainWorker.postMessage(
544 _serializeMessage({'command': 'print', 'msg': msg})); 555 _serializeMessage({'command': 'print', 'msg': msg}));
545 } else { 556 } else {
546 print(msg['msg']); 557 print(msg['msg']);
547 } 558 }
548 break; 559 break;
549 case 'error': 560 case 'error':
550 throw msg['msg']; 561 throw msg['msg'];
551 break; 562 break;
552 } 563 }
553 } 564 }
554 565
555 /** Log a message, forwarding to the main worker if appropriate. */ 566 /** Log a message, forwarding to the main worker if appropriate. */
556 static _log(msg) { 567 static _log(msg) {
557 if (_globalState.inWorker) { 568 if (_globalState.isWorker) {
558 _globalState.mainWorker.postMessage( 569 _globalState.mainWorker.postMessage(
559 _serializeMessage({'command': 'log', 'msg': msg })); 570 _serializeMessage({'command': 'log', 'msg': msg }));
560 } else { 571 } else {
561 try { 572 try {
562 _consoleLog(msg); 573 _consoleLog(msg);
563 } catch(e, trace) { 574 } catch(e, trace) {
564 throw new Exception(trace); 575 throw new Exception(trace);
565 } 576 }
566 } 577 }
567 } 578 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 // isolate. This way, we do not get cross-isolate references 612 // isolate. This way, we do not get cross-isolate references
602 // through the runnable. 613 // through the runnable.
603 final ctor = _getJSConstructor(runnable); 614 final ctor = _getJSConstructor(runnable);
604 _globalState.topEventLoop.enqueue(spawned, function() { 615 _globalState.topEventLoop.enqueue(spawned, function() {
605 _startIsolate(_allocate(ctor), replyTo); 616 _startIsolate(_allocate(ctor), replyTo);
606 }, 'nonworker start'); 617 }, 'nonworker start');
607 } 618 }
608 619
609 /** Given a ready-to-start runnable, start running it. */ 620 /** Given a ready-to-start runnable, start running it. */
610 static void _startIsolate(Isolate isolate, SendPort replyTo) { 621 static void _startIsolate(Isolate isolate, SendPort replyTo) {
622 _fillStatics(_globalState.currentContext);
611 ReceivePort port = new ReceivePort(); 623 ReceivePort port = new ReceivePort();
612 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); 624 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
613 isolate._run(port); 625 isolate._run(port);
614 } 626 }
615 627
616 static void _sendMessage(int workerId, int isolateId, int receivePortId, 628 static void _sendMessage(int workerId, int isolateId, int receivePortId,
617 message, replyTo) { 629 message, replyTo) {
618 // Both the message and the replyTo are already serialized. 630 // Both the message and the replyTo are already serialized.
619 if (workerId == _globalState.currentWorkerId) { 631 if (workerId == _globalState.currentWorkerId) {
620 var isolate = _globalState.isolates[isolateId]; 632 var isolate = _globalState.isolates[isolateId];
621 if (isolate == null) return; // Isolate has been closed. 633 if (isolate == null) return; // Isolate has been closed.
622 var receivePort = isolate.lookup(receivePortId); 634 var receivePort = isolate.lookup(receivePortId);
623 if (receivePort == null) return; // ReceivePort has been closed. 635 if (receivePort == null) return; // ReceivePort has been closed.
624 _globalState.topEventLoop.enqueue(isolate, () { 636 _globalState.topEventLoop.enqueue(isolate, () {
625 if (receivePort._callback != null) { 637 if (receivePort._callback != null) {
626 receivePort._callback( 638 receivePort._callback(
627 _deserializeMessage(message), _deserializeMessage(replyTo)); 639 _deserializeMessage(message), _deserializeMessage(replyTo));
628 } 640 }
629 }, 'receive ' + message); 641 }, 'receive ' + message);
630 } else { 642 } else {
631 var worker; 643 var worker;
632 // communication between workers go through the main worker 644 // communication between workers go through the main worker
633 if (_globalState.inWorker) { 645 if (_globalState.isWorker) {
634 worker = _globalState.mainWorker; 646 worker = _globalState.mainWorker;
635 } else { 647 } else {
636 // TODO(sigmund): make sure this works 648 // TODO(sigmund): make sure this works
637 worker = _globalState.workers[workerId]; 649 worker = _globalState.workers[workerId];
638 } 650 }
639 worker.postMessage(_serializeMessage({ 651 worker.postMessage(_serializeMessage({
640 'command': 'message', 652 'command': 'message',
641 'workerId': workerId, 653 'workerId': workerId,
642 'isolateId': isolateId, 654 'isolateId': isolateId,
643 'portId': receivePortId, 655 'portId': receivePortId,
644 'msg': message, 656 'msg': message,
645 'replyTo': replyTo })); 657 'replyTo': replyTo }));
646 } 658 }
647 } 659 }
648 } 660 }
OLDNEW
« no previous file with comments | « frog/gen.dart ('k') | frog/member.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698