| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 | 104 |
| 105 HInstruction instruction = block.first; | 105 HInstruction instruction = block.first; |
| 106 while (instruction !== null) { | 106 while (instruction !== null) { |
| 107 // Note that visitInstruction (from the phis and here) might insert an | 107 // Note that visitInstruction (from the phis and here) might insert an |
| 108 // HTypeGuard instruction. We have to skip those. | 108 // HTypeGuard instruction. We have to skip those. |
| 109 if (instruction is !HTypeGuard) visitInstruction(instruction); | 109 if (instruction is !HTypeGuard) visitInstruction(instruction); |
| 110 instruction = instruction.next; | 110 instruction = instruction.next; |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 bool typeGuardWouldBeValuable(HInstruction instruction, | |
| 115 HType speculativeType) { | |
| 116 bool isNested(HBasicBlock inner, HBasicBlock outer) { | |
| 117 if (inner === outer) return false; | |
| 118 if (outer === null) return true; | |
| 119 while (inner !== null) { | |
| 120 if (inner === outer) return true; | |
| 121 inner = inner.parentLoopHeader; | |
| 122 } | |
| 123 return false; | |
| 124 } | |
| 125 | |
| 126 // If the instruction is not in a loop then the header will be null. | |
| 127 HBasicBlock currentLoopHeader = instruction.block.enclosingLoopHeader; | |
| 128 for (HInstruction user in instruction.usedBy) { | |
| 129 HBasicBlock userLoopHeader = user.block.enclosingLoopHeader; | |
| 130 if (isNested(userLoopHeader, currentLoopHeader)) return true; | |
| 131 } | |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 bool shouldInsertTypeGuard(HInstruction instruction) { | 114 bool shouldInsertTypeGuard(HInstruction instruction) { |
| 136 HType speculativeType = instruction.propagatedType; | 115 HType speculativeType = instruction.propagatedType; |
| 137 HType computedType = instruction.computeTypeFromInputTypes(); | 116 HType computedType = instruction.computeTypeFromInputTypes(); |
| 138 // Start by reverting the propagated type. If we add a type guard then the | 117 // Start by reverting the propagated type. If we add a type guard then the |
| 139 // guard will expose the speculative type. If we don't add a type guard | 118 // guard will expose the speculative type. If we don't add a type guard |
| 140 // then this avoids subsequent instructions to use the the wrong type. | 119 // then this avoids subsequent instructions to use the the wrong type. |
| 141 // | 120 // |
| 142 // Note that just setting the propagatedType of the instruction is not | 121 // Note that just setting the propagatedType of the instruction is not |
| 143 // complete since the type could lead to a phi node which in turn could | 122 // complete since the type could lead to a phi node which in turn could |
| 144 // change the computedType. In this case we might miss some guards we | 123 // change the computedType. In this case we might miss some guards we |
| 145 // would have liked to insert. Most of the time this should however be | 124 // would have liked to insert. Most of the time this should however be |
| 146 // fine, due to dominator-order visiting. | 125 // fine, due to dominator-order visiting. |
| 147 instruction.propagatedType = computedType; | 126 instruction.propagatedType = computedType; |
| 148 | 127 |
| 149 if (!speculativeType.isUseful()) return false; | 128 if (!speculativeType.isUseful()) return false; |
| 150 // If the types agree we don't need to check. | 129 // If the types agree we don't need to check. |
| 151 if (speculativeType == computedType) return false; | 130 if (speculativeType == computedType) return false; |
| 152 // If a bailout check is more expensive than doing the actual operation | 131 // TODO(floitsch): Make the creation of type guards more conditional. |
| 153 // don't do it either. | 132 return true; |
| 154 return typeGuardWouldBeValuable(instruction, speculativeType); | |
| 155 } | 133 } |
| 156 | 134 |
| 157 void visitInstruction(HInstruction instruction) { | 135 void visitInstruction(HInstruction instruction) { |
| 158 HType speculativeType = instruction.propagatedType; | 136 HType speculativeType = instruction.propagatedType; |
| 159 if (shouldInsertTypeGuard(instruction)) { | 137 if (shouldInsertTypeGuard(instruction)) { |
| 160 List<HInstruction> inputs = <HInstruction>[instruction]; | 138 List<HInstruction> inputs = <HInstruction>[instruction]; |
| 161 HTypeGuard guard = new HTypeGuard(speculativeType, stateId++, inputs); | 139 HTypeGuard guard = new HTypeGuard(speculativeType, stateId++, inputs); |
| 162 guard.propagatedType = speculativeType; | 140 guard.propagatedType = speculativeType; |
| 163 work.guards.add(guard); | 141 work.guards.add(guard); |
| 164 instruction.block.rewrite(instruction, guard); | 142 instruction.block.rewrite(instruction, guard); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 compiler.internalError('Control flow instructions already dealt with.', | 426 compiler.internalError('Control flow instructions already dealt with.', |
| 449 instruction: instruction); | 427 instruction: instruction); |
| 450 } | 428 } |
| 451 | 429 |
| 452 visitTypeGuard(HTypeGuard guard) { | 430 visitTypeGuard(HTypeGuard guard) { |
| 453 blocks.forEach((HBasicBlock block) { | 431 blocks.forEach((HBasicBlock block) { |
| 454 block.guards.add(guard); | 432 block.guards.add(guard); |
| 455 }); | 433 }); |
| 456 } | 434 } |
| 457 } | 435 } |
| OLD | NEW |