OLD | NEW |
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 /** | 5 /** |
6 * Concepts used here: | 6 * Concepts used here: |
7 * | 7 * |
8 * "manager" - A manager contains one or more isolates, schedules their | 8 * "manager" - A manager contains one or more isolates, schedules their |
9 * execution, and performs other plumbing on their behalf. The isolate | 9 * execution, and performs other plumbing on their behalf. The isolate |
10 * present at the creation of the manager is designated as its "root isolate". | 10 * present at the creation of the manager is designated as its "root isolate". |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 /** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ | 110 /** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ |
111 _ManagerStub mainManager; | 111 _ManagerStub mainManager; |
112 | 112 |
113 /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */ | 113 /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */ |
114 Map<int, _ManagerStub> managers; | 114 Map<int, _ManagerStub> managers; |
115 | 115 |
116 _Manager() { | 116 _Manager() { |
117 _nativeDetectEnvironment(); | 117 _nativeDetectEnvironment(); |
118 topEventLoop = new _EventLoop(); | 118 topEventLoop = new _EventLoop(); |
119 isolates = {}; | 119 isolates = new Map<int, _IsolateContext>(); |
120 managers = {}; | 120 managers = new Map<int, _ManagerStub>(); |
121 if (isWorker) { // "if we are not the main manager ourself" is the intent. | 121 if (isWorker) { // "if we are not the main manager ourself" is the intent. |
122 mainManager = new _MainManagerStub(); | 122 mainManager = new _MainManagerStub(); |
123 _nativeInitWorkerMessageHandler(); | 123 _nativeInitWorkerMessageHandler(); |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 void _nativeDetectEnvironment() native @""" | 127 void _nativeDetectEnvironment() native @""" |
128 this.isWorker = typeof ($globalThis['importScripts']) != 'undefined'; | 128 this.isWorker = typeof ($globalThis['importScripts']) != 'undefined'; |
129 this.fromCommandLine = typeof(window) == 'undefined'; | 129 this.fromCommandLine = typeof(window) == 'undefined'; |
130 this.supportsWorkers = this.isWorker || | 130 this.supportsWorkers = this.isWorker || |
(...skipping 22 matching lines...) Expand all Loading... |
153 int id; | 153 int id; |
154 | 154 |
155 /** Registry of receive ports currently active on this isolate. */ | 155 /** Registry of receive ports currently active on this isolate. */ |
156 Map<int, ReceivePort> ports; | 156 Map<int, ReceivePort> ports; |
157 | 157 |
158 /** Holds isolate globals (statics and top-level properties). */ | 158 /** Holds isolate globals (statics and top-level properties). */ |
159 var isolateStatics; // native object containing all globals of an isolate. | 159 var isolateStatics; // native object containing all globals of an isolate. |
160 | 160 |
161 _IsolateContext() { | 161 _IsolateContext() { |
162 id = _globalState.nextIsolateId++; | 162 id = _globalState.nextIsolateId++; |
163 ports = {}; | 163 ports = new Map<int, ReceivePort>(); |
164 initGlobals(); | 164 initGlobals(); |
165 } | 165 } |
166 | 166 |
167 // these are filled lazily the first time the isolate starts running. | 167 // these are filled lazily the first time the isolate starts running. |
168 void initGlobals() native @'$initGlobals(this);'; | 168 void initGlobals() native @'$initGlobals(this);'; |
169 | 169 |
170 /** | 170 /** |
171 * Run [code] in the context of the isolate represented by [this]. Note this | 171 * Run [code] in the context of the isolate represented by [this]. Note this |
172 * is called from JavaScript (see $wrap_call in corejs.dart). | 172 * is called from JavaScript (see $wrap_call in corejs.dart). |
173 */ | 173 */ |
174 void eval(Function code) { | 174 void eval(Function code) { |
175 var old = _globalState.currentContext; | 175 var old = _globalState.currentContext; |
176 _globalState.currentContext = this; | 176 _globalState.currentContext = this; |
177 this._setGlobals(); | 177 this._setGlobals(); |
178 var result = null; | 178 var result = null; |
179 try { | 179 try { |
180 result = code(); | 180 result = code(); |
181 } finally { | 181 } finally { |
182 _globalState.currentContext = old; | 182 _globalState.currentContext = old; |
183 if (old != null) old._setGlobals(); | 183 if (old != null) old._setGlobals(); |
184 } | 184 } |
185 return result; | 185 return result; |
186 } | 186 } |
187 | 187 |
188 void _setGlobals() native @'$setGlobals(this);'; | 188 void _setGlobals() native @'$setGlobals(this);'; |
189 | 189 |
190 /** Lookup a port registered for this isolate. */ | 190 /** Lookup a port registered for this isolate. */ |
191 ReceivePort lookup(int id) => ports[id]; | 191 ReceivePort lookup(int portId) => ports[portId]; |
192 | 192 |
193 /** Register a port on this isolate. */ | 193 /** Register a port on this isolate. */ |
194 void register(int portId, ReceivePort port) { | 194 void register(int portId, ReceivePort port) { |
195 if (ports.containsKey(portId)) { | 195 if (ports.containsKey(portId)) { |
196 throw new Exception("Registry: ports must be registered only once."); | 196 throw new Exception("Registry: ports must be registered only once."); |
197 } | 197 } |
198 ports[portId] = port; | 198 ports[portId] = port; |
199 _globalState.isolates[id] = this; // indicate this isolate is active | 199 _globalState.isolates[id] = this; // indicate this isolate is active |
200 } | 200 } |
201 | 201 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 void set id(int i); | 315 void set id(int i); |
316 void set onmessage(Function f); | 316 void set onmessage(Function f); |
317 void postMessage(msg); | 317 void postMessage(msg); |
318 void terminate(); | 318 void terminate(); |
319 } | 319 } |
320 | 320 |
321 /** A stub for interacting with the main manager. */ | 321 /** A stub for interacting with the main manager. */ |
322 class _MainManagerStub implements _ManagerStub { | 322 class _MainManagerStub implements _ManagerStub { |
323 get id() => 0; | 323 get id() => 0; |
324 void set id(int i) { throw new NotImplementedException(); } | 324 void set id(int i) { throw new NotImplementedException(); } |
| 325 void set onmessage(f) { |
| 326 throw new Exception("onmessage should not be set on MainManagerStub"); |
| 327 } |
325 void postMessage(msg) native @"$globalThis.postMessage(msg);"; | 328 void postMessage(msg) native @"$globalThis.postMessage(msg);"; |
326 void terminate() {} // Nothing useful to do here. | 329 void terminate() {} // Nothing useful to do here. |
327 } | 330 } |
328 | 331 |
329 /** | 332 /** |
330 * A stub for interacting with a manager built on a web worker. The type | 333 * A stub for interacting with a manager built on a web worker. The type |
331 * Worker is also defined in 'dart:dom', but we define it here to avoid | 334 * Worker is also defined in 'dart:dom', but we define it here to avoid |
332 * introducing a dependency from corelib to dom. This definition uses a | 335 * introducing a dependency from corelib to dom. This definition uses a |
333 * 'hidden' type (* prefix on the native name) to enforce that the type is | 336 * 'hidden' type (* prefix on the native name) to enforce that the type is |
334 * defined dynamically only when web workers are actually available. | 337 * defined dynamically only when web workers are actually available. |
335 */ | 338 */ |
336 class _WorkerStub implements _ManagerStub native "*Worker" { | 339 class _WorkerStub implements _ManagerStub native "*Worker" { |
337 get id() native "return this.id;"; | 340 get id() native "return this.id;"; |
338 void set id(i) native "this.id = i;"; | 341 void set id(i) native "this.id = i;"; |
339 void set onmessage(f) native "this.onmessage = f;"; | 342 void set onmessage(f) native "this.onmessage = f;"; |
340 void postMessage(msg) native "return this.postMessage(msg);"; | 343 void postMessage(msg) native "return this.postMessage(msg);"; |
341 // terminate() is implemented by Worker. | 344 // terminate() is implemented by Worker. |
| 345 abstract void terminate(); |
342 } | 346 } |
343 | 347 |
344 final String _SPAWNED_SIGNAL = "spawned"; | 348 final String _SPAWNED_SIGNAL = "spawned"; |
345 | 349 |
346 class _IsolateNatives { | 350 class _IsolateNatives { |
347 | 351 |
348 /** JavaScript-specific implementation to spawn an isolate. */ | 352 /** JavaScript-specific implementation to spawn an isolate. */ |
349 static Future<SendPort> spawn(Isolate isolate, bool isLight) { | 353 static Future<SendPort> spawn(Isolate isolate, bool isLight) { |
350 Completer<SendPort> completer = new Completer<SendPort>(); | 354 Completer<SendPort> completer = new Completer<SendPort>(); |
351 ReceivePort port = new ReceivePort(); | 355 ReceivePort port = new ReceivePort(); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 } | 505 } |
502 | 506 |
503 /** Log a message, forwarding to the main [_Manager] if appropriate. */ | 507 /** Log a message, forwarding to the main [_Manager] if appropriate. */ |
504 static _log(msg) { | 508 static _log(msg) { |
505 if (_globalState.isWorker) { | 509 if (_globalState.isWorker) { |
506 _globalState.mainManager.postMessage( | 510 _globalState.mainManager.postMessage( |
507 _serializeMessage({'command': 'log', 'msg': msg })); | 511 _serializeMessage({'command': 'log', 'msg': msg })); |
508 } else { | 512 } else { |
509 try { | 513 try { |
510 _consoleLog(msg); | 514 _consoleLog(msg); |
511 } catch(e, trace) { | 515 } catch(var e, var trace) { |
512 throw new Exception(trace); | 516 throw new Exception(trace); |
513 } | 517 } |
514 } | 518 } |
515 } | 519 } |
516 | 520 |
517 static void _consoleLog(msg) native "\$globalThis.console.log(msg);"; | 521 static void _consoleLog(msg) native "\$globalThis.console.log(msg);"; |
518 | 522 |
519 | 523 |
520 /** | 524 /** |
521 * Extract the constructor of runnable, so it can be allocated in another | 525 * Extract the constructor of runnable, so it can be allocated in another |
522 * isolate. | 526 * isolate. |
523 */ | 527 */ |
524 static var _getJSConstructor(Isolate runnable) native """ | 528 static Dynamic _getJSConstructor(Isolate runnable) native """ |
525 return runnable.constructor; | 529 return runnable.constructor; |
526 """; | 530 """; |
527 | 531 |
528 /** Extract the constructor name of a runnable */ | 532 /** Extract the constructor name of a runnable */ |
529 // TODO(sigmund): find a browser-generic way to support this. | 533 // TODO(sigmund): find a browser-generic way to support this. |
530 static var _getJSConstructorName(Isolate runnable) native """ | 534 static Dynamic _getJSConstructorName(Isolate runnable) native """ |
531 return runnable.constructor.name; | 535 return runnable.constructor.name; |
532 """; | 536 """; |
533 | 537 |
534 /** Find a constructor given its name. */ | 538 /** Find a constructor given its name. */ |
535 static var _getJSConstructorFromName(String factoryName) native """ | 539 static Dynamic _getJSConstructorFromName(String factoryName) native """ |
536 return \$globalThis[factoryName]; | 540 return \$globalThis[factoryName]; |
537 """; | 541 """; |
538 | 542 |
539 static var _getJSFunctionFromName(String functionName) native """ | 543 static Dynamic _getJSFunctionFromName(String functionName) native """ |
540 return \$globalThis[functionName]; | 544 return \$globalThis[functionName]; |
541 """; | 545 """; |
542 | 546 |
543 /** | 547 /** |
544 * Get a string name for the function, if possible. The result for | 548 * Get a string name for the function, if possible. The result for |
545 * anonymous functions is browser-dependent -- it may be "" or "anonymous" | 549 * anonymous functions is browser-dependent -- it may be "" or "anonymous" |
546 * but you should probably not count on this. | 550 * but you should probably not count on this. |
547 */ | 551 */ |
548 static String _getJSFunctionName(Function f) | 552 static String _getJSFunctionName(Function f) |
549 // Comments on the code, outside of the string so they won't bulk up | 553 // Comments on the code, outside of the string so they won't bulk up |
(...skipping 13 matching lines...) Expand all Loading... |
563 // in discussion on the CL, 9416119. | 567 // in discussion on the CL, 9416119. |
564 native @""" | 568 native @""" |
565 if (typeof(f.name) === 'undefined') { | 569 if (typeof(f.name) === 'undefined') { |
566 return (f.toString().match(/function (.+)\(/) || [, (void 0)])[1]; | 570 return (f.toString().match(/function (.+)\(/) || [, (void 0)])[1]; |
567 } else { | 571 } else { |
568 return f.name || (void 0); | 572 return f.name || (void 0); |
569 } | 573 } |
570 """; | 574 """; |
571 | 575 |
572 /** Create a new JavaScript object instance given its constructor. */ | 576 /** Create a new JavaScript object instance given its constructor. */ |
573 static var _allocate(var ctor) native "return new ctor();"; | 577 static Dynamic _allocate(var ctor) native "return new ctor();"; |
574 | 578 |
575 /** Starts a non-worker isolate. */ | 579 /** Starts a non-worker isolate. */ |
576 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) { | 580 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) { |
577 // Spawn a new isolate and create the receive port in it. | 581 // Spawn a new isolate and create the receive port in it. |
578 final spawned = new _IsolateContext(); | 582 final spawned = new _IsolateContext(); |
579 | 583 |
580 // Instead of just running the provided runnable, we create a | 584 // Instead of just running the provided runnable, we create a |
581 // new cloned instance of it with a fresh state in the spawned | 585 // new cloned instance of it with a fresh state in the spawned |
582 // isolate. This way, we do not get cross-isolate references | 586 // isolate. This way, we do not get cross-isolate references |
583 // through the runnable. | 587 // through the runnable. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 'command': 'start2', | 675 'command': 'start2', |
672 'id': workerId, | 676 'id': workerId, |
673 // Note: we serialize replyPort twice because the child worker needs to | 677 // Note: we serialize replyPort twice because the child worker needs to |
674 // first deserialize the worker id, before it can correctly deserialize | 678 // first deserialize the worker id, before it can correctly deserialize |
675 // the port (port deserialization is sensitive to what is the current | 679 // the port (port deserialization is sensitive to what is the current |
676 // workerId). | 680 // workerId). |
677 'replyTo': _serializeMessage(replyPort), | 681 'replyTo': _serializeMessage(replyPort), |
678 'functionName': functionName })); | 682 'functionName': functionName })); |
679 } | 683 } |
680 } | 684 } |
OLD | NEW |