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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/compiler.dart

Issue 17759007: First pass at asynchronous input loading in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 part of dart2js; 5 part of dart2js;
6 6
7 /** 7 /**
8 * If true, print a warning for each method that was resolved, but not 8 * If true, print a warning for each method that was resolved, but not
9 * compiled. 9 * compiled.
10 */ 10 */
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 Element invokeOnMethod; 372 Element invokeOnMethod;
373 Element createInvocationMirrorElement; 373 Element createInvocationMirrorElement;
374 374
375 Element get currentElement => _currentElement; 375 Element get currentElement => _currentElement;
376 376
377 /** 377 /**
378 * Perform an operation, [f], returning the return value from [f]. If an 378 * Perform an operation, [f], returning the return value from [f]. If an
379 * error occurs then report it as having occurred during compilation of 379 * error occurs then report it as having occurred during compilation of
380 * [element]. Can be nested. 380 * [element]. Can be nested.
381 */ 381 */
382 // TODO(rnystrom): Handle futures.
Bob Nystrom 2013/06/26 01:03:24 This method assumes the f() is completely done by
382 withCurrentElement(Element element, f()) { 383 withCurrentElement(Element element, f()) {
383 Element old = currentElement; 384 Element old = currentElement;
384 _currentElement = element; 385 _currentElement = element;
385 try { 386 try {
386 return f(); 387 return f();
387 } on SpannableAssertionFailure catch (ex) { 388 } on SpannableAssertionFailure catch (ex) {
388 if (!hasCrashed) { 389 if (!hasCrashed) {
389 SourceSpan span = spanFromSpannable(ex.node); 390 SourceSpan span = spanFromSpannable(ex.node);
390 reportDiagnostic(span, ex.message, api.Diagnostic.ERROR); 391 reportDiagnostic(span, ex.message, api.Diagnostic.ERROR);
391 pleaseReportCrash(); 392 pleaseReportCrash();
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 withCurrentElement(element, () { 642 withCurrentElement(element, () {
642 cancel(reason, node: node, token: token, instruction: instruction, 643 cancel(reason, node: node, token: token, instruction: instruction,
643 element: element); 644 element: element);
644 }); 645 });
645 } 646 }
646 647
647 void log(message) { 648 void log(message) {
648 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); 649 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO);
649 } 650 }
650 651
651 bool run(Uri uri) { 652 Future<bool> run(Uri uri) {
652 totalCompileTime.start(); 653 totalCompileTime.start();
653 try { 654
654 runCompiler(uri); 655 return runCompiler(uri).then((_) {
655 } on CompilerCancelledException catch (exception) { 656 return true;
656 log('Error: $exception'); 657 }).catchError((error) {
657 return false; 658 if (error is CompilerCancelledException) {
658 } catch (exception) { 659 log('Error: $error');
660 return false;
661 }
662
659 try { 663 try {
660 if (!hasCrashed) { 664 if (!hasCrashed) {
661 hasCrashed = true; 665 hasCrashed = true;
662 reportDiagnostic(new SourceSpan(uri, 0, 0), 666 reportDiagnostic(new SourceSpan(uri, 0, 0),
663 MessageKind.COMPILER_CRASHED.error().toString(), 667 MessageKind.COMPILER_CRASHED.error().toString(),
664 api.Diagnostic.CRASH); 668 api.Diagnostic.CRASH);
665 pleaseReportCrash(); 669 pleaseReportCrash();
666 } 670 }
667 } catch (doubleFault) { 671 } catch (doubleFault) {
668 // Ignoring exceptions in exception handling. 672 // Ignoring exceptions in exception handling.
669 } 673 }
670 rethrow; 674 throw error;
671 } finally { 675 }).whenComplete(() {
672 tracer.close(); 676 tracer.close();
673 totalCompileTime.stop(); 677 totalCompileTime.stop();
674 } 678 }).then((_) {
675 return true; 679 return true;
680 });
676 } 681 }
677 682
678 bool hasIsolateSupport() => isolateLibrary != null; 683 bool hasIsolateSupport() => isolateLibrary != null;
679 684
680 /** 685 /**
681 * This method is called before [library] import and export scopes have been 686 * This method is called before [library] import and export scopes have been
682 * set up. 687 * set up.
683 */ 688 */
684 void onLibraryScanned(LibraryElement library, Uri uri) { 689 void onLibraryScanned(LibraryElement library, Uri uri) {
685 if (dynamicClass != null) { 690 if (dynamicClass != null) {
(...skipping 18 matching lines...) Expand all
704 mirrorSystemGetNameFunction = 709 mirrorSystemGetNameFunction =
705 cls.lookupLocalMember(const SourceString('getName')); 710 cls.lookupLocalMember(const SourceString('getName'));
706 } else if (symbolClass == cls) { 711 } else if (symbolClass == cls) {
707 symbolConstructor = cls.constructors.head; 712 symbolConstructor = cls.constructors.head;
708 } else if (symbolImplementationClass == cls) { 713 } else if (symbolImplementationClass == cls) {
709 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor( 714 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor(
710 symbolValidatedConstructorSelector); 715 symbolValidatedConstructorSelector);
711 } 716 }
712 } 717 }
713 718
714 LibraryElement scanBuiltinLibrary(String filename); 719 Future<LibraryElement> scanBuiltinLibrary(String filename);
715 720
716 void initializeSpecialClasses() { 721 void initializeSpecialClasses() {
717 final List missingCoreClasses = []; 722 final List missingCoreClasses = [];
718 ClassElement lookupCoreClass(String name) { 723 ClassElement lookupCoreClass(String name) {
719 ClassElement result = coreLibrary.find(new SourceString(name)); 724 ClassElement result = coreLibrary.find(new SourceString(name));
720 if (result == null) { 725 if (result == null) {
721 missingCoreClasses.add(name); 726 missingCoreClasses.add(name);
722 } 727 }
723 return result; 728 return result;
724 } 729 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 785
781 Element _filledListConstructor; 786 Element _filledListConstructor;
782 Element get filledListConstructor { 787 Element get filledListConstructor {
783 if (_filledListConstructor != null) return _filledListConstructor; 788 if (_filledListConstructor != null) return _filledListConstructor;
784 Selector callConstructor = new Selector.callConstructor( 789 Selector callConstructor = new Selector.callConstructor(
785 const SourceString("filled"), listClass.getLibrary()); 790 const SourceString("filled"), listClass.getLibrary());
786 return _filledListConstructor = 791 return _filledListConstructor =
787 listClass.lookupConstructor(callConstructor); 792 listClass.lookupConstructor(callConstructor);
788 } 793 }
789 794
790 void scanBuiltinLibraries() { 795 Future scanBuiltinLibraries() {
791 jsHelperLibrary = scanBuiltinLibrary('_js_helper'); 796 return scanBuiltinLibrary('_js_helper').then((library) {
792 interceptorsLibrary = scanBuiltinLibrary('_interceptors'); 797 jsHelperLibrary = library;
793 foreignLibrary = scanBuiltinLibrary('_foreign_helper'); 798 return scanBuiltinLibrary('_interceptors');
794 isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper'); 799 }).then((library) {
800 interceptorsLibrary = library;
801 return scanBuiltinLibrary('_foreign_helper');
802 }).then((library) {
803 foreignLibrary = library;
804 return scanBuiltinLibrary('_isolate_helper');
805 }).then((library) {
806 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
795 807
796 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); 808 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper'));
797 identicalFunction = coreLibrary.find(const SourceString('identical')); 809 identicalFunction = coreLibrary.find(const SourceString('identical'));
798 810
799 initializeSpecialClasses(); 811 initializeSpecialClasses();
800 812
801 functionClass.ensureResolved(this); 813 functionClass.ensureResolved(this);
802 functionApplyMethod = 814 functionApplyMethod =
803 functionClass.lookupLocalMember(const SourceString('apply')); 815 functionClass.lookupLocalMember(const SourceString('apply'));
804 jsInvocationMirrorClass.ensureResolved(this); 816 jsInvocationMirrorClass.ensureResolved(this);
805 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); 817 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON);
806 818
807 if (preserveComments) { 819 if (preserveComments) {
808 var uri = new Uri(scheme: 'dart', path: 'mirrors'); 820 var uri = new Uri(scheme: 'dart', path: 'mirrors');
809 LibraryElement libraryElement = 821 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.
810 libraryLoader.loadLibrary(uri, null, uri); 822 documentClass = libraryElement.find(const SourceString('Comment'));
811 documentClass = libraryElement.find(const SourceString('Comment')); 823 });
812 } 824 }
825 });
813 } 826 }
814 827
815 void importHelperLibrary(LibraryElement library) { 828 void importHelperLibrary(LibraryElement library) {
816 if (jsHelperLibrary != null) { 829 if (jsHelperLibrary != null) {
817 libraryLoader.importLibrary(library, jsHelperLibrary, null); 830 libraryLoader.importLibrary(library, jsHelperLibrary, null);
818 } 831 }
819 } 832 }
820 833
821 /** 834 /**
822 * Get an [Uri] pointing to a patch for the dart: library with 835 * Get an [Uri] pointing to a patch for the dart: library with
823 * the given path. Returns null if there is no patch. 836 * the given path. Returns null if there is no patch.
824 */ 837 */
825 Uri resolvePatchUri(String dartLibraryPath); 838 Uri resolvePatchUri(String dartLibraryPath);
826 839
827 void runCompiler(Uri uri) { 840 Future runCompiler(Uri uri) {
828 assert(uri != null || analyzeOnly); 841 assert(uri != null || analyzeOnly);
829 scanBuiltinLibraries(); 842 return scanBuiltinLibraries().then((_) {
830 if (librariesToAnalyzeWhenRun != null) { 843 if (librariesToAnalyzeWhenRun != null) {
831 for (Uri libraryUri in librariesToAnalyzeWhenRun) { 844 return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) {
832 log('analyzing $libraryUri ($buildId)'); 845 log('analyzing $libraryUri ($buildId)');
833 libraryLoader.loadLibrary(libraryUri, null, libraryUri); 846 return libraryLoader.loadLibrary(libraryUri, null, libraryUri);
834 }
835 }
836 if (uri != null) {
837 if (analyzeOnly) {
838 log('analyzing $uri ($buildId)');
839 } else {
840 log('compiling $uri ($buildId)');
841 }
842 mainApp = libraryLoader.loadLibrary(uri, null, uri);
843 }
844 Element main = null;
845 if (mainApp != null) {
846 main = mainApp.find(MAIN);
847 if (main == null) {
848 if (!analyzeOnly) {
849 // Allow analyze only of libraries with no main.
850 reportFatalError('Could not find $MAIN', mainApp);
851 } else if (!analyzeAll) {
852 reportFatalError(
853 "Could not find $MAIN. "
854 "No source will be analyzed. "
855 "Use '--analyze-all' to analyze all code in the library.",
856 mainApp);
857 }
858 } else {
859 if (!main.isFunction()) {
860 reportFatalError('main is not a function', main);
861 }
862 FunctionElement mainMethod = main;
863 FunctionSignature parameters = mainMethod.computeSignature(this);
864 parameters.forEachParameter((Element parameter) {
865 reportFatalError('main cannot have parameters', parameter);
866 }); 847 });
867 } 848 }
849 }).then((_) {
850 if (uri != null) {
851 if (analyzeOnly) {
852 log('analyzing $uri ($buildId)');
853 } else {
854 log('compiling $uri ($buildId)');
855 }
856 return libraryLoader.loadLibrary(uri, null, uri).then((library) {
857 mainApp = library;
858 });
859 }
860 }).then((_) {
861 Element main = null;
862 if (mainApp != null) {
863 main = mainApp.find(MAIN);
864 if (main == null) {
865 if (!analyzeOnly) {
866 // Allow analyze only of libraries with no main.
867 reportFatalError('Could not find $MAIN', mainApp);
868 } else if (!analyzeAll) {
869 reportFatalError(
870 "Could not find $MAIN. "
871 "No source will be analyzed. "
872 "Use '--analyze-all' to analyze all code in the library.",
873 mainApp);
874 }
875 } else {
876 if (!main.isFunction()) {
877 reportFatalError('main is not a function', main);
878 }
879 FunctionElement mainMethod = main;
880 FunctionSignature parameters = mainMethod.computeSignature(this);
881 parameters.forEachParameter((Element parameter) {
882 reportFatalError('main cannot have parameters', parameter);
883 });
884 }
868 885
869 // In order to see if a library is deferred, we must compute the 886 // In order to see if a library is deferred, we must compute the
870 // compile-time constants that are metadata. This means adding 887 // compile-time constants that are metadata. This means adding
871 // something to the resolution queue. So we cannot wait with 888 // something to the resolution queue. So we cannot wait with
872 // this until after the resolution queue is processed. 889 // this until after the resolution queue is processed.
873 // TODO(ahe): Clean this up, for example, by not enqueueing 890 // TODO(ahe): Clean this up, for example, by not enqueueing
874 // classes only used for metadata. 891 // classes only used for metadata.
875 deferredLoadTask.findDeferredLibraries(mainApp); 892 deferredLoadTask.findDeferredLibraries(mainApp);
876 } 893 }
877 894
878 log('Resolving...'); 895 log('Resolving...');
879 phase = PHASE_RESOLVING; 896 phase = PHASE_RESOLVING;
880 if (analyzeAll) { 897 if (analyzeAll) {
881 libraries.forEach( 898 libraries.forEach(
882 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); 899 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution));
883 } 900 }
884 // Elements required by enqueueHelpers are global dependencies 901 // Elements required by enqueueHelpers are global dependencies
885 // that are not pulled in by a particular element. 902 // that are not pulled in by a particular element.
886 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); 903 backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
887 resolveReflectiveDataIfNeeded(); 904 resolveReflectiveDataIfNeeded();
888 processQueue(enqueuer.resolution, main); 905 processQueue(enqueuer.resolution, main);
889 enqueuer.resolution.logSummary(log); 906 enqueuer.resolution.logSummary(log);
890 907
891 if (compilationFailed) return; 908 if (compilationFailed) return;
892 if (analyzeOnly) return; 909 if (analyzeOnly) return;
893 assert(main != null); 910 assert(main != null);
894 phase = PHASE_DONE_RESOLVING; 911 phase = PHASE_DONE_RESOLVING;
895 912
896 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution 913 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution
897 // should know this. 914 // should know this.
898 world.populate(); 915 world.populate();
899 // Compute whole-program-knowledge that the backend needs. (This might 916 // Compute whole-program-knowledge that the backend needs. (This might
900 // require the information computed in [world.populate].) 917 // require the information computed in [world.populate].)
901 backend.onResolutionComplete(); 918 backend.onResolutionComplete();
902 919
903 deferredLoadTask.onResolutionComplete(main); 920 deferredLoadTask.onResolutionComplete(main);
904 921
905 log('Inferring types...'); 922 log('Inferring types...');
906 typesTask.onResolutionComplete(main); 923 typesTask.onResolutionComplete(main);
907 924
908 log('Compiling...'); 925 log('Compiling...');
909 phase = PHASE_COMPILING; 926 phase = PHASE_COMPILING;
910 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. 927 // TODO(johnniwinther): Move these to [CodegenEnqueuer].
911 if (hasIsolateSupport()) { 928 if (hasIsolateSupport()) {
912 enqueuer.codegen.addToWorkList( 929 enqueuer.codegen.addToWorkList(
913 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); 930 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE));
914 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); 931 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN));
915 } 932 }
916 if (enabledNoSuchMethod) { 933 if (enabledNoSuchMethod) {
917 enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, noSuchMethodSelector); 934 enqueuer.codegen.registerInvocation(NO_SUCH_METHOD,
918 enqueuer.codegen.addToWorkList(createInvocationMirrorElement); 935 noSuchMethodSelector);
919 } 936 enqueuer.codegen.addToWorkList(createInvocationMirrorElement);
920 if (compileAll) { 937 }
921 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, enqueuer.codegen)); 938 if (compileAll) {
922 } 939 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib,
923 processQueue(enqueuer.codegen, main); 940 enqueuer.codegen));
924 enqueuer.codegen.logSummary(log); 941 }
942 processQueue(enqueuer.codegen, main);
943 enqueuer.codegen.logSummary(log);
925 944
926 if (compilationFailed) return; 945 if (compilationFailed) return;
927 946
928 backend.assembleProgram(); 947 backend.assembleProgram();
929 948
930 checkQueues(); 949 checkQueues();
950 });
931 } 951 }
932 952
933 void resolveReflectiveDataIfNeeded() { 953 void resolveReflectiveDataIfNeeded() {
934 // Only need reflective data when dart:mirrors is loaded. 954 // Only need reflective data when dart:mirrors is loaded.
935 if (!mirrorsEnabled) return; 955 if (!mirrorsEnabled) return;
936 956
937 for (LibraryElement library in libraries.values) { 957 for (LibraryElement library in libraries.values) {
938 for (Link link = library.metadata; !link.isEmpty; link = link.tail) { 958 for (Link link = library.metadata; !link.isEmpty; link = link.tail) {
939 link.head.ensureResolved(this); 959 link.head.ensureResolved(this);
940 } 960 }
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 Uri translateResolvedUri(LibraryElement importingLibrary, 1277 Uri translateResolvedUri(LibraryElement importingLibrary,
1258 Uri resolvedUri, Node node) { 1278 Uri resolvedUri, Node node) {
1259 unimplemented('Compiler.translateResolvedUri'); 1279 unimplemented('Compiler.translateResolvedUri');
1260 } 1280 }
1261 1281
1262 /** 1282 /**
1263 * Reads the script specified by the [readableUri]. 1283 * Reads the script specified by the [readableUri].
1264 * 1284 *
1265 * See [LibraryLoader] for terminology on URIs. 1285 * See [LibraryLoader] for terminology on URIs.
1266 */ 1286 */
1267 Script readScript(Uri readableUri, [Node node]) { 1287 Future<Script> readScript(Uri readableUri, [Node node]) {
1268 unimplemented('Compiler.readScript'); 1288 unimplemented('Compiler.readScript');
1269 } 1289 }
1270 1290
1271 String get legDirectory { 1291 String get legDirectory {
1272 unimplemented('Compiler.legDirectory'); 1292 unimplemented('Compiler.legDirectory');
1273 } 1293 }
1274 1294
1275 // TODO(karlklose): split into findHelperFunction and findHelperClass and 1295 // TODO(karlklose): split into findHelperFunction and findHelperClass and
1276 // add a check that the element has the expected kind. 1296 // add a check that the element has the expected kind.
1277 Element findHelper(SourceString name) 1297 Element findHelper(SourceString name)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 } finally { 1355 } finally {
1336 watch.stop(); 1356 watch.stop();
1337 if (previous != null) previous.watch.start(); 1357 if (previous != null) previous.watch.start();
1338 compiler.measuredTask = previous; 1358 compiler.measuredTask = previous;
1339 } 1359 }
1340 } 1360 }
1341 1361
1342 measureElement(Element element, action()) { 1362 measureElement(Element element, action()) {
1343 compiler.withCurrentElement(element, () => measure(action)); 1363 compiler.withCurrentElement(element, () => measure(action));
1344 } 1364 }
1365
1366 Future measureAsync(Future action()) {
1367 if (watch == null) return action();
1368 CompilerTask previous = compiler.measuredTask;
1369 if (identical(this, previous)) return action();
1370 compiler.measuredTask = this;
1371 if (previous != null) previous.watch.stop();
1372 watch.start();
1373 print("start measuring async $this");
1374 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.
1375 print("done measuring async $this");
Bob Nystrom 2013/06/26 01:03:24 Oops, I'll delete these debug prints.
1376 watch.stop();
1377 if (previous != null) previous.watch.start();
1378 compiler.measuredTask = previous;
1379 });
1380 }
1345 } 1381 }
1346 1382
1347 class CompilerCancelledException implements Exception { 1383 class CompilerCancelledException implements Exception {
1348 final String reason; 1384 final String reason;
1349 CompilerCancelledException(this.reason); 1385 CompilerCancelledException(this.reason);
1350 1386
1351 String toString() { 1387 String toString() {
1352 String banner = 'compiler cancelled'; 1388 String banner = 'compiler cancelled';
1353 return (reason != null) ? '$banner: $reason' : '$banner'; 1389 return (reason != null) ? '$banner: $reason' : '$banner';
1354 } 1390 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1432 1468
1433 void close() {} 1469 void close() {}
1434 1470
1435 toString() => name; 1471 toString() => name;
1436 1472
1437 /// Convenience method for getting an [api.CompilerOutputProvider]. 1473 /// Convenience method for getting an [api.CompilerOutputProvider].
1438 static NullSink outputProvider(String name, String extension) { 1474 static NullSink outputProvider(String name, String extension) {
1439 return new NullSink('$name.$extension'); 1475 return new NullSink('$name.$extension');
1440 } 1476 }
1441 } 1477 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698