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 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 | 74 |
75 typedef void PostProcessAction(); | 75 typedef void PostProcessAction(); |
76 | 76 |
77 class PostProcessTask { | 77 class PostProcessTask { |
78 final Element element; | 78 final Element element; |
79 final PostProcessAction action; | 79 final PostProcessAction action; |
80 | 80 |
81 PostProcessTask(this.element, this.action); | 81 PostProcessTask(this.element, this.action); |
82 } | 82 } |
83 | 83 |
84 // TODO(rnystrom): Now that file reading is asynchronous, this task is no longer | |
85 // used and the time spent reading files isn't easily measurable (or even that | |
86 // well-defined). As Peter says: | |
87 // | |
88 // As far as I can tell, we can only count how much time is being spent reading | |
89 // files by having a global counter that covers the time from the beginning of | |
90 // the compiler until it reaches a point when all libraries are scanned, and | |
91 // subtract the time spent in other tasks. | |
92 // | |
93 // I think you should drop measureAsync. I think we can measure the time spent | |
94 // reading files in dart2js.dart (you can just add a TODO). | |
84 class ReadingFilesTask extends CompilerTask { | 95 class ReadingFilesTask extends CompilerTask { |
85 ReadingFilesTask(Compiler compiler) : super(compiler); | 96 ReadingFilesTask(Compiler compiler) : super(compiler); |
86 String get name => 'Reading input files'; | 97 String get name => 'Reading input files'; |
87 } | 98 } |
88 | 99 |
89 abstract class Backend { | 100 abstract class Backend { |
90 final Compiler compiler; | 101 final Compiler compiler; |
91 final ConstantSystem constantSystem; | 102 final ConstantSystem constantSystem; |
92 | 103 |
93 Backend(this.compiler, | 104 Backend(this.compiler, |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 ClassElement jsInvocationMirrorClass; | 404 ClassElement jsInvocationMirrorClass; |
394 /// Document class from dart:mirrors. | 405 /// Document class from dart:mirrors. |
395 ClassElement documentClass; | 406 ClassElement documentClass; |
396 Element assertMethod; | 407 Element assertMethod; |
397 Element identicalFunction; | 408 Element identicalFunction; |
398 Element functionApplyMethod; | 409 Element functionApplyMethod; |
399 Element invokeOnMethod; | 410 Element invokeOnMethod; |
400 Element createInvocationMirrorElement; | 411 Element createInvocationMirrorElement; |
401 | 412 |
402 Element get currentElement => _currentElement; | 413 Element get currentElement => _currentElement; |
414 | |
415 void _setCurrentElement(Element newElement, Element oldElement) { | |
416 assert(invariant( | |
417 newElement == null ? CURRENT_ELEMENT_SPANNABLE : newElement, | |
418 _currentElement == oldElement, | |
419 message: "Current element mismatch. " | |
420 "Expected $oldElement but found $_currentElement.")); | |
421 _currentElement = newElement; | |
422 } | |
403 | 423 |
404 /** | 424 /** |
405 * Perform an operation, [f], returning the return value from [f]. If an | 425 * Perform an operation, [f], returning the return value from [f]. If an |
406 * error occurs then report it as having occurred during compilation of | 426 * error occurs then report it as having occurred during compilation of |
407 * [element]. Can be nested. | 427 * [element]. Can be nested. |
408 */ | 428 */ |
409 withCurrentElement(Element element, f()) { | 429 withCurrentElement(Element element, f()) { |
410 Element old = currentElement; | 430 Element old = currentElement; |
411 _currentElement = element; | 431 _setCurrentElement(element, old); |
412 try { | 432 try { |
413 return f(); | 433 var result = f(); |
434 assert(invariant(element, result is! Future, | |
435 message: '"withCurrentElement" called with asynchronous function. ' | |
436 'Use "withCurrentElementAsync" instead.')); | |
437 return result; | |
414 } on SpannableAssertionFailure catch (ex) { | 438 } on SpannableAssertionFailure catch (ex) { |
415 if (!hasCrashed) { | 439 onSpannableAssertionFailure(ex); |
416 SourceSpan span = spanFromSpannable(ex.node); | |
417 reportError(ex.node, MessageKind.GENERIC, {'text': ex.message}); | |
418 pleaseReportCrash(); | |
419 } | |
420 hasCrashed = true; | |
421 rethrow; | 440 rethrow; |
422 } on CompilerCancelledException catch (ex) { | 441 } on CompilerCancelledException catch (ex) { |
423 rethrow; | 442 rethrow; |
424 } on StackOverflowError catch (ex) { | 443 } on StackOverflowError catch (ex) { |
425 // We cannot report anything useful in this case, because we | 444 // We cannot report anything useful in this case, because we |
426 // do not have enough stack space. | 445 // do not have enough stack space. |
427 rethrow; | 446 rethrow; |
428 } catch (ex) { | 447 } catch (ex) { |
429 try { | 448 onUnhandledException(element); |
430 unhandledExceptionOnElement(element); | |
431 } catch (doubleFault) { | |
432 // Ignoring exceptions in exception handling. | |
433 } | |
434 rethrow; | 449 rethrow; |
435 } finally { | 450 } finally { |
436 _currentElement = old; | 451 _setCurrentElement(old, element); |
452 } | |
453 } | |
454 | |
455 Future withCurrentElementAsync(Element element, Future f()) { | |
456 Element old = currentElement; | |
457 _setCurrentElement(element, old); | |
458 try { | |
459 return f().catchError((ex) { | |
ahe
2013/08/02 11:50:19
I don't think this will work. I'l talk to you in p
Johnni Winther
2013/08/02 13:47:47
Removed.
| |
460 if (ex is SpannableAssertionFailure) { | |
461 onSpannableAssertionFailure(ex); | |
462 } else if (ex is CompilerCancelledException || | |
463 ex is StackOverflowError) { | |
464 // Do nothing. | |
ahe
2013/08/02 11:50:19
Why is that?
| |
465 } else { | |
466 onUnhandledException(element); | |
467 } | |
468 return new Future.error(ex); | |
469 }) | |
470 .whenComplete(() { | |
471 _setCurrentElement(old, element); | |
472 }); | |
473 } catch (ex) { | |
474 _setCurrentElement(old, element); | |
475 return new Future.error(ex); | |
476 } | |
477 } | |
478 | |
479 void onSpannableAssertionFailure(SpannableAssertionFailure ex) { | |
480 if (!hasCrashed) { | |
481 SourceSpan span = spanFromSpannable(ex.node); | |
482 reportError(ex.node, MessageKind.GENERIC, {'text': ex.message}); | |
483 pleaseReportCrash(); | |
484 } | |
485 hasCrashed = true; | |
486 } | |
487 | |
488 void onUnhandledException(Element element) { | |
489 try { | |
490 unhandledExceptionOnElement(element); | |
491 } catch (doubleFault) { | |
492 // Ignoring exceptions in exception handling. | |
437 } | 493 } |
438 } | 494 } |
439 | 495 |
440 List<CompilerTask> tasks; | 496 List<CompilerTask> tasks; |
441 ScannerTask scanner; | 497 ScannerTask scanner; |
442 DietParserTask dietParser; | 498 DietParserTask dietParser; |
443 ParserTask parser; | 499 ParserTask parser; |
444 PatchParserTask patchParser; | 500 PatchParserTask patchParser; |
445 LibraryLoader libraryLoader; | 501 LibraryLoader libraryLoader; |
446 TreeValidatorTask validator; | 502 TreeValidatorTask validator; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 return spanFromTokens(annotation.beginToken, annotation.endToken); | 717 return spanFromTokens(annotation.beginToken, annotation.endToken); |
662 } else { | 718 } else { |
663 throw 'No error location.'; | 719 throw 'No error location.'; |
664 } | 720 } |
665 } | 721 } |
666 | 722 |
667 void log(message) { | 723 void log(message) { |
668 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); | 724 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); |
669 } | 725 } |
670 | 726 |
671 bool run(Uri uri) { | 727 Future<bool> run(Uri uri) { |
672 totalCompileTime.start(); | 728 totalCompileTime.start(); |
673 try { | 729 |
674 runCompiler(uri); | 730 return runCompiler(uri).then((_) { |
675 } on CompilerCancelledException catch (exception) { | 731 return true; |
676 log('Error: $exception'); | 732 }).catchError((error) { |
677 return false; | 733 if (error is CompilerCancelledException) { |
678 } catch (exception) { | 734 log('Error: $error'); |
735 return false; | |
736 } | |
737 | |
679 try { | 738 try { |
680 if (!hasCrashed) { | 739 if (!hasCrashed) { |
681 hasCrashed = true; | 740 hasCrashed = true; |
682 reportDiagnostic(new SourceSpan(uri, 0, 0), | 741 reportDiagnostic(new SourceSpan(uri, 0, 0), |
683 MessageKind.COMPILER_CRASHED.error().toString(), | 742 MessageKind.COMPILER_CRASHED.error().toString(), |
684 api.Diagnostic.CRASH); | 743 api.Diagnostic.CRASH); |
685 pleaseReportCrash(); | 744 pleaseReportCrash(); |
686 } | 745 } |
687 } catch (doubleFault) { | 746 } catch (doubleFault) { |
688 // Ignoring exceptions in exception handling. | 747 // Ignoring exceptions in exception handling. |
689 } | 748 } |
690 rethrow; | 749 throw error; |
691 } finally { | 750 }).whenComplete(() { |
692 tracer.close(); | 751 tracer.close(); |
693 totalCompileTime.stop(); | 752 totalCompileTime.stop(); |
694 } | 753 }).then((_) { |
695 return !compilationFailed; | 754 return !compilationFailed; |
755 }); | |
696 } | 756 } |
697 | 757 |
698 bool hasIsolateSupport() => isolateLibrary != null; | 758 bool hasIsolateSupport() => isolateLibrary != null; |
699 | 759 |
700 /** | 760 /** |
701 * This method is called before [library] import and export scopes have been | 761 * This method is called before [library] import and export scopes have been |
702 * set up. | 762 * set up. |
703 */ | 763 */ |
704 void onLibraryScanned(LibraryElement library, Uri uri) { | 764 void onLibraryScanned(LibraryElement library, Uri uri) { |
705 if (dynamicClass != null) { | 765 if (dynamicClass != null) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 mirrorSystemGetNameFunction = | 802 mirrorSystemGetNameFunction = |
743 cls.lookupLocalMember(const SourceString('getName')); | 803 cls.lookupLocalMember(const SourceString('getName')); |
744 } else if (symbolClass == cls) { | 804 } else if (symbolClass == cls) { |
745 symbolConstructor = cls.constructors.head; | 805 symbolConstructor = cls.constructors.head; |
746 } else if (symbolImplementationClass == cls) { | 806 } else if (symbolImplementationClass == cls) { |
747 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor( | 807 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor( |
748 symbolValidatedConstructorSelector); | 808 symbolValidatedConstructorSelector); |
749 } | 809 } |
750 } | 810 } |
751 | 811 |
752 LibraryElement scanBuiltinLibrary(String filename); | 812 Future<LibraryElement> scanBuiltinLibrary(String filename); |
753 | 813 |
754 void initializeSpecialClasses() { | 814 void initializeSpecialClasses() { |
755 final List missingCoreClasses = []; | 815 final List missingCoreClasses = []; |
756 ClassElement lookupCoreClass(String name) { | 816 ClassElement lookupCoreClass(String name) { |
757 ClassElement result = coreLibrary.find(new SourceString(name)); | 817 ClassElement result = coreLibrary.find(new SourceString(name)); |
758 if (result == null) { | 818 if (result == null) { |
759 missingCoreClasses.add(name); | 819 missingCoreClasses.add(name); |
760 } | 820 } |
761 return result; | 821 return result; |
762 } | 822 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
818 | 878 |
819 Element _filledListConstructor; | 879 Element _filledListConstructor; |
820 Element get filledListConstructor { | 880 Element get filledListConstructor { |
821 if (_filledListConstructor != null) return _filledListConstructor; | 881 if (_filledListConstructor != null) return _filledListConstructor; |
822 Selector callConstructor = new Selector.callConstructor( | 882 Selector callConstructor = new Selector.callConstructor( |
823 const SourceString("filled"), listClass.getLibrary()); | 883 const SourceString("filled"), listClass.getLibrary()); |
824 return _filledListConstructor = | 884 return _filledListConstructor = |
825 listClass.lookupConstructor(callConstructor); | 885 listClass.lookupConstructor(callConstructor); |
826 } | 886 } |
827 | 887 |
828 void scanBuiltinLibraries() { | 888 Future scanBuiltinLibraries() { |
829 jsHelperLibrary = scanBuiltinLibrary('_js_helper'); | 889 return scanBuiltinLibrary('_js_helper').then((LibraryElement library) { |
830 interceptorsLibrary = scanBuiltinLibrary('_interceptors'); | 890 jsHelperLibrary = library; |
831 foreignLibrary = scanBuiltinLibrary('_foreign_helper'); | 891 return scanBuiltinLibrary('_interceptors'); |
832 isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper'); | 892 }).then((LibraryElement library) { |
893 interceptorsLibrary = library; | |
894 return scanBuiltinLibrary('_foreign_helper'); | |
895 }).then((LibraryElement library) { | |
896 foreignLibrary = library; | |
897 return scanBuiltinLibrary('_isolate_helper'); | |
898 }).then((LibraryElement library) { | |
899 isolateHelperLibrary = library; | |
833 | 900 |
834 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); | 901 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); |
835 identicalFunction = coreLibrary.find(const SourceString('identical')); | 902 identicalFunction = coreLibrary.find(const SourceString('identical')); |
836 | 903 |
837 initializeSpecialClasses(); | 904 initializeSpecialClasses(); |
838 | 905 |
839 functionClass.ensureResolved(this); | 906 functionClass.ensureResolved(this); |
840 functionApplyMethod = | 907 functionApplyMethod = |
841 functionClass.lookupLocalMember(const SourceString('apply')); | 908 functionClass.lookupLocalMember(const SourceString('apply')); |
842 jsInvocationMirrorClass.ensureResolved(this); | 909 jsInvocationMirrorClass.ensureResolved(this); |
843 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); | 910 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); |
844 | 911 |
845 if (preserveComments) { | 912 if (preserveComments) { |
846 var uri = new Uri(scheme: 'dart', path: 'mirrors'); | 913 var uri = new Uri(scheme: 'dart', path: 'mirrors'); |
847 LibraryElement libraryElement = | 914 return libraryLoader.loadLibrary(uri, null, uri).then( |
848 libraryLoader.loadLibrary(uri, null, uri); | 915 (LibraryElement libraryElement) { |
849 documentClass = libraryElement.find(const SourceString('Comment')); | 916 documentClass = libraryElement.find(const SourceString('Comment')); |
850 } | 917 }); |
918 } | |
919 }); | |
851 } | 920 } |
852 | 921 |
853 void importHelperLibrary(LibraryElement library) { | 922 void importHelperLibrary(LibraryElement library) { |
854 if (jsHelperLibrary != null) { | 923 if (jsHelperLibrary != null) { |
855 libraryLoader.importLibrary(library, jsHelperLibrary, null); | 924 libraryLoader.importLibrary(library, jsHelperLibrary, null); |
856 } | 925 } |
857 } | 926 } |
858 | 927 |
859 /** | 928 /** |
860 * Get an [Uri] pointing to a patch for the dart: library with | 929 * Get an [Uri] pointing to a patch for the dart: library with |
861 * the given path. Returns null if there is no patch. | 930 * the given path. Returns null if there is no patch. |
862 */ | 931 */ |
863 Uri resolvePatchUri(String dartLibraryPath); | 932 Uri resolvePatchUri(String dartLibraryPath); |
864 | 933 |
865 void runCompiler(Uri uri) { | 934 Future runCompiler(Uri uri) { |
866 // TODO(ahe): This prevents memory leaks when invoking the compiler | 935 // TODO(ahe): This prevents memory leaks when invoking the compiler |
867 // multiple times. Implement a better mechanism where StringWrapper | 936 // multiple times. Implement a better mechanism where StringWrapper |
868 // instances are shared on a per library basis. | 937 // instances are shared on a per library basis. |
869 SourceString.canonicalizedValues.clear(); | 938 SourceString.canonicalizedValues.clear(); |
870 | 939 |
871 assert(uri != null || analyzeOnly); | 940 assert(uri != null || analyzeOnly); |
872 scanBuiltinLibraries(); | 941 return scanBuiltinLibraries().then((_) { |
873 if (librariesToAnalyzeWhenRun != null) { | 942 if (librariesToAnalyzeWhenRun != null) { |
874 for (Uri libraryUri in librariesToAnalyzeWhenRun) { | 943 return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) { |
875 log('analyzing $libraryUri ($buildId)'); | 944 log('analyzing $libraryUri ($buildId)'); |
876 libraryLoader.loadLibrary(libraryUri, null, libraryUri); | 945 return libraryLoader.loadLibrary(libraryUri, null, libraryUri); |
877 } | |
878 } | |
879 if (uri != null) { | |
880 if (analyzeOnly) { | |
881 log('analyzing $uri ($buildId)'); | |
882 } else { | |
883 log('compiling $uri ($buildId)'); | |
884 } | |
885 mainApp = libraryLoader.loadLibrary(uri, null, uri); | |
886 } | |
887 Element main = null; | |
888 if (mainApp != null) { | |
889 main = mainApp.find(MAIN); | |
890 if (main == null) { | |
891 if (!analyzeOnly) { | |
892 // Allow analyze only of libraries with no main. | |
893 reportFatalError( | |
894 mainApp, | |
895 MessageKind.GENERIC, | |
896 {'text': 'Error: Could not find "${MAIN.slowToString()}".'}); | |
897 } else if (!analyzeAll) { | |
898 reportFatalError( | |
899 mainApp, | |
900 MessageKind.GENERIC, | |
901 {'text': 'Error: Could not find "${MAIN.slowToString()}". ' | |
902 'No source will be analyzed. ' | |
903 'Use "--analyze-all" to analyze all code in the library.'}); | |
904 } | |
905 } else { | |
906 if (!main.isFunction()) { | |
907 reportFatalError( | |
908 main, | |
909 MessageKind.GENERIC, | |
910 {'text': 'Error: "${MAIN.slowToString()}" is not a function.'}); | |
911 } | |
912 FunctionElement mainMethod = main; | |
913 FunctionSignature parameters = mainMethod.computeSignature(this); | |
914 parameters.forEachParameter((Element parameter) { | |
915 reportError( | |
916 parameter, | |
917 MessageKind.GENERIC, | |
918 {'text': | |
919 'Error: "${MAIN.slowToString()}" cannot have parameters.'}); | |
920 }); | 946 }); |
921 } | 947 } |
948 }).then((_) { | |
949 if (uri != null) { | |
950 if (analyzeOnly) { | |
951 log('analyzing $uri ($buildId)'); | |
952 } else { | |
953 log('compiling $uri ($buildId)'); | |
954 } | |
955 return libraryLoader.loadLibrary(uri, null, uri) | |
956 .then((LibraryElement library) { | |
957 mainApp = library; | |
958 }); | |
959 } | |
960 }).then((_) { | |
961 Element main = null; | |
962 if (mainApp != null) { | |
963 main = mainApp.find(MAIN); | |
964 if (main == null) { | |
965 if (!analyzeOnly) { | |
966 // Allow analyze only of libraries with no main. | |
967 reportFatalError( | |
968 mainApp, | |
969 MessageKind.GENERIC, | |
970 {'text': 'Error: Could not find "${MAIN.slowToString()}".'}); | |
971 } else if (!analyzeAll) { | |
972 reportFatalError( | |
973 mainApp, | |
974 MessageKind.GENERIC, | |
975 {'text': 'Error: Could not find "${MAIN.slowToString()}". ' | |
976 'No source will be analyzed. ' | |
977 'Use "--analyze-all" to analyze all code in the library.'}); | |
978 } | |
979 } else { | |
980 if (!main.isFunction()) { | |
981 reportFatalError( | |
982 main, | |
983 MessageKind.GENERIC, | |
984 {'text': 'Error: "${MAIN.slowToString()}" is not a function.'}); | |
985 } | |
986 FunctionElement mainMethod = main; | |
987 FunctionSignature parameters = mainMethod.computeSignature(this); | |
988 parameters.forEachParameter((Element parameter) { | |
989 reportError( | |
990 parameter, | |
991 MessageKind.GENERIC, | |
992 {'text': | |
993 'Error: "${MAIN.slowToString()}" cannot have parameters.'}); | |
994 }); | |
995 } | |
922 | 996 |
923 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); | 997 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); |
924 | 998 |
925 // In order to see if a library is deferred, we must compute the | 999 // In order to see if a library is deferred, we must compute the |
926 // compile-time constants that are metadata. This means adding | 1000 // compile-time constants that are metadata. This means adding |
927 // something to the resolution queue. So we cannot wait with | 1001 // something to the resolution queue. So we cannot wait with |
928 // this until after the resolution queue is processed. | 1002 // this until after the resolution queue is processed. |
929 // TODO(ahe): Clean this up, for example, by not enqueueing | 1003 // TODO(ahe): Clean this up, for example, by not enqueueing |
930 // classes only used for metadata. | 1004 // classes only used for metadata. |
931 deferredLoadTask.findDeferredLibraries(mainApp); | 1005 deferredLoadTask.findDeferredLibraries(mainApp); |
932 } | 1006 } |
933 | 1007 |
934 log('Resolving...'); | 1008 log('Resolving...'); |
935 phase = PHASE_RESOLVING; | 1009 phase = PHASE_RESOLVING; |
936 if (analyzeAll) { | 1010 if (analyzeAll) { |
937 libraries.forEach( | 1011 libraries.forEach( |
938 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); | 1012 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); |
939 } | 1013 } |
940 // Elements required by enqueueHelpers are global dependencies | 1014 // Elements required by enqueueHelpers are global dependencies |
941 // that are not pulled in by a particular element. | 1015 // that are not pulled in by a particular element. |
942 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); | 1016 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); |
943 processQueue(enqueuer.resolution, main); | 1017 processQueue(enqueuer.resolution, main); |
944 enqueuer.resolution.logSummary(log); | 1018 enqueuer.resolution.logSummary(log); |
945 | 1019 |
946 if (compilationFailed) return; | 1020 if (compilationFailed) return; |
947 if (analyzeOnly) return; | 1021 if (analyzeOnly) return; |
948 assert(main != null); | 1022 assert(main != null); |
949 phase = PHASE_DONE_RESOLVING; | 1023 phase = PHASE_DONE_RESOLVING; |
950 | 1024 |
951 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution | 1025 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
952 // should know this. | 1026 // should know this. |
953 world.populate(); | 1027 world.populate(); |
954 // Compute whole-program-knowledge that the backend needs. (This might | 1028 // Compute whole-program-knowledge that the backend needs. (This might |
955 // require the information computed in [world.populate].) | 1029 // require the information computed in [world.populate].) |
956 backend.onResolutionComplete(); | 1030 backend.onResolutionComplete(); |
957 | 1031 |
958 deferredLoadTask.onResolutionComplete(main); | 1032 deferredLoadTask.onResolutionComplete(main); |
959 | 1033 |
960 log('Inferring types...'); | 1034 log('Inferring types...'); |
961 typesTask.onResolutionComplete(main); | 1035 typesTask.onResolutionComplete(main); |
962 | 1036 |
963 log('Compiling...'); | 1037 log('Compiling...'); |
964 phase = PHASE_COMPILING; | 1038 phase = PHASE_COMPILING; |
965 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. | 1039 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. |
966 if (hasIsolateSupport()) { | 1040 if (hasIsolateSupport()) { |
967 enqueuer.codegen.addToWorkList( | 1041 enqueuer.codegen.addToWorkList( |
968 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); | 1042 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); |
969 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); | 1043 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); |
970 } | 1044 } |
971 if (enabledNoSuchMethod) { | 1045 if (enabledNoSuchMethod) { |
972 enqueuer.codegen.registerInvocation(noSuchMethodSelector); | 1046 enqueuer.codegen.registerInvocation(noSuchMethodSelector); |
973 enqueuer.codegen.addToWorkList(createInvocationMirrorElement); | 1047 enqueuer.codegen.addToWorkList(createInvocationMirrorElement); |
974 } | 1048 } |
975 if (compileAll) { | 1049 if (compileAll) { |
976 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, enqueuer.codegen)); | 1050 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, |
977 } | 1051 enqueuer.codegen)); |
978 processQueue(enqueuer.codegen, main); | 1052 } |
979 enqueuer.codegen.logSummary(log); | 1053 processQueue(enqueuer.codegen, main); |
1054 enqueuer.codegen.logSummary(log); | |
980 | 1055 |
981 if (compilationFailed) return; | 1056 if (compilationFailed) return; |
982 | 1057 |
983 backend.assembleProgram(); | 1058 backend.assembleProgram(); |
984 | 1059 |
985 checkQueues(); | 1060 checkQueues(); |
986 | 1061 |
987 if (compilationFailed) { | 1062 if (compilationFailed) { |
988 assembledCode = null; // Signals failure. | 1063 assembledCode = null; // Signals failure. |
989 } | 1064 } |
1065 }); | |
990 } | 1066 } |
991 | 1067 |
992 void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) { | 1068 void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) { |
993 void enqueueAll(Element element) { | 1069 void enqueueAll(Element element) { |
994 fullyEnqueueTopLevelElement(element, world); | 1070 fullyEnqueueTopLevelElement(element, world); |
995 } | 1071 } |
996 library.implementation.forEachLocalMember(enqueueAll); | 1072 library.implementation.forEachLocalMember(enqueueAll); |
997 } | 1073 } |
998 | 1074 |
999 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) { | 1075 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) { |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1311 Uri translateResolvedUri(LibraryElement importingLibrary, | 1387 Uri translateResolvedUri(LibraryElement importingLibrary, |
1312 Uri resolvedUri, Node node) { | 1388 Uri resolvedUri, Node node) { |
1313 unimplemented('Compiler.translateResolvedUri'); | 1389 unimplemented('Compiler.translateResolvedUri'); |
1314 } | 1390 } |
1315 | 1391 |
1316 /** | 1392 /** |
1317 * Reads the script specified by the [readableUri]. | 1393 * Reads the script specified by the [readableUri]. |
1318 * | 1394 * |
1319 * See [LibraryLoader] for terminology on URIs. | 1395 * See [LibraryLoader] for terminology on URIs. |
1320 */ | 1396 */ |
1321 Script readScript(Uri readableUri, [Node node]) { | 1397 Future<Script> readScript(Uri readableUri, [Node node]) { |
1322 unimplemented('Compiler.readScript'); | 1398 unimplemented('Compiler.readScript'); |
1323 } | 1399 } |
1324 | 1400 |
1325 String get legDirectory { | 1401 String get legDirectory { |
1326 unimplemented('Compiler.legDirectory'); | 1402 unimplemented('Compiler.legDirectory'); |
1327 } | 1403 } |
1328 | 1404 |
1329 // TODO(karlklose): split into findHelperFunction and findHelperClass and | 1405 // TODO(karlklose): split into findHelperFunction and findHelperClass and |
1330 // add a check that the element has the expected kind. | 1406 // add a check that the element has the expected kind. |
1331 Element findHelper(SourceString name) | 1407 Element findHelper(SourceString name) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1455 * [invariant] as the argument to an [:assert:] statement: | 1531 * [invariant] as the argument to an [:assert:] statement: |
1456 * | 1532 * |
1457 * assert(invariant(position, isValid)); | 1533 * assert(invariant(position, isValid)); |
1458 * | 1534 * |
1459 * [spannable] must be non-null and will be used to provide positional | 1535 * [spannable] must be non-null and will be used to provide positional |
1460 * information in the generated error message. | 1536 * information in the generated error message. |
1461 */ | 1537 */ |
1462 bool invariant(Spannable spannable, var condition, {var message: null}) { | 1538 bool invariant(Spannable spannable, var condition, {var message: null}) { |
1463 // TODO(johnniwinther): Use [spannable] and [message] to provide better | 1539 // TODO(johnniwinther): Use [spannable] and [message] to provide better |
1464 // information on assertion errors. | 1540 // information on assertion errors. |
1541 if (spannable == null) { | |
1542 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | |
1543 "Spannable was null for invariant. Use CURRENT_ELEMENT_SPANNABLE."); | |
1544 } | |
1465 if (condition is Function){ | 1545 if (condition is Function){ |
1466 condition = condition(); | 1546 condition = condition(); |
1467 } | 1547 } |
1468 if (spannable == null || !condition) { | 1548 if (!condition) { |
1469 if (message is Function) { | 1549 if (message is Function) { |
1470 message = message(); | 1550 message = message(); |
1471 } | 1551 } |
1472 throw new SpannableAssertionFailure(spannable, message); | 1552 throw new SpannableAssertionFailure(spannable, message); |
1473 } | 1553 } |
1474 return true; | 1554 return true; |
1475 } | 1555 } |
1476 | 1556 |
1477 /// A sink that drains into /dev/null. | 1557 /// A sink that drains into /dev/null. |
1478 class NullSink implements EventSink<String> { | 1558 class NullSink implements EventSink<String> { |
1479 final String name; | 1559 final String name; |
1480 | 1560 |
1481 NullSink(this.name); | 1561 NullSink(this.name); |
1482 | 1562 |
1483 add(String value) {} | 1563 add(String value) {} |
1484 | 1564 |
1485 void addError(Object error) {} | 1565 void addError(Object error) {} |
1486 | 1566 |
1487 void close() {} | 1567 void close() {} |
1488 | 1568 |
1489 toString() => name; | 1569 toString() => name; |
1490 | 1570 |
1491 /// Convenience method for getting an [api.CompilerOutputProvider]. | 1571 /// Convenience method for getting an [api.CompilerOutputProvider]. |
1492 static NullSink outputProvider(String name, String extension) { | 1572 static NullSink outputProvider(String name, String extension) { |
1493 return new NullSink('$name.$extension'); | 1573 return new NullSink('$name.$extension'); |
1494 } | 1574 } |
1495 } | 1575 } |
OLD | NEW |