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

Side by Side Diff: pkg/compiler/lib/src/compiler.dart

Issue 1146813009: Introduce WorldImpact (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Rebased Created 5 years, 6 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
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 14 matching lines...) Expand all
25 * Invariant: [element] must be a declaration element. 25 * Invariant: [element] must be a declaration element.
26 */ 26 */
27 final AstElement element; 27 final AstElement element;
28 28
29 TreeElements get resolutionTree; 29 TreeElements get resolutionTree;
30 30
31 WorkItem(this.element, this.compilationContext) { 31 WorkItem(this.element, this.compilationContext) {
32 assert(invariant(element, element.isDeclaration)); 32 assert(invariant(element, element.isDeclaration));
33 } 33 }
34 34
35 void run(Compiler compiler, Enqueuer world); 35 WorldImpact run(Compiler compiler, Enqueuer world);
36 } 36 }
37 37
38 /// [WorkItem] used exclusively by the [ResolutionEnqueuer]. 38 /// [WorkItem] used exclusively by the [ResolutionEnqueuer].
39 class ResolutionWorkItem extends WorkItem { 39 class ResolutionWorkItem extends WorkItem {
40 TreeElements resolutionTree; 40 TreeElements resolutionTree;
41 41
42 ResolutionWorkItem(AstElement element, 42 ResolutionWorkItem(AstElement element,
43 ItemCompilationContext compilationContext) 43 ItemCompilationContext compilationContext)
44 : super(element, compilationContext); 44 : super(element, compilationContext);
45 45
46 void run(Compiler compiler, ResolutionEnqueuer world) { 46 WorldImpact run(Compiler compiler, ResolutionEnqueuer world) {
47 compiler.analyze(this, world); 47 WorldImpact impact = compiler.analyze(this, world);
48 resolutionTree = element.resolvedAst.elements; 48 resolutionTree = element.resolvedAst.elements;
49 return impact;
49 } 50 }
50 51
51 bool isAnalyzed() => resolutionTree != null; 52 bool isAnalyzed() => resolutionTree != null;
52 } 53 }
53 54
54 // TODO(johnniwinther): Split this class into interface and implementation. 55 // TODO(johnniwinther): Split this class into interface and implementation.
55 // TODO(johnniwinther): Move this implementation to the JS backend. 56 // TODO(johnniwinther): Move this implementation to the JS backend.
56 class CodegenRegistry extends Registry { 57 class CodegenRegistry extends Registry {
57 final Compiler compiler; 58 final Compiler compiler;
58 final TreeElements treeElements; 59 final TreeElements treeElements;
(...skipping 15 matching lines...) Expand all
74 treeElements.registerDependency(element); 75 treeElements.registerDependency(element);
75 } 76 }
76 77
77 void registerInlining(Element inlinedElement, Element context) { 78 void registerInlining(Element inlinedElement, Element context) {
78 if (compiler.dumpInfo) { 79 if (compiler.dumpInfo) {
79 compiler.dumpInfoTask.registerInlined(inlinedElement, context); 80 compiler.dumpInfoTask.registerInlined(inlinedElement, context);
80 } 81 }
81 } 82 }
82 83
83 void registerInstantiatedClass(ClassElement element) { 84 void registerInstantiatedClass(ClassElement element) {
84 world.registerInstantiatedClass(element, this); 85 world.registerInstantiatedType(element.rawType, this);
85 } 86 }
86 87
87 void registerInstantiatedType(InterfaceType type) { 88 void registerInstantiatedType(InterfaceType type) {
88 world.registerInstantiatedType(type, this); 89 world.registerInstantiatedType(type, this);
89 } 90 }
90 91
91 void registerStaticUse(Element element) { 92 void registerStaticUse(Element element) {
92 world.registerStaticUse(element); 93 world.registerStaticUse(element);
93 } 94 }
94 95
(...skipping 18 matching lines...) Expand all
113 114
114 void registerFieldGetter(Element element) { 115 void registerFieldGetter(Element element) {
115 world.registerFieldGetter(element); 116 world.registerFieldGetter(element);
116 } 117 }
117 118
118 void registerFieldSetter(Element element) { 119 void registerFieldSetter(Element element) {
119 world.registerFieldSetter(element); 120 world.registerFieldSetter(element);
120 } 121 }
121 122
122 void registerIsCheck(DartType type) { 123 void registerIsCheck(DartType type) {
123 world.registerIsCheck(type, this); 124 world.registerIsCheck(type);
124 backend.registerIsCheckForCodegen(type, world, this); 125 backend.registerIsCheckForCodegen(type, world, this);
125 } 126 }
126 127
127 void registerCompileTimeConstant(ConstantValue constant) { 128 void registerCompileTimeConstant(ConstantValue constant) {
128 backend.registerCompileTimeConstant(constant, this); 129 backend.registerCompileTimeConstant(constant, this);
129 backend.constants.addCompileTimeConstantForEmission(constant); 130 backend.constants.addCompileTimeConstantForEmission(constant);
130 } 131 }
131 132
132 void registerTypeVariableBoundsSubtypeCheck(DartType subtype, 133 void registerTypeVariableBoundsSubtypeCheck(DartType subtype,
133 DartType supertype) { 134 DartType supertype) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 180 }
180 181
181 void registerAsyncMarker(FunctionElement element) { 182 void registerAsyncMarker(FunctionElement element) {
182 backend.registerAsyncMarker(element, world, this); 183 backend.registerAsyncMarker(element, world, this);
183 } 184 }
184 185
185 } 186 }
186 187
187 /// [WorkItem] used exclusively by the [CodegenEnqueuer]. 188 /// [WorkItem] used exclusively by the [CodegenEnqueuer].
188 class CodegenWorkItem extends WorkItem { 189 class CodegenWorkItem extends WorkItem {
189 Registry registry; 190 CodegenRegistry registry;
190 191
191 factory CodegenWorkItem( 192 factory CodegenWorkItem(
192 Compiler compiler, 193 Compiler compiler,
193 AstElement element, 194 AstElement element,
194 ItemCompilationContext compilationContext) { 195 ItemCompilationContext compilationContext) {
195 // If this assertion fails, the resolution callbacks of the backend may be 196 // If this assertion fails, the resolution callbacks of the backend may be
196 // missing call of form registry.registerXXX. Alternatively, the code 197 // missing call of form registry.registerXXX. Alternatively, the code
197 // generation could spuriously be adding dependencies on things we know we 198 // generation could spuriously be adding dependencies on things we know we
198 // don't need. 199 // don't need.
199 assert(invariant(element, 200 assert(invariant(element,
200 compiler.enqueuer.resolution.hasBeenResolved(element), 201 compiler.enqueuer.resolution.hasBeenResolved(element),
201 message: "$element has not been resolved.")); 202 message: "$element has not been resolved."));
202 assert(invariant(element, element.resolvedAst.elements != null, 203 assert(invariant(element, element.resolvedAst.elements != null,
203 message: 'Resolution tree is null for $element in codegen work item')); 204 message: 'Resolution tree is null for $element in codegen work item'));
204 return new CodegenWorkItem.internal(element, compilationContext); 205 return new CodegenWorkItem.internal(element, compilationContext);
205 } 206 }
206 207
207 CodegenWorkItem.internal( 208 CodegenWorkItem.internal(
208 AstElement element, 209 AstElement element,
209 ItemCompilationContext compilationContext) 210 ItemCompilationContext compilationContext)
210 : super(element, compilationContext); 211 : super(element, compilationContext);
211 212
212 TreeElements get resolutionTree => element.resolvedAst.elements; 213 TreeElements get resolutionTree => element.resolvedAst.elements;
213 214
214 void run(Compiler compiler, CodegenEnqueuer world) { 215 WorldImpact run(Compiler compiler, CodegenEnqueuer world) {
215 if (world.isProcessed(element)) return; 216 if (world.isProcessed(element)) return const WorldImpact();
216 217
217 registry = new CodegenRegistry(compiler, resolutionTree); 218 registry = new CodegenRegistry(compiler, resolutionTree);
218 compiler.codegen(this, world); 219 return compiler.codegen(this, world);
219 } 220 }
220 } 221 }
221 222
222 typedef void DeferredAction(); 223 typedef void DeferredAction();
223 224
224 class DeferredTask { 225 class DeferredTask {
225 final Element element; 226 final Element element;
226 final DeferredAction action; 227 final DeferredAction action;
227 228
228 DeferredTask(this.element, this.action); 229 DeferredTask(this.element, this.action);
(...skipping 13 matching lines...) Expand all
242 243
243 void registerDynamicGetter(Selector selector); 244 void registerDynamicGetter(Selector selector);
244 245
245 void registerDynamicSetter(Selector selector); 246 void registerDynamicSetter(Selector selector);
246 247
247 void registerStaticInvocation(Element element); 248 void registerStaticInvocation(Element element);
248 249
249 void registerInstantiation(InterfaceType type); 250 void registerInstantiation(InterfaceType type);
250 251
251 void registerGetOfStaticFunction(FunctionElement element); 252 void registerGetOfStaticFunction(FunctionElement element);
252
253 void registerAsyncMarker(FunctionElement element);
254 } 253 }
255 254
256 abstract class Backend { 255 abstract class Backend {
257 final Compiler compiler; 256 final Compiler compiler;
258 257
259 Backend(this.compiler); 258 Backend(this.compiler);
260 259
261 /// The [ConstantSystem] used to interpret compile-time constants for this 260 /// The [ConstantSystem] used to interpret compile-time constants for this
262 /// backend. 261 /// backend.
263 ConstantSystem get constantSystem; 262 ConstantSystem get constantSystem;
(...skipping 16 matching lines...) Expand all
280 /// otherwise visible during resolution. 279 /// otherwise visible during resolution.
281 Iterable<ClassElement> classesRequiredForReflection = const []; 280 Iterable<ClassElement> classesRequiredForReflection = const [];
282 281
283 // Given a [FunctionElement], return a buffer with the code generated for it 282 // Given a [FunctionElement], return a buffer with the code generated for it
284 // or null if no code was generated. 283 // or null if no code was generated.
285 CodeBuffer codeOf(Element element) => null; 284 CodeBuffer codeOf(Element element) => null;
286 285
287 void initializeHelperClasses() {} 286 void initializeHelperClasses() {}
288 287
289 void enqueueHelpers(ResolutionEnqueuer world, Registry registry); 288 void enqueueHelpers(ResolutionEnqueuer world, Registry registry);
290 void codegen(CodegenWorkItem work); 289 WorldImpact codegen(CodegenWorkItem work);
291 290
292 // The backend determines the native resolution enqueuer, with a no-op 291 // The backend determines the native resolution enqueuer, with a no-op
293 // default, so tools like dart2dart can ignore the native classes. 292 // default, so tools like dart2dart can ignore the native classes.
294 native.NativeEnqueuer nativeResolutionEnqueuer(world) { 293 native.NativeEnqueuer nativeResolutionEnqueuer(world) {
295 return new native.NativeEnqueuer(); 294 return new native.NativeEnqueuer();
296 } 295 }
297 native.NativeEnqueuer nativeCodegenEnqueuer(world) { 296 native.NativeEnqueuer nativeCodegenEnqueuer(world) {
298 return new native.NativeEnqueuer(); 297 return new native.NativeEnqueuer();
299 } 298 }
300 299
(...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 fullyEnqueueTopLevelElement(element, world); 1690 fullyEnqueueTopLevelElement(element, world);
1692 } 1691 }
1693 library.implementation.forEachLocalMember(enqueueAll); 1692 library.implementation.forEachLocalMember(enqueueAll);
1694 } 1693 }
1695 1694
1696 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) { 1695 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) {
1697 if (element.isClass) { 1696 if (element.isClass) {
1698 ClassElement cls = element; 1697 ClassElement cls = element;
1699 cls.ensureResolved(this); 1698 cls.ensureResolved(this);
1700 cls.forEachLocalMember(enqueuer.resolution.addToWorkList); 1699 cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
1701 world.registerInstantiatedClass(element, globalDependencies); 1700 world.registerInstantiatedType(cls.rawType, globalDependencies);
1702 } else { 1701 } else {
1703 world.addToWorkList(element); 1702 world.addToWorkList(element);
1704 } 1703 }
1705 } 1704 }
1706 1705
1707 // Resolves metadata on library elements. This is necessary in order to 1706 // Resolves metadata on library elements. This is necessary in order to
1708 // resolve metadata classes referenced only from metadata on library tags. 1707 // resolve metadata classes referenced only from metadata on library tags.
1709 // TODO(ahe): Figure out how to do this lazily. 1708 // TODO(ahe): Figure out how to do this lazily.
1710 void resolveLibraryMetadata() { 1709 void resolveLibraryMetadata() {
1711 for (LibraryElement library in libraryLoader.libraries) { 1710 for (LibraryElement library in libraryLoader.libraries) {
1712 if (library.metadata != null) { 1711 if (library.metadata != null) {
1713 for (MetadataAnnotation metadata in library.metadata) { 1712 for (MetadataAnnotation metadata in library.metadata) {
1714 metadata.ensureResolved(this); 1713 metadata.ensureResolved(this);
1715 } 1714 }
1716 } 1715 }
1717 } 1716 }
1718 } 1717 }
1719 1718
1720 void processQueue(Enqueuer world, Element main) { 1719 void processQueue(Enqueuer world, Element main) {
1721 world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries); 1720 world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
1722 if (main != null && !main.isErroneous) { 1721 if (main != null && !main.isErroneous) {
1723 FunctionElement mainMethod = main; 1722 FunctionElement mainMethod = main;
1724 if (mainMethod.computeSignature(this).parameterCount != 0) { 1723 if (mainMethod.computeSignature(this).parameterCount != 0) {
1725 // The first argument could be a list of strings. 1724 // The first argument could be a list of strings.
1726 world.registerInstantiatedClass( 1725 backend.listImplementation.ensureResolved(this);
1727 backend.listImplementation, globalDependencies); 1726 world.registerInstantiatedType(
1728 world.registerInstantiatedClass( 1727 backend.listImplementation.rawType, globalDependencies);
1729 backend.stringImplementation, globalDependencies); 1728 backend.stringImplementation.ensureResolved(this);
1729 world.registerInstantiatedType(
1730 backend.stringImplementation.rawType, globalDependencies);
1730 1731
1731 backend.registerMainHasArguments(world); 1732 backend.registerMainHasArguments(world);
1732 } 1733 }
1733 world.addToWorkList(main); 1734 world.addToWorkList(main);
1734 } 1735 }
1735 if (verbose) { 1736 if (verbose) {
1736 progress.reset(); 1737 progress.reset();
1737 } 1738 }
1738 world.forEach((WorkItem work) { 1739 world.forEach((WorkItem work) {
1739 withCurrentElement(work.element, () => work.run(this, world)); 1740 withCurrentElement(work.element, () {
1741 world.applyImpact(work.element, work.run(this, world));
1742 });
1740 }); 1743 });
1741 world.queueIsClosed = true; 1744 world.queueIsClosed = true;
1742 assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods()); 1745 assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
1743 } 1746 }
1744 1747
1745 /** 1748 /**
1746 * Perform various checks of the queues. This includes checking that 1749 * Perform various checks of the queues. This includes checking that
1747 * the queues are empty (nothing was added after we stopped 1750 * the queues are empty (nothing was added after we stopped
1748 * processing the queues). Also compute the number of methods that 1751 * processing the queues). Also compute the number of methods that
1749 * were resolved, but not compiled (aka excess resolution). 1752 * were resolved, but not compiled (aka excess resolution).
(...skipping 25 matching lines...) Expand all
1775 } 1778 }
1776 } 1779 }
1777 log('Excess resolution work: ${resolved.length}.'); 1780 log('Excess resolution work: ${resolved.length}.');
1778 for (Element e in resolved) { 1781 for (Element e in resolved) {
1779 reportWarning(e, 1782 reportWarning(e,
1780 MessageKind.GENERIC, 1783 MessageKind.GENERIC,
1781 {'text': 'Warning: $e resolved but not compiled.'}); 1784 {'text': 'Warning: $e resolved but not compiled.'});
1782 } 1785 }
1783 } 1786 }
1784 1787
1785 void analyzeElement(Element element) { 1788 WorldImpact analyzeElement(Element element) {
1786 assert(invariant(element, 1789 assert(invariant(element,
1787 element.impliesType || 1790 element.impliesType ||
1788 element.isField || 1791 element.isField ||
1789 element.isFunction || 1792 element.isFunction ||
1790 element.isGenerativeConstructor || 1793 element.isGenerativeConstructor ||
1791 element.isGetter || 1794 element.isGetter ||
1792 element.isSetter, 1795 element.isSetter,
1793 message: 'Unexpected element kind: ${element.kind}')); 1796 message: 'Unexpected element kind: ${element.kind}'));
1794 assert(invariant(element, element is AnalyzableElement, 1797 assert(invariant(element, element is AnalyzableElement,
1795 message: 'Element $element is not analyzable.')); 1798 message: 'Element $element is not analyzable.'));
1796 assert(invariant(element, element.isDeclaration)); 1799 assert(invariant(element, element.isDeclaration));
1797 ResolutionEnqueuer world = enqueuer.resolution; 1800 ResolutionEnqueuer world = enqueuer.resolution;
1798 if (world.hasBeenResolved(element)) return; 1801 if (world.hasBeenResolved(element)) {
1802 return const WorldImpact();
1803 }
1799 assert(parser != null); 1804 assert(parser != null);
1800 Node tree = parser.parse(element); 1805 Node tree = parser.parse(element);
1801 assert(invariant(element, !element.isSynthesized || tree == null)); 1806 assert(invariant(element, !element.isSynthesized || tree == null));
1802 TreeElements elements = resolver.resolve(element); 1807 WorldImpact worldImpact = resolver.resolve(element);
1803 if (elements != null) { 1808 if (tree != null && !analyzeSignaturesOnly &&
1804 if (tree != null && !analyzeSignaturesOnly && 1809 !suppressWarnings) {
1805 !suppressWarnings) { 1810 // Only analyze nodes with a corresponding [TreeElements].
1806 // Only analyze nodes with a corresponding [TreeElements]. 1811 checker.check(element);
1807 checker.check(elements);
1808 }
1809 world.registerResolvedElement(element);
1810 } 1812 }
1813 world.registerResolvedElement(element);
1814 return worldImpact;
1811 } 1815 }
1812 1816
1813 void analyze(ResolutionWorkItem work, ResolutionEnqueuer world) { 1817 WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) {
1814 assert(invariant(work.element, identical(world, enqueuer.resolution))); 1818 assert(invariant(work.element, identical(world, enqueuer.resolution)));
1815 assert(invariant(work.element, !work.isAnalyzed(), 1819 assert(invariant(work.element, !work.isAnalyzed(),
1816 message: 'Element ${work.element} has already been analyzed')); 1820 message: 'Element ${work.element} has already been analyzed'));
1817 if (shouldPrintProgress) { 1821 if (shouldPrintProgress) {
1818 // TODO(ahe): Add structured diagnostics to the compiler API and 1822 // TODO(ahe): Add structured diagnostics to the compiler API and
1819 // use it to separate this from the --verbose option. 1823 // use it to separate this from the --verbose option.
1820 if (phase == PHASE_RESOLVING) { 1824 if (phase == PHASE_RESOLVING) {
1821 log('Resolved ${enqueuer.resolution.resolvedElements.length} ' 1825 log('Resolved ${enqueuer.resolution.resolvedElements.length} '
1822 'elements.'); 1826 'elements.');
1823 progress.reset(); 1827 progress.reset();
1824 } 1828 }
1825 } 1829 }
1826 AstElement element = work.element; 1830 AstElement element = work.element;
1827 if (world.hasBeenResolved(element)) return; 1831 if (world.hasBeenResolved(element)) {
1828 analyzeElement(element); 1832 return const WorldImpact();
1833 }
1834 WorldImpact worldImpact = analyzeElement(element);
1829 backend.onElementResolved(element, element.resolvedAst.elements); 1835 backend.onElementResolved(element, element.resolvedAst.elements);
1836 return worldImpact;
1830 } 1837 }
1831 1838
1832 void codegen(CodegenWorkItem work, CodegenEnqueuer world) { 1839 WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) {
1833 assert(invariant(work.element, identical(world, enqueuer.codegen))); 1840 assert(invariant(work.element, identical(world, enqueuer.codegen)));
1834 if (shouldPrintProgress) { 1841 if (shouldPrintProgress) {
1835 // TODO(ahe): Add structured diagnostics to the compiler API and 1842 // TODO(ahe): Add structured diagnostics to the compiler API and
1836 // use it to separate this from the --verbose option. 1843 // use it to separate this from the --verbose option.
1837 log('Compiled ${enqueuer.codegen.generatedCode.length} methods.'); 1844 log('Compiled ${enqueuer.codegen.generatedCode.length} methods.');
1838 progress.reset(); 1845 progress.reset();
1839 } 1846 }
1840 backend.codegen(work); 1847 return backend.codegen(work);
1841 } 1848 }
1842 1849
1843 void reportError(Spannable node, 1850 void reportError(Spannable node,
1844 MessageKind messageKind, 1851 MessageKind messageKind,
1845 [Map arguments = const {}]) { 1852 [Map arguments = const {}]) {
1846 reportDiagnosticInternal( 1853 reportDiagnosticInternal(
1847 node, messageKind, arguments, api.Diagnostic.ERROR); 1854 node, messageKind, arguments, api.Diagnostic.ERROR);
1848 } 1855 }
1849 1856
1850 void reportWarning(Spannable node, MessageKind messageKind, 1857 void reportWarning(Spannable node, MessageKind messageKind,
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
2459 return futureClass.computeType(compiler).createInstantiation([elementType]); 2466 return futureClass.computeType(compiler).createInstantiation([elementType]);
2460 } 2467 }
2461 2468
2462 @override 2469 @override
2463 InterfaceType streamType([DartType elementType = const DynamicType()]) { 2470 InterfaceType streamType([DartType elementType = const DynamicType()]) {
2464 return streamClass.computeType(compiler).createInstantiation([elementType]); 2471 return streamClass.computeType(compiler).createInstantiation([elementType]);
2465 } 2472 }
2466 } 2473 }
2467 2474
2468 typedef void InternalErrorFunction(Spannable location, String message); 2475 typedef void InternalErrorFunction(Spannable location, String message);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/compile_time_constants.dart ('k') | pkg/compiler/lib/src/dart_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698