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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/gen.dart ('k') | frog/member.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/lib/isolate.dart
diff --git a/frog/lib/isolate.dart b/frog/lib/isolate.dart
index 2695cbc1fd037a3f8b1baee3ec72ddac34135523..b3465f0edf9e1c1472307cbc50d79a7a4305d776 100644
--- a/frog/lib/isolate.dart
+++ b/frog/lib/isolate.dart
@@ -16,29 +16,36 @@ set _globalState(GlobalState val) native "\$globalState = val;";
/**
* Wrapper that takes the dart entry point and runs it within an isolate. The
- * frog compiler will inject a call of the form [: startAsIsolate(main); :] when
- * it determines that this wrapping is needed. For single-isolate applications
- * (e.g. hello world), this call is not emited.
+ * frog compiler will inject a call of the form [: startRootIsolate(main); :]
+ * when it determines that this wrapping is needed. For single-isolate
+ * applications (e.g. hello world), this call is not emitted.
*/
-void startAsIsolate(entry) {
+void startRootIsolate(entry) {
_globalState = new GlobalState();
// Don't start the main loop again, if we are in a worker.
- if (_globalState.inWorker) return;
- final entryIsolate = new IsolateContext();
- _globalState.rootIsolate = entryIsolate;
-
- // BUG(5151491): Setting _thisISolate should not be necessary, but because
- // closures passed to the DOM as event handlers do not bind their isolate
- // automatically we try to give them a reasonable context to live in by having
- // a "default" isolate (the first one created).
- _globalState.currentIsolate = entryIsolate;
-
- entryIsolate.eval(entry);
+ if (_globalState.isWorker) return;
+ final rootContext = new IsolateContext();
+ _globalState.rootContext = rootContext;
+ _fillStatics(rootContext);
+
+ // BUG(5151491): Setting currentContext should not be necessary, but
+ // because closures passed to the DOM as event handlers do not bind their
+ // isolate automatically we try to give them a reasonable context to live in
+ // by having a "default" isolate (the first one created).
+ _globalState.currentContext = rootContext;
+
+ rootContext.eval(entry);
_globalState.topEventLoop.run();
}
+void _fillStatics(context) native @"""
+ $globals = context.isolateStatics;
+ $static_init();
+""";
+
/** Global state associated with the current worker. See [_globalState]. */
+// TODO(sigmund): split in multiple classes: global, thread, main-worker states?
class GlobalState {
/** Next available isolate id. */
@@ -54,16 +61,16 @@ class GlobalState {
int nextWorkerId = 1;
/** Context for the currently running [Isolate]. */
- IsolateContext currentIsolate = null;
+ IsolateContext currentContext = null;
/** Context for the root [Isolate] that first run in this worker. */
- IsolateContext rootIsolate = null;
+ IsolateContext rootContext = null;
/** The top-level event loop. */
EventLoop topEventLoop;
/** Whether this program is running in a background worker. */
- bool inWorker;
+ bool isWorker;
/** Whether this program is running in a UI worker. */
bool inWindow;
@@ -78,11 +85,11 @@ class GlobalState {
bool get useWorkers() => supportsWorkers;
/**
- * Whether to use the web-worker JSON-based message serialization protocol,
- * even if not using web workers. Set to true to always use the web-worker
- * JSON-based message serialization protocol, e.g. for testing purposes.
+ * Whether to use the web-worker JSON-based message serialization protocol. By
+ * default this is only used with web workers. For debugging, you can force
+ * using this protocol by changing this field value to [true].
*/
- bool get useWorkerSerializationProtocol() => useWorkers;
+ bool get needSerialization() => useWorkers;
/**
* Registry of isolates. Isolates must be registered if, and only if, receive
@@ -106,9 +113,9 @@ class GlobalState {
}
void _nativeInit() native @"""
- this.inWorker = typeof ($globalThis['importScripts']) != 'undefined';
+ this.isWorker = typeof ($globalThis['importScripts']) != 'undefined';
this.inWindow = typeof(window) !== 'undefined';
- this.supportsWorkers = this.inWorker ||
+ this.supportsWorkers = this.isWorker ||
((typeof $globalThis['Worker']) != 'undefined');
// if workers are supported, treat this as a main worker:
@@ -124,11 +131,11 @@ class GlobalState {
* run.
*/
void closeWorker() {
- if (inWorker) {
+ if (isWorker) {
if (!isolates.isEmpty()) return;
mainWorker.postMessage(
_serializeMessage({'command': 'close'}));
- } else if (isolates.containsKey(rootIsolate.id) && workers.isEmpty() &&
+ } else if (isolates.containsKey(rootContext.id) && workers.isEmpty() &&
!supportsWorkers && !inWindow) {
// This should only trigger when running on the command-line.
// We don't want this check to execute in the browser where the isolate
@@ -139,7 +146,7 @@ class GlobalState {
}
_serializeMessage(message) {
- if (_globalState.useWorkerSerializationProtocol) {
+ if (_globalState.needSerialization) {
return new Serializer().traverse(message);
} else {
return new Copier().traverse(message);
@@ -147,7 +154,7 @@ _serializeMessage(message) {
}
_deserializeMessage(message) {
- if (_globalState.useWorkerSerializationProtocol) {
+ if (_globalState.needSerialization) {
return new Deserializer().deserialize(message);
} else {
// Nothing more to do.
@@ -178,8 +185,8 @@ class IsolateContext {
initGlobals();
}
- // TODO(sigmund): actually do the initialization too.
- void initGlobals() native "this.isolateStatics = {};";
+ // these are filled lazily the first time the isolate starts running.
+ void initGlobals() native 'this.isolateStatics = {};';
/**
* Run [code] in the context of the isolate represented by [this]. Note this
@@ -187,17 +194,21 @@ class IsolateContext {
* corejs.dart).
*/
void eval(Function code) native {
- var old = _globalState.currentIsolate;
- _globalState.currentIsolate = this;
+ var old = _globalState.currentContext;
+ _globalState.currentContext = this;
+ this._setGlobals();
var result = null;
try {
result = code();
} finally {
- _globalState.currentIsolate = old;
+ _globalState.currentContext = old;
+ old._setGlobals();
}
return result;
}
+ void _setGlobals() native @'$globals = this.isolateStatics;';
+
/** Lookup a port registered for this isolate. */
ReceivePort lookup(int id) => ports[id];
@@ -246,7 +257,7 @@ class EventLoop {
}
/** Function equivalent to [:window.setTimeout:] when available, or null. */
- static Function _platformDefer() native """
+ static Function _wrapSetTimeout() native """
return typeof window != 'undefined' ?
function(a, b) { window.setTimeout(a, b); } : undefined;
""";
@@ -256,7 +267,7 @@ class EventLoop {
* run asynchronously.
*/
void _runHelper() {
- final setTimeout = _platformDefer();
+ final setTimeout = _wrapSetTimeout();
if (setTimeout != null) {
// Run each iteration from the browser's top event loop.
void next() {
@@ -276,7 +287,7 @@ class EventLoop {
* $wrap_call in corejs.dart).
*/
void run() native {
- if (!_globalState.inWorker) {
+ if (!_globalState.isWorker) {
_runHelper();
} else {
try {
@@ -363,7 +374,7 @@ class ReceivePortFactory {
class ReceivePortImpl implements ReceivePort {
ReceivePortImpl()
: _id = _nextFreeId++ {
- _globalState.currentIsolate.register(_id, this);
+ _globalState.currentContext.register(_id, this);
}
void receive(void onMessage(var message, SendPort replyTo)) {
@@ -372,7 +383,7 @@ class ReceivePortImpl implements ReceivePort {
void close() {
_callback = null;
- _globalState.currentIsolate.unregister(_id);
+ _globalState.currentContext.unregister(_id);
}
/**
@@ -381,7 +392,7 @@ class ReceivePortImpl implements ReceivePort {
*/
SendPort toSendPort() {
return new SendPortImpl(
- _globalState.currentWorkerId, _globalState.currentIsolate.id, _id);
+ _globalState.currentWorkerId, _globalState.currentContext.id, _id);
}
int _id;
@@ -437,7 +448,7 @@ class IsolateNatives {
static SendPort _startWorker(Isolate runnable, SendPort replyPort) {
var factoryName = _getJSConstructorName(runnable);
- if (_globalState.inWorker) {
+ if (_globalState.isWorker) {
_globalState.mainWorker.postMessage(_serializeMessage({
'command': 'spawn-worker',
'factoryName': factoryName,
@@ -460,7 +471,7 @@ class IsolateNatives {
// TODO(sigmund): fix - this code should be run synchronously when loading the
// script. Running lazily on DOMContentLoaded will yield incorrect results.
static String _computeThisScript() native @"""
- if (!$globalState.supportsWorkers || $globalState.inWorker) return null;
+ if (!$globalState.supportsWorkers || $globalState.isWorker) return null;
// TODO(5334778): Find a cross-platform non-brittle way of getting the
// currently running script.
@@ -468,11 +479,11 @@ class IsolateNatives {
// The scripts variable only contains the scripts that have already been
// executed. The last one is the currently running script.
var script = scripts[scripts.length - 1];
- var src = script.src;
+ var src = script && script.src;
if (!src) {
// TODO()
src = "FIXME:5407062" + "_" + Math.random().toString();
- script.src = src;
+ if (script) script.src = src;
}
IsolateNatives._thisScriptCache = src;
return src;
@@ -539,7 +550,7 @@ class IsolateNatives {
_log(msg['msg']);
break;
case 'print':
- if (_globalState.inWorker) {
+ if (_globalState.isWorker) {
_globalState.mainWorker.postMessage(
_serializeMessage({'command': 'print', 'msg': msg}));
} else {
@@ -554,7 +565,7 @@ class IsolateNatives {
/** Log a message, forwarding to the main worker if appropriate. */
static _log(msg) {
- if (_globalState.inWorker) {
+ if (_globalState.isWorker) {
_globalState.mainWorker.postMessage(
_serializeMessage({'command': 'log', 'msg': msg }));
} else {
@@ -608,6 +619,7 @@ class IsolateNatives {
/** Given a ready-to-start runnable, start running it. */
static void _startIsolate(Isolate isolate, SendPort replyTo) {
+ _fillStatics(_globalState.currentContext);
ReceivePort port = new ReceivePort();
replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
isolate._run(port);
@@ -630,7 +642,7 @@ class IsolateNatives {
} else {
var worker;
// communication between workers go through the main worker
- if (_globalState.inWorker) {
+ if (_globalState.isWorker) {
worker = _globalState.mainWorker;
} else {
// TODO(sigmund): make sure this works
« 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