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 |