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 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |