OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/operation-typer.h" | 5 #include "src/compiler/operation-typer.h" |
6 | 6 |
7 #include "src/factory.h" | 7 #include "src/factory.h" |
8 #include "src/isolate.h" | 8 #include "src/isolate.h" |
9 #include "src/type-cache.h" | 9 #include "src/type-cache.h" |
10 #include "src/types.h" | 10 #include "src/types.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 omin = 0 - abs; | 226 omin = 0 - abs; |
227 omax = abs; | 227 omax = abs; |
228 maybe_minus_zero = true; | 228 maybe_minus_zero = true; |
229 } | 229 } |
230 | 230 |
231 Type* result = Type::Range(omin, omax, zone()); | 231 Type* result = Type::Range(omin, omax, zone()); |
232 if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone()); | 232 if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone()); |
233 return result; | 233 return result; |
234 } | 234 } |
235 | 235 |
| 236 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { |
| 237 double results[4]; |
| 238 double lmin = lhs->AsRange()->Min(); |
| 239 double lmax = lhs->AsRange()->Max(); |
| 240 double rmin = rhs->AsRange()->Min(); |
| 241 double rmax = rhs->AsRange()->Max(); |
| 242 results[0] = lmin * rmin; |
| 243 results[1] = lmin * rmax; |
| 244 results[2] = lmax * rmin; |
| 245 results[3] = lmax * rmax; |
| 246 // If the result may be nan, we give up on calculating a precise type, |
| 247 // because |
| 248 // the discontinuity makes it too complicated. Note that even if none of |
| 249 // the |
| 250 // "results" above is nan, the actual result may still be, so we have to do |
| 251 // a |
| 252 // different check: |
| 253 bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) && |
| 254 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
| 255 (rhs->Maybe(cache_.kSingletonZero) && |
| 256 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
| 257 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. |
| 258 bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) || |
| 259 (rhs->Maybe(cache_.kSingletonZero) && lmin < 0); |
| 260 Type* range = |
| 261 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
| 262 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) |
| 263 : range; |
| 264 } |
| 265 |
236 Type* OperationTyper::ToNumber(Type* type) { | 266 Type* OperationTyper::ToNumber(Type* type) { |
237 if (type->Is(Type::Number())) return type; | 267 if (type->Is(Type::Number())) return type; |
238 if (type->Is(Type::NullOrUndefined())) { | 268 if (type->Is(Type::NullOrUndefined())) { |
239 if (type->Is(Type::Null())) return cache_.kSingletonZero; | 269 if (type->Is(Type::Null())) return cache_.kSingletonZero; |
240 if (type->Is(Type::Undefined())) return Type::NaN(); | 270 if (type->Is(Type::Undefined())) return Type::NaN(); |
241 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); | 271 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); |
242 } | 272 } |
243 if (type->Is(Type::NumberOrUndefined())) { | 273 if (type->Is(Type::NumberOrUndefined())) { |
244 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 274 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
245 Type::NaN(), zone()); | 275 Type::NaN(), zone()); |
(...skipping 29 matching lines...) Expand all Loading... |
275 lhs = Rangify(lhs); | 305 lhs = Rangify(lhs); |
276 rhs = Rangify(rhs); | 306 rhs = Rangify(rhs); |
277 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 307 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
278 if (lhs->IsRange() && rhs->IsRange()) { | 308 if (lhs->IsRange() && rhs->IsRange()) { |
279 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); | 309 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); |
280 } | 310 } |
281 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 311 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
282 return Type::Number(); | 312 return Type::Number(); |
283 } | 313 } |
284 | 314 |
| 315 Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) { |
| 316 DCHECK(lhs->Is(Type::Number())); |
| 317 DCHECK(rhs->Is(Type::Number())); |
| 318 lhs = Rangify(lhs); |
| 319 rhs = Rangify(rhs); |
| 320 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 321 if (lhs->IsRange() && rhs->IsRange()) { |
| 322 return MultiplyRanger(lhs, rhs); |
| 323 } |
| 324 return Type::Number(); |
| 325 } |
| 326 |
| 327 Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) { |
| 328 DCHECK(lhs->Is(Type::Number())); |
| 329 DCHECK(rhs->Is(Type::Number())); |
| 330 |
| 331 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 332 // Division is tricky, so all we do is try ruling out nan. |
| 333 bool maybe_nan = |
| 334 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 335 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 336 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 337 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 338 } |
| 339 |
| 340 Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) { |
| 341 DCHECK(lhs->Is(Type::Number())); |
| 342 DCHECK(rhs->Is(Type::Number())); |
| 343 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 344 |
| 345 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 346 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
| 347 // Result maybe NaN. |
| 348 return Type::Number(); |
| 349 } |
| 350 |
| 351 lhs = Rangify(lhs); |
| 352 rhs = Rangify(rhs); |
| 353 if (lhs->IsRange() && rhs->IsRange()) { |
| 354 return ModulusRanger(lhs->AsRange(), rhs->AsRange()); |
| 355 } |
| 356 return Type::OrderedNumber(); |
| 357 } |
| 358 |
285 Type* OperationTyper::ToPrimitive(Type* type) { | 359 Type* OperationTyper::ToPrimitive(Type* type) { |
286 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { | 360 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
287 return type; | 361 return type; |
288 } | 362 } |
289 return Type::Primitive(); | 363 return Type::Primitive(); |
290 } | 364 } |
291 | 365 |
292 Type* OperationTyper::Invert(Type* type) { | 366 Type* OperationTyper::Invert(Type* type) { |
293 DCHECK(type->Is(Type::Boolean())); | 367 DCHECK(type->Is(Type::Boolean())); |
294 DCHECK(type->IsInhabited()); | 368 DCHECK(type->IsInhabited()); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 return NumericAdd(lhs, rhs); | 406 return NumericAdd(lhs, rhs); |
333 } | 407 } |
334 | 408 |
335 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 409 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
336 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); | 410 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); |
337 } | 411 } |
338 | 412 |
339 } // namespace compiler | 413 } // namespace compiler |
340 } // namespace internal | 414 } // namespace internal |
341 } // namespace v8 | 415 } // namespace v8 |
OLD | NEW |