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 |