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 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 if (type->Is(singleton_false_)) return cache_.kSingletonZero; | 278 if (type->Is(singleton_false_)) return cache_.kSingletonZero; |
279 if (type->Is(singleton_true_)) return cache_.kSingletonOne; | 279 if (type->Is(singleton_true_)) return cache_.kSingletonOne; |
280 if (type->Is(Type::Boolean())) return cache_.kZeroOrOne; | 280 if (type->Is(Type::Boolean())) return cache_.kZeroOrOne; |
281 if (type->Is(Type::BooleanOrNumber())) { | 281 if (type->Is(Type::BooleanOrNumber())) { |
282 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 282 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
283 cache_.kZeroOrOne, zone()); | 283 cache_.kZeroOrOne, zone()); |
284 } | 284 } |
285 return Type::Number(); | 285 return Type::Number(); |
286 } | 286 } |
287 | 287 |
288 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { | 288 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { |
289 DCHECK(lhs->Is(Type::Number())); | 289 DCHECK(lhs->Is(Type::Number())); |
290 DCHECK(rhs->Is(Type::Number())); | 290 DCHECK(rhs->Is(Type::Number())); |
291 | 291 |
292 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 292 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
293 return Type::None(); | 293 return Type::None(); |
294 } | 294 } |
295 | 295 |
296 // We can give more precise types for integers. | 296 // We can give more precise types for integers. |
297 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || | 297 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || |
298 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { | 298 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { |
299 return Type::Number(); | 299 return Type::Number(); |
300 } | 300 } |
301 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); | 301 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); |
302 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); | 302 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); |
303 Type* result = | 303 Type* result = |
304 AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max()); | 304 AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max()); |
305 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { | 305 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
306 result = Type::Union(result, Type::NaN(), zone()); | 306 result = Type::Union(result, Type::NaN(), zone()); |
307 } | 307 } |
308 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { | 308 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { |
309 result = Type::Union(result, Type::MinusZero(), zone()); | 309 result = Type::Union(result, Type::MinusZero(), zone()); |
310 } | 310 } |
311 return result; | 311 return result; |
312 } | 312 } |
313 | 313 |
314 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { | 314 Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) { |
315 DCHECK(lhs->Is(Type::Number())); | 315 DCHECK(lhs->Is(Type::Number())); |
316 DCHECK(rhs->Is(Type::Number())); | 316 DCHECK(rhs->Is(Type::Number())); |
317 | 317 |
318 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 318 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
319 return Type::None(); | 319 return Type::None(); |
320 } | 320 } |
321 | 321 |
322 lhs = Rangify(lhs); | 322 lhs = Rangify(lhs); |
323 rhs = Rangify(rhs); | 323 rhs = Rangify(rhs); |
324 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 324 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
325 if (lhs->IsRange() && rhs->IsRange()) { | 325 if (lhs->IsRange() && rhs->IsRange()) { |
326 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); | 326 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); |
327 } | 327 } |
328 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 328 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
329 return Type::Number(); | 329 return Type::Number(); |
330 } | 330 } |
331 | 331 |
332 Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) { | 332 Type* OperationTyper::NumberMultiply(Type* lhs, Type* rhs) { |
333 DCHECK(lhs->Is(Type::Number())); | 333 DCHECK(lhs->Is(Type::Number())); |
334 DCHECK(rhs->Is(Type::Number())); | 334 DCHECK(rhs->Is(Type::Number())); |
335 | 335 |
336 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 336 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
337 return Type::None(); | 337 return Type::None(); |
338 } | 338 } |
339 | 339 |
340 lhs = Rangify(lhs); | 340 lhs = Rangify(lhs); |
341 rhs = Rangify(rhs); | 341 rhs = Rangify(rhs); |
342 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 342 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
343 if (lhs->IsRange() && rhs->IsRange()) { | 343 if (lhs->IsRange() && rhs->IsRange()) { |
344 return MultiplyRanger(lhs, rhs); | 344 return MultiplyRanger(lhs, rhs); |
345 } | 345 } |
346 return Type::Number(); | 346 return Type::Number(); |
347 } | 347 } |
348 | 348 |
349 Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) { | 349 Type* OperationTyper::NumberDivide(Type* lhs, Type* rhs) { |
350 DCHECK(lhs->Is(Type::Number())); | 350 DCHECK(lhs->Is(Type::Number())); |
351 DCHECK(rhs->Is(Type::Number())); | 351 DCHECK(rhs->Is(Type::Number())); |
352 | 352 |
353 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 353 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
354 return Type::None(); | 354 return Type::None(); |
355 } | 355 } |
356 | 356 |
357 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 357 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
358 // Division is tricky, so all we do is try ruling out nan. | 358 // Division is tricky, so all we do is try ruling out nan. |
359 bool maybe_nan = | 359 bool maybe_nan = |
360 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 360 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
361 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | 361 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
362 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | 362 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
363 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 363 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
364 } | 364 } |
365 | 365 |
366 Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) { | 366 Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) { |
367 DCHECK(lhs->Is(Type::Number())); | 367 DCHECK(lhs->Is(Type::Number())); |
368 DCHECK(rhs->Is(Type::Number())); | 368 DCHECK(rhs->Is(Type::Number())); |
369 | 369 |
370 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 370 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
371 return Type::None(); | 371 return Type::None(); |
372 } | 372 } |
373 | 373 |
374 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 374 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
375 | 375 |
376 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 376 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
377 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { | 377 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
378 // Result maybe NaN. | 378 // Result maybe NaN. |
379 return Type::Number(); | 379 return Type::Number(); |
380 } | 380 } |
381 | 381 |
382 lhs = Rangify(lhs); | 382 lhs = Rangify(lhs); |
383 rhs = Rangify(rhs); | 383 rhs = Rangify(rhs); |
384 if (lhs->IsRange() && rhs->IsRange()) { | 384 if (lhs->IsRange() && rhs->IsRange()) { |
385 return ModulusRanger(lhs->AsRange(), rhs->AsRange()); | 385 return ModulusRanger(lhs->AsRange(), rhs->AsRange()); |
386 } | 386 } |
387 return Type::OrderedNumber(); | 387 return Type::OrderedNumber(); |
388 } | 388 } |
389 | 389 |
| 390 Type* OperationTyper::NumberAbs(Type* type) { |
| 391 DCHECK(type->Is(Type::Number())); |
| 392 |
| 393 if (!type->IsInhabited()) { |
| 394 return Type::None(); |
| 395 } |
| 396 |
| 397 bool const maybe_nan = type->Maybe(Type::NaN()); |
| 398 bool const maybe_minuszero = type->Maybe(Type::MinusZero()); |
| 399 type = Type::Intersect(type, Type::PlainNumber(), zone()); |
| 400 double const max = type->Max(); |
| 401 double const min = type->Min(); |
| 402 if (min < 0) { |
| 403 if (type->Is(cache_.kInteger)) { |
| 404 type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone()); |
| 405 } else { |
| 406 type = Type::PlainNumber(); |
| 407 } |
| 408 } |
| 409 if (maybe_minuszero) { |
| 410 type = Type::Union(type, cache_.kSingletonZero, zone()); |
| 411 } |
| 412 if (maybe_nan) { |
| 413 type = Type::Union(type, Type::NaN(), zone()); |
| 414 } |
| 415 return type; |
| 416 } |
| 417 |
390 Type* OperationTyper::ToPrimitive(Type* type) { | 418 Type* OperationTyper::ToPrimitive(Type* type) { |
391 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { | 419 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
392 return type; | 420 return type; |
393 } | 421 } |
394 return Type::Primitive(); | 422 return Type::Primitive(); |
395 } | 423 } |
396 | 424 |
397 Type* OperationTyper::Invert(Type* type) { | 425 Type* OperationTyper::Invert(Type* type) { |
398 DCHECK(type->Is(Type::Boolean())); | 426 DCHECK(type->Is(Type::Boolean())); |
399 DCHECK(type->IsInhabited()); | 427 DCHECK(type->IsInhabited()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 | 460 |
433 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { | 461 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { |
434 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { | 462 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { |
435 return Type::String(); | 463 return Type::String(); |
436 } else { | 464 } else { |
437 return Type::NumberOrString(); | 465 return Type::NumberOrString(); |
438 } | 466 } |
439 } | 467 } |
440 lhs = ToNumber(lhs); | 468 lhs = ToNumber(lhs); |
441 rhs = ToNumber(rhs); | 469 rhs = ToNumber(rhs); |
442 return NumericAdd(lhs, rhs); | 470 return NumberAdd(lhs, rhs); |
443 } | 471 } |
444 | 472 |
445 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 473 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
446 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); | 474 return NumberSubtract(ToNumber(lhs), ToNumber(rhs)); |
447 } | 475 } |
448 | 476 |
449 } // namespace compiler | 477 } // namespace compiler |
450 } // namespace internal | 478 } // namespace internal |
451 } // namespace v8 | 479 } // namespace v8 |
OLD | NEW |