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 | 7 |
| 8 class ValueRangeInfo { | 8 class ValueRangeInfo { |
| 9 final ConstantSystem constantSystem; | 9 final ConstantSystem constantSystem; |
| 10 | 10 |
| 11 IntValue intZero; | 11 IntValue intZero; |
| 12 IntValue intOne; | 12 IntValue intOne; |
| 13 | 13 |
| 14 ValueRangeInfo(this.constantSystem) { | 14 ValueRangeInfo(this.constantSystem) { |
| 15 intZero = newIntValue(0); | 15 intZero = newIntValue(0); |
| 16 intOne = newIntValue(1); | 16 intOne = newIntValue(1); |
| 17 } | 17 } |
| 18 | 18 |
| 19 Value newIntValue(int value) { | 19 Value newIntValue(int value) { |
| 20 return new IntValue(value, this); | 20 return new IntValue(value, this); |
| 21 } | 21 } |
| 22 | 22 |
| 23 Value newInstructionValue(HInstruction instruction) { | 23 Value newInstructionValue(HInstruction instruction) { |
| 24 return new InstructionValue(instruction, this); | 24 return new InstructionValue(instruction, this); |
| 25 } | 25 } |
| 26 | 26 |
| 27 Value newLengthValue(HInstruction instruction) { | 27 Value newPositiveValue(HInstruction instruction) { |
| 28 return new LengthValue(instruction, this); | 28 return new PositiveValue(instruction, this); |
| 29 } | 29 } |
| 30 | 30 |
| 31 Value newAddValue(Value left, Value right) { | 31 Value newAddValue(Value left, Value right) { |
| 32 return new AddValue(left, right, this); | 32 return new AddValue(left, right, this); |
| 33 } | 33 } |
| 34 | 34 |
| 35 Value newSubtractValue(Value left, Value right) { | 35 Value newSubtractValue(Value left, Value right) { |
| 36 return new SubtractValue(left, right, this); | 36 return new SubtractValue(left, right, this); |
| 37 } | 37 } |
| 38 | 38 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 return info.newNegateValue(this); | 284 return info.newNegateValue(this); |
| 285 } | 285 } |
| 286 | 286 |
| 287 bool get isNegative => false; | 287 bool get isNegative => false; |
| 288 bool get isPositive => false; | 288 bool get isPositive => false; |
| 289 | 289 |
| 290 String toString() => 'Instruction: $instruction'; | 290 String toString() => 'Instruction: $instruction'; |
| 291 } | 291 } |
| 292 | 292 |
| 293 /** | 293 /** |
| 294 * Special value for instructions that represent the length of an | 294 * Special value for instructions whose type is a positive integer. |
| 295 * array. The difference with an [InstructionValue] is that we know | |
| 296 * the value is positive. | |
| 297 */ | 295 */ |
| 298 class LengthValue extends InstructionValue { | 296 class PositiveValue extends InstructionValue { |
|
sra1
2013/11/27 20:29:36
Zero is possible, but is not positive.
Perhaps lea
| |
| 299 LengthValue(HInstruction instruction, info) : super(instruction, info); | 297 PositiveValue(HInstruction instruction, info) : super(instruction, info); |
| 300 bool get isPositive => true; | 298 bool get isPositive => true; |
| 301 String toString() => 'Length: $instruction'; | |
| 302 } | 299 } |
| 303 | 300 |
| 304 /** | 301 /** |
| 305 * Represents a binary operation on two [Value], where the operation | 302 * Represents a binary operation on two [Value], where the operation |
| 306 * did not yield a canonical value. | 303 * did not yield a canonical value. |
| 307 */ | 304 */ |
| 308 class BinaryOperationValue extends Value { | 305 class BinaryOperationValue extends Value { |
| 309 final Value left; | 306 final Value left; |
| 310 final Value right; | 307 final Value right; |
| 311 BinaryOperationValue(this.left, this.right, info) : super(info); | 308 BinaryOperationValue(this.left, this.right, info) : super(info); |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 assert(range != null); | 627 assert(range != null); |
| 631 ranges[instruction] = range; | 628 ranges[instruction] = range; |
| 632 } | 629 } |
| 633 } | 630 } |
| 634 | 631 |
| 635 block.forEachPhi(visit); | 632 block.forEachPhi(visit); |
| 636 block.forEachInstruction(visit); | 633 block.forEachInstruction(visit); |
| 637 } | 634 } |
| 638 | 635 |
| 639 Range visitInstruction(HInstruction instruction) { | 636 Range visitInstruction(HInstruction instruction) { |
| 640 return info.newUnboundRange(); | 637 if (instruction.isUInt32(compiler)) { |
| 641 } | 638 return info.newNormalizedRange( |
| 642 | 639 info.intZero, info.newPositiveValue(instruction)); |
| 643 Range visitParameterValue(HParameterValue parameter) { | 640 } else if (instruction.isInteger(compiler)) { |
| 644 if (!parameter.isInteger(compiler)) return info.newUnboundRange(); | 641 InstructionValue value = info.newInstructionValue(instruction); |
| 645 Value value = info.newInstructionValue(parameter); | 642 return info.newNormalizedRange(value, value); |
| 646 return info.newNormalizedRange(value, value); | 643 } else { |
| 644 return info.newUnboundRange(); | |
| 645 } | |
| 647 } | 646 } |
| 648 | 647 |
| 649 Range visitPhi(HPhi phi) { | 648 Range visitPhi(HPhi phi) { |
| 650 if (!phi.isInteger(compiler)) return info.newUnboundRange(); | 649 if (!phi.isInteger(compiler)) return info.newUnboundRange(); |
| 651 // Some phases may replace instructions that change the inputs of | 650 // Some phases may replace instructions that change the inputs of |
| 652 // this phi. Only the [SsaTypesPropagation] phase will update the | 651 // this phi. Only the [SsaTypesPropagation] phase will update the |
| 653 // phi type. Play it safe by assuming the [SsaTypesPropagation] | 652 // phi type. Play it safe by assuming the [SsaTypesPropagation] |
| 654 // phase is not necessarily run before the [ValueRangeAnalyzer]. | 653 // phase is not necessarily run before the [ValueRangeAnalyzer]. |
| 655 if (phi.inputs.any((i) => !i.isInteger(compiler))) { | 654 if (phi.inputs.any((i) => !i.isInteger(compiler))) { |
| 656 return info.newUnboundRange(); | 655 return info.newUnboundRange(); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 675 return info.newNormalizedRange(value, value); | 674 return info.newNormalizedRange(value, value); |
| 676 } | 675 } |
| 677 | 676 |
| 678 Range visitFieldGet(HFieldGet fieldGet) { | 677 Range visitFieldGet(HFieldGet fieldGet) { |
| 679 if (!fieldGet.isInteger(compiler)) return info.newUnboundRange(); | 678 if (!fieldGet.isInteger(compiler)) return info.newUnboundRange(); |
| 680 if (!fieldGet.receiver.isIndexablePrimitive(compiler)) { | 679 if (!fieldGet.receiver.isIndexablePrimitive(compiler)) { |
| 681 return visitInstruction(fieldGet); | 680 return visitInstruction(fieldGet); |
| 682 } | 681 } |
| 683 JavaScriptBackend backend = compiler.backend; | 682 JavaScriptBackend backend = compiler.backend; |
| 684 assert(fieldGet.element == backend.jsIndexableLength); | 683 assert(fieldGet.element == backend.jsIndexableLength); |
| 685 LengthValue value = info.newLengthValue(fieldGet); | 684 PositiveValue value = info.newPositiveValue(fieldGet); |
| 686 // We know this range is above zero. To simplify the analysis, we | 685 // We know this range is above zero. To simplify the analysis, we |
| 687 // put the zero value as the lower bound of this range. This | 686 // put the zero value as the lower bound of this range. This |
| 688 // allows to easily remove the second bound check in the following | 687 // allows to easily remove the second bound check in the following |
| 689 // expression: a[1] + a[0]. | 688 // expression: a[1] + a[0]. |
| 690 return info.newNormalizedRange(info.intZero, value); | 689 return info.newNormalizedRange(info.intZero, value); |
| 691 } | 690 } |
| 692 | 691 |
| 693 Range visitBoundsCheck(HBoundsCheck check) { | 692 Range visitBoundsCheck(HBoundsCheck check) { |
| 694 // Save the next instruction, in case the check gets removed. | 693 // Save the next instruction, in case the check gets removed. |
| 695 HInstruction next = check.next; | 694 HInstruction next = check.next; |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1008 } | 1007 } |
| 1009 | 1008 |
| 1010 Range handleBinaryOperation(HBinaryArithmetic instruction) { | 1009 Range handleBinaryOperation(HBinaryArithmetic instruction) { |
| 1011 Range leftRange = visit(instruction.left); | 1010 Range leftRange = visit(instruction.left); |
| 1012 Range rightRange = visit(instruction.right); | 1011 Range rightRange = visit(instruction.right); |
| 1013 if (leftRange == null || rightRange == null) return null; | 1012 if (leftRange == null || rightRange == null) return null; |
| 1014 BinaryOperation operation = instruction.operation(info.constantSystem); | 1013 BinaryOperation operation = instruction.operation(info.constantSystem); |
| 1015 return operation.apply(leftRange, rightRange); | 1014 return operation.apply(leftRange, rightRange); |
| 1016 } | 1015 } |
| 1017 } | 1016 } |
| OLD | NEW |