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