| 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 /** | 5 /** |
| 6 * A [Value] represents both symbolic values like the value of a | 6 * A [Value] represents both symbolic values like the value of a |
| 7 * parameter, or the length of an array, and concrete values, like | 7 * parameter, or the length of an array, and concrete values, like |
| 8 * constants. | 8 * constants. |
| 9 */ | 9 */ |
| 10 abstract class Value { | 10 abstract class Value { |
| 11 const Value(); | 11 const Value(); |
| 12 | 12 |
| 13 Value operator +(Value other); | 13 Value operator +(Value other); |
| 14 Value operator -(Value other); | 14 Value operator -(Value other); |
| 15 Value operator -(); | 15 Value operator -(); |
| 16 Value operator &(Value other); | 16 Value operator &(Value other); |
| 17 | 17 |
| 18 Value min(Value other) { | 18 Value min(Value other) { |
| 19 if (this == other) return this; | 19 if (this == other) return this; |
| 20 if (other == const MinIntValue()) return other; | 20 if (other == const MinIntValue()) return other; |
| 21 if (other == const MaxIntValue()) return this; | 21 if (other == const MaxIntValue()) return this; |
| 22 Value value = this - other; | 22 Value value = this - other; |
| 23 if (value.isPositive()) return other; | 23 if (value.isPositive) return other; |
| 24 if (value.isNegative()) return this; | 24 if (value.isNegative) return this; |
| 25 return const UnknownValue(); | 25 return const UnknownValue(); |
| 26 } | 26 } |
| 27 | 27 |
| 28 Value max(Value other) { | 28 Value max(Value other) { |
| 29 if (this == other) return this; | 29 if (this == other) return this; |
| 30 if (other == const MinIntValue()) return this; | 30 if (other == const MinIntValue()) return this; |
| 31 if (other == const MaxIntValue()) return other; | 31 if (other == const MaxIntValue()) return other; |
| 32 Value value = this - other; | 32 Value value = this - other; |
| 33 if (value.isPositive()) return this; | 33 if (value.isPositive) return this; |
| 34 if (value.isNegative()) return other; | 34 if (value.isNegative) return other; |
| 35 return const UnknownValue(); | 35 return const UnknownValue(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 bool isNegative() => false; | 38 bool get isNegative => false; |
| 39 bool isPositive() => false; | 39 bool get isPositive => false; |
| 40 bool isZero() => false; | 40 bool get isZero => false; |
| 41 } | 41 } |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * An [IntValue] contains a constant integer value. | 44 * An [IntValue] contains a constant integer value. |
| 45 */ | 45 */ |
| 46 class IntValue extends Value { | 46 class IntValue extends Value { |
| 47 final int value; | 47 final int value; |
| 48 const IntValue(this.value); | 48 const IntValue(this.value); |
| 49 | 49 |
| 50 Value operator +(other) { | 50 Value operator +(other) { |
| 51 if (other.isZero()) return this; | 51 if (other.isZero) return this; |
| 52 if (other is !IntValue) return other + this; | 52 if (other is !IntValue) return other + this; |
| 53 return new IntValue(value + other.value); | 53 return new IntValue(value + other.value); |
| 54 } | 54 } |
| 55 | 55 |
| 56 Value operator -(other) { | 56 Value operator -(other) { |
| 57 if (other.isZero()) return this; | 57 if (other.isZero) return this; |
| 58 if (other is !IntValue) return -other + this; | 58 if (other is !IntValue) return -other + this; |
| 59 return new IntValue(value - other.value); | 59 return new IntValue(value - other.value); |
| 60 } | 60 } |
| 61 | 61 |
| 62 Value operator -() { | 62 Value operator -() { |
| 63 if (isZero()) return this; | 63 if (isZero) return this; |
| 64 return new IntValue(-value); | 64 return new IntValue(-value); |
| 65 } | 65 } |
| 66 | 66 |
| 67 Value operator &(other) { | 67 Value operator &(other) { |
| 68 if (other is !IntValue) { | 68 if (other is !IntValue) { |
| 69 if (isPositive()) return this; | 69 if (isPositive) return this; |
| 70 if (other.isPositive()) return new IntValue(-value); | 70 if (other.isPositive) return new IntValue(-value); |
| 71 return const UnknownValue(); | 71 return const UnknownValue(); |
| 72 } | 72 } |
| 73 return new IntValue(value & other.value); | 73 return new IntValue(value & other.value); |
| 74 } | 74 } |
| 75 | 75 |
| 76 Value min(other) { | 76 Value min(other) { |
| 77 if (other is !IntValue) return other.min(this); | 77 if (other is !IntValue) return other.min(this); |
| 78 return this.value < other.value ? this : other; | 78 return this.value < other.value ? this : other; |
| 79 } | 79 } |
| 80 | 80 |
| 81 Value max(other) { | 81 Value max(other) { |
| 82 if (other is !IntValue) return other.max(this); | 82 if (other is !IntValue) return other.max(this); |
| 83 return this.value < other.value ? other : this; | 83 return this.value < other.value ? other : this; |
| 84 } | 84 } |
| 85 | 85 |
| 86 bool operator ==(other) { | 86 bool operator ==(other) { |
| 87 if (other is !IntValue) return false; | 87 if (other is !IntValue) return false; |
| 88 return this.value == other.value; | 88 return this.value == other.value; |
| 89 } | 89 } |
| 90 | 90 |
| 91 String toString() => 'IntValue $value'; | 91 String toString() => 'IntValue $value'; |
| 92 bool isNegative() => value < 0; | 92 bool get isNegative => value < 0; |
| 93 bool isPositive() => value >= 0; | 93 bool get isPositive => value >= 0; |
| 94 bool isZero() => value == 0; | 94 bool get isZero => value == 0; |
| 95 } | 95 } |
| 96 | 96 |
| 97 /** | 97 /** |
| 98 * The [MaxIntValue] represents the maximum value an integer can have, | 98 * The [MaxIntValue] represents the maximum value an integer can have, |
| 99 * which is currently +infinity. | 99 * which is currently +infinity. |
| 100 */ | 100 */ |
| 101 class MaxIntValue extends Value { | 101 class MaxIntValue extends Value { |
| 102 const MaxIntValue(); | 102 const MaxIntValue(); |
| 103 Value operator +(Value other) => this; | 103 Value operator +(Value other) => this; |
| 104 Value operator -(Value other) => this; | 104 Value operator -(Value other) => this; |
| 105 Value operator -() => const MinIntValue(); | 105 Value operator -() => const MinIntValue(); |
| 106 Value operator &(Value other) { | 106 Value operator &(Value other) { |
| 107 if (other.isPositive()) return other; | 107 if (other.isPositive) return other; |
| 108 if (other.isNegative()) return const IntValue(0); | 108 if (other.isNegative) return const IntValue(0); |
| 109 return this; | 109 return this; |
| 110 } | 110 } |
| 111 Value min(Value other) => other; | 111 Value min(Value other) => other; |
| 112 Value max(Value other) => this; | 112 Value max(Value other) => this; |
| 113 String toString() => 'Max'; | 113 String toString() => 'Max'; |
| 114 bool isNegative() => false; | 114 bool get isNegative => false; |
| 115 bool isPositive() => true; | 115 bool get isPositive => true; |
| 116 } | 116 } |
| 117 | 117 |
| 118 /** | 118 /** |
| 119 * The [MinIntValue] represents the minimum value an integer can have, | 119 * The [MinIntValue] represents the minimum value an integer can have, |
| 120 * which is currently -infinity. | 120 * which is currently -infinity. |
| 121 */ | 121 */ |
| 122 class MinIntValue extends Value { | 122 class MinIntValue extends Value { |
| 123 const MinIntValue(); | 123 const MinIntValue(); |
| 124 Value operator +(Value other) => this; | 124 Value operator +(Value other) => this; |
| 125 Value operator -(Value other) => this; | 125 Value operator -(Value other) => this; |
| 126 Value operator -() => const MaxIntValue(); | 126 Value operator -() => const MaxIntValue(); |
| 127 Value operator &(Value other) { | 127 Value operator &(Value other) { |
| 128 if (other.isPositive()) return const IntValue(0); | 128 if (other.isPositive) return const IntValue(0); |
| 129 return this; | 129 return this; |
| 130 } | 130 } |
| 131 Value min(Value other) => this; | 131 Value min(Value other) => this; |
| 132 Value max(Value other) => other; | 132 Value max(Value other) => other; |
| 133 String toString() => 'Min'; | 133 String toString() => 'Min'; |
| 134 bool isNegative() => true; | 134 bool get isNegative => true; |
| 135 bool isPositive() => false; | 135 bool get isPositive => false; |
| 136 } | 136 } |
| 137 | 137 |
| 138 /** | 138 /** |
| 139 * The [UnknownValue] is the sentinel in our analysis to mark an | 139 * The [UnknownValue] is the sentinel in our analysis to mark an |
| 140 * operation that could not be done because of too much complexity. | 140 * operation that could not be done because of too much complexity. |
| 141 */ | 141 */ |
| 142 class UnknownValue extends Value { | 142 class UnknownValue extends Value { |
| 143 const UnknownValue(); | 143 const UnknownValue(); |
| 144 Value operator +(Value other) => const UnknownValue(); | 144 Value operator +(Value other) => const UnknownValue(); |
| 145 Value operator -(Value other) => const UnknownValue(); | 145 Value operator -(Value other) => const UnknownValue(); |
| 146 Value operator -() => const UnknownValue(); | 146 Value operator -() => const UnknownValue(); |
| 147 Value operator &(Value other) => const UnknownValue(); | 147 Value operator &(Value other) => const UnknownValue(); |
| 148 Value min(Value other) => const UnknownValue(); | 148 Value min(Value other) => const UnknownValue(); |
| 149 Value max(Value other) => const UnknownValue(); | 149 Value max(Value other) => const UnknownValue(); |
| 150 bool isNegative() => false; | 150 bool get isNegative => false; |
| 151 bool isPositive() => false; | 151 bool get isPositive => false; |
| 152 String toString() => 'Unknown'; | 152 String toString() => 'Unknown'; |
| 153 } | 153 } |
| 154 | 154 |
| 155 /** | 155 /** |
| 156 * A symbolic value representing an [HInstruction]. | 156 * A symbolic value representing an [HInstruction]. |
| 157 */ | 157 */ |
| 158 class InstructionValue extends Value { | 158 class InstructionValue extends Value { |
| 159 final HInstruction instruction; | 159 final HInstruction instruction; |
| 160 InstructionValue(this.instruction); | 160 InstructionValue(this.instruction); |
| 161 | 161 |
| 162 bool operator ==(other) { | 162 bool operator ==(other) { |
| 163 if (other is !InstructionValue) return false; | 163 if (other is !InstructionValue) return false; |
| 164 return this.instruction == other.instruction; | 164 return this.instruction == other.instruction; |
| 165 } | 165 } |
| 166 | 166 |
| 167 Value operator +(Value other) { | 167 Value operator +(Value other) { |
| 168 if (other.isZero()) return this; | 168 if (other.isZero) return this; |
| 169 if (other is IntValue) { | 169 if (other is IntValue) { |
| 170 if (other.isNegative()) { | 170 if (other.isNegative) { |
| 171 return new SubtractValue(this, -other); | 171 return new SubtractValue(this, -other); |
| 172 } | 172 } |
| 173 return new AddValue(this, other); | 173 return new AddValue(this, other); |
| 174 } | 174 } |
| 175 if (other is InstructionValue) { | 175 if (other is InstructionValue) { |
| 176 return new AddValue(this, other); | 176 return new AddValue(this, other); |
| 177 } | 177 } |
| 178 return other + this; | 178 return other + this; |
| 179 } | 179 } |
| 180 | 180 |
| 181 Value operator -(Value other) { | 181 Value operator -(Value other) { |
| 182 if (other.isZero()) return this; | 182 if (other.isZero) return this; |
| 183 if (this == other) return const IntValue(0); | 183 if (this == other) return const IntValue(0); |
| 184 if (other is IntValue) { | 184 if (other is IntValue) { |
| 185 if (other.isNegative()) { | 185 if (other.isNegative) { |
| 186 return new AddValue(this, -other); | 186 return new AddValue(this, -other); |
| 187 } | 187 } |
| 188 return new SubtractValue(this, other); | 188 return new SubtractValue(this, other); |
| 189 } | 189 } |
| 190 if (other is InstructionValue) { | 190 if (other is InstructionValue) { |
| 191 return new SubtractValue(this, other); | 191 return new SubtractValue(this, other); |
| 192 } | 192 } |
| 193 return -other + this; | 193 return -other + this; |
| 194 } | 194 } |
| 195 | 195 |
| 196 Value operator -() { | 196 Value operator -() { |
| 197 return new NegateValue(this); | 197 return new NegateValue(this); |
| 198 } | 198 } |
| 199 | 199 |
| 200 Value operator &(Value other) { | 200 Value operator &(Value other) { |
| 201 if (other is IntValue) return other & this; | 201 if (other is IntValue) return other & this; |
| 202 return this; | 202 return this; |
| 203 } | 203 } |
| 204 | 204 |
| 205 bool isNegative() => false; | 205 bool get isNegative => false; |
| 206 bool isPositive() => false; | 206 bool get isPositive => false; |
| 207 | 207 |
| 208 String toString() => 'Instruction: $instruction'; | 208 String toString() => 'Instruction: $instruction'; |
| 209 } | 209 } |
| 210 | 210 |
| 211 /** | 211 /** |
| 212 * Special value for instructions that represent the length of an | 212 * Special value for instructions that represent the length of an |
| 213 * array. The difference with an [InstructionValue] is that we know | 213 * array. The difference with an [InstructionValue] is that we know |
| 214 * the value is positive. | 214 * the value is positive. |
| 215 */ | 215 */ |
| 216 class LengthValue extends InstructionValue { | 216 class LengthValue extends InstructionValue { |
| 217 LengthValue(HInstruction instruction) : super(instruction); | 217 LengthValue(HInstruction instruction) : super(instruction); |
| 218 bool isPositive() => true; | 218 bool get isPositive => true; |
| 219 String toString() => 'Length: $instruction'; | 219 String toString() => 'Length: $instruction'; |
| 220 } | 220 } |
| 221 | 221 |
| 222 /** | 222 /** |
| 223 * Represents a binary operation on two [Value], where the operation | 223 * Represents a binary operation on two [Value], where the operation |
| 224 * did not yield a canonical value. | 224 * did not yield a canonical value. |
| 225 */ | 225 */ |
| 226 class OperationValue extends Value { | 226 class OperationValue extends Value { |
| 227 Operation operation; | 227 Operation operation; |
| 228 } | 228 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 239 bool operator ==(other) { | 239 bool operator ==(other) { |
| 240 if (other is !AddValue) return false; | 240 if (other is !AddValue) return false; |
| 241 return (left == other.left && right == other.right) | 241 return (left == other.left && right == other.right) |
| 242 || (left == other.right && right == other.left); | 242 || (left == other.right && right == other.left); |
| 243 } | 243 } |
| 244 | 244 |
| 245 Value operator &(Value other) => const UnknownValue(); | 245 Value operator &(Value other) => const UnknownValue(); |
| 246 Value operator -() => -left - right; | 246 Value operator -() => -left - right; |
| 247 | 247 |
| 248 Value operator +(Value other) { | 248 Value operator +(Value other) { |
| 249 if (other.isZero()) return this; | 249 if (other.isZero) return this; |
| 250 Value value = left + other; | 250 Value value = left + other; |
| 251 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 251 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 252 return value + right; | 252 return value + right; |
| 253 } | 253 } |
| 254 // If the result is not simple enough, we try the same approach | 254 // If the result is not simple enough, we try the same approach |
| 255 // with [right]. | 255 // with [right]. |
| 256 value = right + other; | 256 value = right + other; |
| 257 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 257 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 258 return left + value; | 258 return left + value; |
| 259 } | 259 } |
| 260 return const UnknownValue(); | 260 return const UnknownValue(); |
| 261 } | 261 } |
| 262 | 262 |
| 263 Value operator -(Value other) { | 263 Value operator -(Value other) { |
| 264 if (other.isZero()) return this; | 264 if (other.isZero) return this; |
| 265 Value value = left - other; | 265 Value value = left - other; |
| 266 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 266 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 267 return value + right; | 267 return value + right; |
| 268 } | 268 } |
| 269 // If the result is not simple enough, we try the same approach | 269 // If the result is not simple enough, we try the same approach |
| 270 // with [right]. | 270 // with [right]. |
| 271 value = right - other; | 271 value = right - other; |
| 272 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 272 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 273 return left + value; | 273 return left + value; |
| 274 } | 274 } |
| 275 return const UnknownValue(); | 275 return const UnknownValue(); |
| 276 } | 276 } |
| 277 | 277 |
| 278 bool isNegative() => left.isNegative() && right.isNegative(); | 278 bool get isNegative => left.isNegative && right.isNegative; |
| 279 bool isPositive() => left.isPositive() && right.isPositive(); | 279 bool get isPositive => left.isPositive && right.isPositive; |
| 280 String toString() => '$left + $right'; | 280 String toString() => '$left + $right'; |
| 281 } | 281 } |
| 282 | 282 |
| 283 class SubtractValue extends BinaryOperationValue { | 283 class SubtractValue extends BinaryOperationValue { |
| 284 SubtractValue(left, right) : super(left, right); | 284 SubtractValue(left, right) : super(left, right); |
| 285 | 285 |
| 286 bool operator ==(other) { | 286 bool operator ==(other) { |
| 287 if (other is !SubtractValue) return false; | 287 if (other is !SubtractValue) return false; |
| 288 return left == other.left && right == other.right; | 288 return left == other.left && right == other.right; |
| 289 } | 289 } |
| 290 | 290 |
| 291 Value operator &(Value other) => const UnknownValue(); | 291 Value operator &(Value other) => const UnknownValue(); |
| 292 Value operator -() => right - left; | 292 Value operator -() => right - left; |
| 293 | 293 |
| 294 Value operator +(Value other) { | 294 Value operator +(Value other) { |
| 295 if (other.isZero()) return this; | 295 if (other.isZero) return this; |
| 296 Value value = left + other; | 296 Value value = left + other; |
| 297 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 297 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 298 return value - right; | 298 return value - right; |
| 299 } | 299 } |
| 300 // If the result is not simple enough, we try the same approach | 300 // If the result is not simple enough, we try the same approach |
| 301 // with [right]. | 301 // with [right]. |
| 302 value = other - right; | 302 value = other - right; |
| 303 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 303 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 304 return left + value; | 304 return left + value; |
| 305 } | 305 } |
| 306 return const UnknownValue(); | 306 return const UnknownValue(); |
| 307 } | 307 } |
| 308 | 308 |
| 309 Value operator -(Value other) { | 309 Value operator -(Value other) { |
| 310 if (other.isZero()) return this; | 310 if (other.isZero) return this; |
| 311 Value value = left - other; | 311 Value value = left - other; |
| 312 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 312 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 313 return value - right; | 313 return value - right; |
| 314 } | 314 } |
| 315 // If the result is not simple enough, we try the same approach | 315 // If the result is not simple enough, we try the same approach |
| 316 // with [right]. | 316 // with [right]. |
| 317 value = right + other; | 317 value = right + other; |
| 318 if (value != const UnknownValue() && value is! BinaryOperationValue) { | 318 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 319 return left - value; | 319 return left - value; |
| 320 } | 320 } |
| 321 return const UnknownValue(); | 321 return const UnknownValue(); |
| 322 } | 322 } |
| 323 | 323 |
| 324 bool isNegative() => left.isNegative() && right.isPositive(); | 324 bool get isNegative => left.isNegative && right.isPositive; |
| 325 bool isPositive() => left.isPositive() && right.isNegative(); | 325 bool get isPositive => left.isPositive && right.isNegative; |
| 326 String toString() => '$left - $right'; | 326 String toString() => '$left - $right'; |
| 327 } | 327 } |
| 328 | 328 |
| 329 class NegateValue extends OperationValue { | 329 class NegateValue extends OperationValue { |
| 330 final Value value; | 330 final Value value; |
| 331 NegateValue(this.value); | 331 NegateValue(this.value); |
| 332 | 332 |
| 333 bool operator ==(other) { | 333 bool operator ==(other) { |
| 334 if (other is !NegateValue) return false; | 334 if (other is !NegateValue) return false; |
| 335 return value == other.value; | 335 return value == other.value; |
| 336 } | 336 } |
| 337 | 337 |
| 338 Value operator +(other) { | 338 Value operator +(other) { |
| 339 if (other.isZero()) return this; | 339 if (other.isZero) return this; |
| 340 if (other == value) return const IntValue(0); | 340 if (other == value) return const IntValue(0); |
| 341 if (other is NegateValue) return this - other.value; | 341 if (other is NegateValue) return this - other.value; |
| 342 if (other is IntValue) { | 342 if (other is IntValue) { |
| 343 if (other.isNegative()) { | 343 if (other.isNegative) { |
| 344 return new SubtractValue(this, -other); | 344 return new SubtractValue(this, -other); |
| 345 } | 345 } |
| 346 return new SubtractValue(other, value); | 346 return new SubtractValue(other, value); |
| 347 } | 347 } |
| 348 if (other is InstructionValue) { | 348 if (other is InstructionValue) { |
| 349 return new SubtractValue(other, value); | 349 return new SubtractValue(other, value); |
| 350 } | 350 } |
| 351 return other - value; | 351 return other - value; |
| 352 } | 352 } |
| 353 | 353 |
| 354 Value operator &(Value other) => const UnknownValue(); | 354 Value operator &(Value other) => const UnknownValue(); |
| 355 | 355 |
| 356 Value operator -(other) { | 356 Value operator -(other) { |
| 357 if (other.isZero()) return this; | 357 if (other.isZero) return this; |
| 358 if (other is IntValue) { | 358 if (other is IntValue) { |
| 359 if (other.isNegative()) { | 359 if (other.isNegative) { |
| 360 return new SubtractValue(-other, value); | 360 return new SubtractValue(-other, value); |
| 361 } | 361 } |
| 362 return new SubtractValue(this, other); | 362 return new SubtractValue(this, other); |
| 363 } | 363 } |
| 364 if (other is InstructionValue) { | 364 if (other is InstructionValue) { |
| 365 return new SubtractValue(this, other); | 365 return new SubtractValue(this, other); |
| 366 } | 366 } |
| 367 if (other is NegateValue) return this + other.value; | 367 if (other is NegateValue) return this + other.value; |
| 368 return -other - value; | 368 return -other - value; |
| 369 } | 369 } |
| 370 | 370 |
| 371 Value operator -() => value; | 371 Value operator -() => value; |
| 372 | 372 |
| 373 bool isNegative() => value.isPositive(); | 373 bool get isNegative => value.isPositive; |
| 374 bool isPositive() => value.isNegative(); | 374 bool get isPositive => value.isNegative; |
| 375 String toString() => '-$value'; | 375 String toString() => '-$value'; |
| 376 } | 376 } |
| 377 | 377 |
| 378 /** | 378 /** |
| 379 * A [Range] represents the possible integer values an instruction | 379 * A [Range] represents the possible integer values an instruction |
| 380 * can have, from its [lower] bound to its [upper] bound, both | 380 * can have, from its [lower] bound to its [upper] bound, both |
| 381 * included. | 381 * included. |
| 382 */ | 382 */ |
| 383 class Range { | 383 class Range { |
| 384 final Value lower; | 384 final Value lower; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 | 423 |
| 424 Range operator -(Range other) { | 424 Range operator -(Range other) { |
| 425 return new Range.normalize(lower - other.upper, upper - other.lower); | 425 return new Range.normalize(lower - other.upper, upper - other.lower); |
| 426 } | 426 } |
| 427 | 427 |
| 428 Range operator -() { | 428 Range operator -() { |
| 429 return new Range.normalize(-upper, -lower); | 429 return new Range.normalize(-upper, -lower); |
| 430 } | 430 } |
| 431 | 431 |
| 432 Range operator &(Range other) { | 432 Range operator &(Range other) { |
| 433 if (isSingleValue() | 433 if (isSingleValue |
| 434 && other.isSingleValue() | 434 && other.isSingleValue |
| 435 && lower is IntValue | 435 && lower is IntValue |
| 436 && other.lower is IntValue) { | 436 && other.lower is IntValue) { |
| 437 return new Range(lower & other.lower, upper & other.upper); | 437 return new Range(lower & other.lower, upper & other.upper); |
| 438 } | 438 } |
| 439 if (isPositive() && other.isPositive()) { | 439 if (isPositive && other.isPositive) { |
| 440 Value up = upper.min(other.upper); | 440 Value up = upper.min(other.upper); |
| 441 if (up == const UnknownValue()) { | 441 if (up == const UnknownValue()) { |
| 442 // If we could not find a trivial bound, just try to use the | 442 // If we could not find a trivial bound, just try to use the |
| 443 // one that is an int. | 443 // one that is an int. |
| 444 up = upper is IntValue ? upper : other.upper; | 444 up = upper is IntValue ? upper : other.upper; |
| 445 // Make sure we get the same upper bound, whether it's a & b | 445 // Make sure we get the same upper bound, whether it's a & b |
| 446 // or b & a. | 446 // or b & a. |
| 447 if (up is! IntValue && upper != other.upper) up = const MaxIntValue(); | 447 if (up is! IntValue && upper != other.upper) up = const MaxIntValue(); |
| 448 } | 448 } |
| 449 return new Range(const IntValue(0), up); | 449 return new Range(const IntValue(0), up); |
| 450 } else if (isPositive()) { | 450 } else if (isPositive) { |
| 451 return new Range(const IntValue(0), upper); | 451 return new Range(const IntValue(0), upper); |
| 452 } else if (other.isPositive()) { | 452 } else if (other.isPositive) { |
| 453 return new Range(const IntValue(0), other.upper); | 453 return new Range(const IntValue(0), other.upper); |
| 454 } else { | 454 } else { |
| 455 return const Range.unbound(); | 455 return const Range.unbound(); |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 | 458 |
| 459 bool operator ==(other) { | 459 bool operator ==(other) { |
| 460 if (other is! Range) return false; | 460 if (other is! Range) return false; |
| 461 return other.lower == lower && other.upper == upper; | 461 return other.lower == lower && other.upper == upper; |
| 462 } | 462 } |
| 463 | 463 |
| 464 bool operator <(Range other) { | 464 bool operator <(Range other) { |
| 465 return upper != other.lower && upper.min(other.lower) == upper; | 465 return upper != other.lower && upper.min(other.lower) == upper; |
| 466 } | 466 } |
| 467 | 467 |
| 468 bool operator >(Range other) { | 468 bool operator >(Range other) { |
| 469 return lower != other.upper && lower.max(other.upper) == lower; | 469 return lower != other.upper && lower.max(other.upper) == lower; |
| 470 } | 470 } |
| 471 | 471 |
| 472 bool operator <=(Range other) { | 472 bool operator <=(Range other) { |
| 473 return upper.min(other.lower) == upper; | 473 return upper.min(other.lower) == upper; |
| 474 } | 474 } |
| 475 | 475 |
| 476 bool operator >=(Range other) { | 476 bool operator >=(Range other) { |
| 477 return lower.max(other.upper) == lower; | 477 return lower.max(other.upper) == lower; |
| 478 } | 478 } |
| 479 | 479 |
| 480 bool isNegative() => upper.isNegative(); | 480 bool get isNegative => upper.isNegative; |
| 481 bool isPositive() => lower.isPositive(); | 481 bool get isPositive => lower.isPositive; |
| 482 bool isSingleValue() => lower == upper; | 482 bool get isSingleValue => lower == upper; |
| 483 | 483 |
| 484 String toString() => '[$lower, $upper]'; | 484 String toString() => '[$lower, $upper]'; |
| 485 } | 485 } |
| 486 | 486 |
| 487 /** | 487 /** |
| 488 * Visits the graph in dominator order, and computes value ranges for | 488 * Visits the graph in dominator order, and computes value ranges for |
| 489 * integer instructions. While visiting the graph, this phase also | 489 * integer instructions. While visiting the graph, this phase also |
| 490 * removes unnecessary bounds checks, and comparisons that are proven | 490 * removes unnecessary bounds checks, and comparisons that are proven |
| 491 * to be true or false. | 491 * to be true or false. |
| 492 */ | 492 */ |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 // range. | 602 // range. |
| 603 Value maxIndex = lengthRange.upper - const IntValue(1); | 603 Value maxIndex = lengthRange.upper - const IntValue(1); |
| 604 bool belowLength = maxIndex != const MaxIntValue() | 604 bool belowLength = maxIndex != const MaxIntValue() |
| 605 && indexRange.upper.min(maxIndex) == indexRange.upper; | 605 && indexRange.upper.min(maxIndex) == indexRange.upper; |
| 606 | 606 |
| 607 // Check if the index is strictly below the lower bound of the length | 607 // Check if the index is strictly below the lower bound of the length |
| 608 // range. | 608 // range. |
| 609 belowLength = belowLength | 609 belowLength = belowLength |
| 610 || (indexRange.upper != lengthRange.lower | 610 || (indexRange.upper != lengthRange.lower |
| 611 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); | 611 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); |
| 612 if (indexRange.isPositive() && belowLength) { | 612 if (indexRange.isPositive && belowLength) { |
| 613 check.block.rewrite(check, check.index); | 613 check.block.rewrite(check, check.index); |
| 614 check.block.remove(check); | 614 check.block.remove(check); |
| 615 } else if (indexRange.isNegative() || lengthRange < indexRange) { | 615 } else if (indexRange.isNegative || lengthRange < indexRange) { |
| 616 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; | 616 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; |
| 617 // The check is always false, and whatever instruction it | 617 // The check is always false, and whatever instruction it |
| 618 // dominates is dead code. | 618 // dominates is dead code. |
| 619 return indexRange; | 619 return indexRange; |
| 620 } else if (indexRange.isPositive()) { | 620 } else if (indexRange.isPositive) { |
| 621 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; | 621 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; |
| 622 } else if (belowLength) { | 622 } else if (belowLength) { |
| 623 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; | 623 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; |
| 624 } | 624 } |
| 625 | 625 |
| 626 if (indexRange.isPositive()) { | 626 if (indexRange.isPositive) { |
| 627 // If the test passes, we know the lower bound of the length is | 627 // If the test passes, we know the lower bound of the length is |
| 628 // greater or equal than the lower bound of the index. | 628 // greater or equal than the lower bound of the index. |
| 629 Value low = lengthRange.lower.max(indexRange.lower); | 629 Value low = lengthRange.lower.max(indexRange.lower); |
| 630 if (low != const UnknownValue()) { | 630 if (low != const UnknownValue()) { |
| 631 HInstruction instruction = | 631 HInstruction instruction = |
| 632 createRangeConversion(next, check.length); | 632 createRangeConversion(next, check.length); |
| 633 ranges[instruction] = new Range(low, lengthRange.upper); | 633 ranges[instruction] = new Range(low, lengthRange.upper); |
| 634 } | 634 } |
| 635 } | 635 } |
| 636 | 636 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 667 relational.block.rewrite( | 667 relational.block.rewrite( |
| 668 relational, graph.addConstantBool(false, constantSystem)); | 668 relational, graph.addConstantBool(false, constantSystem)); |
| 669 relational.block.remove(relational); | 669 relational.block.remove(relational); |
| 670 } | 670 } |
| 671 return const Range.unbound(); | 671 return const Range.unbound(); |
| 672 } | 672 } |
| 673 | 673 |
| 674 void handleEqualityCheck(HRelational node) { | 674 void handleEqualityCheck(HRelational node) { |
| 675 Range right = ranges[node.right]; | 675 Range right = ranges[node.right]; |
| 676 Range left = ranges[node.left]; | 676 Range left = ranges[node.left]; |
| 677 if (left.isSingleValue() && right.isSingleValue() && left == right) { | 677 if (left.isSingleValue && right.isSingleValue && left == right) { |
| 678 node.block.rewrite( | 678 node.block.rewrite( |
| 679 node, graph.addConstantBool(true, constantSystem)); | 679 node, graph.addConstantBool(true, constantSystem)); |
| 680 node.block.remove(node); | 680 node.block.remove(node); |
| 681 } | 681 } |
| 682 } | 682 } |
| 683 | 683 |
| 684 Range handleBinaryOperation(HBinaryArithmetic instruction) { | 684 Range handleBinaryOperation(HBinaryArithmetic instruction) { |
| 685 if (!instruction.isInteger(types)) return const Range.unbound(); | 685 if (!instruction.isInteger(types)) return const Range.unbound(); |
| 686 return instruction.operation(constantSystem).apply( | 686 return instruction.operation(constantSystem).apply( |
| 687 ranges[instruction.left], ranges[instruction.right]); | 687 ranges[instruction.left], ranges[instruction.right]); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 698 Range visitBitAnd(HBitAnd node) { | 698 Range visitBitAnd(HBitAnd node) { |
| 699 if (!node.isInteger(types)) return const Range.unbound(); | 699 if (!node.isInteger(types)) return const Range.unbound(); |
| 700 HInstruction right = node.right; | 700 HInstruction right = node.right; |
| 701 HInstruction left = node.left; | 701 HInstruction left = node.left; |
| 702 if (left.isInteger(types) && right.isInteger(types)) { | 702 if (left.isInteger(types) && right.isInteger(types)) { |
| 703 return ranges[left] & ranges[right]; | 703 return ranges[left] & ranges[right]; |
| 704 } | 704 } |
| 705 | 705 |
| 706 Range tryComputeRange(HInstruction instruction) { | 706 Range tryComputeRange(HInstruction instruction) { |
| 707 Range range = ranges[instruction]; | 707 Range range = ranges[instruction]; |
| 708 if (range.isPositive()) { | 708 if (range.isPositive) { |
| 709 return new Range(const IntValue(0), range.upper); | 709 return new Range(const IntValue(0), range.upper); |
| 710 } else if (range.isNegative()) { | 710 } else if (range.isNegative) { |
| 711 return new Range(range.lower, const IntValue(0)); | 711 return new Range(range.lower, const IntValue(0)); |
| 712 } | 712 } |
| 713 return const Range.unbound(); | 713 return const Range.unbound(); |
| 714 } | 714 } |
| 715 | 715 |
| 716 if (left.isInteger(types)) { | 716 if (left.isInteger(types)) { |
| 717 return tryComputeRange(left); | 717 return tryComputeRange(left); |
| 718 } else if (right.isInteger(types)) { | 718 } else if (right.isInteger(types)) { |
| 719 return tryComputeRange(right); | 719 return tryComputeRange(right); |
| 720 } | 720 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 class LoopUpdateRecognizer extends HBaseVisitor { | 848 class LoopUpdateRecognizer extends HBaseVisitor { |
| 849 final HPhi loopPhi; | 849 final HPhi loopPhi; |
| 850 final Map<HInstruction, Range> ranges; | 850 final Map<HInstruction, Range> ranges; |
| 851 final HTypeMap types; | 851 final HTypeMap types; |
| 852 LoopUpdateRecognizer(this.loopPhi, this.ranges, this.types); | 852 LoopUpdateRecognizer(this.loopPhi, this.ranges, this.types); |
| 853 | 853 |
| 854 Range visitAdd(HAdd operation) { | 854 Range visitAdd(HAdd operation) { |
| 855 Range range = getRangeForRecognizableOperation(operation); | 855 Range range = getRangeForRecognizableOperation(operation); |
| 856 if (range == null) return const Range.unbound(); | 856 if (range == null) return const Range.unbound(); |
| 857 Range initial = ranges[loopPhi.inputs[0]]; | 857 Range initial = ranges[loopPhi.inputs[0]]; |
| 858 if (range.isPositive()) { | 858 if (range.isPositive) { |
| 859 return new Range(initial.lower, const MaxIntValue()); | 859 return new Range(initial.lower, const MaxIntValue()); |
| 860 } else if (range.isNegative()) { | 860 } else if (range.isNegative) { |
| 861 return new Range(const MinIntValue(), initial.upper); | 861 return new Range(const MinIntValue(), initial.upper); |
| 862 } | 862 } |
| 863 return const Range.unbound(); | 863 return const Range.unbound(); |
| 864 } | 864 } |
| 865 | 865 |
| 866 Range visitSubtract(HSubtract operation) { | 866 Range visitSubtract(HSubtract operation) { |
| 867 Range range = getRangeForRecognizableOperation(operation); | 867 Range range = getRangeForRecognizableOperation(operation); |
| 868 if (range == null) return const Range.unbound(); | 868 if (range == null) return const Range.unbound(); |
| 869 Range initial = ranges[loopPhi.inputs[0]]; | 869 Range initial = ranges[loopPhi.inputs[0]]; |
| 870 if (range.isPositive()) { | 870 if (range.isPositive) { |
| 871 return new Range(const MinIntValue(), initial.upper); | 871 return new Range(const MinIntValue(), initial.upper); |
| 872 } else if (range.isNegative()) { | 872 } else if (range.isNegative) { |
| 873 return new Range(initial.lower, const MaxIntValue()); | 873 return new Range(initial.lower, const MaxIntValue()); |
| 874 } | 874 } |
| 875 return const Range.unbound(); | 875 return const Range.unbound(); |
| 876 } | 876 } |
| 877 | 877 |
| 878 Range visitPhi(HPhi phi) { | 878 Range visitPhi(HPhi phi) { |
| 879 Range phiRange; | 879 Range phiRange; |
| 880 for (HInstruction input in phi.inputs) { | 880 for (HInstruction input in phi.inputs) { |
| 881 HInstruction instruction = unwrap(input); | 881 HInstruction instruction = unwrap(input); |
| 882 // If one of the inputs is the loop phi, then we're only | 882 // If one of the inputs is the loop phi, then we're only |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 if (instruction is HPhi && !instruction.block.isLoopHeader()) { | 937 if (instruction is HPhi && !instruction.block.isLoopHeader()) { |
| 938 HInstruction result = unwrap(instruction.inputs[0]); | 938 HInstruction result = unwrap(instruction.inputs[0]); |
| 939 for (int i = 1; i < instruction.inputs.length; i++) { | 939 for (int i = 1; i < instruction.inputs.length; i++) { |
| 940 if (result != unwrap(instruction.inputs[i])) return instruction; | 940 if (result != unwrap(instruction.inputs[i])) return instruction; |
| 941 } | 941 } |
| 942 return result; | 942 return result; |
| 943 } | 943 } |
| 944 return instruction; | 944 return instruction; |
| 945 } | 945 } |
| 946 } | 946 } |
| OLD | NEW |