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 |