| 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 library dart2js.compiler_base; | 5 library dart2js.compiler_base; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import '../compiler_new.dart' as api; | 9 import '../compiler_new.dart' as api; |
| 10 import 'backend_strategy.dart'; | 10 import 'backend_strategy.dart'; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 /// Options provided from command-line arguments. | 101 /// Options provided from command-line arguments. |
| 102 final CompilerOptions options; | 102 final CompilerOptions options; |
| 103 | 103 |
| 104 /** | 104 /** |
| 105 * If true, stop compilation after type inference is complete. Used for | 105 * If true, stop compilation after type inference is complete. Used for |
| 106 * debugging and testing purposes only. | 106 * debugging and testing purposes only. |
| 107 */ | 107 */ |
| 108 bool stopAfterTypeInference = false; | 108 bool stopAfterTypeInference = false; |
| 109 | 109 |
| 110 /// Output provider from user of Compiler API. | 110 /// Output provider from user of Compiler API. |
| 111 api.CompilerOutput userOutputProvider; | 111 api.CompilerOutput _outputProvider; |
| 112 |
| 113 api.CompilerOutput get outputProvider => _outputProvider; |
| 112 | 114 |
| 113 List<Uri> librariesToAnalyzeWhenRun; | 115 List<Uri> librariesToAnalyzeWhenRun; |
| 114 | 116 |
| 115 ResolvedUriTranslator get resolvedUriTranslator; | 117 ResolvedUriTranslator get resolvedUriTranslator; |
| 116 | 118 |
| 117 Uri mainLibraryUri; | 119 Uri mainLibraryUri; |
| 118 | 120 |
| 119 ClosedWorld backendClosedWorldForTesting; | 121 ClosedWorld backendClosedWorldForTesting; |
| 120 | 122 |
| 121 DiagnosticReporter get reporter => _reporter; | 123 DiagnosticReporter get reporter => _reporter; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 /// constants. | 157 /// constants. |
| 156 ConstantEnvironment constants; | 158 ConstantEnvironment constants; |
| 157 | 159 |
| 158 EnqueueTask enqueuer; | 160 EnqueueTask enqueuer; |
| 159 DeferredLoadTask deferredLoadTask; | 161 DeferredLoadTask deferredLoadTask; |
| 160 MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask; | 162 MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask; |
| 161 DumpInfoTask dumpInfoTask; | 163 DumpInfoTask dumpInfoTask; |
| 162 | 164 |
| 163 bool get hasCrashed => _reporter.hasCrashed; | 165 bool get hasCrashed => _reporter.hasCrashed; |
| 164 | 166 |
| 165 Stopwatch progress; | 167 Progress progress = const Progress(); |
| 166 | |
| 167 bool get shouldPrintProgress { | |
| 168 return options.verbose && progress.elapsedMilliseconds > 500; | |
| 169 } | |
| 170 | 168 |
| 171 static const int PHASE_SCANNING = 0; | 169 static const int PHASE_SCANNING = 0; |
| 172 static const int PHASE_RESOLVING = 1; | 170 static const int PHASE_RESOLVING = 1; |
| 173 static const int PHASE_DONE_RESOLVING = 2; | 171 static const int PHASE_DONE_RESOLVING = 2; |
| 174 static const int PHASE_COMPILING = 3; | 172 static const int PHASE_COMPILING = 3; |
| 175 int phase; | 173 int phase; |
| 176 | 174 |
| 177 bool compilationFailed = false; | 175 bool compilationFailed = false; |
| 178 | 176 |
| 179 Compiler( | 177 Compiler( |
| 180 {CompilerOptions options, | 178 {CompilerOptions options, |
| 181 api.CompilerOutput outputProvider, | 179 api.CompilerOutput outputProvider, |
| 182 this.environment: const _EmptyEnvironment(), | 180 this.environment: const _EmptyEnvironment(), |
| 183 MakeReporterFunction makeReporter}) | 181 MakeReporterFunction makeReporter}) |
| 184 : this.options = options, | 182 : this.options = options { |
| 185 this.userOutputProvider = outputProvider == null | 183 _outputProvider = new _CompilerOutput(this, outputProvider); |
| 186 ? const NullCompilerOutput() | |
| 187 : outputProvider { | |
| 188 if (makeReporter != null) { | 184 if (makeReporter != null) { |
| 189 _reporter = makeReporter(this, options); | 185 _reporter = makeReporter(this, options); |
| 190 } else { | 186 } else { |
| 191 _reporter = new CompilerDiagnosticReporter(this, options); | 187 _reporter = new CompilerDiagnosticReporter(this, options); |
| 192 } | 188 } |
| 193 frontendStrategy = options.useKernel | 189 frontendStrategy = options.useKernel |
| 194 ? new KernelFrontEndStrategy(options, reporter, environment) | 190 ? new KernelFrontEndStrategy(options, reporter, environment) |
| 195 : new ResolutionFrontEndStrategy(this); | 191 : new ResolutionFrontEndStrategy(this); |
| 196 backendStrategy = options.useKernel | 192 backendStrategy = options.useKernel |
| 197 ? new KernelBackendStrategy(this) | 193 ? new KernelBackendStrategy(this) |
| 198 : new ElementBackendStrategy(this); | 194 : new ElementBackendStrategy(this); |
| 199 _resolution = createResolution(); | 195 _resolution = createResolution(); |
| 200 | 196 |
| 201 if (options.verbose) { | 197 if (options.verbose) { |
| 202 progress = new Stopwatch()..start(); | 198 progress = new ProgressImpl(_reporter); |
| 203 } | 199 } |
| 204 | 200 |
| 205 backend = createBackend(); | 201 backend = createBackend(); |
| 206 enqueuer = backend.makeEnqueuer(); | 202 enqueuer = backend.makeEnqueuer(); |
| 207 | 203 |
| 208 tasks = [ | 204 tasks = [ |
| 209 dietParser = new DietParserTask(idGenerator, backend, reporter, measurer), | 205 dietParser = new DietParserTask(idGenerator, backend, reporter, measurer), |
| 210 scanner = createScannerTask(), | 206 scanner = createScannerTask(), |
| 211 serialization = new SerializationTask(this), | 207 serialization = new SerializationTask(this), |
| 212 patchParser = new PatchParserTask(this), | 208 patchParser = new PatchParserTask(this), |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 | 471 |
| 476 /// Analyze all members of the library in [libraryUri]. | 472 /// Analyze all members of the library in [libraryUri]. |
| 477 /// | 473 /// |
| 478 /// If [skipLibraryWithPartOfTag] is `true`, member analysis is skipped if the | 474 /// If [skipLibraryWithPartOfTag] is `true`, member analysis is skipped if the |
| 479 /// library has a `part of` tag, assuming it is a part and not a library. | 475 /// library has a `part of` tag, assuming it is a part and not a library. |
| 480 /// | 476 /// |
| 481 /// This operation assumes an unclosed resolution queue and is only supported | 477 /// This operation assumes an unclosed resolution queue and is only supported |
| 482 /// when the '--analyze-main' option is used. | 478 /// when the '--analyze-main' option is used. |
| 483 Future<LibraryElement> analyzeUri(Uri libraryUri, | 479 Future<LibraryElement> analyzeUri(Uri libraryUri, |
| 484 {bool skipLibraryWithPartOfTag: true}) async { | 480 {bool skipLibraryWithPartOfTag: true}) async { |
| 481 phase = PHASE_RESOLVING; |
| 485 assert(options.analyzeMain); | 482 assert(options.analyzeMain); |
| 486 reporter.log('Analyzing $libraryUri (${options.buildId})'); | 483 reporter.log('Analyzing $libraryUri (${options.buildId})'); |
| 487 LoadedLibraries loadedLibraries = await libraryLoader | 484 LoadedLibraries loadedLibraries = await libraryLoader |
| 488 .loadLibrary(libraryUri, skipFileWithPartOfTag: true); | 485 .loadLibrary(libraryUri, skipFileWithPartOfTag: true); |
| 489 if (loadedLibraries == null) return null; | 486 if (loadedLibraries == null) return null; |
| 490 processLoadedLibraries(loadedLibraries); | 487 processLoadedLibraries(loadedLibraries); |
| 491 LibraryElement library = loadedLibraries.rootLibrary; | 488 LibraryElement library = loadedLibraries.rootLibrary; |
| 492 ResolutionEnqueuer resolutionEnqueuer = startResolution(); | 489 ResolutionEnqueuer resolutionEnqueuer = startResolution(); |
| 493 resolutionEnqueuer.applyImpact(computeImpactForLibrary(library)); | 490 resolutionEnqueuer.applyImpact(computeImpactForLibrary(library)); |
| 494 emptyQueue(resolutionEnqueuer, onProgress: showResolutionProgress); | 491 emptyQueue(resolutionEnqueuer, onProgress: showResolutionProgress); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 if (mainFunction == null) return; | 582 if (mainFunction == null) return; |
| 586 if (!backend | 583 if (!backend |
| 587 .enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) { | 584 .enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) { |
| 588 return; | 585 return; |
| 589 } | 586 } |
| 590 } | 587 } |
| 591 | 588 |
| 592 if (options.resolveOnly && !compilationFailed) { | 589 if (options.resolveOnly && !compilationFailed) { |
| 593 reporter.log('Serializing to ${options.resolutionOutput}'); | 590 reporter.log('Serializing to ${options.resolutionOutput}'); |
| 594 serialization.serializeToSink( | 591 serialization.serializeToSink( |
| 595 userOutputProvider.createOutputSink( | 592 outputProvider.createOutputSink( |
| 596 '', 'data', api.OutputType.serializationData), | 593 '', 'data', api.OutputType.serializationData), |
| 597 libraryLoader.libraries.where((LibraryEntity library) { | 594 libraryLoader.libraries.where((LibraryEntity library) { |
| 598 return !serialization.isDeserialized(library); | 595 return !serialization.isDeserialized(library); |
| 599 })); | 596 })); |
| 600 } | 597 } |
| 601 if (options.analyzeOnly) return; | 598 if (options.analyzeOnly) return; |
| 602 assert(mainFunction != null); | 599 assert(mainFunction != null); |
| 603 | 600 |
| 604 ClosedWorldRefiner closedWorldRefiner = closeResolution(mainFunction); | 601 ClosedWorldRefiner closedWorldRefiner = closeResolution(mainFunction); |
| 605 ClosedWorld closedWorld = closedWorldRefiner.closedWorld; | 602 ClosedWorld closedWorld = closedWorldRefiner.closedWorld; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 })); | 751 })); |
| 755 }); | 752 }); |
| 756 }); | 753 }); |
| 757 } | 754 } |
| 758 | 755 |
| 759 void processQueue(ElementEnvironment elementEnvironment, Enqueuer enqueuer, | 756 void processQueue(ElementEnvironment elementEnvironment, Enqueuer enqueuer, |
| 760 FunctionEntity mainMethod, Iterable<LibraryEntity> libraries, | 757 FunctionEntity mainMethod, Iterable<LibraryEntity> libraries, |
| 761 {void onProgress(Enqueuer enqueuer)}) { | 758 {void onProgress(Enqueuer enqueuer)}) { |
| 762 selfTask.measureSubtask("Compiler.processQueue", () { | 759 selfTask.measureSubtask("Compiler.processQueue", () { |
| 763 enqueuer.open(impactStrategy, mainMethod, libraries); | 760 enqueuer.open(impactStrategy, mainMethod, libraries); |
| 764 if (options.verbose) { | 761 progress.startPhase(); |
| 765 progress.reset(); | |
| 766 } | |
| 767 emptyQueue(enqueuer, onProgress: onProgress); | 762 emptyQueue(enqueuer, onProgress: onProgress); |
| 768 enqueuer.queueIsClosed = true; | 763 enqueuer.queueIsClosed = true; |
| 769 enqueuer.close(); | 764 enqueuer.close(); |
| 770 // Notify the impact strategy impacts are no longer needed for this | 765 // Notify the impact strategy impacts are no longer needed for this |
| 771 // enqueuer. | 766 // enqueuer. |
| 772 impactStrategy.onImpactUsed(enqueuer.impactUse); | 767 impactStrategy.onImpactUsed(enqueuer.impactUse); |
| 773 assert(compilationFailed || | 768 assert(compilationFailed || |
| 774 enqueuer.checkNoEnqueuedInvokedInstanceMethods(elementEnvironment)); | 769 enqueuer.checkNoEnqueuedInvokedInstanceMethods(elementEnvironment)); |
| 775 }); | 770 }); |
| 776 } | 771 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 802 } | 797 } |
| 803 } | 798 } |
| 804 reporter.log('Excess resolution work: ${resolved.length}.'); | 799 reporter.log('Excess resolution work: ${resolved.length}.'); |
| 805 for (MemberEntity e in resolved) { | 800 for (MemberEntity e in resolved) { |
| 806 reporter.reportWarningMessage(e, MessageKind.GENERIC, | 801 reporter.reportWarningMessage(e, MessageKind.GENERIC, |
| 807 {'text': 'Warning: $e resolved but not compiled.'}); | 802 {'text': 'Warning: $e resolved but not compiled.'}); |
| 808 } | 803 } |
| 809 } | 804 } |
| 810 | 805 |
| 811 void showResolutionProgress(Enqueuer enqueuer) { | 806 void showResolutionProgress(Enqueuer enqueuer) { |
| 812 if (shouldPrintProgress) { | 807 assert(phase == PHASE_RESOLVING, 'Unexpected phase: $phase'); |
| 813 // TODO(ahe): Add structured diagnostics to the compiler API and | 808 progress.showProgress( |
| 814 // use it to separate this from the --verbose option. | 809 'Resolved ', enqueuer.processedEntities.length, ' elements.'); |
| 815 assert(phase == PHASE_RESOLVING); | |
| 816 reporter.log('Resolved ${enqueuer.processedEntities.length} ' | |
| 817 'elements.'); | |
| 818 progress.reset(); | |
| 819 } | |
| 820 } | 810 } |
| 821 | 811 |
| 822 void showCodegenProgress(Enqueuer enqueuer) { | 812 void showCodegenProgress(Enqueuer enqueuer) { |
| 823 if (shouldPrintProgress) { | 813 progress.showProgress( |
| 824 // TODO(ahe): Add structured diagnostics to the compiler API and | 814 'Compiled ', enqueuer.processedEntities.length, ' methods.'); |
| 825 // use it to separate this from the --verbose option. | |
| 826 reporter.log('Compiled ${enqueuer.processedEntities.length} methods.'); | |
| 827 progress.reset(); | |
| 828 } | |
| 829 } | 815 } |
| 830 | 816 |
| 831 void reportDiagnostic(DiagnosticMessage message, | 817 void reportDiagnostic(DiagnosticMessage message, |
| 832 List<DiagnosticMessage> infos, api.Diagnostic kind); | 818 List<DiagnosticMessage> infos, api.Diagnostic kind); |
| 833 | 819 |
| 834 void reportCrashInUserCode(String message, exception, stackTrace) { | 820 void reportCrashInUserCode(String message, exception, stackTrace) { |
| 835 reporter.onCrashInUserCode(message, exception, stackTrace); | 821 reporter.onCrashInUserCode(message, exception, stackTrace); |
| 836 } | 822 } |
| 837 | 823 |
| 838 /// Messages for which compile-time errors are reported but compilation | 824 /// Messages for which compile-time errors are reported but compilation |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 // Record as global error. | 952 // Record as global error. |
| 967 // TODO(zarah): Extend element model to represent compile-time | 953 // TODO(zarah): Extend element model to represent compile-time |
| 968 // errors instead of using a map. | 954 // errors instead of using a map. |
| 969 element = frontendStrategy.elementEnvironment.mainFunction; | 955 element = frontendStrategy.elementEnvironment.mainFunction; |
| 970 } | 956 } |
| 971 elementsWithCompileTimeErrors | 957 elementsWithCompileTimeErrors |
| 972 .putIfAbsent(element, () => <DiagnosticMessage>[]) | 958 .putIfAbsent(element, () => <DiagnosticMessage>[]) |
| 973 .add(message); | 959 .add(message); |
| 974 } | 960 } |
| 975 } | 961 } |
| 962 } |
| 976 | 963 |
| 977 api.OutputSink outputProvider( | 964 class _CompilerOutput implements api.CompilerOutput { |
| 965 final Compiler _compiler; |
| 966 final api.CompilerOutput _userOutput; |
| 967 |
| 968 _CompilerOutput(this._compiler, api.CompilerOutput output) |
| 969 : this._userOutput = output ?? const NullCompilerOutput(); |
| 970 |
| 971 @override |
| 972 api.OutputSink createOutputSink( |
| 978 String name, String extension, api.OutputType type) { | 973 String name, String extension, api.OutputType type) { |
| 979 if (compilationFailed) { | 974 if (_compiler.compilationFailed) { |
| 980 if (!options.generateCodeWithCompileTimeErrors || options.testMode) { | 975 if (!_compiler.options.generateCodeWithCompileTimeErrors || |
| 976 _compiler.options.testMode) { |
| 981 // Disable output in test mode: The build bot currently uses the time | 977 // Disable output in test mode: The build bot currently uses the time |
| 982 // stamp of the generated file to determine whether the output is | 978 // stamp of the generated file to determine whether the output is |
| 983 // up-to-date. | 979 // up-to-date. |
| 984 return NullSink.outputProvider(name, extension, type); | 980 return NullSink.outputProvider(name, extension, type); |
| 985 } | 981 } |
| 986 } | 982 } |
| 987 return userOutputProvider.createOutputSink(name, extension, type); | 983 return _userOutput.createOutputSink(name, extension, type); |
| 988 } | 984 } |
| 989 } | 985 } |
| 990 | 986 |
| 991 /// Information about suppressed warnings and hints for a given library. | 987 /// Information about suppressed warnings and hints for a given library. |
| 992 class SuppressionInfo { | 988 class SuppressionInfo { |
| 993 int warnings = 0; | 989 int warnings = 0; |
| 994 int hints = 0; | 990 int hints = 0; |
| 995 } | 991 } |
| 996 | 992 |
| 997 class CompilerDiagnosticReporter extends DiagnosticReporter { | 993 class CompilerDiagnosticReporter extends DiagnosticReporter { |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 _ElementScanner(this.scanner); | 1601 _ElementScanner(this.scanner); |
| 1606 void scanLibrary(LibraryElement library) => scanner.scanLibrary(library); | 1602 void scanLibrary(LibraryElement library) => scanner.scanLibrary(library); |
| 1607 void scanUnit(CompilationUnitElement unit) => scanner.scan(unit); | 1603 void scanUnit(CompilationUnitElement unit) => scanner.scan(unit); |
| 1608 } | 1604 } |
| 1609 | 1605 |
| 1610 class _EmptyEnvironment implements Environment { | 1606 class _EmptyEnvironment implements Environment { |
| 1611 const _EmptyEnvironment(); | 1607 const _EmptyEnvironment(); |
| 1612 | 1608 |
| 1613 String valueOf(String key) => null; | 1609 String valueOf(String key) => null; |
| 1614 } | 1610 } |
| 1611 |
| 1612 /// Interface for showing progress during compilation. |
| 1613 class Progress { |
| 1614 const Progress(); |
| 1615 |
| 1616 /// Starts a new phase for which to show progress. |
| 1617 void startPhase() {} |
| 1618 |
| 1619 /// Shows progress of the current phase if needed. The shown message is |
| 1620 /// computed as '$prefix$count$suffix'. |
| 1621 void showProgress(String prefix, int count, String suffix) {} |
| 1622 } |
| 1623 |
| 1624 /// Progress implementations that prints progress to the [DiagnosticReporter] |
| 1625 /// with 500ms intervals. |
| 1626 class ProgressImpl implements Progress { |
| 1627 final DiagnosticReporter _reporter; |
| 1628 final Stopwatch _stopwatch = new Stopwatch()..start(); |
| 1629 |
| 1630 ProgressImpl(this._reporter); |
| 1631 |
| 1632 void showProgress(String prefix, int count, String suffix) { |
| 1633 if (_stopwatch.elapsedMilliseconds > 500) { |
| 1634 _reporter.log('$prefix$count$suffix'); |
| 1635 _stopwatch.reset(); |
| 1636 } |
| 1637 } |
| 1638 |
| 1639 void startPhase() { |
| 1640 _stopwatch.reset(); |
| 1641 } |
| 1642 } |
| OLD | NEW |