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

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: Cosmetic change (updated comment). 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:] of the work item in an inconsistent way.
71 * inconsistent way. No further analysis should rely on them. 71 * No further analysis should 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 JavaScriptWorkItem work;
77 bool calledInLoop = false; 77 bool calledInLoop = false;
78 bool isRecursiveMethod = false; 78 bool isRecursiveMethod = false;
79 int stateId = 1; 79 int stateId = 1;
80 80
81 SsaTypeGuardInserter(this.compiler, this.work); 81 SsaTypeGuardInserter(this.compiler, this.work);
82 82
83 void visitGraph(HGraph graph) { 83 void visitGraph(HGraph graph) {
84 isRecursiveMethod = graph.isRecursiveMethod; 84 isRecursiveMethod = graph.isRecursiveMethod;
85 calledInLoop = graph.calledInLoop; 85 calledInLoop = graph.calledInLoop;
86 work.guards = <HTypeGuard>[]; 86 work.guards = <HTypeGuard>[];
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 return false; 138 return false;
139 } 139 }
140 140
141 // If the instruction is not in a loop then the header will be null. 141 // If the instruction is not in a loop then the header will be null.
142 HBasicBlock currentLoopHeader = instruction.block.enclosingLoopHeader; 142 HBasicBlock currentLoopHeader = instruction.block.enclosingLoopHeader;
143 for (HInstruction user in instruction.usedBy) { 143 for (HInstruction user in instruction.usedBy) {
144 HBasicBlock userLoopHeader = user.block.enclosingLoopHeader; 144 HBasicBlock userLoopHeader = user.block.enclosingLoopHeader;
145 if (isNested(userLoopHeader, currentLoopHeader)) return true; 145 if (isNested(userLoopHeader, currentLoopHeader)) return true;
146 } 146 }
147 147
148 HTypeMap types = work.types;
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 HTypeMap types = work.types;
193 if (shouldInsertTypeGuard(instruction)) { 183 HType speculativeType = types[instruction];
184 HType computedType = instruction.computeTypeFromInputTypes(types);
185 // Start by reverting the propagated type. If we add a type guard then the
Lasse Reichstein Nielsen 2012/08/08 07:44:53 How do you revert a type? "propagated" isn't menti
floitsch 2012/08/08 19:18:37 Done.
186 // guard will expose the speculative type. If we don't add a type guard
187 // then this avoids subsequent instructions to use the the wrong type.
Lasse Reichstein Nielsen 2012/08/08 07:44:53 "avoids ... to use" -> "avoids ... using" "the the
floitsch 2012/08/08 19:18:37 reworded.
188 //
189 // Note that just setting the speculative type of the instruction is not
190 // complete since the type could lead to a phi node which in turn could
191 // change the speculative type. In this case we might miss some guards we
192 // would have liked to insert. Most of the time this should however be
193 // fine, due to dominator-order visiting.
194 types[instruction] = computedType;
195
196 if (shouldInsertTypeGuard(instruction, speculativeType, computedType)) {
194 HInstruction insertionPoint; 197 HInstruction insertionPoint;
195 if (instruction is HPhi) { 198 if (instruction is HPhi) {
196 insertionPoint = instruction.block.first; 199 insertionPoint = instruction.block.first;
197 } else if (instruction is HParameterValue) { 200 } else if (instruction is HParameterValue) {
198 // We insert the type guard at the end of the entry block 201 // 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 202 // because if a parameter is live, it must be kept in the live
200 // environment. Not doing so would mean we could visit a 203 // environment. Not doing so would mean we could visit a
201 // parameter and remove it from the environment before 204 // parameter and remove it from the environment before
202 // visiting a type guard. 205 // visiting a type guard.
203 insertionPoint = instruction.block.last; 206 insertionPoint = instruction.block.last;
204 } else { 207 } else {
205 insertionPoint = instruction.next; 208 insertionPoint = instruction.next;
206 } 209 }
207 // If the previous instruction is also a type guard, then both 210 // If the previous instruction is also a type guard, then both
208 // guards have the same environment, and can therefore share the 211 // guards have the same environment, and can therefore share the
209 // same state id. 212 // same state id.
210 HBailoutTarget target; 213 HBailoutTarget target;
211 int state; 214 int state;
212 if (insertionPoint.previous is HTypeGuard) { 215 if (insertionPoint.previous is HTypeGuard) {
213 HTypeGuard other = insertionPoint.previous; 216 HTypeGuard other = insertionPoint.previous;
214 target = other.bailoutTarget; 217 target = other.bailoutTarget;
215 } else { 218 } else {
216 state = stateId++; 219 state = stateId++;
217 target = new HBailoutTarget(state); 220 target = new HBailoutTarget(state);
218 insertionPoint.block.addBefore(insertionPoint, target); 221 insertionPoint.block.addBefore(insertionPoint, target);
219 } 222 }
220 HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target); 223 HTypeGuard guard = new HTypeGuard(speculativeType, instruction, target);
221 guard.propagatedType = speculativeType; 224 types[guard] = speculativeType;
222 work.guards.add(guard); 225 work.guards.add(guard);
223 instruction.block.rewrite(instruction, guard); 226 instruction.block.rewrite(instruction, guard);
224 insertionPoint.block.addBefore(insertionPoint, guard); 227 insertionPoint.block.addBefore(insertionPoint, guard);
225 } 228 }
226 } 229 }
227 } 230 }
228 231
229 /** 232 /**
230 * Computes the environment for each SSA instruction: visits the graph 233 * Computes the environment for each SSA instruction: visits the graph
231 * in post-dominator order. Removes an instruction from the environment 234 * 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; 526 hasComplexBailoutTargets = true;
524 } 527 }
525 } else { 528 } else {
526 hasComplexBailoutTargets = true; 529 hasComplexBailoutTargets = true;
527 blocks.forEach((HBasicBlock block) { 530 blocks.forEach((HBasicBlock block) {
528 block.bailoutTargets.add(target); 531 block.bailoutTargets.add(target);
529 }); 532 });
530 } 533 }
531 } 534 }
532 } 535 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698