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

Unified Diff: sdk/lib/_internal/lib/isolate_helper.dart

Issue 163733003: Let deferred load work from worker isolates. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix status file Created 6 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/lib/isolate_helper.dart
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index cd3ee4ad56d5108a7bea28b98c0d61e420773756..42da6a887dc04695d6585cebe1c3311fa0cc8096 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -32,6 +32,32 @@ _callInIsolate(_IsolateContext isolate, Function function) {
return result;
}
+/// Marks entering a javascript async operation to keep the worker alive.
+/// Marks entering a JavaScript async operation to keep the worker alive.
+///
+/// To be called by library code before starting an async operation controlled
+/// by the JavaScript event handler.
+///
+/// Also call [leaveJsAsync] in all callback handlers marking the end of that
+/// async operation (also error handlers) so the worker can be released.
+///
+/// These functions only has to be called for code that can be run from a
+/// worker-isolate (so not for general dom operations).
+enterJsAsync() {
+ _globalState.topEventLoop._activeJsAsyncCount++;
+}
+
+/// Marks leaving a javascript async operation.
+///
+/// See [enterJsAsync].
+leaveJsAsync() {
+ _globalState.topEventLoop._activeJsAsyncCount--;
+ assert(_globalState.topEventLoop._activeJsAsyncCount >= 0);
+}
+
+/// Returns true if we are currently in a worker context.
+bool isWorker() => _globalState.isWorker;
+
/**
* Called by the compiler to fetch the current isolate context.
*/
@@ -208,12 +234,12 @@ class _Manager {
/**
* Close the worker running this code if all isolates are done and
- * there is no active timer.
+ * there are no active async JavaScript tasks still running.
*/
void maybeCloseWorker() {
if (isWorker
&& isolates.isEmpty
- && topEventLoop.activeTimerCount == 0) {
+ && topEventLoop._activeJsAsyncCount == 0) {
mainManager.postMessage(_serializeMessage({'command': 'close'}));
}
}
@@ -346,7 +372,14 @@ class _IsolateContext implements IsolateContext {
/** Represent the event loop on a javascript thread (DOM or worker). */
class _EventLoop {
final Queue<_IsolateEvent> events = new Queue<_IsolateEvent>();
- int activeTimerCount = 0;
+
+ /// The number of waiting callbacks not controlled by the dart event loop.
+ ///
+ /// This could be timers or http requests. The worker will only be killed if
+ /// this count reaches 0.
+ /// Access this by using [enterJsAsync] before starting a JavaScript async
+ /// operation and [leaveJsAsync] when the callback has fired.
+ int _activeJsAsyncCount = 0;
_EventLoop();
@@ -484,6 +517,8 @@ class IsolateNatives {
if (currentScript != null) {
return JS('String', 'String(#.src)', currentScript);
}
+ // A worker has no script tag - so get an url from a stack-trace.
+ if (_globalState.isWorker) return computeThisScriptFromTrace();
if (Primitives.isD8) return computeThisScriptD8();
if (Primitives.isJsshell) return computeThisScriptJsshell();
return null;
@@ -493,10 +528,11 @@ class IsolateNatives {
return JS('String|Null', 'thisFilename()');
}
- static String computeThisScriptD8() {
- // TODO(ahe): The following is for supporting D8. We should move this code
- // to a helper library that is only loaded when testing on D8.
+ // TODO(ahe): The following is for supporting D8. We should move this code
+ // to a helper library that is only loaded when testing on D8.
+ static String computeThisScriptD8() => computeThisScriptFromTrace();
+ static String computeThisScriptFromTrace() {
var stack = JS('String|Null', 'new Error().stack');
if (stack == null) {
// According to Internet Explorer documentation, the stack
@@ -1365,11 +1401,12 @@ class TimerImpl implements Timer {
void internalCallback() {
_handle = null;
- _globalState.topEventLoop.activeTimerCount--;
+ leaveJsAsync();
callback();
}
- _globalState.topEventLoop.activeTimerCount++;
+ enterJsAsync();
+
_handle = JS('int', '#.setTimeout(#, #)',
globalThis,
convertDartClosureToJS(internalCallback, 0),
@@ -1383,7 +1420,7 @@ class TimerImpl implements Timer {
TimerImpl.periodic(int milliseconds, void callback(Timer timer))
: _once = false {
if (hasTimer()) {
- _globalState.topEventLoop.activeTimerCount++;
+ enterJsAsync();
_handle = JS('int', '#.setInterval(#, #)',
globalThis,
convertDartClosureToJS(() { callback(this); }, 0),
@@ -1399,7 +1436,7 @@ class TimerImpl implements Timer {
throw new UnsupportedError("Timer in event loop cannot be canceled.");
}
if (_handle == null) return;
- _globalState.topEventLoop.activeTimerCount--;
+ leaveJsAsync();
if (_once) {
JS('void', '#.clearTimeout(#)', globalThis, _handle);
} else {

Powered by Google App Engine
This is Rietveld 408576698