| 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 CodegenRegistry, 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; |
| 11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
| 13 import '../js/js.dart' as js; | 13 import '../js/js.dart' as js; |
| 14 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 14 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
| 15 import '../js_backend/js_backend.dart'; | 15 import '../js_backend/js_backend.dart'; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 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 bool trustPrimitives = compiler.options.trustPrimitives; | 52 bool trustPrimitives = compiler.options.trustPrimitives; |
| 53 CodegenRegistry registry = work.registry; |
| 53 Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 54 Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| 54 SsaCodeMotion codeMotion; | 55 SsaCodeMotion codeMotion; |
| 55 measure(() { | 56 measure(() { |
| 56 List<OptimizationPhase> phases = <OptimizationPhase>[ | 57 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 57 // Run trivial instruction simplification first to optimize | 58 // Run trivial instruction simplification first to optimize |
| 58 // some patterns useful for type conversion. | 59 // some patterns useful for type conversion. |
| 59 new SsaInstructionSimplifier(constantSystem, backend, this), | 60 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 60 new SsaTypeConversionInserter(compiler), | 61 new SsaTypeConversionInserter(compiler), |
| 61 new SsaRedundantPhiEliminator(), | 62 new SsaRedundantPhiEliminator(), |
| 62 new SsaDeadPhiEliminator(), | 63 new SsaDeadPhiEliminator(), |
| 63 new SsaTypePropagator(compiler), | 64 new SsaTypePropagator(compiler), |
| 64 // After type propagation, more instructions can be | 65 // After type propagation, more instructions can be |
| 65 // simplified. | 66 // simplified. |
| 66 new SsaInstructionSimplifier(constantSystem, backend, this), | 67 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 67 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), | 68 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 68 new SsaInstructionSimplifier(constantSystem, backend, this), | 69 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 69 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), | 70 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 70 new SsaTypePropagator(compiler), | 71 new SsaTypePropagator(compiler), |
| 71 // Run a dead code eliminator before LICM because dead | 72 // Run a dead code eliminator before LICM because dead |
| 72 // interceptors are often in the way of LICM'able instructions. | 73 // interceptors are often in the way of LICM'able instructions. |
| 73 new SsaDeadCodeEliminator(compiler, this), | 74 new SsaDeadCodeEliminator(compiler, this), |
| 74 new SsaGlobalValueNumberer(compiler), | 75 new SsaGlobalValueNumberer(compiler), |
| 75 // After GVN, some instructions might need their type to be | 76 // After GVN, some instructions might need their type to be |
| 76 // updated because they now have different inputs. | 77 // updated because they now have different inputs. |
| 77 new SsaTypePropagator(compiler), | 78 new SsaTypePropagator(compiler), |
| 78 codeMotion = new SsaCodeMotion(), | 79 codeMotion = new SsaCodeMotion(), |
| 79 new SsaLoadElimination(compiler), | 80 new SsaLoadElimination(compiler), |
| 80 new SsaRedundantPhiEliminator(), | 81 new SsaRedundantPhiEliminator(), |
| 81 new SsaDeadPhiEliminator(), | 82 new SsaDeadPhiEliminator(), |
| 82 new SsaTypePropagator(compiler), | 83 new SsaTypePropagator(compiler), |
| 83 new SsaValueRangeAnalyzer(compiler, constantSystem, this), | 84 new SsaValueRangeAnalyzer(compiler, constantSystem, this), |
| 84 // Previous optimizations may have generated new | 85 // Previous optimizations may have generated new |
| 85 // opportunities for instruction simplification. | 86 // opportunities for instruction simplification. |
| 86 new SsaInstructionSimplifier(constantSystem, backend, this), | 87 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 87 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), | 88 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 88 ]; | 89 ]; |
| 89 phases.forEach(runPhase); | 90 phases.forEach(runPhase); |
| 90 | 91 |
| 91 // Simplifying interceptors is not strictly just an optimization, it is | 92 // Simplifying interceptors is not strictly just an optimization, it is |
| 92 // required for implementation correctness because the code generator | 93 // required for implementation correctness because the code generator |
| 93 // assumes it is always performed. | 94 // assumes it is always performed. |
| 94 runPhase( | 95 runPhase( |
| 95 new SsaSimplifyInterceptors(compiler, constantSystem, work.element)); | 96 new SsaSimplifyInterceptors(compiler, constantSystem, work.element)); |
| 96 | 97 |
| 97 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this); | 98 SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(compiler, this); |
| 98 runPhase(dce); | 99 runPhase(dce); |
| 99 if (codeMotion.movedCode || dce.eliminatedSideEffects) { | 100 if (codeMotion.movedCode || dce.eliminatedSideEffects) { |
| 100 phases = <OptimizationPhase>[ | 101 phases = <OptimizationPhase>[ |
| 101 new SsaTypePropagator(compiler), | 102 new SsaTypePropagator(compiler), |
| 102 new SsaGlobalValueNumberer(compiler), | 103 new SsaGlobalValueNumberer(compiler), |
| 103 new SsaCodeMotion(), | 104 new SsaCodeMotion(), |
| 104 new SsaValueRangeAnalyzer(compiler, constantSystem, this), | 105 new SsaValueRangeAnalyzer(compiler, constantSystem, this), |
| 105 new SsaInstructionSimplifier(constantSystem, backend, this), | 106 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 106 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), | 107 new SsaCheckInserter(trustPrimitives, backend, boundsChecked), |
| 107 new SsaSimplifyInterceptors(compiler, constantSystem, work.element), | 108 new SsaSimplifyInterceptors(compiler, constantSystem, work.element), |
| 108 new SsaDeadCodeEliminator(compiler, this), | 109 new SsaDeadCodeEliminator(compiler, this), |
| 109 ]; | 110 ]; |
| 110 } else { | 111 } else { |
| 111 phases = <OptimizationPhase>[ | 112 phases = <OptimizationPhase>[ |
| 112 new SsaTypePropagator(compiler), | 113 new SsaTypePropagator(compiler), |
| 113 // Run the simplifier to remove unneeded type checks inserted by | 114 // Run the simplifier to remove unneeded type checks inserted by |
| 114 // type propagation. | 115 // type propagation. |
| 115 new SsaInstructionSimplifier(constantSystem, backend, this), | 116 new SsaInstructionSimplifier(constantSystem, backend, this, registry), |
| 116 ]; | 117 ]; |
| 117 } | 118 } |
| 118 phases.forEach(runPhase); | 119 phases.forEach(runPhase); |
| 119 }); | 120 }); |
| 120 } | 121 } |
| 121 } | 122 } |
| 122 | 123 |
| 123 /// Returns `true` if [mask] represents only types that have a length that | 124 /// Returns `true` if [mask] represents only types that have a length that |
| 124 /// cannot change. The current implementation is conservative for the purpose | 125 /// cannot change. The current implementation is conservative for the purpose |
| 125 /// of identifying gvn-able lengths and mis-identifies some unions of fixed | 126 /// of identifying gvn-able lengths and mis-identifies some unions of fixed |
| (...skipping 22 matching lines...) Expand all Loading... |
| 148 class SsaInstructionSimplifier extends HBaseVisitor | 149 class SsaInstructionSimplifier extends HBaseVisitor |
| 149 implements OptimizationPhase { | 150 implements OptimizationPhase { |
| 150 // We don't produce constant-folded strings longer than this unless they have | 151 // We don't produce constant-folded strings longer than this unless they have |
| 151 // a single use. This protects against exponentially large constant folded | 152 // a single use. This protects against exponentially large constant folded |
| 152 // strings. | 153 // strings. |
| 153 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; | 154 static const MAX_SHARED_CONSTANT_FOLDED_STRING_LENGTH = 512; |
| 154 | 155 |
| 155 final String name = "SsaInstructionSimplifier"; | 156 final String name = "SsaInstructionSimplifier"; |
| 156 final JavaScriptBackend backend; | 157 final JavaScriptBackend backend; |
| 157 final ConstantSystem constantSystem; | 158 final ConstantSystem constantSystem; |
| 159 final CodegenRegistry registry; |
| 158 HGraph graph; | 160 HGraph graph; |
| 159 Compiler get compiler => backend.compiler; | 161 Compiler get compiler => backend.compiler; |
| 160 final SsaOptimizerTask optimizer; | 162 final SsaOptimizerTask optimizer; |
| 161 | 163 |
| 162 SsaInstructionSimplifier(this.constantSystem, this.backend, this.optimizer); | 164 SsaInstructionSimplifier( |
| 165 this.constantSystem, this.backend, this.optimizer, this.registry); |
| 163 | 166 |
| 164 CoreClasses get coreClasses => compiler.coreClasses; | 167 CoreClasses get coreClasses => compiler.coreClasses; |
| 165 | 168 |
| 166 BackendHelpers get helpers => backend.helpers; | 169 BackendHelpers get helpers => backend.helpers; |
| 167 | 170 |
| 168 void visitGraph(HGraph visitee) { | 171 void visitGraph(HGraph visitee) { |
| 169 graph = visitee; | 172 graph = visitee; |
| 170 visitDominatorTree(visitee); | 173 visitDominatorTree(visitee); |
| 171 } | 174 } |
| 172 | 175 |
| (...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 } | 1155 } |
| 1153 return node; | 1156 return node; |
| 1154 } | 1157 } |
| 1155 | 1158 |
| 1156 // Look for an allocation with type information and re-write type variable | 1159 // Look for an allocation with type information and re-write type variable |
| 1157 // as a function of the type parameters of the allocation. This effectively | 1160 // as a function of the type parameters of the allocation. This effectively |
| 1158 // store-forwards a type variable read through an allocation. | 1161 // store-forwards a type variable read through an allocation. |
| 1159 | 1162 |
| 1160 // Match: | 1163 // Match: |
| 1161 // | 1164 // |
| 1162 // setRuntimeTypeInfo( | 1165 // HCreate(ClassElement, |
| 1163 // HCreate(ClassElement), | 1166 // [arg_i, |
| 1164 // HTypeInfoExpression(t_0, t_1, t_2, ...)); | 1167 // ..., |
| 1168 // HTypeInfoExpression(t_0, t_1, t_2, ...)]); |
| 1165 // | 1169 // |
| 1166 // The `t_i` are the values of the type parameters of ClassElement. | 1170 // The `t_i` are the values of the type parameters of ClassElement. |
| 1167 if (object is HInvokeStatic) { | 1171 |
| 1168 if (object.element == helpers.setRuntimeTypeInfo) { | 1172 if (object is HCreate) { |
| 1169 HInstruction allocation = object.inputs[0]; | 1173 void registerInstantiations() { |
| 1170 if (allocation is HCreate) { | 1174 // Forwarding the type variable references might cause the HCreate to |
| 1171 HInstruction typeInfo = object.inputs[1]; | 1175 // become dead. This breaks the algorithm for generating the per-type |
| 1172 if (typeInfo is HTypeInfoExpression) { | 1176 // runtime type information, so we instantiate them here in case the |
| 1173 return finishSubstituted( | 1177 // HCreate becomes dead. |
| 1174 allocation.element, (int index) => typeInfo.inputs[index]); | 1178 object.instantiatedTypes?.forEach(registry.registerInstantiation); |
| 1175 } | 1179 } |
| 1180 |
| 1181 if (object.hasRtiInput) { |
| 1182 HInstruction typeInfo = object.rtiInput; |
| 1183 if (typeInfo is HTypeInfoExpression) { |
| 1184 registerInstantiations(); |
| 1185 return finishSubstituted( |
| 1186 object.element, (int index) => typeInfo.inputs[index]); |
| 1176 } | 1187 } |
| 1177 return node; | 1188 } else { |
| 1189 // Non-generic type (which extends or mixes in a generic type, for |
| 1190 // example CodeUnits extends UnmodifiableListBase<int>). Also used for |
| 1191 // raw-type when the type parameters are elided. |
| 1192 registerInstantiations(); |
| 1193 return finishSubstituted( |
| 1194 object.element, |
| 1195 // If there are type arguments, all type arguments are 'dynamic'. |
| 1196 (int i) => graph.addConstantNull(compiler)); |
| 1178 } | 1197 } |
| 1179 // TODO(sra): Factory constructors pass type arguments after the value | |
| 1180 // arguments. The [select] argument indexes into these type arguments. | |
| 1181 } | 1198 } |
| 1182 | 1199 |
| 1183 // Non-generic type (which extends or mixes in a generic type, for example | 1200 // TODO(sra): Factory constructors pass type arguments after the value |
| 1184 // CodeUnits extends UnmodifiableListBase<int>). | 1201 // arguments. The [selectTypeArgumentFromObjectCreation] argument of |
| 1185 // Also used for raw-type when the type parameters are elided. | 1202 // [finishSubstituted] indexes into these type arguments. |
| 1186 if (object is HCreate) { | |
| 1187 return finishSubstituted( | |
| 1188 object.element, | |
| 1189 // If there are type arguments, all type arguments are 'dynamic'. | |
| 1190 (int i) => graph.addConstantNull(compiler)); | |
| 1191 } | |
| 1192 | 1203 |
| 1193 return node; | 1204 return node; |
| 1194 } | 1205 } |
| 1195 } | 1206 } |
| 1196 | 1207 |
| 1197 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { | 1208 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { |
| 1198 final Set<HInstruction> boundsChecked; | 1209 final Set<HInstruction> boundsChecked; |
| 1199 final bool trustPrimitives; | 1210 final bool trustPrimitives; |
| 1200 final JavaScriptBackend backend; | 1211 final JavaScriptBackend backend; |
| 1201 final String name = "SsaCheckInserter"; | 1212 final String name = "SsaCheckInserter"; |
| (...skipping 1382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2584 | 2595 |
| 2585 keyedValues.forEach((receiver, values) { | 2596 keyedValues.forEach((receiver, values) { |
| 2586 result.keyedValues[receiver] = | 2597 result.keyedValues[receiver] = |
| 2587 new Map<HInstruction, HInstruction>.from(values); | 2598 new Map<HInstruction, HInstruction>.from(values); |
| 2588 }); | 2599 }); |
| 2589 | 2600 |
| 2590 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2601 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2591 return result; | 2602 return result; |
| 2592 } | 2603 } |
| 2593 } | 2604 } |
| OLD | NEW |