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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 block.remove(instruction); | 193 block.remove(instruction); |
| 194 } | 194 } |
| 195 instruction = next; | 195 instruction = next; |
| 196 } | 196 } |
| 197 } | 197 } |
| 198 | 198 |
| 199 HInstruction visitInstruction(HInstruction node) { | 199 HInstruction visitInstruction(HInstruction node) { |
| 200 return node; | 200 return node; |
| 201 } | 201 } |
| 202 | 202 |
| 203 ConstantValue getConstantFromType(HInstruction node) { | |
| 204 if (node.isValue() && !node.canBeNull()) { | |
| 205 ValueTypeMask valueMask = node.instructionType; | |
| 206 if (valueMask.value.isBool) { | |
| 207 return valueMask.value; | |
| 208 } | |
| 209 // TODO(het): consider supporting other values (short strings?) | |
| 210 } | |
| 211 return null; | |
| 212 } | |
| 213 | |
| 214 void propagateConstantValueToUses(HInstruction known) { | |
|
sra1
2015/10/01 01:48:00
Maybe call it 'node'.
It is not known until we tes
Harry Terkelsen
2015/10/01 21:06:36
Done.
| |
| 215 if (known.usedBy.isEmpty) return; | |
| 216 ConstantValue value = getConstantFromType(known); | |
| 217 if (value != null) { | |
| 218 // If this instruction is ever assigned to, then do not propagate the | |
| 219 // value since it may | |
|
sra1
2015/10/01 01:48:00
Not needed.
Only parameters (and Locals) can be as
Harry Terkelsen
2015/10/01 21:06:36
Done.
| |
| 220 if (known.usedBy.any( | |
| 221 (user) => user is HLocalSet && identical(user.local, known))) { | |
| 222 return; | |
| 223 } | |
| 224 for (HInstruction user in known.usedBy.toList()) { | |
| 225 user.changeUse(known, graph.addConstant(value, compiler)); | |
|
sra1
2015/10/01 01:48:00
You can lift this out of the loop:
HInstruction c
Harry Terkelsen
2015/10/01 21:06:36
Done.
| |
| 226 } | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 HInstruction visitParameterValue(HParameterValue node) { | |
| 231 // It is possible for the parameter value to be assigned to in the function | |
| 232 // body. If that happens then we should not forward the constant value to | |
| 233 // its uses since they are shadowed by the assignment. | |
|
sra1
2015/10/01 01:48:00
"since the uses reachable from the assignment may
Harry Terkelsen
2015/10/01 21:06:36
I just tried out this program. The p is not recogn
| |
| 234 if (node.usedBy.any((user) => | |
| 235 user is HLocalSet && identical(user.local, node))) { | |
| 236 return node; | |
| 237 } | |
| 238 propagateConstantValueToUses(node); | |
| 239 return node; | |
| 240 } | |
| 241 | |
| 203 HInstruction visitBoolify(HBoolify node) { | 242 HInstruction visitBoolify(HBoolify node) { |
| 204 List<HInstruction> inputs = node.inputs; | 243 List<HInstruction> inputs = node.inputs; |
| 205 assert(inputs.length == 1); | 244 assert(inputs.length == 1); |
| 206 HInstruction input = inputs[0]; | 245 HInstruction input = inputs[0]; |
| 207 if (input.isBoolean(compiler)) return input; | 246 if (input.isBoolean(compiler)) return input; |
| 208 | 247 |
| 209 // If the code is unreachable, remove the HBoolify. This can happen when | 248 // If the code is unreachable, remove the HBoolify. This can happen when |
| 210 // there is a throw expression in a short-circuit conditional. Removing the | 249 // there is a throw expression in a short-circuit conditional. Removing the |
| 211 // unreachable HBoolify makes it easier to reconstruct the short-circuit | 250 // unreachable HBoolify makes it easier to reconstruct the short-circuit |
| 212 // operation. | 251 // operation. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 if (selector.applies(backend.jsIndexableLength, world)) { | 404 if (selector.applies(backend.jsIndexableLength, world)) { |
| 366 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); | 405 HInstruction optimized = tryOptimizeLengthInterceptedGetter(node); |
| 367 if (optimized != null) return optimized; | 406 if (optimized != null) return optimized; |
| 368 } | 407 } |
| 369 } | 408 } |
| 370 | 409 |
| 371 return node; | 410 return node; |
| 372 } | 411 } |
| 373 | 412 |
| 374 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 413 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 414 propagateConstantValueToUses(node); | |
| 375 if (node.isInterceptedCall) { | 415 if (node.isInterceptedCall) { |
| 376 HInstruction folded = handleInterceptedCall(node); | 416 HInstruction folded = handleInterceptedCall(node); |
| 377 if (folded != node) return folded; | 417 if (folded != node) return folded; |
| 378 } | 418 } |
| 379 | 419 |
| 380 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; | 420 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; |
| 381 Element element = | 421 Element element = |
| 382 compiler.world.locateSingleElement(node.selector, receiverType); | 422 compiler.world.locateSingleElement(node.selector, receiverType); |
| 383 // TODO(ngeoffray): Also fold if it's a getter or variable. | 423 // TODO(ngeoffray): Also fold if it's a getter or variable. |
| 384 if (element != null | 424 if (element != null |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 instruction = node.index; | 839 instruction = node.index; |
| 800 int index = instruction.constant.primitiveValue; | 840 int index = instruction.constant.primitiveValue; |
| 801 if (index >= 0 && index < entries.length) { | 841 if (index >= 0 && index < entries.length) { |
| 802 return graph.addConstant(entries[index], compiler); | 842 return graph.addConstant(entries[index], compiler); |
| 803 } | 843 } |
| 804 } | 844 } |
| 805 return node; | 845 return node; |
| 806 } | 846 } |
| 807 | 847 |
| 808 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 848 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
| 849 propagateConstantValueToUses(node); | |
| 809 if (node.isInterceptedCall) { | 850 if (node.isInterceptedCall) { |
| 810 HInstruction folded = handleInterceptedCall(node); | 851 HInstruction folded = handleInterceptedCall(node); |
| 811 if (folded != node) return folded; | 852 if (folded != node) return folded; |
| 812 } | 853 } |
| 813 HInstruction receiver = node.getDartReceiver(compiler); | 854 HInstruction receiver = node.getDartReceiver(compiler); |
| 814 Element field = findConcreteFieldForDynamicAccess( | 855 Element field = findConcreteFieldForDynamicAccess( |
| 815 receiver, node.selector); | 856 receiver, node.selector); |
| 816 if (field == null) return node; | 857 if (field == null) return node; |
| 817 return directFieldGet(receiver, field); | 858 return directFieldGet(receiver, field); |
| 818 } | 859 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 HTypeConversion.CHECKED_MODE_CHECK); | 901 HTypeConversion.CHECKED_MODE_CHECK); |
| 861 if (other != value) { | 902 if (other != value) { |
| 862 node.block.addBefore(node, other); | 903 node.block.addBefore(node, other); |
| 863 value = other; | 904 value = other; |
| 864 } | 905 } |
| 865 } | 906 } |
| 866 return new HFieldSet(field, receiver, value); | 907 return new HFieldSet(field, receiver, value); |
| 867 } | 908 } |
| 868 | 909 |
| 869 HInstruction visitInvokeStatic(HInvokeStatic node) { | 910 HInstruction visitInvokeStatic(HInvokeStatic node) { |
| 911 propagateConstantValueToUses(node); | |
| 870 if (node.element == backend.getCheckConcurrentModificationError()) { | 912 if (node.element == backend.getCheckConcurrentModificationError()) { |
| 871 if (node.inputs.length == 2) { | 913 if (node.inputs.length == 2) { |
| 872 HInstruction firstArgument = node.inputs[0]; | 914 HInstruction firstArgument = node.inputs[0]; |
| 873 if (firstArgument is HConstant) { | 915 if (firstArgument is HConstant) { |
| 874 HConstant constant = firstArgument; | 916 HConstant constant = firstArgument; |
| 875 if (constant.constant.isTrue) return constant; | 917 if (constant.constant.isTrue) return constant; |
| 876 } | 918 } |
| 877 } | 919 } |
| 878 } | 920 } |
| 879 return node; | 921 return node; |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1299 } | 1341 } |
| 1300 | 1342 |
| 1301 void visitIf(HIf instruction) { | 1343 void visitIf(HIf instruction) { |
| 1302 HInstruction condition = instruction.condition; | 1344 HInstruction condition = instruction.condition; |
| 1303 if (condition.isConstant()) { | 1345 if (condition.isConstant()) { |
| 1304 if (condition.isConstantTrue()) { | 1346 if (condition.isConstantTrue()) { |
| 1305 markBlockLive(instruction.thenBlock); | 1347 markBlockLive(instruction.thenBlock); |
| 1306 } else { | 1348 } else { |
| 1307 markBlockLive(instruction.elseBlock); | 1349 markBlockLive(instruction.elseBlock); |
| 1308 } | 1350 } |
| 1309 } else if (condition.isValue()) { | |
| 1310 ValueTypeMask valueType = condition.instructionType; | |
| 1311 if (valueType.value == true) { | |
| 1312 markBlockLive(instruction.thenBlock); | |
| 1313 } else { | |
| 1314 markBlockLive(instruction.elseBlock); | |
| 1315 } | |
| 1316 } else { | 1351 } else { |
| 1317 visitControlFlow(instruction); | 1352 visitControlFlow(instruction); |
| 1318 } | 1353 } |
| 1319 } | 1354 } |
| 1320 | 1355 |
| 1321 void visitSwitch(HSwitch node) { | 1356 void visitSwitch(HSwitch node) { |
| 1322 if (node.expression.isInteger(compiler)) { | 1357 if (node.expression.isInteger(compiler)) { |
| 1323 Range switchRange = ranges[node.expression]; | 1358 Range switchRange = ranges[node.expression]; |
| 1324 if (switchRange != null && | 1359 if (switchRange != null && |
| 1325 switchRange.lower is IntValue && | 1360 switchRange.lower is IntValue && |
| (...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2359 | 2394 |
| 2360 keyedValues.forEach((receiver, values) { | 2395 keyedValues.forEach((receiver, values) { |
| 2361 result.keyedValues[receiver] = | 2396 result.keyedValues[receiver] = |
| 2362 new Map<HInstruction, HInstruction>.from(values); | 2397 new Map<HInstruction, HInstruction>.from(values); |
| 2363 }); | 2398 }); |
| 2364 | 2399 |
| 2365 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2400 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2366 return result; | 2401 return result; |
| 2367 } | 2402 } |
| 2368 } | 2403 } |
| OLD | NEW |