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