| 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 48           new SsaTypePropagator(compiler), | 48           new SsaTypePropagator(compiler), | 
| 49           // Run a dead code eliminator before LICM because dead | 49           // Run a dead code eliminator before LICM because dead | 
| 50           // interceptors are often in the way of LICM'able instructions. | 50           // interceptors are often in the way of LICM'able instructions. | 
| 51           new SsaDeadCodeEliminator(compiler, this), | 51           new SsaDeadCodeEliminator(compiler, this), | 
| 52           new SsaGlobalValueNumberer(compiler), | 52           new SsaGlobalValueNumberer(compiler), | 
| 53           // After GVN, some instructions might need their type to be | 53           // After GVN, some instructions might need their type to be | 
| 54           // updated because they now have different inputs. | 54           // updated because they now have different inputs. | 
| 55           new SsaTypePropagator(compiler), | 55           new SsaTypePropagator(compiler), | 
| 56           new SsaCodeMotion(), | 56           new SsaCodeMotion(), | 
| 57           new SsaLoadElimination(compiler), | 57           new SsaLoadElimination(compiler), | 
|  | 58           new SsaRedundantPhiEliminator(), | 
| 58           new SsaDeadPhiEliminator(), | 59           new SsaDeadPhiEliminator(), | 
| 59           new SsaTypePropagator(compiler), | 60           new SsaTypePropagator(compiler), | 
| 60           new SsaValueRangeAnalyzer(compiler, constantSystem, this, work), | 61           new SsaValueRangeAnalyzer(compiler, constantSystem, this, work), | 
| 61           // Previous optimizations may have generated new | 62           // Previous optimizations may have generated new | 
| 62           // opportunities for instruction simplification. | 63           // opportunities for instruction simplification. | 
| 63           new SsaInstructionSimplifier(constantSystem, backend, this, work), | 64           new SsaInstructionSimplifier(constantSystem, backend, this, work), | 
| 64           new SsaCheckInserter( | 65           new SsaCheckInserter( | 
| 65               trustPrimitives, backend, work, context.boundsChecked), | 66               trustPrimitives, backend, work, context.boundsChecked), | 
| 66       ]; | 67       ]; | 
| 67       phases.forEach(runPhase); | 68       phases.forEach(runPhase); | 
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 190 | 191 | 
| 191   HInstruction visitInstruction(HInstruction node) { | 192   HInstruction visitInstruction(HInstruction node) { | 
| 192     return node; | 193     return node; | 
| 193   } | 194   } | 
| 194 | 195 | 
| 195   HInstruction visitBoolify(HBoolify node) { | 196   HInstruction visitBoolify(HBoolify node) { | 
| 196     List<HInstruction> inputs = node.inputs; | 197     List<HInstruction> inputs = node.inputs; | 
| 197     assert(inputs.length == 1); | 198     assert(inputs.length == 1); | 
| 198     HInstruction input = inputs[0]; | 199     HInstruction input = inputs[0]; | 
| 199     if (input.isBoolean(compiler)) return input; | 200     if (input.isBoolean(compiler)) return input; | 
|  | 201 | 
|  | 202     // If the code is unreachable, remove the HBoolify.  This can happen when | 
|  | 203     // there is a throw expression in a short-circuit conditional.  Removing the | 
|  | 204     // unreachable HBoolify makes it easier to reconstruct the short-circuit | 
|  | 205     // operation. | 
|  | 206     if (input.instructionType.isEmpty && !input.instructionType.isNullable) | 
|  | 207       return input; | 
|  | 208 | 
| 200     // All values that cannot be 'true' are boolified to false. | 209     // All values that cannot be 'true' are boolified to false. | 
| 201     TypeMask mask = input.instructionType; | 210     TypeMask mask = input.instructionType; | 
| 202     if (!mask.contains(backend.jsBoolClass, compiler.world)) { | 211     if (!mask.contains(backend.jsBoolClass, compiler.world)) { | 
| 203       return graph.addConstantBool(false, compiler); | 212       return graph.addConstantBool(false, compiler); | 
| 204     } | 213     } | 
| 205     return node; | 214     return node; | 
| 206   } | 215   } | 
| 207 | 216 | 
| 208   HInstruction visitNot(HNot node) { | 217   HInstruction visitNot(HNot node) { | 
| 209     List<HInstruction> inputs = node.inputs; | 218     List<HInstruction> inputs = node.inputs; | 
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 506     // in the remaining optimizations. | 515     // in the remaining optimizations. | 
| 507     return super.visitRelational(node); | 516     return super.visitRelational(node); | 
| 508   } | 517   } | 
| 509 | 518 | 
| 510   HInstruction handleIdentityCheck(HRelational node) { | 519   HInstruction handleIdentityCheck(HRelational node) { | 
| 511     HInstruction left = node.left; | 520     HInstruction left = node.left; | 
| 512     HInstruction right = node.right; | 521     HInstruction right = node.right; | 
| 513     TypeMask leftType = left.instructionType; | 522     TypeMask leftType = left.instructionType; | 
| 514     TypeMask rightType = right.instructionType; | 523     TypeMask rightType = right.instructionType; | 
| 515 | 524 | 
|  | 525     HInstruction makeTrue() => graph.addConstantBool(true, compiler); | 
|  | 526     HInstruction makeFalse() => graph.addConstantBool(false, compiler); | 
|  | 527 | 
| 516     // Intersection of int and double return conflicting, so | 528     // Intersection of int and double return conflicting, so | 
| 517     // we don't optimize on numbers to preserve the runtime semantics. | 529     // we don't optimize on numbers to preserve the runtime semantics. | 
| 518     if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) { | 530     if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) { | 
| 519       TypeMask intersection = leftType.intersection(rightType, compiler.world); | 531       TypeMask intersection = leftType.intersection(rightType, compiler.world); | 
| 520       if (intersection.isEmpty && !intersection.isNullable) { | 532       if (intersection.isEmpty && !intersection.isNullable) { | 
| 521         return graph.addConstantBool(false, compiler); | 533         return makeFalse(); | 
| 522       } | 534       } | 
| 523     } | 535     } | 
| 524 | 536 | 
| 525     if (left.isNull() && right.isNull()) { | 537     if (left.isNull() && right.isNull()) { | 
| 526       return graph.addConstantBool(true, compiler); | 538       return makeTrue(); | 
|  | 539     } | 
|  | 540 | 
|  | 541     HInstruction compareConstant(HConstant constant, HInstruction input) { | 
|  | 542       if (constant.constant.isTrue) { | 
|  | 543         return input; | 
|  | 544       } else { | 
|  | 545         return new HNot(input, backend.boolType); | 
|  | 546       } | 
| 527     } | 547     } | 
| 528 | 548 | 
| 529     if (left.isConstantBoolean() && right.isBoolean(compiler)) { | 549     if (left.isConstantBoolean() && right.isBoolean(compiler)) { | 
| 530       HConstant constant = left; | 550       return compareConstant(left, right); | 
| 531       if (constant.constant.isTrue) { |  | 
| 532         return right; |  | 
| 533       } else { |  | 
| 534         return new HNot(right, backend.boolType); |  | 
| 535       } |  | 
| 536     } | 551     } | 
| 537 | 552 | 
| 538     if (right.isConstantBoolean() && left.isBoolean(compiler)) { | 553     if (right.isConstantBoolean() && left.isBoolean(compiler)) { | 
| 539       HConstant constant = right; | 554       return compareConstant(right, left); | 
| 540       if (constant.constant.isTrue) { | 555     } | 
| 541         return left; | 556 | 
| 542       } else { | 557 | 
| 543         return new HNot(left, backend.boolType); | 558     if (identical(left.nonCheck(), right.nonCheck())) { | 
| 544       } | 559       // Avoid constant-folding `identical(x, x)` when `x` might be double.  The | 
|  | 560       // dart2js runtime has not always been consistent with the Dart | 
|  | 561       // specification (section 16.0.1), which makes distinctions on NaNs and | 
|  | 562       // -0.0 that are hard to implement efficiently. | 
|  | 563       if (left.isIntegerOrNull(compiler)) return makeTrue(); | 
|  | 564       if (!left.canBePrimitiveNumber(compiler)) return makeTrue(); | 
| 545     } | 565     } | 
| 546 | 566 | 
| 547     return null; | 567     return null; | 
| 548   } | 568   } | 
| 549 | 569 | 
| 550   HInstruction visitIdentity(HIdentity node) { | 570   HInstruction visitIdentity(HIdentity node) { | 
| 551     HInstruction newInstruction = handleIdentityCheck(node); | 571     HInstruction newInstruction = handleIdentityCheck(node); | 
| 552     return newInstruction == null ? super.visitIdentity(node) : newInstruction; | 572     return newInstruction == null ? super.visitIdentity(node) : newInstruction; | 
| 553   } | 573   } | 
| 554 | 574 | 
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 815           type, | 835           type, | 
| 816           HTypeConversion.CHECKED_MODE_CHECK); | 836           HTypeConversion.CHECKED_MODE_CHECK); | 
| 817       if (other != value) { | 837       if (other != value) { | 
| 818         node.block.addBefore(node, other); | 838         node.block.addBefore(node, other); | 
| 819         value = other; | 839         value = other; | 
| 820       } | 840       } | 
| 821     } | 841     } | 
| 822     return new HFieldSet(field, receiver, value); | 842     return new HFieldSet(field, receiver, value); | 
| 823   } | 843   } | 
| 824 | 844 | 
|  | 845   HInstruction visitInvokeStatic(HInvokeStatic node) { | 
|  | 846     if (node.element == backend.getCheckConcurrentModificationError()) { | 
|  | 847       if (node.inputs.length == 2) { | 
|  | 848         HInstruction firstArgument = node.inputs[0]; | 
|  | 849         if (firstArgument is HConstant) { | 
|  | 850           HConstant constant = firstArgument; | 
|  | 851           if (constant.constant.isTrue) return constant; | 
|  | 852         } | 
|  | 853       } | 
|  | 854     } | 
|  | 855     return node; | 
|  | 856   } | 
|  | 857 | 
| 825   HInstruction visitStringConcat(HStringConcat node) { | 858   HInstruction visitStringConcat(HStringConcat node) { | 
| 826     // Simplify string concat: | 859     // Simplify string concat: | 
| 827     // | 860     // | 
| 828     //     "" + R                ->  R | 861     //     "" + R                ->  R | 
| 829     //     L + ""                ->  L | 862     //     L + ""                ->  L | 
| 830     //     "L" + "R"             ->  "LR" | 863     //     "L" + "R"             ->  "LR" | 
| 831     //     (prefix + "L") + "R"  ->  prefix + "LR" | 864     //     (prefix + "L") + "R"  ->  prefix + "LR" | 
| 832     // | 865     // | 
| 833     StringConstantValue getString(HInstruction instruction) { | 866     StringConstantValue getString(HInstruction instruction) { | 
| 834       if (!instruction.isConstantString()) return null; | 867       if (!instruction.isConstantString()) return null; | 
| (...skipping 1411 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2246 | 2279 | 
| 2247     keyedValues.forEach((receiver, values) { | 2280     keyedValues.forEach((receiver, values) { | 
| 2248       result.keyedValues[receiver] = | 2281       result.keyedValues[receiver] = | 
| 2249           new Map<HInstruction, HInstruction>.from(values); | 2282           new Map<HInstruction, HInstruction>.from(values); | 
| 2250     }); | 2283     }); | 
| 2251 | 2284 | 
| 2252     result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2285     result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 
| 2253     return result; | 2286     return result; | 
| 2254   } | 2287   } | 
| 2255 } | 2288 } | 
| OLD | NEW | 
|---|