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 CodegenRegistry, CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
6 import '../common/names.dart' show Selectors; | 6 import '../common/names.dart' show Selectors; |
7 import '../common/tasks.dart' show CompilerTask; | 7 import '../common/tasks.dart' show CompilerTask; |
8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
(...skipping 2092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 | 2103 |
2104 void visitIs(HIs instruction) { | 2104 void visitIs(HIs instruction) { |
2105 DartType type = instruction.typeExpression; | 2105 DartType type = instruction.typeExpression; |
2106 Element element = type.element; | 2106 Element element = type.element; |
2107 if (!instruction.isRawCheck) { | 2107 if (!instruction.isRawCheck) { |
2108 return; | 2108 return; |
2109 } else if (element.isTypedef) { | 2109 } else if (element.isTypedef) { |
2110 return; | 2110 return; |
2111 } | 2111 } |
2112 | 2112 |
2113 List<HInstruction> ifUsers = <HInstruction>[]; | 2113 List<HBasicBlock> trueTargets = <HBasicBlock>[]; |
2114 List<HInstruction> notIfUsers = <HInstruction>[]; | 2114 List<HBasicBlock> falseTargets = <HBasicBlock>[]; |
2115 | 2115 |
2116 collectIfUsers(instruction, ifUsers, notIfUsers); | 2116 collectTargets(instruction, trueTargets, falseTargets); |
2117 | 2117 |
2118 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 2118 if (trueTargets.isEmpty && falseTargets.isEmpty) return; |
2119 | 2119 |
2120 TypeMask convertedType = | 2120 TypeMask convertedType = |
2121 new TypeMask.nonNullSubtype(element, compiler.closedWorld); | 2121 new TypeMask.nonNullSubtype(element, compiler.closedWorld); |
2122 HInstruction input = instruction.expression; | 2122 HInstruction input = instruction.expression; |
2123 | 2123 |
2124 for (HIf ifUser in ifUsers) { | 2124 for (HBasicBlock block in trueTargets) { |
2125 insertTypePropagationForDominatedUsers( | 2125 insertTypePropagationForDominatedUsers(block, input, convertedType); |
2126 ifUser.thenBlock, input, convertedType); | |
2127 // TODO(ngeoffray): Also change uses for the else block on a type | |
2128 // that knows it is not of a specific type. | |
2129 } | 2126 } |
2130 for (HIf ifUser in notIfUsers) { | 2127 // TODO(sra): Also strengthen uses for when the condition is known |
2131 insertTypePropagationForDominatedUsers( | 2128 // false. Avoid strengthening to `null`. |
2132 ifUser.elseBlock, input, convertedType); | |
2133 // TODO(ngeoffray): Also change uses for the then block on a type | |
2134 // that knows it is not of a specific type. | |
2135 } | |
2136 } | 2129 } |
2137 | 2130 |
2138 void visitIdentity(HIdentity instruction) { | 2131 void visitIdentity(HIdentity instruction) { |
2139 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. | 2132 // At HIf(HIdentity(x, null)) strengthens x to non-null on else branch. |
2140 HInstruction left = instruction.left; | 2133 HInstruction left = instruction.left; |
2141 HInstruction right = instruction.right; | 2134 HInstruction right = instruction.right; |
2142 HInstruction input; | 2135 HInstruction input; |
2143 | 2136 |
2144 if (left.isConstantNull()) { | 2137 if (left.isConstantNull()) { |
2145 input = right; | 2138 input = right; |
2146 } else if (right.isConstantNull()) { | 2139 } else if (right.isConstantNull()) { |
2147 input = left; | 2140 input = left; |
2148 } else { | 2141 } else { |
2149 return; | 2142 return; |
2150 } | 2143 } |
2151 | 2144 |
2152 if (!input.instructionType.isNullable) return; | 2145 if (!input.instructionType.isNullable) return; |
2153 | 2146 |
2154 List<HInstruction> ifUsers = <HInstruction>[]; | 2147 List<HBasicBlock> trueTargets = <HBasicBlock>[]; |
2155 List<HInstruction> notIfUsers = <HInstruction>[]; | 2148 List<HBasicBlock> falseTargets = <HBasicBlock>[]; |
2156 | 2149 |
2157 collectIfUsers(instruction, ifUsers, notIfUsers); | 2150 collectTargets(instruction, trueTargets, falseTargets); |
2158 | 2151 |
2159 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; | 2152 if (trueTargets.isEmpty && falseTargets.isEmpty) return; |
2160 | 2153 |
2161 TypeMask nonNullType = input.instructionType.nonNullable(); | 2154 TypeMask nonNullType = input.instructionType.nonNullable(); |
2162 | 2155 |
2163 for (HIf ifUser in ifUsers) { | 2156 for (HBasicBlock block in falseTargets) { |
2164 insertTypePropagationForDominatedUsers( | 2157 insertTypePropagationForDominatedUsers(block, input, nonNullType); |
2165 ifUser.elseBlock, input, nonNullType); | |
2166 // Uses in thenBlock are `null`, but probably not common. | |
2167 } | 2158 } |
2168 for (HIf ifUser in notIfUsers) { | 2159 // We don't strengthen the known-true references. It doesn't happen often |
2169 insertTypePropagationForDominatedUsers( | 2160 // and we don't want "if (x==null) return x;" to convert between JavaScript |
2170 ifUser.thenBlock, input, nonNullType); | 2161 // 'null' and 'undefined'. |
2171 // Uses in elseBlock are `null`, but probably not common. | |
2172 } | |
2173 } | 2162 } |
2174 | 2163 |
2175 collectIfUsers(HInstruction instruction, List<HInstruction> ifUsers, | 2164 collectTargets(HInstruction instruction, List<HBasicBlock> trueTargets, |
2176 List<HInstruction> notIfUsers) { | 2165 List<HBasicBlock> falseTargets) { |
2177 for (HInstruction user in instruction.usedBy) { | 2166 for (HInstruction user in instruction.usedBy) { |
2178 if (user is HIf) { | 2167 if (user is HIf) { |
2179 ifUsers.add(user); | 2168 trueTargets?.add(user.thenBlock); |
| 2169 falseTargets?.add(user.elseBlock); |
2180 } else if (user is HNot) { | 2170 } else if (user is HNot) { |
2181 collectIfUsers(user, notIfUsers, ifUsers); | 2171 collectTargets(user, falseTargets, trueTargets); |
| 2172 } else if (user is HPhi) { |
| 2173 List<HInstruction> inputs = user.inputs; |
| 2174 if (inputs.length == 2) { |
| 2175 assert(inputs.contains(instruction)); |
| 2176 HInstruction other = inputs[(inputs[0] == instruction) ? 1 : 0]; |
| 2177 if (other.isConstantTrue()) { |
| 2178 // The condition flows to a HPhi(true, user), which means that a |
| 2179 // downstream HIf has true-branch control flow that does not depend |
| 2180 // on the original instruction, so stop collecting [trueTargets]. |
| 2181 collectTargets(user, null, falseTargets); |
| 2182 } else if (other.isConstantFalse()) { |
| 2183 // Ditto for false. |
| 2184 collectTargets(user, trueTargets, null); |
| 2185 } |
| 2186 } |
| 2187 } else if (user is HBoolify) { |
| 2188 // We collect targets for strictly boolean operations so HBoolify cannot |
| 2189 // change the result. |
| 2190 collectTargets(user, trueTargets, falseTargets); |
2182 } | 2191 } |
2183 } | 2192 } |
2184 } | 2193 } |
2185 } | 2194 } |
2186 | 2195 |
2187 /** | 2196 /** |
2188 * Optimization phase that tries to eliminate memory loads (for | 2197 * Optimization phase that tries to eliminate memory loads (for |
2189 * example [HFieldGet]), when it knows the value stored in that memory | 2198 * example [HFieldGet]), when it knows the value stored in that memory |
2190 * location. | 2199 * location. |
2191 */ | 2200 */ |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2709 | 2718 |
2710 keyedValues.forEach((receiver, values) { | 2719 keyedValues.forEach((receiver, values) { |
2711 result.keyedValues[receiver] = | 2720 result.keyedValues[receiver] = |
2712 new Map<HInstruction, HInstruction>.from(values); | 2721 new Map<HInstruction, HInstruction>.from(values); |
2713 }); | 2722 }); |
2714 | 2723 |
2715 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2724 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
2716 return result; | 2725 return result; |
2717 } | 2726 } |
2718 } | 2727 } |
OLD | NEW |