| 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 String code = world.universe.generatedCode[element]; | 28 CodeBlock codeBlock = world.universe.generatedCode[element]; |
| 29 if (code !== null) return code; | 29 if (codeBlock !== null) return codeBlock.code; |
| 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 String codegen(WorkItem work); | 47 abstract CodeBlock 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 String codegen(WorkItem work) { | 89 CodeBlock 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 String code = generator.generateBailoutMethod(work, graph); | 94 CodeBlock codeBlock = generator.generateBailoutMethod(work, graph); |
| 95 compiler.codegenWorld.addBailoutCode(work, code); | 95 compiler.codegenWorld.addBailoutCode(work, codeBlock); |
| 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 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 }); | 573 }); |
| 574 world.queueIsClosed = true; | 574 world.queueIsClosed = true; |
| 575 assert(world.checkNoEnqueuedInvokedInstanceMethods()); | 575 assert(world.checkNoEnqueuedInvokedInstanceMethods()); |
| 576 world.registerFieldClosureInvocations(); | 576 world.registerFieldClosureInvocations(); |
| 577 } | 577 } |
| 578 | 578 |
| 579 void processRecompilationQueue(Enqueuer world) { | 579 void processRecompilationQueue(Enqueuer world) { |
| 580 assert(phase == PHASE_RECOMPILING); | 580 assert(phase == PHASE_RECOMPILING); |
| 581 while (!world.recompilationCandidates.isEmpty()) { | 581 while (!world.recompilationCandidates.isEmpty()) { |
| 582 WorkItem work = world.recompilationCandidates.next(); | 582 WorkItem work = world.recompilationCandidates.next(); |
| 583 String oldCode = world.universe.generatedCode[work.element]; | 583 String oldCode = world.universe.generatedCode[work.element].code; |
| 584 world.universe.generatedCode.remove(work.element); | 584 world.universe.generatedCode.remove(work.element); |
| 585 world.universe.generatedBailoutCode.remove(work.element); | 585 world.universe.generatedBailoutCode.remove(work.element); |
| 586 withCurrentElement(work.element, () => work.run(this, world)); | 586 withCurrentElement(work.element, () => work.run(this, world)); |
| 587 String newCode = world.universe.generatedCode[work.element]; | 587 String newCode = world.universe.generatedCode[work.element].code; |
| 588 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { | 588 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { |
| 589 log("Pass 2 optimization:"); | 589 log("Pass 2 optimization:"); |
| 590 log("Before:\n$oldCode"); | 590 log("Before:\n$oldCode"); |
| 591 log("After:\n$newCode"); | 591 log("After:\n$newCode"); |
| 592 } | 592 } |
| 593 } | 593 } |
| 594 } | 594 } |
| 595 | 595 |
| 596 /** | 596 /** |
| 597 * Perform various checks of the queues. This includes checking that | 597 * Perform various checks of the queues. This includes checking that |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 693 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
| 694 } else { | 694 } else { |
| 695 log('Recompiled ${world.recompilationCandidates.processed} methods.'); | 695 log('Recompiled ${world.recompilationCandidates.processed} methods.'); |
| 696 } | 696 } |
| 697 progress.reset(); | 697 progress.reset(); |
| 698 } | 698 } |
| 699 if (work.element.kind.category == ElementCategory.VARIABLE) { | 699 if (work.element.kind.category == ElementCategory.VARIABLE) { |
| 700 constantHandler.compileWorkItem(work); | 700 constantHandler.compileWorkItem(work); |
| 701 return null; | 701 return null; |
| 702 } else { | 702 } else { |
| 703 String code = backend.codegen(work); | 703 CodeBlock codeBlock = backend.codegen(work); |
| 704 codegenWorld.addGeneratedCode(work, code); | 704 codegenWorld.addGeneratedCode(work, codeBlock); |
| 705 return code; | 705 return codeBlock.code; |
| 706 } | 706 } |
| 707 } | 707 } |
| 708 | 708 |
| 709 void registerInstantiatedClass(ClassElement cls) { | 709 void registerInstantiatedClass(ClassElement cls) { |
| 710 enqueuer.resolution.registerInstantiatedClass(cls); | 710 enqueuer.resolution.registerInstantiatedClass(cls); |
| 711 enqueuer.codegen.registerInstantiatedClass(cls); | 711 enqueuer.codegen.registerInstantiatedClass(cls); |
| 712 } | 712 } |
| 713 | 713 |
| 714 void resolveClass(ClassElement element) { | 714 void resolveClass(ClassElement element) { |
| 715 withCurrentElement(element, () => resolver.resolveClass(element)); | 715 withCurrentElement(element, () => resolver.resolveClass(element)); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 // invariant that endOffset > beginOffset, but for EOF the | 882 // invariant that endOffset > beginOffset, but for EOF the |
| 883 // charoffset of the next token may be [beginOffset]. This can | 883 // charoffset of the next token may be [beginOffset]. This can |
| 884 // also happen for synthetized tokens that are produced during | 884 // also happen for synthetized tokens that are produced during |
| 885 // error handling. | 885 // error handling. |
| 886 final endOffset = | 886 final endOffset = |
| 887 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); | 887 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); |
| 888 assert(endOffset > beginOffset); | 888 assert(endOffset > beginOffset); |
| 889 return f(beginOffset, endOffset); | 889 return f(beginOffset, endOffset); |
| 890 } | 890 } |
| 891 } | 891 } |
| OLD | NEW |