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 | 5 |
6 /** | 6 /** |
7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
8 * compiled. | 8 * compiled. |
9 */ | 9 */ |
10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
11 | 11 |
12 /** | 12 /** |
13 * If true, trace information on pass2 optimizations. | 13 * If true, trace information on pass2 optimizations. |
14 */ | 14 */ |
15 final bool REPORT_PASS2_OPTIMIZATIONS = false; | 15 final bool REPORT_PASS2_OPTIMIZATIONS = false; |
16 | 16 |
17 class WorkItem { | 17 class WorkItem { |
18 final Element element; | 18 final Element element; |
19 TreeElements resolutionTree; | 19 TreeElements resolutionTree; |
20 bool allowSpeculativeOptimization = true; | 20 bool allowSpeculativeOptimization = true; |
21 List<HTypeGuard> guards = const <HTypeGuard>[]; | 21 List<HTypeGuard> guards = const <HTypeGuard>[]; |
22 | 22 |
23 WorkItem(this.element, this.resolutionTree); | 23 WorkItem(this.element, this.resolutionTree); |
24 | 24 |
25 bool isAnalyzed() => resolutionTree !== null; | 25 bool isAnalyzed() => resolutionTree !== null; |
26 | 26 |
27 String run(Compiler compiler, Enqueuer world) { | 27 String run(Compiler compiler, Enqueuer world) { |
28 CodeBlock codeBlock = world.universe.generatedCode[element]; | 28 CodeBuffer codeBuffer = world.universe.generatedCode[element]; |
29 if (codeBlock !== null) return codeBlock.code; | 29 if (codeBuffer !== null) return codeBuffer.toString(); |
30 resolutionTree = compiler.analyze(this, world); | 30 resolutionTree = compiler.analyze(this, world); |
31 return compiler.codegen(this, world); | 31 return compiler.codegen(this, world); |
32 } | 32 } |
33 } | 33 } |
34 | 34 |
35 class Backend { | 35 class Backend { |
36 final Compiler compiler; | 36 final Compiler compiler; |
37 | 37 |
38 Backend(this.compiler); | 38 Backend(this.compiler); |
39 | 39 |
40 void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) { | 40 void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) { |
41 lib.forEachExport((Element e) { | 41 lib.forEachExport((Element e) { |
42 if (e.isFunction()) world.addToWorkList(e); | 42 if (e.isFunction()) world.addToWorkList(e); |
43 }); | 43 }); |
44 } | 44 } |
45 | 45 |
46 abstract void enqueueHelpers(Enqueuer world); | 46 abstract void enqueueHelpers(Enqueuer world); |
47 abstract CodeBlock codegen(WorkItem work); | 47 abstract CodeBuffer codegen(WorkItem work); |
48 abstract void processNativeClasses(Enqueuer world, | 48 abstract void processNativeClasses(Enqueuer world, |
49 Collection<LibraryElement> libraries); | 49 Collection<LibraryElement> libraries); |
50 abstract void assembleProgram(); | 50 abstract void assembleProgram(); |
51 abstract List<CompilerTask> get tasks(); | 51 abstract List<CompilerTask> get tasks(); |
52 } | 52 } |
53 | 53 |
54 class JavaScriptBackend extends Backend { | 54 class JavaScriptBackend extends Backend { |
55 SsaBuilderTask builder; | 55 SsaBuilderTask builder; |
56 SsaOptimizerTask optimizer; | 56 SsaOptimizerTask optimizer; |
57 SsaCodeGeneratorTask generator; | 57 SsaCodeGeneratorTask generator; |
(...skipping 21 matching lines...) Expand all Loading... |
79 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); | 79 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world); |
80 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); | 80 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world); |
81 for (var helper in [const SourceString('Closure'), | 81 for (var helper in [const SourceString('Closure'), |
82 const SourceString('ConstantMap'), | 82 const SourceString('ConstantMap'), |
83 const SourceString('ConstantProtoMap')]) { | 83 const SourceString('ConstantProtoMap')]) { |
84 var e = compiler.findHelper(helper); | 84 var e = compiler.findHelper(helper); |
85 if (e !== null) world.registerInstantiatedClass(e); | 85 if (e !== null) world.registerInstantiatedClass(e); |
86 } | 86 } |
87 } | 87 } |
88 | 88 |
89 CodeBlock codegen(WorkItem work) { | 89 CodeBuffer codegen(WorkItem work) { |
90 HGraph graph = builder.build(work); | 90 HGraph graph = builder.build(work); |
91 optimizer.optimize(work, graph); | 91 optimizer.optimize(work, graph); |
92 if (work.allowSpeculativeOptimization | 92 if (work.allowSpeculativeOptimization |
93 && optimizer.trySpeculativeOptimizations(work, graph)) { | 93 && optimizer.trySpeculativeOptimizations(work, graph)) { |
94 CodeBlock codeBlock = generator.generateBailoutMethod(work, graph); | 94 CodeBuffer codeBuffer = generator.generateBailoutMethod(work, graph); |
95 compiler.codegenWorld.addBailoutCode(work, codeBlock); | 95 compiler.codegenWorld.addBailoutCode(work, codeBuffer); |
96 optimizer.prepareForSpeculativeOptimizations(work, graph); | 96 optimizer.prepareForSpeculativeOptimizations(work, graph); |
97 optimizer.optimize(work, graph); | 97 optimizer.optimize(work, graph); |
98 } | 98 } |
99 return generator.generateMethod(work, graph); | 99 return generator.generateMethod(work, graph); |
100 } | 100 } |
101 | 101 |
102 void processNativeClasses(Enqueuer world, | 102 void processNativeClasses(Enqueuer world, |
103 Collection<LibraryElement> libraries) { | 103 Collection<LibraryElement> libraries) { |
104 native.processNativeClasses(world, emitter, libraries); | 104 native.processNativeClasses(world, emitter, libraries); |
105 } | 105 } |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 }); | 766 }); |
767 world.queueIsClosed = true; | 767 world.queueIsClosed = true; |
768 assert(world.checkNoEnqueuedInvokedInstanceMethods()); | 768 assert(world.checkNoEnqueuedInvokedInstanceMethods()); |
769 world.registerFieldClosureInvocations(); | 769 world.registerFieldClosureInvocations(); |
770 } | 770 } |
771 | 771 |
772 void processRecompilationQueue(Enqueuer world) { | 772 void processRecompilationQueue(Enqueuer world) { |
773 assert(phase == PHASE_RECOMPILING); | 773 assert(phase == PHASE_RECOMPILING); |
774 while (!world.recompilationCandidates.isEmpty()) { | 774 while (!world.recompilationCandidates.isEmpty()) { |
775 WorkItem work = world.recompilationCandidates.next(); | 775 WorkItem work = world.recompilationCandidates.next(); |
776 String oldCode = world.universe.generatedCode[work.element].code; | 776 CodeBuffer oldCode = world.universe.generatedCode[work.element]; |
777 world.universe.generatedCode.remove(work.element); | 777 world.universe.generatedCode.remove(work.element); |
778 world.universe.generatedBailoutCode.remove(work.element); | 778 world.universe.generatedBailoutCode.remove(work.element); |
779 withCurrentElement(work.element, () => work.run(this, world)); | 779 withCurrentElement(work.element, () => work.run(this, world)); |
780 String newCode = world.universe.generatedCode[work.element].code; | 780 CodeBuffer newCode = world.universe.generatedCode[work.element]; |
781 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { | 781 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { |
782 log("Pass 2 optimization:"); | 782 log("Pass 2 optimization:"); |
783 log("Before:\n$oldCode"); | 783 log("Before:\n$oldCode"); |
784 log("After:\n$newCode"); | 784 log("After:\n$newCode"); |
785 } | 785 } |
786 } | 786 } |
787 } | 787 } |
788 | 788 |
789 /** | 789 /** |
790 * Perform various checks of the queues. This includes checking that | 790 * Perform various checks of the queues. This includes checking that |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 890 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
891 } else { | 891 } else { |
892 log('Recompiled ${world.recompilationCandidates.processed} methods.'); | 892 log('Recompiled ${world.recompilationCandidates.processed} methods.'); |
893 } | 893 } |
894 progress.reset(); | 894 progress.reset(); |
895 } | 895 } |
896 if (work.element.kind.category == ElementCategory.VARIABLE) { | 896 if (work.element.kind.category == ElementCategory.VARIABLE) { |
897 constantHandler.compileWorkItem(work); | 897 constantHandler.compileWorkItem(work); |
898 return null; | 898 return null; |
899 } else { | 899 } else { |
900 CodeBlock codeBlock = backend.codegen(work); | 900 CodeBuffer codeBuffer = backend.codegen(work); |
901 codegenWorld.addGeneratedCode(work, codeBlock); | 901 codegenWorld.addGeneratedCode(work, codeBuffer); |
902 return codeBlock.code; | 902 return codeBuffer.toString(); |
903 } | 903 } |
904 } | 904 } |
905 | 905 |
906 void registerInstantiatedClass(ClassElement cls) { | 906 void registerInstantiatedClass(ClassElement cls) { |
907 enqueuer.resolution.registerInstantiatedClass(cls); | 907 enqueuer.resolution.registerInstantiatedClass(cls); |
908 enqueuer.codegen.registerInstantiatedClass(cls); | 908 enqueuer.codegen.registerInstantiatedClass(cls); |
909 } | 909 } |
910 | 910 |
911 void resolveClass(ClassElement element) { | 911 void resolveClass(ClassElement element) { |
912 withCurrentElement(element, () => resolver.resolveClass(element)); | 912 withCurrentElement(element, () => resolver.resolveClass(element)); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 final endOffset = end.charOffset + end.slowCharCount; | 1085 final endOffset = end.charOffset + end.slowCharCount; |
1086 | 1086 |
1087 // [begin] and [end] might be the same for the same empty token. This | 1087 // [begin] and [end] might be the same for the same empty token. This |
1088 // happens for instance when scanning '$$'. | 1088 // happens for instance when scanning '$$'. |
1089 assert(endOffset >= beginOffset); | 1089 assert(endOffset >= beginOffset); |
1090 return f(beginOffset, endOffset); | 1090 return f(beginOffset, endOffset); |
1091 } | 1091 } |
1092 | 1092 |
1093 String toString() => 'SourceSpan($uri, $begin, $end)'; | 1093 String toString() => 'SourceSpan($uri, $begin, $end)'; |
1094 } | 1094 } |
OLD | NEW |