Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: lib/compiler/implementation/ssa/bailout.dart

Issue 10827180: Move types out of the HInstructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Simplifications. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 class BailoutInfo { 5 class BailoutInfo {
6 int instructionId; 6 int instructionId;
7 int bailoutId; 7 int bailoutId;
8 BailoutInfo(this.instructionId, this.bailoutId); 8 BailoutInfo(this.instructionId, this.bailoutId);
9 } 9 }
10 10
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 } 60 }
61 61
62 bool isEmpty() => lives.isEmpty() && loopMarkers.isEmpty(); 62 bool isEmpty() => lives.isEmpty() && loopMarkers.isEmpty();
63 } 63 }
64 64
65 65
66 /** 66 /**
67 * Visits the graph in dominator order and inserts TypeGuards in places where 67 * Visits the graph in dominator order and inserts TypeGuards in places where
68 * we consider the guard to be of value. 68 * we consider the guard to be of value.
69 * 69 *
70 * Might modify the [:propagatedType:] fields of the instructions in an 70 * Might modify the [types] in an inconsistent way. No further analysis should
71 * inconsistent way. No further analysis should rely on them. 71 * rely on them.
72 */ 72 */
73 class SsaTypeGuardInserter extends HGraphVisitor implements OptimizationPhase { 73 class SsaTypeGuardInserter extends HGraphVisitor implements OptimizationPhase {
74 final Compiler compiler; 74 final Compiler compiler;
75 final String name = 'SsaTypeGuardInserter'; 75 final String name = 'SsaTypeGuardInserter';
76 final WorkItem work; 76 final WorkItem work;
77 final HTypeMap types;
77 bool calledInLoop = false; 78 bool calledInLoop = false;
78 bool isRecursiveMethod = false; 79 bool isRecursiveMethod = false;
79 int stateId = 1; 80 int stateId = 1;
80 81
81 SsaTypeGuardInserter(this.compiler, this.work); 82 SsaTypeGuardInserter(this.compiler, this.work, this.types);
82 83
83 void visitGraph(HGraph graph) { 84 void visitGraph(HGraph graph) {
84 isRecursiveMethod = graph.isRecursiveMethod; 85 isRecursiveMethod = graph.isRecursiveMethod;
85 calledInLoop = graph.calledInLoop; 86 calledInLoop = graph.calledInLoop;
86 work.guards = <HTypeGuard>[]; 87 work.guards = <HTypeGuard>[];
87 visitDominatorTree(graph); 88 visitDominatorTree(graph);
88 } 89 }
89 90
90 void visitBasicBlock(HBasicBlock block) { 91 void visitBasicBlock(HBasicBlock block) {
91 block.forEachPhi(visitInstruction); 92 block.forEachPhi(visitInstruction);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 } 147 }
147 148
148 // To speed up computations on values loaded from arrays, we 149 // To speed up computations on values loaded from arrays, we
149 // insert type guards for builtin array indexing operations in 150 // insert type guards for builtin array indexing operations in
150 // nested loops. Since this can blow up code size quite 151 // nested loops. Since this can blow up code size quite
151 // significantly, we only do it if type guards have already been 152 // significantly, we only do it if type guards have already been
152 // inserted for this method. The code size price for an additional 153 // inserted for this method. The code size price for an additional
153 // type guard is much smaller than the first one that causes the 154 // type guard is much smaller than the first one that causes the
154 // generation of a bailout method. 155 // generation of a bailout method.
155 if (instruction is HIndex && 156 if (instruction is HIndex &&
156 (instruction as HIndex).builtin && 157 (instruction as HIndex).isBuiltin(types) &&
157 hasTypeGuards) { 158 hasTypeGuards) {
158 HBasicBlock loopHeader = instruction.block.enclosingLoopHeader; 159 HBasicBlock loopHeader = instruction.block.enclosingLoopHeader;
159 if (loopHeader != null && loopHeader.parentLoopHeader != null) { 160 if (loopHeader != null && loopHeader.parentLoopHeader != null) {
160 return true; 161 return true;
161 } 162 }
162 } 163 }
163 164
164 // Insert type guards if the method is likely to be called in a 165 // Insert type guards if the method is likely to be called in a
165 // loop. 166 // loop.
166 return calledInLoop; 167 return calledInLoop;
167 } 168 }
168 169
169 bool shouldInsertTypeGuard(HInstruction instruction) { 170 bool shouldInsertTypeGuard(HInstruction instruction,
170 HType speculativeType = instruction.propagatedType; 171 HType speculativeType,
171 HType computedType = instruction.computeTypeFromInputTypes(); 172 HType computedType) {
172 // Start by reverting the propagated type. If we add a type guard then the
173 // guard will expose the speculative type. If we don't add a type guard
174 // then this avoids subsequent instructions to use the the wrong type.
175 //
176 // Note that just setting the propagatedType of the instruction is not
177 // complete since the type could lead to a phi node which in turn could
178 // change the computedType. In this case we might miss some guards we
179 // would have liked to insert. Most of the time this should however be
180 // fine, due to dominator-order visiting.
181 instruction.propagatedType = computedType;
182
183 if (!speculativeType.isUseful()) return false; 173 if (!speculativeType.isUseful()) return false;
184 // If the types agree we don't need to check. 174 // If the types agree we don't need to check.
185 if (speculativeType == computedType) return false; 175 if (speculativeType == computedType) return false;
186 // If a bailout check is more expensive than doing the actual operation 176 // If a bailout check is more expensive than doing the actual operation
187 // don't do it either. 177 // don't do it either.
188 return typeGuardWouldBeValuable(instruction, speculativeType); 178 return typeGuardWouldBeValuable(instruction, speculativeType);
189 } 179 }
190 180
191 void visitInstruction(HInstruction instruction) { 181 void visitInstruction(HInstruction instruction) {
192 HType speculativeType = instruction.propagatedType; 182 HType speculativeType = types[instruction];
193 if (shouldInsertTypeGuard(instruction)) { 183 HType computedType = instruction.computeTypeFromInputTypes(types);
184 // Currently the type in [types] is the speculative type each instruction
185 // would like to have. We start by recomputing the type non-speculatively.
186 // If we add a type guard then the guard will expose the speculative type.
187 // If we don't add a type guard then this avoids that subsequent
188 // instructions use the wrong (speculative) type.
189 //
190 // Note that just setting the speculative type of the instruction is not
191 // complete since the type could lead to a phi node which in turn could
192 // change the speculative type. In this case we might miss some guards we
193 // would have liked to insert. Most of the time this should however be
194 // fine, due to dominator-order visiting.
195 types[instruction] = computedType;
196
197 if (shouldInsertTypeGuard(instruction, speculativeType, computedType)) {
194 HInstruction insertionPoint; 198 HInstruction insertionPoint;
195 if (instruction is HPhi) { 199 if (instruction is HPhi) {
196 insertionPoint = instruction.block.first; 200 insertionPoint = instruction.block.first;
197 } else if (instruction is HParameterValue) { 201 } else if (instruction is HParameterValue) {
198 // We insert the type guard at the end of the entry block 202 // We insert the type guard at the end of the entry block
199 // because if a parameter is live, it must be kept in the live 203 // because if a parameter is live, it must be kept in the live
200 // environment. Not doing so would mean we could visit a 204 // environment. Not doing so would mean we could visit a
201 // parameter and remove it from the environment before 205 // parameter and remove it from the environment before
202 // visiting a type guard. 206 // visiting a type guard.
203 insertionPoint = instruction.block.last; 207 insertionPoint = instruction.block.last;
204 } else { 208 } else {
205 insertionPoint = instruction.next; 209 insertionPoint = instruction.next;
206 } 210 }
207 // If the previous instruction is also a type guard, then both 211 // If the previous instruction is also a type guard, then both
208 // guards have the same environment, and can therefore share the 212 // guards have the same environment, and can therefore share the
209 // same state id. 213 // same state id.
210 HBailoutTarget target; 214 HBailoutTarget target;
211 int state; 215 int state;
212 if (insertionPoint.previous is HTypeGuard) { 216 if (insertionPoint.previous is HTypeGuard) {
213 HTypeGuard other = insertionPoint.previous; 217 HTypeGuard other = insertionPoint.previous;
214 target = other.bailoutTarget; 218 target = other.bailoutTarget;
215 } else { 219 } else {
216 state = stateId++; 220 state = stateId++;
217 target = new HBailoutTarget(state); 221 target = new HBailoutTarget(state);
218 insertionPoint.block.addBefore(insertionPoint, target); 222 insertionPoint.block.addBefore(insertionPoint, target);
219 } 223 }
220 HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target); 224 HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target);
221 guard.propagatedType = speculativeType; 225 types[guard] = speculativeType;
222 work.guards.add(guard); 226 work.guards.add(guard);
223 instruction.block.rewrite(instruction, guard); 227 instruction.block.rewrite(instruction, guard);
224 insertionPoint.block.addBefore(insertionPoint, guard); 228 insertionPoint.block.addBefore(insertionPoint, guard);
225 } 229 }
226 } 230 }
227 } 231 }
228 232
229 /** 233 /**
230 * Computes the environment for each SSA instruction: visits the graph 234 * Computes the environment for each SSA instruction: visits the graph
231 * in post-dominator order. Removes an instruction from the environment 235 * in post-dominator order. Removes an instruction from the environment
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 hasComplexBailoutTargets = true; 527 hasComplexBailoutTargets = true;
524 } 528 }
525 } else { 529 } else {
526 hasComplexBailoutTargets = true; 530 hasComplexBailoutTargets = true;
527 blocks.forEach((HBasicBlock block) { 531 blocks.forEach((HBasicBlock block) {
528 block.bailoutTargets.add(target); 532 block.bailoutTargets.add(target);
529 }); 533 });
530 } 534 }
531 } 535 }
532 } 536 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698