Index: sdk/lib/_internal/compiler/implementation/compiler.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart |
index 96490f5c03790dbf7f869857c9fc4a0d3e50e52b..ec8d0655d6caa4c070868a862db92e52fbc286f0 100644 |
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart |
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart |
@@ -379,6 +379,7 @@ abstract class Compiler implements DiagnosticListener { |
* error occurs then report it as having occurred during compilation of |
* [element]. Can be nested. |
*/ |
+ // TODO(rnystrom): Handle futures. |
Bob Nystrom
2013/06/26 01:03:24
This method assumes the f() is completely done by
|
withCurrentElement(Element element, f()) { |
Element old = currentElement; |
_currentElement = element; |
@@ -648,14 +649,17 @@ abstract class Compiler implements DiagnosticListener { |
reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); |
} |
- bool run(Uri uri) { |
+ Future<bool> run(Uri uri) { |
totalCompileTime.start(); |
- try { |
- runCompiler(uri); |
- } on CompilerCancelledException catch (exception) { |
- log('Error: $exception'); |
- return false; |
- } catch (exception) { |
+ |
+ return runCompiler(uri).then((_) { |
+ return true; |
+ }).catchError((error) { |
+ if (error is CompilerCancelledException) { |
+ log('Error: $error'); |
+ return false; |
+ } |
+ |
try { |
if (!hasCrashed) { |
hasCrashed = true; |
@@ -667,12 +671,13 @@ abstract class Compiler implements DiagnosticListener { |
} catch (doubleFault) { |
// Ignoring exceptions in exception handling. |
} |
- rethrow; |
- } finally { |
+ throw error; |
+ }).whenComplete(() { |
tracer.close(); |
totalCompileTime.stop(); |
- } |
- return true; |
+ }).then((_) { |
+ return true; |
+ }); |
} |
bool hasIsolateSupport() => isolateLibrary != null; |
@@ -711,7 +716,7 @@ abstract class Compiler implements DiagnosticListener { |
} |
} |
- LibraryElement scanBuiltinLibrary(String filename); |
+ Future<LibraryElement> scanBuiltinLibrary(String filename); |
void initializeSpecialClasses() { |
final List missingCoreClasses = []; |
@@ -787,29 +792,37 @@ abstract class Compiler implements DiagnosticListener { |
listClass.lookupConstructor(callConstructor); |
} |
- void scanBuiltinLibraries() { |
- jsHelperLibrary = scanBuiltinLibrary('_js_helper'); |
- interceptorsLibrary = scanBuiltinLibrary('_interceptors'); |
- foreignLibrary = scanBuiltinLibrary('_foreign_helper'); |
- isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper'); |
- |
- assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); |
- identicalFunction = coreLibrary.find(const SourceString('identical')); |
- |
- initializeSpecialClasses(); |
- |
- functionClass.ensureResolved(this); |
- functionApplyMethod = |
- functionClass.lookupLocalMember(const SourceString('apply')); |
- jsInvocationMirrorClass.ensureResolved(this); |
- invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); |
- |
- if (preserveComments) { |
- var uri = new Uri(scheme: 'dart', path: 'mirrors'); |
- LibraryElement libraryElement = |
- libraryLoader.loadLibrary(uri, null, uri); |
- documentClass = libraryElement.find(const SourceString('Comment')); |
- } |
+ Future scanBuiltinLibraries() { |
+ return scanBuiltinLibrary('_js_helper').then((library) { |
+ jsHelperLibrary = library; |
+ return scanBuiltinLibrary('_interceptors'); |
+ }).then((library) { |
+ interceptorsLibrary = library; |
+ return scanBuiltinLibrary('_foreign_helper'); |
+ }).then((library) { |
+ foreignLibrary = library; |
+ return scanBuiltinLibrary('_isolate_helper'); |
+ }).then((library) { |
+ isolateHelperLibrary = library; |
Bob Nystrom
2013/06/26 01:03:24
This is a bit ugly, but it ensures that these libr
ahe
2013/06/26 07:02:00
I think we can use Future.wait here. Normally the
Bob Nystrom
2013/06/27 00:38:18
I just tried that but it apparently causes some ot
|
+ |
+ assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); |
+ identicalFunction = coreLibrary.find(const SourceString('identical')); |
+ |
+ initializeSpecialClasses(); |
+ |
+ functionClass.ensureResolved(this); |
+ functionApplyMethod = |
+ functionClass.lookupLocalMember(const SourceString('apply')); |
+ jsInvocationMirrorClass.ensureResolved(this); |
+ invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); |
+ |
+ if (preserveComments) { |
+ var uri = new Uri(scheme: 'dart', path: 'mirrors'); |
+ return libraryLoader.loadLibrary(uri, null, uri).then((libraryElement) { |
ahe
2013/06/26 07:02:00
Please restore the explicit type of libraryElement
Bob Nystrom
2013/06/27 00:38:18
Done.
|
+ documentClass = libraryElement.find(const SourceString('Comment')); |
+ }); |
+ } |
+ }); |
} |
void importHelperLibrary(LibraryElement library) { |
@@ -824,110 +837,117 @@ abstract class Compiler implements DiagnosticListener { |
*/ |
Uri resolvePatchUri(String dartLibraryPath); |
- void runCompiler(Uri uri) { |
+ Future runCompiler(Uri uri) { |
assert(uri != null || analyzeOnly); |
- scanBuiltinLibraries(); |
- if (librariesToAnalyzeWhenRun != null) { |
- for (Uri libraryUri in librariesToAnalyzeWhenRun) { |
- log('analyzing $libraryUri ($buildId)'); |
- libraryLoader.loadLibrary(libraryUri, null, libraryUri); |
- } |
- } |
- if (uri != null) { |
- if (analyzeOnly) { |
- log('analyzing $uri ($buildId)'); |
- } else { |
- log('compiling $uri ($buildId)'); |
+ return scanBuiltinLibraries().then((_) { |
+ if (librariesToAnalyzeWhenRun != null) { |
+ return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) { |
+ log('analyzing $libraryUri ($buildId)'); |
+ return libraryLoader.loadLibrary(libraryUri, null, libraryUri); |
+ }); |
} |
- mainApp = libraryLoader.loadLibrary(uri, null, uri); |
- } |
- Element main = null; |
- if (mainApp != null) { |
- main = mainApp.find(MAIN); |
- if (main == null) { |
- if (!analyzeOnly) { |
- // Allow analyze only of libraries with no main. |
- reportFatalError('Could not find $MAIN', mainApp); |
- } else if (!analyzeAll) { |
- reportFatalError( |
- "Could not find $MAIN. " |
- "No source will be analyzed. " |
- "Use '--analyze-all' to analyze all code in the library.", |
- mainApp); |
- } |
- } else { |
- if (!main.isFunction()) { |
- reportFatalError('main is not a function', main); |
+ }).then((_) { |
+ if (uri != null) { |
+ if (analyzeOnly) { |
+ log('analyzing $uri ($buildId)'); |
+ } else { |
+ log('compiling $uri ($buildId)'); |
} |
- FunctionElement mainMethod = main; |
- FunctionSignature parameters = mainMethod.computeSignature(this); |
- parameters.forEachParameter((Element parameter) { |
- reportFatalError('main cannot have parameters', parameter); |
+ return libraryLoader.loadLibrary(uri, null, uri).then((library) { |
+ mainApp = library; |
}); |
} |
+ }).then((_) { |
+ Element main = null; |
+ if (mainApp != null) { |
+ main = mainApp.find(MAIN); |
+ if (main == null) { |
+ if (!analyzeOnly) { |
+ // Allow analyze only of libraries with no main. |
+ reportFatalError('Could not find $MAIN', mainApp); |
+ } else if (!analyzeAll) { |
+ reportFatalError( |
+ "Could not find $MAIN. " |
+ "No source will be analyzed. " |
+ "Use '--analyze-all' to analyze all code in the library.", |
+ mainApp); |
+ } |
+ } else { |
+ if (!main.isFunction()) { |
+ reportFatalError('main is not a function', main); |
+ } |
+ FunctionElement mainMethod = main; |
+ FunctionSignature parameters = mainMethod.computeSignature(this); |
+ parameters.forEachParameter((Element parameter) { |
+ reportFatalError('main cannot have parameters', parameter); |
+ }); |
+ } |
- // In order to see if a library is deferred, we must compute the |
- // compile-time constants that are metadata. This means adding |
- // something to the resolution queue. So we cannot wait with |
- // this until after the resolution queue is processed. |
- // TODO(ahe): Clean this up, for example, by not enqueueing |
- // classes only used for metadata. |
- deferredLoadTask.findDeferredLibraries(mainApp); |
- } |
- |
- log('Resolving...'); |
- phase = PHASE_RESOLVING; |
- if (analyzeAll) { |
- libraries.forEach( |
- (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); |
- } |
- // Elements required by enqueueHelpers are global dependencies |
- // that are not pulled in by a particular element. |
- backend.enqueueHelpers(enqueuer.resolution, globalDependencies); |
- resolveReflectiveDataIfNeeded(); |
- processQueue(enqueuer.resolution, main); |
- enqueuer.resolution.logSummary(log); |
+ // In order to see if a library is deferred, we must compute the |
+ // compile-time constants that are metadata. This means adding |
+ // something to the resolution queue. So we cannot wait with |
+ // this until after the resolution queue is processed. |
+ // TODO(ahe): Clean this up, for example, by not enqueueing |
+ // classes only used for metadata. |
+ deferredLoadTask.findDeferredLibraries(mainApp); |
+ } |
- if (compilationFailed) return; |
- if (analyzeOnly) return; |
- assert(main != null); |
- phase = PHASE_DONE_RESOLVING; |
- |
- // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
- // should know this. |
- world.populate(); |
- // Compute whole-program-knowledge that the backend needs. (This might |
- // require the information computed in [world.populate].) |
- backend.onResolutionComplete(); |
- |
- deferredLoadTask.onResolutionComplete(main); |
- |
- log('Inferring types...'); |
- typesTask.onResolutionComplete(main); |
- |
- log('Compiling...'); |
- phase = PHASE_COMPILING; |
- // TODO(johnniwinther): Move these to [CodegenEnqueuer]. |
- if (hasIsolateSupport()) { |
- enqueuer.codegen.addToWorkList( |
- isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); |
- enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); |
- } |
- if (enabledNoSuchMethod) { |
- enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, noSuchMethodSelector); |
- enqueuer.codegen.addToWorkList(createInvocationMirrorElement); |
- } |
- if (compileAll) { |
- libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, enqueuer.codegen)); |
- } |
- processQueue(enqueuer.codegen, main); |
- enqueuer.codegen.logSummary(log); |
+ log('Resolving...'); |
+ phase = PHASE_RESOLVING; |
+ if (analyzeAll) { |
+ libraries.forEach( |
+ (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); |
+ } |
+ // Elements required by enqueueHelpers are global dependencies |
+ // that are not pulled in by a particular element. |
+ backend.enqueueHelpers(enqueuer.resolution, globalDependencies); |
+ resolveReflectiveDataIfNeeded(); |
+ processQueue(enqueuer.resolution, main); |
+ enqueuer.resolution.logSummary(log); |
+ |
+ if (compilationFailed) return; |
+ if (analyzeOnly) return; |
+ assert(main != null); |
+ phase = PHASE_DONE_RESOLVING; |
+ |
+ // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
+ // should know this. |
+ world.populate(); |
+ // Compute whole-program-knowledge that the backend needs. (This might |
+ // require the information computed in [world.populate].) |
+ backend.onResolutionComplete(); |
+ |
+ deferredLoadTask.onResolutionComplete(main); |
+ |
+ log('Inferring types...'); |
+ typesTask.onResolutionComplete(main); |
+ |
+ log('Compiling...'); |
+ phase = PHASE_COMPILING; |
+ // TODO(johnniwinther): Move these to [CodegenEnqueuer]. |
+ if (hasIsolateSupport()) { |
+ enqueuer.codegen.addToWorkList( |
+ isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); |
+ enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); |
+ } |
+ if (enabledNoSuchMethod) { |
+ enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, |
+ noSuchMethodSelector); |
+ enqueuer.codegen.addToWorkList(createInvocationMirrorElement); |
+ } |
+ if (compileAll) { |
+ libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, |
+ enqueuer.codegen)); |
+ } |
+ processQueue(enqueuer.codegen, main); |
+ enqueuer.codegen.logSummary(log); |
- if (compilationFailed) return; |
+ if (compilationFailed) return; |
- backend.assembleProgram(); |
+ backend.assembleProgram(); |
- checkQueues(); |
+ checkQueues(); |
+ }); |
} |
void resolveReflectiveDataIfNeeded() { |
@@ -1264,7 +1284,7 @@ abstract class Compiler implements DiagnosticListener { |
* |
* See [LibraryLoader] for terminology on URIs. |
*/ |
- Script readScript(Uri readableUri, [Node node]) { |
+ Future<Script> readScript(Uri readableUri, [Node node]) { |
unimplemented('Compiler.readScript'); |
} |
@@ -1342,6 +1362,22 @@ class CompilerTask { |
measureElement(Element element, action()) { |
compiler.withCurrentElement(element, () => measure(action)); |
} |
+ |
+ Future measureAsync(Future action()) { |
+ if (watch == null) return action(); |
+ CompilerTask previous = compiler.measuredTask; |
+ if (identical(this, previous)) return action(); |
+ compiler.measuredTask = this; |
+ if (previous != null) previous.watch.stop(); |
+ watch.start(); |
+ print("start measuring async $this"); |
+ return action().whenComplete(() { |
ahe
2013/06/26 07:02:00
I'm not sure measureAsync actually works.
The pro
Bob Nystrom
2013/06/27 00:38:18
That sounds good to me.
|
+ print("done measuring async $this"); |
Bob Nystrom
2013/06/26 01:03:24
Oops, I'll delete these debug prints.
|
+ watch.stop(); |
+ if (previous != null) previous.watch.start(); |
+ compiler.measuredTask = previous; |
+ }); |
+ } |
} |
class CompilerCancelledException implements Exception { |