| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
| 6 String get name(); | 6 String get name(); |
| 7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
| 8 } | 8 } |
| 9 | 9 |
| 10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
| 11 final JavaScriptBackend backend; | 11 final JavaScriptBackend backend; |
| 12 SsaOptimizerTask(JavaScriptBackend backend) | 12 SsaOptimizerTask(JavaScriptBackend backend) |
| 13 : this.backend = backend, | 13 : this.backend = backend, |
| 14 super(backend.compiler); | 14 super(backend.compiler); |
| 15 String get name() => 'SSA optimizer'; | 15 String get name() => 'SSA optimizer'; |
| 16 Compiler get compiler() => backend.compiler; | 16 Compiler get compiler() => backend.compiler; |
| 17 | 17 |
| 18 void runPhases(HGraph graph, List<OptimizationPhase> phases) { | 18 void runPhases(HGraph graph, List<OptimizationPhase> phases) { |
| 19 for (OptimizationPhase phase in phases) { | 19 for (OptimizationPhase phase in phases) { |
| 20 phase.visitGraph(graph); | 20 phase.visitGraph(graph); |
| 21 compiler.tracer.traceGraph(phase.name, graph); | 21 compiler.tracer.traceGraph(phase.name, graph); |
| 22 } | 22 } |
| 23 } | 23 } |
| 24 | 24 |
| 25 void optimize(WorkItem work, HGraph graph) { | 25 void optimize(WorkItem work, HGraph graph) { |
| 26 measure(() { | 26 measure(() { |
| 27 List<OptimizationPhase> phases = <OptimizationPhase>[ | 27 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 28 // Run trivial constant folding first to optimize | 28 // Run trivial constant folding first to optimize |
| 29 // some patterns useful for type conversion. | 29 // some patterns useful for type conversion. |
| 30 new SsaConstantFolder(backend), | 30 new SsaConstantFolder(backend, work), |
| 31 new SsaTypeConversionInserter(compiler), | 31 new SsaTypeConversionInserter(compiler), |
| 32 new SsaTypePropagator(compiler), | 32 new SsaTypePropagator(compiler), |
| 33 new SsaCheckInserter(backend), | 33 new SsaCheckInserter(backend), |
| 34 new SsaConstantFolder(backend), | 34 new SsaConstantFolder(backend, work), |
| 35 new SsaRedundantPhiEliminator(), | 35 new SsaRedundantPhiEliminator(), |
| 36 new SsaDeadPhiEliminator(), | 36 new SsaDeadPhiEliminator(), |
| 37 new SsaGlobalValueNumberer(compiler), | 37 new SsaGlobalValueNumberer(compiler), |
| 38 new SsaCodeMotion(), | 38 new SsaCodeMotion(), |
| 39 new SsaDeadCodeEliminator()]; | 39 new SsaDeadCodeEliminator()]; |
| 40 runPhases(graph, phases); | 40 runPhases(graph, phases); |
| 41 }); | 41 }); |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { | 44 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 | 85 |
| 86 /** | 86 /** |
| 87 * If both inputs to known operations are available execute the operation at | 87 * If both inputs to known operations are available execute the operation at |
| 88 * compile-time. | 88 * compile-time. |
| 89 */ | 89 */ |
| 90 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase { | 90 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase { |
| 91 final String name = "SsaConstantFolder"; | 91 final String name = "SsaConstantFolder"; |
| 92 final JavaScriptBackend backend; | 92 final JavaScriptBackend backend; |
| 93 final WorkItem work; |
| 93 HGraph graph; | 94 HGraph graph; |
| 94 Compiler get compiler() => backend.compiler; | 95 Compiler get compiler() => backend.compiler; |
| 95 | 96 |
| 96 SsaConstantFolder(this.backend); | 97 SsaConstantFolder(this.backend, this.work); |
| 97 | 98 |
| 98 void visitGraph(HGraph visitee) { | 99 void visitGraph(HGraph visitee) { |
| 99 graph = visitee; | 100 graph = visitee; |
| 100 visitDominatorTree(visitee); | 101 visitDominatorTree(visitee); |
| 101 } | 102 } |
| 102 | 103 |
| 103 visitBasicBlock(HBasicBlock block) { | 104 visitBasicBlock(HBasicBlock block) { |
| 104 HInstruction instruction = block.first; | 105 HInstruction instruction = block.first; |
| 105 while (instruction !== null) { | 106 while (instruction !== null) { |
| 106 HInstruction next = instruction.next; | 107 HInstruction next = instruction.next; |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 if (!receiver.propagatedType.isUseful()) return node; | 572 if (!receiver.propagatedType.isUseful()) return node; |
| 572 Type type = receiver.propagatedType.computeType(compiler); | 573 Type type = receiver.propagatedType.computeType(compiler); |
| 573 if (type === null) return node; | 574 if (type === null) return node; |
| 574 Element field = compiler.world.locateSingleField(type, node.name); | 575 Element field = compiler.world.locateSingleField(type, node.name); |
| 575 if (field === null) return node; | 576 if (field === null) return node; |
| 576 Modifiers modifiers = field.modifiers; | 577 Modifiers modifiers = field.modifiers; |
| 577 bool isFinalOrConst = false; | 578 bool isFinalOrConst = false; |
| 578 if (modifiers != null) { | 579 if (modifiers != null) { |
| 579 isFinalOrConst = modifiers.isFinal() || modifiers.isConst(); | 580 isFinalOrConst = modifiers.isFinal() || modifiers.isConst(); |
| 580 } | 581 } |
| 582 // If field is not final or const but no setters are used then the field |
| 583 // might be considered final anyway as it will be either un-initialized |
| 584 // or initialized in the constructor initializer list. |
| 585 if (!isFinalOrConst && !compiler.world.isSetterUsed(type, node.name)) { |
| 586 switch (compiler.pass) { |
| 587 case 1: |
| 588 compiler.enqueuer.codegen.addToWorkList2(work.element); |
| 589 break; |
| 590 case 2: |
| 591 isFinalOrConst = true; |
| 592 break; |
| 593 } |
| 594 } |
| 581 return new HFieldGet(field, node.inputs[0], isFinalOrConst: isFinalOrConst); | 595 return new HFieldGet(field, node.inputs[0], isFinalOrConst: isFinalOrConst); |
| 582 } | 596 } |
| 583 | 597 |
| 584 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 598 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 585 HInstruction receiver = node.inputs[0]; | 599 HInstruction receiver = node.inputs[0]; |
| 586 if (!receiver.propagatedType.isUseful()) return node; | 600 if (!receiver.propagatedType.isUseful()) return node; |
| 587 Type type = receiver.propagatedType.computeType(compiler); | 601 Type type = receiver.propagatedType.computeType(compiler); |
| 588 if (type === null) return node; | 602 if (type === null) return node; |
| 603 compiler.world.setterUsed(type, node.name); |
| 589 Element field = compiler.world.locateSingleField(type, node.name); | 604 Element field = compiler.world.locateSingleField(type, node.name); |
| 590 if (field === null) return node; | 605 if (field === null) return node; |
| 591 return new HFieldSet(field, node.inputs[0], node.inputs[1]); | 606 return new HFieldSet(field, node.inputs[0], node.inputs[1]); |
| 592 } | 607 } |
| 593 | 608 |
| 594 HInstruction visitStringConcat(HStringConcat node) { | 609 HInstruction visitStringConcat(HStringConcat node) { |
| 595 DartString folded = const LiteralDartString(""); | 610 DartString folded = const LiteralDartString(""); |
| 596 for (int i = 0; i < node.inputs.length; i++) { | 611 for (int i = 0; i < node.inputs.length; i++) { |
| 597 HInstruction part = node.inputs[i]; | 612 HInstruction part = node.inputs[i]; |
| 598 if (!part.isConstant()) return node; | 613 if (!part.isConstant()) return node; |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1137 // the if block terminates. So any use of the instruction | 1152 // the if block terminates. So any use of the instruction |
| 1138 // after the join block should be changed to the new | 1153 // after the join block should be changed to the new |
| 1139 // instruction. | 1154 // instruction. |
| 1140 changeUsesDominatedBy(ifUser.joinBlock, input, convertedType); | 1155 changeUsesDominatedBy(ifUser.joinBlock, input, convertedType); |
| 1141 } | 1156 } |
| 1142 // TODO(ngeoffray): Also change uses for the then block on a HType | 1157 // TODO(ngeoffray): Also change uses for the then block on a HType |
| 1143 // that knows it is not of a specific Type. | 1158 // that knows it is not of a specific Type. |
| 1144 } | 1159 } |
| 1145 } | 1160 } |
| 1146 } | 1161 } |
| OLD | NEW |