| 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 &(Value other); | 16 Value operator &(Value other); |
| 16 | 17 |
| 17 Value min(Value other) { | 18 Value min(Value other) { |
| 18 if (this == other) return this; | 19 if (this == other) return this; |
| 19 if (other == const MinIntValue()) return other; | 20 if (other == const MinIntValue()) return other; |
| 20 if (other == const MaxIntValue()) return this; | 21 if (other == const MaxIntValue()) return this; |
| 21 Value value = this - other; | 22 Value value = this - other; |
| 22 if (value.isPositive()) return other; | 23 if (value.isPositive()) return other; |
| 23 if (value.isNegative()) return this; | 24 if (value.isNegative()) return this; |
| 24 return const UnknownValue(); | 25 return const UnknownValue(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 40 } | 41 } |
| 41 | 42 |
| 42 /** | 43 /** |
| 43 * An [IntValue] contains a constant integer value. | 44 * An [IntValue] contains a constant integer value. |
| 44 */ | 45 */ |
| 45 class IntValue extends Value { | 46 class IntValue extends Value { |
| 46 final int value; | 47 final int value; |
| 47 const IntValue(this.value); | 48 const IntValue(this.value); |
| 48 | 49 |
| 49 Value operator +(other) { | 50 Value operator +(other) { |
| 51 if (other.isZero()) return this; |
| 50 if (other is !IntValue) return other + this; | 52 if (other is !IntValue) return other + this; |
| 51 return new IntValue(value + other.value); | 53 return new IntValue(value + other.value); |
| 52 } | 54 } |
| 53 | 55 |
| 54 Value operator -(other) { | 56 Value operator -(other) { |
| 55 if (other is !IntValue) { | 57 if (other.isZero()) return this; |
| 56 return new OperationValue(this, other, const SubtractOperation()); | 58 if (other is !IntValue) return -other + this; |
| 57 } | |
| 58 return new IntValue(value - other.value); | 59 return new IntValue(value - other.value); |
| 59 } | 60 } |
| 60 | 61 |
| 62 Value operator -() { |
| 63 if (isZero()) return this; |
| 64 return new IntValue(-value); |
| 65 } |
| 66 |
| 61 Value operator &(other) { | 67 Value operator &(other) { |
| 62 if (other is !IntValue) { | 68 if (other is !IntValue) { |
| 63 if (isPositive()) return this; | 69 if (isPositive()) return this; |
| 64 if (other.isPositive()) return new IntValue(-value); | 70 if (other.isPositive()) return new IntValue(-value); |
| 65 return const UnknownValue(); | 71 return const UnknownValue(); |
| 66 } | 72 } |
| 67 return new IntValue(value & other.value); | 73 return new IntValue(value & other.value); |
| 68 } | 74 } |
| 69 | 75 |
| 70 Value min(other) { | 76 Value min(other) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 89 } | 95 } |
| 90 | 96 |
| 91 /** | 97 /** |
| 92 * The [MaxIntValue] represents the maximum value an integer can have, | 98 * The [MaxIntValue] represents the maximum value an integer can have, |
| 93 * which is currently +infinity. | 99 * which is currently +infinity. |
| 94 */ | 100 */ |
| 95 class MaxIntValue extends Value { | 101 class MaxIntValue extends Value { |
| 96 const MaxIntValue(); | 102 const MaxIntValue(); |
| 97 Value operator +(Value other) => this; | 103 Value operator +(Value other) => this; |
| 98 Value operator -(Value other) => this; | 104 Value operator -(Value other) => this; |
| 105 Value operator -() => const MinIntValue(); |
| 99 Value operator &(Value other) { | 106 Value operator &(Value other) { |
| 100 if (other.isPositive()) return other; | 107 if (other.isPositive()) return other; |
| 101 if (other.isNegative()) return const IntValue(0); | 108 if (other.isNegative()) return const IntValue(0); |
| 102 return this; | 109 return this; |
| 103 } | 110 } |
| 104 Value min(Value other) => other; | 111 Value min(Value other) => other; |
| 105 Value max(Value other) => this; | 112 Value max(Value other) => this; |
| 106 String toString() => 'Max'; | 113 String toString() => 'Max'; |
| 107 bool isNegative() => false; | 114 bool isNegative() => false; |
| 108 bool isPositive() => true; | 115 bool isPositive() => true; |
| 109 } | 116 } |
| 110 | 117 |
| 111 /** | 118 /** |
| 112 * The [MinIntValue] represents the minimum value an integer can have, | 119 * The [MinIntValue] represents the minimum value an integer can have, |
| 113 * which is currently -infinity. | 120 * which is currently -infinity. |
| 114 */ | 121 */ |
| 115 class MinIntValue extends Value { | 122 class MinIntValue extends Value { |
| 116 const MinIntValue(); | 123 const MinIntValue(); |
| 117 Value operator +(Value other) => this; | 124 Value operator +(Value other) => this; |
| 118 Value operator -(Value other) => this; | 125 Value operator -(Value other) => this; |
| 126 Value operator -() => const MaxIntValue(); |
| 119 Value operator &(Value other) { | 127 Value operator &(Value other) { |
| 120 if (other.isPositive()) return const IntValue(0); | 128 if (other.isPositive()) return const IntValue(0); |
| 121 return this; | 129 return this; |
| 122 } | 130 } |
| 123 Value min(Value other) => this; | 131 Value min(Value other) => this; |
| 124 Value max(Value other) => other; | 132 Value max(Value other) => other; |
| 125 String toString() => 'Min'; | 133 String toString() => 'Min'; |
| 126 bool isNegative() => true; | 134 bool isNegative() => true; |
| 127 bool isPositive() => false; | 135 bool isPositive() => false; |
| 128 } | 136 } |
| 129 | 137 |
| 130 /** | 138 /** |
| 131 * The [UnknownValue] is the sentinel in our analysis to mark an | 139 * The [UnknownValue] is the sentinel in our analysis to mark an |
| 132 * operation that could not be done because of too much complexity. | 140 * operation that could not be done because of too much complexity. |
| 133 */ | 141 */ |
| 134 class UnknownValue extends Value { | 142 class UnknownValue extends Value { |
| 135 const UnknownValue(); | 143 const UnknownValue(); |
| 136 Value operator +(Value other) => const UnknownValue(); | 144 Value operator +(Value other) => const UnknownValue(); |
| 137 Value operator -(Value other) => const UnknownValue(); | 145 Value operator -(Value other) => const UnknownValue(); |
| 146 Value operator -() => const UnknownValue(); |
| 138 Value operator &(Value other) => const UnknownValue(); | 147 Value operator &(Value other) => const UnknownValue(); |
| 139 Value min(Value other) => const UnknownValue(); | 148 Value min(Value other) => const UnknownValue(); |
| 140 Value max(Value other) => const UnknownValue(); | 149 Value max(Value other) => const UnknownValue(); |
| 141 bool isNegative() => false; | 150 bool isNegative() => false; |
| 142 bool isPositive() => false; | 151 bool isPositive() => false; |
| 143 String toString() => 'Unknown'; | 152 String toString() => 'Unknown'; |
| 144 } | 153 } |
| 145 | 154 |
| 146 /** | 155 /** |
| 147 * A symbolic value representing an [HInstruction]. | 156 * A symbolic value representing an [HInstruction]. |
| 148 */ | 157 */ |
| 149 class InstructionValue extends Value { | 158 class InstructionValue extends Value { |
| 150 final HInstruction instruction; | 159 final HInstruction instruction; |
| 151 InstructionValue(this.instruction); | 160 InstructionValue(this.instruction); |
| 152 | 161 |
| 153 bool operator ==(other) { | 162 bool operator ==(other) { |
| 154 if (other is !InstructionValue) return false; | 163 if (other is !InstructionValue) return false; |
| 155 return this.instruction == other.instruction; | 164 return this.instruction == other.instruction; |
| 156 } | 165 } |
| 157 | 166 |
| 158 Value operator +(Value other) { | 167 Value operator +(Value other) { |
| 159 if (other.isZero()) return this; | 168 if (other.isZero()) return this; |
| 160 return new OperationValue(this, other, const AddOperation()); | 169 if (other is IntValue) { |
| 170 if (other.isNegative()) { |
| 171 return new SubtractValue(this, -other); |
| 172 } |
| 173 return new AddValue(this, other); |
| 174 } |
| 175 if (other is InstructionValue) { |
| 176 return new AddValue(this, other); |
| 177 } |
| 178 return other + this; |
| 161 } | 179 } |
| 162 | 180 |
| 163 Value operator -(Value other) { | 181 Value operator -(Value other) { |
| 164 if (other.isZero()) return this; | 182 if (other.isZero()) return this; |
| 165 if (this == other) return const IntValue(0); | 183 if (this == other) return const IntValue(0); |
| 166 return new OperationValue(this, other, const SubtractOperation()); | 184 if (other is IntValue) { |
| 185 if (other.isNegative()) { |
| 186 return new AddValue(this, -other); |
| 187 } |
| 188 return new SubtractValue(this, other); |
| 189 } |
| 190 if (other is InstructionValue) { |
| 191 return new SubtractValue(this, other); |
| 192 } |
| 193 return -other + this; |
| 194 } |
| 195 |
| 196 Value operator -() { |
| 197 return new NegateValue(this); |
| 167 } | 198 } |
| 168 | 199 |
| 169 Value operator &(Value other) { | 200 Value operator &(Value other) { |
| 170 if (other is IntValue) return other & this; | 201 if (other is IntValue) return other & this; |
| 171 return this; | 202 return this; |
| 172 } | 203 } |
| 173 | 204 |
| 174 bool isNegative() => false; | 205 bool isNegative() => false; |
| 175 bool isPositive() => false; | 206 bool isPositive() => false; |
| 176 | 207 |
| 177 String toString() => 'Instruction: $instruction'; | 208 String toString() => 'Instruction: $instruction'; |
| 178 } | 209 } |
| 179 | 210 |
| 180 /** | 211 /** |
| 181 * Special value for instructions that represent the length of an | 212 * Special value for instructions that represent the length of an |
| 182 * array. The difference with an [InstructionValue] is that we know | 213 * array. The difference with an [InstructionValue] is that we know |
| 183 * the value is positive. | 214 * the value is positive. |
| 184 */ | 215 */ |
| 185 class LengthValue extends InstructionValue { | 216 class LengthValue extends InstructionValue { |
| 186 LengthValue(HInstruction instruction) : super(instruction); | 217 LengthValue(HInstruction instruction) : super(instruction); |
| 187 bool isPositive() => true; | 218 bool isPositive() => true; |
| 188 String toString() => 'Length: $instruction'; | 219 String toString() => 'Length: $instruction'; |
| 189 } | 220 } |
| 190 | 221 |
| 191 /** | 222 /** |
| 192 * Represents a binary operation on two [Value], where the operation | 223 * Represents a binary operation on two [Value], where the operation |
| 193 * did not yield a canonical value. | 224 * did not yield a canonical value. |
| 194 */ | 225 */ |
| 195 class OperationValue extends Value { | 226 class OperationValue extends Value { |
| 227 Operation operation; |
| 228 } |
| 229 |
| 230 class BinaryOperationValue extends OperationValue { |
| 196 final Value left; | 231 final Value left; |
| 197 final Value right; | 232 final Value right; |
| 198 final BinaryOperation operation; | 233 BinaryOperationValue(this.left, this.right); |
| 199 OperationValue(this.left, this.right, this.operation); | 234 } |
| 235 |
| 236 class AddValue extends BinaryOperationValue { |
| 237 AddValue(left, right) : super(left, right); |
| 200 | 238 |
| 201 bool operator ==(other) { | 239 bool operator ==(other) { |
| 202 if (other is !OperationValue) return false; | 240 if (other is !AddValue) return false; |
| 203 return left == other.left | 241 return (left == other.left && right == other.right) |
| 204 && right == other.right | 242 || (left == other.right && right == other.left); |
| 205 && operation == other.operation; | |
| 206 } | 243 } |
| 207 | 244 |
| 208 Value operator +(Value other) => const UnknownValue(); | |
| 209 Value operator &(Value other) => const UnknownValue(); | 245 Value operator &(Value other) => const UnknownValue(); |
| 246 Value operator -() => -left - right; |
| 210 | 247 |
| 211 Value operator -(Value other) { | 248 Value operator +(Value other) { |
| 212 if (operation is! SubtractOperation && operation is! AddOperation) { | 249 if (other.isZero()) return this; |
| 213 return const UnknownValue(); | 250 Value value = left + other; |
| 214 } | 251 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 215 // We try to create a simple [Value] out of this operation. So we | 252 return value + right; |
| 216 // first try to substract [other] to [left]. If the result is simple | |
| 217 // enough (not unknown and not an operation), we return the result | |
| 218 // of doing the operation of this [OperationValue] on the previous | |
| 219 // result and [right]. | |
| 220 // | |
| 221 // For example: | |
| 222 // OperationValue(LengthValue(i1), IntValue(42), '-') - LengthValue(i1) | |
| 223 // | |
| 224 // Will return IntValue(-42) | |
| 225 Value value = left - other; | |
| 226 if (value != const UnknownValue() && value is! OperationValue) { | |
| 227 return operation.apply(value, right); | |
| 228 } | 253 } |
| 229 // 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 |
| 230 // with [right]. | 255 // with [right]. |
| 231 if (operation is SubtractOperation) { | 256 value = right + other; |
| 232 value = right + other; | 257 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 233 } else { | 258 return left + value; |
| 234 assert(operation is AddOperation); | |
| 235 value = right - other; | |
| 236 } | |
| 237 if (value != const UnknownValue() && value is! OperationValue) { | |
| 238 return operation.apply(left, value); | |
| 239 } | 259 } |
| 240 return const UnknownValue(); | 260 return const UnknownValue(); |
| 241 } | 261 } |
| 242 | 262 |
| 243 bool isNegative() => false; | 263 Value operator -(Value other) { |
| 244 bool isPositive() => false; | 264 if (other.isZero()) return this; |
| 245 String toString() => '$left ${operation.name} $right'; | 265 Value value = left - other; |
| 266 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 267 return value + right; |
| 268 } |
| 269 // If the result is not simple enough, we try the same approach |
| 270 // with [right]. |
| 271 value = right - other; |
| 272 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 273 return left + value; |
| 274 } |
| 275 return const UnknownValue(); |
| 276 } |
| 277 |
| 278 bool isNegative() => left.isNegative() && right.isNegative(); |
| 279 bool isPositive() => left.isPositive() && right.isPositive(); |
| 280 String toString() => '$left + $right'; |
| 281 } |
| 282 |
| 283 class SubtractValue extends BinaryOperationValue { |
| 284 SubtractValue(left, right) : super(left, right); |
| 285 |
| 286 bool operator ==(other) { |
| 287 if (other is !SubtractValue) return false; |
| 288 return left == other.left && right == other.right; |
| 289 } |
| 290 |
| 291 Value operator &(Value other) => const UnknownValue(); |
| 292 Value operator -() => right - left; |
| 293 |
| 294 Value operator +(Value other) { |
| 295 if (other.isZero()) return this; |
| 296 Value value = left + other; |
| 297 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 298 return value - right; |
| 299 } |
| 300 // If the result is not simple enough, we try the same approach |
| 301 // with [right]. |
| 302 value = other - right; |
| 303 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 304 return left + value; |
| 305 } |
| 306 return const UnknownValue(); |
| 307 } |
| 308 |
| 309 Value operator -(Value other) { |
| 310 if (other.isZero()) return this; |
| 311 Value value = left - other; |
| 312 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 313 return value - right; |
| 314 } |
| 315 // If the result is not simple enough, we try the same approach |
| 316 // with [right]. |
| 317 value = right + other; |
| 318 if (value != const UnknownValue() && value is! BinaryOperationValue) { |
| 319 return left - value; |
| 320 } |
| 321 return const UnknownValue(); |
| 322 } |
| 323 |
| 324 bool isNegative() => left.isNegative() && right.isPositive(); |
| 325 bool isPositive() => left.isPositive() && right.isNegative(); |
| 326 String toString() => '$left - $right'; |
| 327 } |
| 328 |
| 329 class NegateValue extends OperationValue { |
| 330 final Value value; |
| 331 NegateValue(this.value); |
| 332 |
| 333 bool operator ==(other) { |
| 334 if (other is !NegateValue) return false; |
| 335 return value == other.value; |
| 336 } |
| 337 |
| 338 Value operator +(other) { |
| 339 if (other.isZero()) return this; |
| 340 if (other == value) return const IntValue(0); |
| 341 if (other is NegateValue) return this - other.value; |
| 342 if (other is IntValue) { |
| 343 if (other.isNegative()) { |
| 344 return new SubtractValue(this, -other); |
| 345 } |
| 346 return new SubtractValue(other, value); |
| 347 } |
| 348 if (other is InstructionValue) { |
| 349 return new SubtractValue(other, value); |
| 350 } |
| 351 return other - value; |
| 352 } |
| 353 |
| 354 Value operator &(Value other) => const UnknownValue(); |
| 355 |
| 356 Value operator -(other) { |
| 357 if (other.isZero()) return this; |
| 358 if (other is IntValue) { |
| 359 if (other.isNegative()) { |
| 360 return new SubtractValue(-other, value); |
| 361 } |
| 362 return new SubtractValue(this, other); |
| 363 } |
| 364 if (other is InstructionValue) { |
| 365 return new SubtractValue(this, other); |
| 366 } |
| 367 if (other is NegateValue) return this + other.value; |
| 368 return -other - value; |
| 369 } |
| 370 |
| 371 Value operator -() => value; |
| 372 |
| 373 bool isNegative() => value.isPositive(); |
| 374 bool isPositive() => value.isNegative(); |
| 375 String toString() => '-$value'; |
| 246 } | 376 } |
| 247 | 377 |
| 248 /** | 378 /** |
| 249 * A [Range] represents the possible integer values an instruction | 379 * A [Range] represents the possible integer values an instruction |
| 250 * can have, from its [lower] bound to its [upper] bound, both | 380 * can have, from its [lower] bound to its [upper] bound, both |
| 251 * included. | 381 * included. |
| 252 */ | 382 */ |
| 253 class Range { | 383 class Range { |
| 254 final Value lower; | 384 final Value lower; |
| 255 final Value upper; | 385 final Value upper; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 } | 418 } |
| 289 | 419 |
| 290 Range operator +(Range other) { | 420 Range operator +(Range other) { |
| 291 return new Range.normalize(lower + other.lower, upper + other.upper); | 421 return new Range.normalize(lower + other.lower, upper + other.upper); |
| 292 } | 422 } |
| 293 | 423 |
| 294 Range operator -(Range other) { | 424 Range operator -(Range other) { |
| 295 return new Range.normalize(lower - other.upper, upper - other.lower); | 425 return new Range.normalize(lower - other.upper, upper - other.lower); |
| 296 } | 426 } |
| 297 | 427 |
| 428 Range operator -() { |
| 429 return new Range.normalize(-upper, -lower); |
| 430 } |
| 431 |
| 298 Range operator &(Range other) { | 432 Range operator &(Range other) { |
| 299 if (isSingleValue() | 433 if (isSingleValue() |
| 300 && other.isSingleValue() | 434 && other.isSingleValue() |
| 301 && lower is IntValue | 435 && lower is IntValue |
| 302 && other.lower is IntValue) { | 436 && other.lower is IntValue) { |
| 303 return new Range(lower & other.lower, upper & other.upper); | 437 return new Range(lower & other.lower, upper & other.upper); |
| 304 } | 438 } |
| 305 if (isPositive() && other.isPositive()) { | 439 if (isPositive() && other.isPositive()) { |
| 306 Value up = upper.min(other.upper); | 440 Value up = upper.min(other.upper); |
| 307 if (up == const UnknownValue()) { | 441 if (up == const UnknownValue()) { |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 if (instruction is HPhi && !instruction.block.isLoopHeader()) { | 937 if (instruction is HPhi && !instruction.block.isLoopHeader()) { |
| 804 HInstruction result = unwrap(instruction.inputs[0]); | 938 HInstruction result = unwrap(instruction.inputs[0]); |
| 805 for (int i = 1; i < instruction.inputs.length; i++) { | 939 for (int i = 1; i < instruction.inputs.length; i++) { |
| 806 if (result != unwrap(instruction.inputs[i])) return instruction; | 940 if (result != unwrap(instruction.inputs[i])) return instruction; |
| 807 } | 941 } |
| 808 return result; | 942 return result; |
| 809 } | 943 } |
| 810 return instruction; | 944 return instruction; |
| 811 } | 945 } |
| 812 } | 946 } |
| OLD | NEW |