| 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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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::NumericAdd(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()) { |
| 293 return Type::None(); |
| 294 } |
| 295 |
| 292 // We can give more precise types for integers. | 296 // We can give more precise types for integers. |
| 293 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || | 297 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || |
| 294 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { | 298 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { |
| 295 return Type::Number(); | 299 return Type::Number(); |
| 296 } | 300 } |
| 297 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); | 301 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); |
| 298 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); | 302 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); |
| 299 Type* result = | 303 Type* result = |
| 300 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()); |
| 301 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { | 305 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
| 302 result = Type::Union(result, Type::NaN(), zone()); | 306 result = Type::Union(result, Type::NaN(), zone()); |
| 303 } | 307 } |
| 304 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { | 308 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { |
| 305 result = Type::Union(result, Type::MinusZero(), zone()); | 309 result = Type::Union(result, Type::MinusZero(), zone()); |
| 306 } | 310 } |
| 307 return result; | 311 return result; |
| 308 } | 312 } |
| 309 | 313 |
| 310 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { | 314 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { |
| 311 DCHECK(lhs->Is(Type::Number())); | 315 DCHECK(lhs->Is(Type::Number())); |
| 312 DCHECK(rhs->Is(Type::Number())); | 316 DCHECK(rhs->Is(Type::Number())); |
| 313 | 317 |
| 318 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 319 return Type::None(); |
| 320 } |
| 321 |
| 314 lhs = Rangify(lhs); | 322 lhs = Rangify(lhs); |
| 315 rhs = Rangify(rhs); | 323 rhs = Rangify(rhs); |
| 316 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(); |
| 317 if (lhs->IsRange() && rhs->IsRange()) { | 325 if (lhs->IsRange() && rhs->IsRange()) { |
| 318 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); | 326 return SubtractRanger(lhs->AsRange(), rhs->AsRange()); |
| 319 } | 327 } |
| 320 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 328 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
| 321 return Type::Number(); | 329 return Type::Number(); |
| 322 } | 330 } |
| 323 | 331 |
| 324 Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) { | 332 Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) { |
| 325 DCHECK(lhs->Is(Type::Number())); | 333 DCHECK(lhs->Is(Type::Number())); |
| 326 DCHECK(rhs->Is(Type::Number())); | 334 DCHECK(rhs->Is(Type::Number())); |
| 335 |
| 336 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 337 return Type::None(); |
| 338 } |
| 339 |
| 327 lhs = Rangify(lhs); | 340 lhs = Rangify(lhs); |
| 328 rhs = Rangify(rhs); | 341 rhs = Rangify(rhs); |
| 329 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(); |
| 330 if (lhs->IsRange() && rhs->IsRange()) { | 343 if (lhs->IsRange() && rhs->IsRange()) { |
| 331 return MultiplyRanger(lhs, rhs); | 344 return MultiplyRanger(lhs, rhs); |
| 332 } | 345 } |
| 333 return Type::Number(); | 346 return Type::Number(); |
| 334 } | 347 } |
| 335 | 348 |
| 336 Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) { | 349 Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) { |
| 337 DCHECK(lhs->Is(Type::Number())); | 350 DCHECK(lhs->Is(Type::Number())); |
| 338 DCHECK(rhs->Is(Type::Number())); | 351 DCHECK(rhs->Is(Type::Number())); |
| 339 | 352 |
| 353 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 354 return Type::None(); |
| 355 } |
| 356 |
| 340 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(); |
| 341 // 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. |
| 342 bool maybe_nan = | 359 bool maybe_nan = |
| 343 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 360 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 344 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | 361 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 345 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | 362 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 346 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 363 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 347 } | 364 } |
| 348 | 365 |
| 349 Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) { | 366 Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) { |
| 350 DCHECK(lhs->Is(Type::Number())); | 367 DCHECK(lhs->Is(Type::Number())); |
| 351 DCHECK(rhs->Is(Type::Number())); | 368 DCHECK(rhs->Is(Type::Number())); |
| 369 |
| 370 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 371 return Type::None(); |
| 372 } |
| 373 |
| 352 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(); |
| 353 | 375 |
| 354 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 376 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 355 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { | 377 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
| 356 // Result maybe NaN. | 378 // Result maybe NaN. |
| 357 return Type::Number(); | 379 return Type::Number(); |
| 358 } | 380 } |
| 359 | 381 |
| 360 lhs = Rangify(lhs); | 382 lhs = Rangify(lhs); |
| 361 rhs = Rangify(rhs); | 383 rhs = Rangify(rhs); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 : singleton_false(); | 418 : singleton_false(); |
| 397 } | 419 } |
| 398 // Type should be non empty, so we know it should be true. | 420 // Type should be non empty, so we know it should be true. |
| 399 DCHECK((outcome & kComparisonTrue) != 0); | 421 DCHECK((outcome & kComparisonTrue) != 0); |
| 400 return singleton_true(); | 422 return singleton_true(); |
| 401 } | 423 } |
| 402 | 424 |
| 403 Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) { | 425 Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) { |
| 404 lhs = ToPrimitive(lhs); | 426 lhs = ToPrimitive(lhs); |
| 405 rhs = ToPrimitive(rhs); | 427 rhs = ToPrimitive(rhs); |
| 428 |
| 429 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 430 return Type::None(); |
| 431 } |
| 432 |
| 406 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { | 433 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { |
| 407 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { | 434 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { |
| 408 return Type::String(); | 435 return Type::String(); |
| 409 } else { | 436 } else { |
| 410 return Type::NumberOrString(); | 437 return Type::NumberOrString(); |
| 411 } | 438 } |
| 412 } | 439 } |
| 413 lhs = ToNumber(lhs); | 440 lhs = ToNumber(lhs); |
| 414 rhs = ToNumber(rhs); | 441 rhs = ToNumber(rhs); |
| 415 return NumericAdd(lhs, rhs); | 442 return NumericAdd(lhs, rhs); |
| 416 } | 443 } |
| 417 | 444 |
| 418 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 445 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
| 419 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); | 446 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); |
| 420 } | 447 } |
| 421 | 448 |
| 422 } // namespace compiler | 449 } // namespace compiler |
| 423 } // namespace internal | 450 } // namespace internal |
| 424 } // namespace v8 | 451 } // namespace v8 |
| OLD | NEW |