| 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 EventSink, Future; | 7 import 'dart:async' show EventSink, Future; |
| 8 | 8 |
| 9 import '../compiler_new.dart' as api; | 9 import '../compiler_new.dart' as api; |
| 10 import 'closure.dart' as closureMapping show ClosureTask; | 10 import 'closure.dart' as closureMapping show ClosureTask; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 DietParserTask dietParser; | 145 DietParserTask dietParser; |
| 146 ParserTask parser; | 146 ParserTask parser; |
| 147 PatchParserTask patchParser; | 147 PatchParserTask patchParser; |
| 148 LibraryLoaderTask libraryLoader; | 148 LibraryLoaderTask libraryLoader; |
| 149 SerializationTask serialization; | 149 SerializationTask serialization; |
| 150 ResolverTask resolver; | 150 ResolverTask resolver; |
| 151 closureMapping.ClosureTask closureToClassMapper; | 151 closureMapping.ClosureTask closureToClassMapper; |
| 152 TypeCheckerTask checker; | 152 TypeCheckerTask checker; |
| 153 GlobalTypeInferenceTask globalInference; | 153 GlobalTypeInferenceTask globalInference; |
| 154 JavaScriptBackend backend; | 154 JavaScriptBackend backend; |
| 155 CodegenWorldBuilder _codegenWorldBuilder; |
| 155 | 156 |
| 156 GenericTask selfTask; | 157 GenericTask selfTask; |
| 157 | 158 |
| 158 /// The constant environment for the frontend interpretation of compile-time | 159 /// The constant environment for the frontend interpretation of compile-time |
| 159 /// constants. | 160 /// constants. |
| 160 ConstantEnvironment constants; | 161 ConstantEnvironment constants; |
| 161 | 162 |
| 162 EnqueueTask enqueuer; | 163 EnqueueTask enqueuer; |
| 163 DeferredLoadTask deferredLoadTask; | 164 DeferredLoadTask deferredLoadTask; |
| 164 MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask; | 165 MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 274 |
| 274 /// Creates the resolver task. | 275 /// Creates the resolver task. |
| 275 /// | 276 /// |
| 276 /// Override this to mock the resolver for testing. | 277 /// Override this to mock the resolver for testing. |
| 277 ResolverTask createResolverTask() { | 278 ResolverTask createResolverTask() { |
| 278 return new ResolverTask(resolution, backend.constantCompilerTask, measurer); | 279 return new ResolverTask(resolution, backend.constantCompilerTask, measurer); |
| 279 } | 280 } |
| 280 | 281 |
| 281 ResolutionWorldBuilder get resolutionWorldBuilder => | 282 ResolutionWorldBuilder get resolutionWorldBuilder => |
| 282 enqueuer.resolution.worldBuilder; | 283 enqueuer.resolution.worldBuilder; |
| 283 CodegenWorldBuilder get codegenWorldBuilder => enqueuer.codegen.worldBuilder; | 284 CodegenWorldBuilder get codegenWorldBuilder { |
| 285 assert(invariant(NO_LOCATION_SPANNABLE, _codegenWorldBuilder != null, |
| 286 message: "CodegenWorldBuilder has not been created yet.")); |
| 287 return _codegenWorldBuilder; |
| 288 } |
| 284 | 289 |
| 285 bool get analyzeAll => options.analyzeAll || compileAll; | 290 bool get analyzeAll => options.analyzeAll || compileAll; |
| 286 | 291 |
| 287 bool get compileAll => false; | 292 bool get compileAll => false; |
| 288 | 293 |
| 289 bool get disableTypeInference => | 294 bool get disableTypeInference => |
| 290 options.disableTypeInference || compilationFailed; | 295 options.disableTypeInference || compilationFailed; |
| 291 | 296 |
| 292 // TODO(het): remove this from here. Either inline at all use sites or add it | 297 // TODO(het): remove this from here. Either inline at all use sites or add it |
| 293 // to Reporter. | 298 // to Reporter. |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 globalInference.runGlobalTypeInference( | 680 globalInference.runGlobalTypeInference( |
| 676 mainFunction, closedWorld, closedWorldRefiner); | 681 mainFunction, closedWorld, closedWorldRefiner); |
| 677 | 682 |
| 678 if (stopAfterTypeInference) return; | 683 if (stopAfterTypeInference) return; |
| 679 | 684 |
| 680 backend.onTypeInferenceComplete(); | 685 backend.onTypeInferenceComplete(); |
| 681 | 686 |
| 682 reporter.log('Compiling...'); | 687 reporter.log('Compiling...'); |
| 683 phase = PHASE_COMPILING; | 688 phase = PHASE_COMPILING; |
| 684 | 689 |
| 685 codegenWorldBuilder.open(closedWorld); | 690 Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(closedWorld); |
| 686 enqueuer.codegen.applyImpact(backend.onCodegenStart(closedWorld)); | 691 _codegenWorldBuilder = codegenEnqueuer.worldBuilder; |
| 692 _codegenWorldBuilder.open(closedWorld); |
| 693 codegenEnqueuer.applyImpact( |
| 694 backend.onCodegenStart(closedWorld, _codegenWorldBuilder)); |
| 687 if (compileAll) { | 695 if (compileAll) { |
| 688 libraryLoader.libraries.forEach((LibraryElement library) { | 696 libraryLoader.libraries.forEach((LibraryElement library) { |
| 689 enqueuer.codegen.applyImpact(computeImpactForLibrary(library)); | 697 codegenEnqueuer.applyImpact(computeImpactForLibrary(library)); |
| 690 }); | 698 }); |
| 691 } | 699 } |
| 692 processQueue(enqueuer.codegen, mainMethod, libraryLoader.libraries, | 700 processQueue(codegenEnqueuer, mainMethod, libraryLoader.libraries, |
| 693 onProgress: showCodegenProgress); | 701 onProgress: showCodegenProgress); |
| 694 enqueuer.codegen.logSummary(reporter.log); | 702 codegenEnqueuer.logSummary(reporter.log); |
| 695 | 703 |
| 696 int programSize = backend.assembleProgram(closedWorld); | 704 int programSize = backend.assembleProgram(closedWorld); |
| 697 | 705 |
| 698 if (options.dumpInfo) { | 706 if (options.dumpInfo) { |
| 699 dumpInfoTask.reportSize(programSize); | 707 dumpInfoTask.reportSize(programSize); |
| 700 dumpInfoTask.dumpInfo(closedWorld); | 708 dumpInfoTask.dumpInfo(closedWorld); |
| 701 } | 709 } |
| 702 | 710 |
| 703 backend.onCodegenEnd(); | 711 backend.onCodegenEnd(); |
| 704 | 712 |
| 705 checkQueues(); | 713 checkQueues(enqueuer.resolution, codegenEnqueuer); |
| 706 }); | 714 }); |
| 707 | 715 |
| 708 /// Perform the steps needed to fully end the resolution phase. | 716 /// Perform the steps needed to fully end the resolution phase. |
| 709 ClosedWorldRefiner closeResolution() { | 717 ClosedWorldRefiner closeResolution() { |
| 710 phase = PHASE_DONE_RESOLVING; | 718 phase = PHASE_DONE_RESOLVING; |
| 711 | 719 |
| 712 ClosedWorldImpl world = resolutionWorldBuilder.closeWorld(reporter); | 720 ClosedWorldImpl world = resolutionWorldBuilder.closeWorld(reporter); |
| 713 // Compute whole-program-knowledge that the backend needs. (This might | 721 // Compute whole-program-knowledge that the backend needs. (This might |
| 714 // require the information computed in [world.closeWorld].) | 722 // require the information computed in [world.closeWorld].) |
| 715 backend.onResolutionComplete(world, world); | 723 backend.onResolutionComplete(world, world); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 for (MetadataAnnotation metadata in library.metadata) { | 793 for (MetadataAnnotation metadata in library.metadata) { |
| 786 metadata.ensureResolved(resolution); | 794 metadata.ensureResolved(resolution); |
| 787 } | 795 } |
| 788 } | 796 } |
| 789 } | 797 } |
| 790 } | 798 } |
| 791 | 799 |
| 792 /** | 800 /** |
| 793 * Empty the [enqueuer] queue. | 801 * Empty the [enqueuer] queue. |
| 794 */ | 802 */ |
| 795 void emptyQueue(Enqueuer enqueuer, {void onProgress()}) { | 803 void emptyQueue(Enqueuer enqueuer, {void onProgress(Enqueuer enqueuer)}) { |
| 796 selfTask.measureSubtask("Compiler.emptyQueue", () { | 804 selfTask.measureSubtask("Compiler.emptyQueue", () { |
| 797 enqueuer.forEach((WorkItem work) { | 805 enqueuer.forEach((WorkItem work) { |
| 798 if (onProgress != null) { | 806 if (onProgress != null) { |
| 799 onProgress(); | 807 onProgress(enqueuer); |
| 800 } | 808 } |
| 801 reporter.withCurrentElement( | 809 reporter.withCurrentElement( |
| 802 work.element, | 810 work.element, |
| 803 () => selfTask.measureSubtask("world.applyImpact", () { | 811 () => selfTask.measureSubtask("world.applyImpact", () { |
| 804 enqueuer.applyImpact( | 812 enqueuer.applyImpact( |
| 805 selfTask.measureSubtask("work.run", () => work.run()), | 813 selfTask.measureSubtask("work.run", () => work.run()), |
| 806 impactSource: work.element); | 814 impactSource: work.element); |
| 807 })); | 815 })); |
| 808 }); | 816 }); |
| 809 }); | 817 }); |
| 810 } | 818 } |
| 811 | 819 |
| 812 void processQueue(Enqueuer enqueuer, MethodElement mainMethod, | 820 void processQueue(Enqueuer enqueuer, MethodElement mainMethod, |
| 813 Iterable<LibraryEntity> libraries, | 821 Iterable<LibraryEntity> libraries, |
| 814 {void onProgress()}) { | 822 {void onProgress(Enqueuer enqueuer)}) { |
| 815 selfTask.measureSubtask("Compiler.processQueue", () { | 823 selfTask.measureSubtask("Compiler.processQueue", () { |
| 816 enqueuer.open(impactStrategy, mainMethod, libraries); | 824 enqueuer.open(impactStrategy, mainMethod, libraries); |
| 817 if (options.verbose) { | 825 if (options.verbose) { |
| 818 progress.reset(); | 826 progress.reset(); |
| 819 } | 827 } |
| 820 emptyQueue(enqueuer, onProgress: onProgress); | 828 emptyQueue(enqueuer, onProgress: onProgress); |
| 821 enqueuer.queueIsClosed = true; | 829 enqueuer.queueIsClosed = true; |
| 822 enqueuer.close(); | 830 enqueuer.close(); |
| 823 // Notify the impact strategy impacts are no longer needed for this | 831 // Notify the impact strategy impacts are no longer needed for this |
| 824 // enqueuer. | 832 // enqueuer. |
| 825 impactStrategy.onImpactUsed(enqueuer.impactUse); | 833 impactStrategy.onImpactUsed(enqueuer.impactUse); |
| 826 backend.onQueueClosed(); | 834 backend.onQueueClosed(); |
| 827 assert(compilationFailed || | 835 assert(compilationFailed || |
| 828 enqueuer.checkNoEnqueuedInvokedInstanceMethods()); | 836 enqueuer.checkNoEnqueuedInvokedInstanceMethods()); |
| 829 }); | 837 }); |
| 830 } | 838 } |
| 831 | 839 |
| 832 /** | 840 /** |
| 833 * Perform various checks of the queues. This includes checking that | 841 * Perform various checks of the queues. This includes checking that |
| 834 * the queues are empty (nothing was added after we stopped | 842 * the queues are empty (nothing was added after we stopped |
| 835 * processing the queues). Also compute the number of methods that | 843 * processing the queues). Also compute the number of methods that |
| 836 * were resolved, but not compiled (aka excess resolution). | 844 * were resolved, but not compiled (aka excess resolution). |
| 837 */ | 845 */ |
| 838 checkQueues() { | 846 checkQueues(Enqueuer resolutionEnqueuer, Enqueuer codegenEnqueuer) { |
| 839 for (Enqueuer enqueuer in [enqueuer.resolution, enqueuer.codegen]) { | 847 for (Enqueuer enqueuer in [resolutionEnqueuer, codegenEnqueuer]) { |
| 840 enqueuer.checkQueueIsEmpty(); | 848 enqueuer.checkQueueIsEmpty(); |
| 841 } | 849 } |
| 842 if (!REPORT_EXCESS_RESOLUTION) return; | 850 if (!REPORT_EXCESS_RESOLUTION) return; |
| 843 var resolved = new Set.from(enqueuer.resolution.processedEntities); | 851 var resolved = new Set.from(resolutionEnqueuer.processedEntities); |
| 844 for (Element e in enqueuer.codegen.processedEntities) { | 852 for (Element e in codegenEnqueuer.processedEntities) { |
| 845 resolved.remove(e); | 853 resolved.remove(e); |
| 846 } | 854 } |
| 847 for (Element e in new Set.from(resolved)) { | 855 for (Element e in new Set.from(resolved)) { |
| 848 if (e.isClass || | 856 if (e.isClass || |
| 849 e.isField || | 857 e.isField || |
| 850 e.isTypeVariable || | 858 e.isTypeVariable || |
| 851 e.isTypedef || | 859 e.isTypedef || |
| 852 identical(e.kind, ElementKind.ABSTRACT_FIELD)) { | 860 identical(e.kind, ElementKind.ABSTRACT_FIELD)) { |
| 853 resolved.remove(e); | 861 resolved.remove(e); |
| 854 } | 862 } |
| 855 if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) { | 863 if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) { |
| 856 resolved.remove(e); | 864 resolved.remove(e); |
| 857 } | 865 } |
| 858 if (backend.isTargetSpecificLibrary(e.library)) { | 866 if (backend.isTargetSpecificLibrary(e.library)) { |
| 859 resolved.remove(e); | 867 resolved.remove(e); |
| 860 } | 868 } |
| 861 } | 869 } |
| 862 reporter.log('Excess resolution work: ${resolved.length}.'); | 870 reporter.log('Excess resolution work: ${resolved.length}.'); |
| 863 for (Element e in resolved) { | 871 for (Element e in resolved) { |
| 864 reporter.reportWarningMessage(e, MessageKind.GENERIC, | 872 reporter.reportWarningMessage(e, MessageKind.GENERIC, |
| 865 {'text': 'Warning: $e resolved but not compiled.'}); | 873 {'text': 'Warning: $e resolved but not compiled.'}); |
| 866 } | 874 } |
| 867 } | 875 } |
| 868 | 876 |
| 869 void showResolutionProgress() { | 877 void showResolutionProgress(Enqueuer enqueuer) { |
| 870 if (shouldPrintProgress) { | 878 if (shouldPrintProgress) { |
| 871 // TODO(ahe): Add structured diagnostics to the compiler API and | 879 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 872 // use it to separate this from the --verbose option. | 880 // use it to separate this from the --verbose option. |
| 873 assert(phase == PHASE_RESOLVING); | 881 assert(phase == PHASE_RESOLVING); |
| 874 reporter.log('Resolved ${enqueuer.resolution.processedEntities.length} ' | 882 reporter.log('Resolved ${enqueuer.processedEntities.length} ' |
| 875 'elements.'); | 883 'elements.'); |
| 876 progress.reset(); | 884 progress.reset(); |
| 877 } | 885 } |
| 878 } | 886 } |
| 879 | 887 |
| 880 void showCodegenProgress() { | 888 void showCodegenProgress(Enqueuer enqueuer) { |
| 881 if (shouldPrintProgress) { | 889 if (shouldPrintProgress) { |
| 882 // TODO(ahe): Add structured diagnostics to the compiler API and | 890 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 883 // use it to separate this from the --verbose option. | 891 // use it to separate this from the --verbose option. |
| 884 reporter.log( | 892 reporter.log('Compiled ${enqueuer.processedEntities.length} methods.'); |
| 885 'Compiled ${enqueuer.codegen.processedEntities.length} methods.'); | |
| 886 progress.reset(); | 893 progress.reset(); |
| 887 } | 894 } |
| 888 } | 895 } |
| 889 | 896 |
| 890 void reportDiagnostic(DiagnosticMessage message, | 897 void reportDiagnostic(DiagnosticMessage message, |
| 891 List<DiagnosticMessage> infos, api.Diagnostic kind); | 898 List<DiagnosticMessage> infos, api.Diagnostic kind); |
| 892 | 899 |
| 893 void reportCrashInUserCode(String message, exception, stackTrace) { | 900 void reportCrashInUserCode(String message, exception, stackTrace) { |
| 894 reporter.onCrashInUserCode(message, exception, stackTrace); | 901 reporter.onCrashInUserCode(message, exception, stackTrace); |
| 895 } | 902 } |
| (...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 } | 1826 } |
| 1820 return transformResolutionImpact(element, resolutionImpact); | 1827 return transformResolutionImpact(element, resolutionImpact); |
| 1821 }); | 1828 }); |
| 1822 }); | 1829 }); |
| 1823 } | 1830 } |
| 1824 | 1831 |
| 1825 @override | 1832 @override |
| 1826 WorldImpact transformResolutionImpact( | 1833 WorldImpact transformResolutionImpact( |
| 1827 Element element, ResolutionImpact resolutionImpact) { | 1834 Element element, ResolutionImpact resolutionImpact) { |
| 1828 WorldImpact worldImpact = _compiler.backend.impactTransformer | 1835 WorldImpact worldImpact = _compiler.backend.impactTransformer |
| 1829 .transformResolutionImpact( | 1836 .transformResolutionImpact(enqueuer, resolutionImpact); |
| 1830 _compiler.enqueuer.resolution, resolutionImpact); | |
| 1831 _worldImpactCache[element] = worldImpact; | 1837 _worldImpactCache[element] = worldImpact; |
| 1832 return worldImpact; | 1838 return worldImpact; |
| 1833 } | 1839 } |
| 1834 | 1840 |
| 1835 @override | 1841 @override |
| 1836 void uncacheWorldImpact(Element element) { | 1842 void uncacheWorldImpact(Element element) { |
| 1837 assert(invariant(element, element.isDeclaration, | 1843 assert(invariant(element, element.isDeclaration, |
| 1838 message: "Element $element must be the declaration.")); | 1844 message: "Element $element must be the declaration.")); |
| 1839 if (retainCachesForTesting) return; | 1845 if (retainCachesForTesting) return; |
| 1840 if (_compiler.serialization.isDeserialized(element)) return; | 1846 if (_compiler.serialization.isDeserialized(element)) return; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 if (library != null && library.isSynthesized) { | 2043 if (library != null && library.isSynthesized) { |
| 2038 return null; | 2044 return null; |
| 2039 } | 2045 } |
| 2040 if (library == null && required) { | 2046 if (library == null && required) { |
| 2041 throw new SpannableAssertionFailure( | 2047 throw new SpannableAssertionFailure( |
| 2042 library, "The library '${uri}' was not found."); | 2048 library, "The library '${uri}' was not found."); |
| 2043 } | 2049 } |
| 2044 return library; | 2050 return library; |
| 2045 } | 2051 } |
| 2046 } | 2052 } |
| OLD | NEW |