| 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 import '../common/codegen.dart' show CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenWorkItem; |
| 6 import '../common/tasks.dart' show CompilerTask; | 6 import '../common/tasks.dart' show CompilerTask; |
| 7 import '../compiler.dart' show Compiler; | 7 import '../compiler.dart' show Compiler; |
| 8 import '../constants/constant_system.dart'; | 8 import '../constants/constant_system.dart'; |
| 9 import '../constants/values.dart'; | 9 import '../constants/values.dart'; |
| 10 import '../core_types.dart' show CoreClasses; | 10 import '../core_types.dart' show CoreClasses; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; | 42 Map<HInstruction, Range> ranges = <HInstruction, Range>{}; |
| 43 | 43 |
| 44 void optimize(CodegenWorkItem work, HGraph graph) { | 44 void optimize(CodegenWorkItem work, HGraph graph) { |
| 45 void runPhase(OptimizationPhase phase) { | 45 void runPhase(OptimizationPhase phase) { |
| 46 measureSubtask(phase.name, () => phase.visitGraph(graph)); | 46 measureSubtask(phase.name, () => phase.visitGraph(graph)); |
| 47 compiler.tracer.traceGraph(phase.name, graph); | 47 compiler.tracer.traceGraph(phase.name, graph); |
| 48 assert(graph.isValid()); | 48 assert(graph.isValid()); |
| 49 } | 49 } |
| 50 | 50 |
| 51 ConstantSystem constantSystem = compiler.backend.constantSystem; | 51 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 52 JavaScriptItemCompilationContext context = work.compilationContext; | |
| 53 bool trustPrimitives = compiler.options.trustPrimitives; | 52 bool trustPrimitives = compiler.options.trustPrimitives; |
| 53 Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| 54 measure(() { | 54 measure(() { |
| 55 List<OptimizationPhase> phases = <OptimizationPhase>[ | 55 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 56 // Run trivial instruction simplification first to optimize | 56 // Run trivial instruction simplification first to optimize |
| 57 // some patterns useful for type conversion. | 57 // some patterns useful for type conversion. |
| 58 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 58 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 59 new SsaTypeConversionInserter(compiler), | 59 new SsaTypeConversionInserter(compiler), |
| 60 new SsaRedundantPhiEliminator(), | 60 new SsaRedundantPhiEliminator(), |
| 61 new SsaDeadPhiEliminator(), | 61 new SsaDeadPhiEliminator(), |
| 62 new SsaTypePropagator(compiler), | 62 new SsaTypePropagator(compiler), |
| 63 // After type propagation, more instructions can be | 63 // After type propagation, more instructions can be |
| 64 // simplified. | 64 // simplified. |
| 65 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 65 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 66 new SsaCheckInserter( | 66 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 67 trustPrimitives, backend, work, context.boundsChecked), | 67 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 68 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 68 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 69 new SsaCheckInserter( | |
| 70 trustPrimitives, backend, work, context.boundsChecked), | |
| 71 new SsaTypePropagator(compiler), | 69 new SsaTypePropagator(compiler), |
| 72 // Run a dead code eliminator before LICM because dead | 70 // Run a dead code eliminator before LICM because dead |
| 73 // interceptors are often in the way of LICM'able instructions. | 71 // interceptors are often in the way of LICM'able instructions. |
| 74 new SsaDeadCodeEliminator(compiler, this), | 72 new SsaDeadCodeEliminator(compiler, this), |
| 75 new SsaGlobalValueNumberer(compiler), | 73 new SsaGlobalValueNumberer(compiler), |
| 76 // After GVN, some instructions might need their type to be | 74 // After GVN, some instructions might need their type to be |
| 77 // updated because they now have different inputs. | 75 // updated because they now have different inputs. |
| 78 new SsaTypePropagator(compiler), | 76 new SsaTypePropagator(compiler), |
| 79 new SsaCodeMotion(), | 77 new SsaCodeMotion(), |
| 80 new SsaLoadElimination(compiler), | 78 new SsaLoadElimination(compiler), |
| 81 new SsaRedundantPhiEliminator(), | 79 new SsaRedundantPhiEliminator(), |
| 82 new SsaDeadPhiEliminator(), | 80 new SsaDeadPhiEliminator(), |
| 83 new SsaTypePropagator(compiler), | 81 new SsaTypePropagator(compiler), |
| 84 new SsaValueRangeAnalyzer(compiler, constantSystem, this, work), | 82 new SsaValueRangeAnalyzer(compiler, constantSystem, this), |
| 85 // Previous optimizations may have generated new | 83 // Previous optimizations may have generated new |
| 86 // opportunities for instruction simplification. | 84 // opportunities for instruction simplification. |
| 87 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 85 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 88 new SsaCheckInserter( | 86 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 89 trustPrimitives, backend, work, context.boundsChecked), | |
| 90 ]; | 87 ]; |
| 91 phases.forEach(runPhase); | 88 phases.forEach(runPhase); |
| 92 | 89 |
| 93 // Simplifying interceptors is not strictly just an optimization, it is | 90 // Simplifying interceptors is not strictly just an optimization, it is |
| 94 // required for implementation correctness because the code generator | 91 // required for implementation correctness because the code generator |
| 95 // assumes it is always performed. | 92 // assumes it is always performed. |
| 96 runPhase(new SsaSimplifyInterceptors(compiler, constantSystem, work)); | 93 runPhase( |
| 94 new SsaSimplifyInterceptors(compiler, constantSystem, work.element)); |
| 97 | 95 |
| 98 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this); | 96 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this); |
| 99 runPhase(dce); | 97 runPhase(dce); |
| 100 if (dce.eliminatedSideEffects) { | 98 if (dce.eliminatedSideEffects) { |
| 101 phases = <OptimizationPhase>[ | 99 phases = <OptimizationPhase>[ |
| 102 new SsaTypePropagator(compiler), | 100 new SsaTypePropagator(compiler), |
| 103 new SsaGlobalValueNumberer(compiler), | 101 new SsaGlobalValueNumberer(compiler), |
| 104 new SsaCodeMotion(), | 102 new SsaCodeMotion(), |
| 105 new SsaValueRangeAnalyzer(compiler, constantSystem, this, work), | 103 new SsaValueRangeAnalyzer(compiler, constantSystem, this), |
| 106 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 104 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 107 new SsaCheckInserter( | 105 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 108 trustPrimitives, backend, work, context.boundsChecked), | 106 new SsaSimplifyInterceptors(compiler, constantSystem, work.element), |
| 109 new SsaSimplifyInterceptors(compiler, constantSystem, work), | |
| 110 new SsaDeadCodeEliminator(compiler, this), | 107 new SsaDeadCodeEliminator(compiler, this), |
| 111 ]; | 108 ]; |
| 112 } else { | 109 } else { |
| 113 phases = <OptimizationPhase>[ | 110 phases = <OptimizationPhase>[ |
| 114 new SsaTypePropagator(compiler), | 111 new SsaTypePropagator(compiler), |
| 115 // Run the simplifier to remove unneeded type checks inserted by | 112 // Run the simplifier to remove unneeded type checks inserted by |
| 116 // type propagation. | 113 // type propagation. |
| 117 new SsaInstructionSimplifier(constantSystem, backend, this, work), | 114 new SsaInstructionSimplifier(constantSystem, backend, this), |
| 118 ]; | 115 ]; |
| 119 } | 116 } |
| 120 phases.forEach(runPhase); | 117 phases.forEach(runPhase); |
| 121 }); | 118 }); |
| 122 } | 119 } |
| 123 } | 120 } |
| 124 | 121 |
| 125 /// Returns `true` if [mask] represents only types that have a length that | 122 /// Returns `true` if [mask] represents only types that have a length that |
| 126 /// cannot change. The current implementation is conservative for the purpose | 123 /// cannot change. The current implementation is conservative for the purpose |
| 127 /// of identifying gvn-able lengths and mis-identifies some unions of fixed | 124 /// of identifying gvn-able lengths and mis-identifies some unions of fixed |
| (...skipping 21 matching lines...) Expand all Loading... |
| 149 */ | 146 */ |
| 150 class SsaInstructionSimplifier extends HBaseVisitor | 147 class SsaInstructionSimplifier extends HBaseVisitor |
| 151 implements OptimizationPhase { | 148 implements OptimizationPhase { |
| 152 // We don't produce constant-folded strings longer than this unless they have | 149 // We don't produce constant-folded strings longer than this unless they have |
| 153 // a single use. This protects against exponentially large constant folded | 150 // a single use. This protects against exponentially large constant folded |
| 154 // strings. | 151 // strings. |
| 155 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; | 152 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; |
| 156 | 153 |
| 157 final String name = "SsaInstructionSimplifier"; | 154 final String name = "SsaInstructionSimplifier"; |
| 158 final JavaScriptBackend backend; | 155 final JavaScriptBackend backend; |
| 159 final CodegenWorkItem work; | |
| 160 final ConstantSystem constantSystem; | 156 final ConstantSystem constantSystem; |
| 161 HGraph graph; | 157 HGraph graph; |
| 162 Compiler get compiler => backend.compiler; | 158 Compiler get compiler => backend.compiler; |
| 163 final SsaOptimizerTask optimizer; | 159 final SsaOptimizerTask optimizer; |
| 160 final Set<HInstruction> allocatedFixedLists; |
| 164 | 161 |
| 165 SsaInstructionSimplifier( | 162 SsaInstructionSimplifier(this.constantSystem, this.backend, this.optimizer); |
| 166 this.constantSystem, this.backend, this.optimizer, this.work); | |
| 167 | 163 |
| 168 CoreClasses get coreClasses => compiler.coreClasses; | 164 CoreClasses get coreClasses => compiler.coreClasses; |
| 169 | 165 |
| 170 BackendHelpers get helpers => backend.helpers; | 166 BackendHelpers get helpers => backend.helpers; |
| 171 | 167 |
| 172 void visitGraph(HGraph visitee) { | 168 void visitGraph(HGraph visitee) { |
| 173 graph = visitee; | 169 graph = visitee; |
| 174 visitDominatorTree(visitee); | 170 visitDominatorTree(visitee); |
| 175 } | 171 } |
| 176 | 172 |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 VariableElement findConcreteFieldForDynamicAccess( | 824 VariableElement findConcreteFieldForDynamicAccess( |
| 829 HInstruction receiver, Selector selector) { | 825 HInstruction receiver, Selector selector) { |
| 830 TypeMask receiverType = receiver.instructionType; | 826 TypeMask receiverType = receiver.instructionType; |
| 831 return compiler.world.locateSingleField(selector, receiverType); | 827 return compiler.world.locateSingleField(selector, receiverType); |
| 832 } | 828 } |
| 833 | 829 |
| 834 HInstruction visitFieldGet(HFieldGet node) { | 830 HInstruction visitFieldGet(HFieldGet node) { |
| 835 if (node.isNullCheck) return node; | 831 if (node.isNullCheck) return node; |
| 836 var receiver = node.receiver; | 832 var receiver = node.receiver; |
| 837 if (node.element == helpers.jsIndexableLength) { | 833 if (node.element == helpers.jsIndexableLength) { |
| 838 JavaScriptItemCompilationContext context = work.compilationContext; | 834 if (graph.allocatedFixedLists.contains(receiver)) { |
| 839 if (context.allocatedFixedLists.contains(receiver)) { | |
| 840 // TODO(ngeoffray): checking if the second input is an integer | 835 // TODO(ngeoffray): checking if the second input is an integer |
| 841 // should not be necessary but it currently makes it easier for | 836 // should not be necessary but it currently makes it easier for |
| 842 // other optimizations to reason about a fixed length constructor | 837 // other optimizations to reason about a fixed length constructor |
| 843 // that we know takes an int. | 838 // that we know takes an int. |
| 844 if (receiver.inputs[0].isInteger(compiler)) { | 839 if (receiver.inputs[0].isInteger(compiler)) { |
| 845 return receiver.inputs[0]; | 840 return receiver.inputs[0]; |
| 846 } | 841 } |
| 847 } else if (receiver.isConstantList() || receiver.isConstantString()) { | 842 } else if (receiver.isConstantList() || receiver.isConstantString()) { |
| 848 return graph.addConstantInt(receiver.constant.length, compiler); | 843 return graph.addConstantInt(receiver.constant.length, compiler); |
| 849 } else { | 844 } else { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 // If there are type arguments, all type arguments are 'dynamic'. | 1189 // If there are type arguments, all type arguments are 'dynamic'. |
| 1195 (int i) => graph.addConstantNull(compiler)); | 1190 (int i) => graph.addConstantNull(compiler)); |
| 1196 } | 1191 } |
| 1197 | 1192 |
| 1198 return node; | 1193 return node; |
| 1199 } | 1194 } |
| 1200 } | 1195 } |
| 1201 | 1196 |
| 1202 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { | 1197 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { |
| 1203 final Set<HInstruction> boundsChecked; | 1198 final Set<HInstruction> boundsChecked; |
| 1204 final CodegenWorkItem work; | |
| 1205 final bool trustPrimitives; | 1199 final bool trustPrimitives; |
| 1206 final JavaScriptBackend backend; | 1200 final JavaScriptBackend backend; |
| 1207 final String name = "SsaCheckInserter"; | 1201 final String name = "SsaCheckInserter"; |
| 1208 HGraph graph; | 1202 HGraph graph; |
| 1209 | 1203 |
| 1210 SsaCheckInserter( | 1204 SsaCheckInserter(this.trustPrimitives, this.backend, this.boundsChecked); |
| 1211 this.trustPrimitives, this.backend, this.work, this.boundsChecked); | |
| 1212 | 1205 |
| 1213 BackendHelpers get helpers => backend.helpers; | 1206 BackendHelpers get helpers => backend.helpers; |
| 1214 | 1207 |
| 1215 void visitGraph(HGraph graph) { | 1208 void visitGraph(HGraph graph) { |
| 1216 this.graph = graph; | 1209 this.graph = graph; |
| 1217 | 1210 |
| 1218 // In --trust-primitives mode we don't add bounds checks. This is better | 1211 // In --trust-primitives mode we don't add bounds checks. This is better |
| 1219 // than trying to remove them later as the limit expression would become | 1212 // than trying to remove them later as the limit expression would become |
| 1220 // dead and require DCE. | 1213 // dead and require DCE. |
| 1221 if (trustPrimitives) return; | 1214 if (trustPrimitives) return; |
| (...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2588 | 2581 |
| 2589 keyedValues.forEach((receiver, values) { | 2582 keyedValues.forEach((receiver, values) { |
| 2590 result.keyedValues[receiver] = | 2583 result.keyedValues[receiver] = |
| 2591 new Map<HInstruction, HInstruction>.from(values); | 2584 new Map<HInstruction, HInstruction>.from(values); |
| 2592 }); | 2585 }); |
| 2593 | 2586 |
| 2594 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2587 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2595 return result; | 2588 return result; |
| 2596 } | 2589 } |
| 2597 } | 2590 } |
| OLD | NEW |