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 |