Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: src/compiler/operation-typer.cc

Issue 2202883005: [turbofan] Unify number operation typing rules. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove useless cementation. DCHECKs instead of defensive programming are way more useful. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/operation-typer.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 11
12 #include "src/objects-inl.h" 12 #include "src/objects-inl.h"
13 13
14 namespace v8 { 14 namespace v8 {
15 namespace internal { 15 namespace internal {
16 namespace compiler { 16 namespace compiler {
17 17
18 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) 18 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone)
19 : zone_(zone), cache_(TypeCache::Get()) { 19 : zone_(zone), cache_(TypeCache::Get()) {
20 Factory* factory = isolate->factory(); 20 Factory* factory = isolate->factory();
21 Type* infinity = Type::Constant(factory->infinity_value(), zone);
22 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone);
23 // Unfortunately, the infinities created in other places might be different
24 // ones (eg the result of NewNumber in TypeNumberConstant).
25 Type* truncating_to_zero =
26 Type::Union(Type::Union(infinity, minus_infinity, zone),
27 Type::MinusZeroOrNaN(), zone);
28 DCHECK(!truncating_to_zero->Maybe(Type::Integral32()));
29
21 singleton_false_ = Type::Constant(factory->false_value(), zone); 30 singleton_false_ = Type::Constant(factory->false_value(), zone);
22 singleton_true_ = Type::Constant(factory->true_value(), zone); 31 singleton_true_ = Type::Constant(factory->true_value(), zone);
23 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); 32 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone);
33 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
34 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
24 } 35 }
25 36
26 Type* OperationTyper::Merge(Type* left, Type* right) { 37 Type* OperationTyper::Merge(Type* left, Type* right) {
27 return Type::Union(left, right, zone()); 38 return Type::Union(left, right, zone());
28 } 39 }
29 40
30 Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) { 41 Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) {
31 static const double kWeakenMinLimits[] = {0.0, 42 static const double kWeakenMinLimits[] = {0.0,
32 -1073741824.0, 43 -1073741824.0,
33 -2147483648.0, 44 -2147483648.0,
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { 218 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) {
208 double results[4]; 219 double results[4];
209 double lmin = lhs->AsRange()->Min(); 220 double lmin = lhs->AsRange()->Min();
210 double lmax = lhs->AsRange()->Max(); 221 double lmax = lhs->AsRange()->Max();
211 double rmin = rhs->AsRange()->Min(); 222 double rmin = rhs->AsRange()->Min();
212 double rmax = rhs->AsRange()->Max(); 223 double rmax = rhs->AsRange()->Max();
213 results[0] = lmin * rmin; 224 results[0] = lmin * rmin;
214 results[1] = lmin * rmax; 225 results[1] = lmin * rmax;
215 results[2] = lmax * rmin; 226 results[2] = lmax * rmin;
216 results[3] = lmax * rmax; 227 results[3] = lmax * rmax;
217 // If the result may be nan, we give up on calculating a precise type, 228 // If the result may be nan, we give up on calculating a precise type, because
218 // because 229 // the discontinuity makes it too complicated. Note that even if none of the
219 // the discontinuity makes it too complicated. Note that even if none of 230 // "results" above is nan, the actual result may still be, so we have to do a
220 // the
221 // "results" above is nan, the actual result may still be, so we have to do
222 // a
223 // different check: 231 // different check:
224 bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) && 232 bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) &&
225 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || 233 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
226 (rhs->Maybe(cache_.kSingletonZero) && 234 (rhs->Maybe(cache_.kSingletonZero) &&
227 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); 235 (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
228 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. 236 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up.
229 bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) || 237 bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) ||
230 (rhs->Maybe(cache_.kSingletonZero) && lmin < 0); 238 (rhs->Maybe(cache_.kSingletonZero) && lmin < 0);
231 Type* range = 239 Type* range =
232 Type::Range(array_min(results, 4), array_max(results, 4), zone()); 240 Type::Range(array_min(results, 4), array_max(results, 4), zone());
233 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) 241 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
234 : range; 242 : range;
235 } 243 }
236 244
237 Type* OperationTyper::ToNumber(Type* type) { 245 Type* OperationTyper::ToNumber(Type* type) {
238 if (type->Is(Type::Number())) return type; 246 if (type->Is(Type::Number())) return type;
239 if (type->Is(Type::NullOrUndefined())) { 247 if (type->Is(Type::NullOrUndefined())) {
240 if (type->Is(Type::Null())) return cache_.kSingletonZero; 248 if (type->Is(Type::Null())) return cache_.kSingletonZero;
241 if (type->Is(Type::Undefined())) return Type::NaN(); 249 if (type->Is(Type::Undefined())) return Type::NaN();
242 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); 250 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
243 } 251 }
244 if (type->Is(Type::NumberOrUndefined())) { 252 if (type->Is(Type::Boolean())) {
245 return Type::Union(Type::Intersect(type, Type::Number(), zone()), 253 if (type->Is(singleton_false_)) return cache_.kSingletonZero;
246 Type::NaN(), zone()); 254 if (type->Is(singleton_true_)) return cache_.kSingletonOne;
247 } 255 return cache_.kZeroOrOne;
248 if (type->Is(singleton_false_)) return cache_.kSingletonZero; 256 }
249 if (type->Is(singleton_true_)) return cache_.kSingletonOne; 257 if (type->Is(Type::NumberOrOddball())) {
250 if (type->Is(Type::Boolean())) return cache_.kZeroOrOne; 258 if (type->Is(Type::NumberOrUndefined())) {
251 if (type->Is(Type::BooleanOrNumber())) { 259 type = Type::Union(type, Type::NaN(), zone());
252 return Type::Union(Type::Intersect(type, Type::Number(), zone()), 260 } else if (type->Is(Type::NullOrNumber())) {
253 cache_.kZeroOrOne, zone()); 261 type = Type::Union(type, cache_.kSingletonZero, zone());
254 } 262 } else if (type->Is(Type::BooleanOrNullOrNumber())) {
255 return Type::Number(); 263 type = Type::Union(type, cache_.kZeroOrOne, zone());
264 } else {
265 type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone());
266 }
267 return Type::Intersect(type, Type::Number(), zone());
268 }
269 return Type::Number();
270 }
271
272 Type* OperationTyper::NumberAbs(Type* type) {
273 DCHECK(type->Is(Type::Number()));
274
275 if (!type->IsInhabited()) {
276 return Type::None();
277 }
278
279 bool const maybe_nan = type->Maybe(Type::NaN());
280 bool const maybe_minuszero = type->Maybe(Type::MinusZero());
281 type = Type::Intersect(type, Type::PlainNumber(), zone());
282 double const max = type->Max();
283 double const min = type->Min();
284 if (min < 0) {
285 if (type->Is(cache_.kInteger)) {
286 type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
287 } else {
288 type = Type::PlainNumber();
289 }
290 }
291 if (maybe_minuszero) {
292 type = Type::Union(type, cache_.kSingletonZero, zone());
293 }
294 if (maybe_nan) {
295 type = Type::Union(type, Type::NaN(), zone());
296 }
297 return type;
298 }
299
300 Type* OperationTyper::NumberAcos(Type* type) {
301 DCHECK(type->Is(Type::Number()));
302 return Type::Number();
303 }
304
305 Type* OperationTyper::NumberAcosh(Type* type) {
306 DCHECK(type->Is(Type::Number()));
307 return Type::Number();
308 }
309
310 Type* OperationTyper::NumberAsin(Type* type) {
311 DCHECK(type->Is(Type::Number()));
312 return Type::Number();
313 }
314
315 Type* OperationTyper::NumberAsinh(Type* type) {
316 DCHECK(type->Is(Type::Number()));
317 return Type::Number();
318 }
319
320 Type* OperationTyper::NumberAtan(Type* type) {
321 DCHECK(type->Is(Type::Number()));
322 return Type::Number();
323 }
324
325 Type* OperationTyper::NumberAtanh(Type* type) {
326 DCHECK(type->Is(Type::Number()));
327 return Type::Number();
328 }
329
330 Type* OperationTyper::NumberCbrt(Type* type) {
331 DCHECK(type->Is(Type::Number()));
332 return Type::Number();
333 }
334
335 Type* OperationTyper::NumberCeil(Type* type) {
336 DCHECK(type->Is(Type::Number()));
337 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
338 // TODO(bmeurer): We could infer a more precise type here.
339 return cache_.kIntegerOrMinusZeroOrNaN;
340 }
341
342 Type* OperationTyper::NumberClz32(Type* type) {
343 DCHECK(type->Is(Type::Number()));
344 return cache_.kZeroToThirtyTwo;
345 }
346
347 Type* OperationTyper::NumberCos(Type* type) {
348 DCHECK(type->Is(Type::Number()));
349 return Type::Number();
350 }
351
352 Type* OperationTyper::NumberCosh(Type* type) {
353 DCHECK(type->Is(Type::Number()));
354 return Type::Number();
355 }
356
357 Type* OperationTyper::NumberExp(Type* type) {
358 DCHECK(type->Is(Type::Number()));
359 return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
360 }
361
362 Type* OperationTyper::NumberExpm1(Type* type) {
363 DCHECK(type->Is(Type::Number()));
364 return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
365 }
366
367 Type* OperationTyper::NumberFloor(Type* type) {
368 DCHECK(type->Is(Type::Number()));
369 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
370 // TODO(bmeurer): We could infer a more precise type here.
371 return cache_.kIntegerOrMinusZeroOrNaN;
372 }
373
374 Type* OperationTyper::NumberFround(Type* type) {
375 DCHECK(type->Is(Type::Number()));
376 return Type::Number();
377 }
378
379 Type* OperationTyper::NumberLog(Type* type) {
380 DCHECK(type->Is(Type::Number()));
381 return Type::Number();
382 }
383
384 Type* OperationTyper::NumberLog1p(Type* type) {
385 DCHECK(type->Is(Type::Number()));
386 return Type::Number();
387 }
388
389 Type* OperationTyper::NumberLog2(Type* type) {
390 DCHECK(type->Is(Type::Number()));
391 return Type::Number();
392 }
393
394 Type* OperationTyper::NumberLog10(Type* type) {
395 DCHECK(type->Is(Type::Number()));
396 return Type::Number();
397 }
398
399 Type* OperationTyper::NumberRound(Type* type) {
400 DCHECK(type->Is(Type::Number()));
401 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
402 // TODO(bmeurer): We could infer a more precise type here.
403 return cache_.kIntegerOrMinusZeroOrNaN;
404 }
405
406 Type* OperationTyper::NumberSign(Type* type) {
407 DCHECK(type->Is(Type::Number()));
408 if (type->Is(cache_.kZeroish)) return type;
409 bool maybe_minuszero = type->Maybe(Type::MinusZero());
410 bool maybe_nan = type->Maybe(Type::NaN());
411 type = Type::Intersect(type, Type::PlainNumber(), zone());
412 if (type->Max() < 0.0) {
413 type = cache_.kSingletonMinusOne;
414 } else if (type->Max() <= 0.0) {
415 type = cache_.kMinusOneOrZero;
416 } else if (type->Min() > 0.0) {
417 type = cache_.kSingletonOne;
418 } else if (type->Min() >= 0.0) {
419 type = cache_.kZeroOrOne;
420 } else {
421 type = Type::Range(-1.0, 1.0, zone());
422 }
423 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
424 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
425 return type;
426 }
427
428 Type* OperationTyper::NumberSin(Type* type) {
429 DCHECK(type->Is(Type::Number()));
430 return Type::Number();
431 }
432
433 Type* OperationTyper::NumberSinh(Type* type) {
434 DCHECK(type->Is(Type::Number()));
435 return Type::Number();
436 }
437
438 Type* OperationTyper::NumberSqrt(Type* type) {
439 DCHECK(type->Is(Type::Number()));
440 return Type::Number();
441 }
442
443 Type* OperationTyper::NumberTan(Type* type) {
444 DCHECK(type->Is(Type::Number()));
445 return Type::Number();
446 }
447
448 Type* OperationTyper::NumberTanh(Type* type) {
449 DCHECK(type->Is(Type::Number()));
450 return Type::Number();
451 }
452
453 Type* OperationTyper::NumberTrunc(Type* type) {
454 DCHECK(type->Is(Type::Number()));
455 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
456 // TODO(bmeurer): We could infer a more precise type here.
457 return cache_.kIntegerOrMinusZeroOrNaN;
458 }
459
460 Type* OperationTyper::NumberToInt32(Type* type) {
461 DCHECK(type->Is(Type::Number()));
462
463 if (type->Is(Type::Signed32())) return type;
464 if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
465 if (type->Is(signed32ish_)) {
466 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
467 Type::Signed32(), zone());
468 }
469 return Type::Signed32();
470 }
471
472 Type* OperationTyper::NumberToUint32(Type* type) {
473 DCHECK(type->Is(Type::Number()));
474
475 if (type->Is(Type::Unsigned32())) return type;
476 if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
477 if (type->Is(unsigned32ish_)) {
478 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
479 Type::Unsigned32(), zone());
480 }
481 return Type::Unsigned32();
482 }
483
484 Type* OperationTyper::NumberSilenceNaN(Type* type) {
485 DCHECK(type->Is(Type::Number()));
486 // TODO(turbofan): We should have a dedicated type for the signaling NaN.
487 return type;
256 } 488 }
257 489
258 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { 490 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) {
259 DCHECK(lhs->Is(Type::Number())); 491 DCHECK(lhs->Is(Type::Number()));
260 DCHECK(rhs->Is(Type::Number())); 492 DCHECK(rhs->Is(Type::Number()));
261 493
262 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { 494 if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
263 return Type::None(); 495 return Type::None();
264 } 496 }
265 497
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 type = Type::PlainNumber(); 631 type = Type::PlainNumber();
400 } 632 }
401 } 633 }
402 634
403 // Take into account the -0 and NaN information computed earlier. 635 // Take into account the -0 and NaN information computed earlier.
404 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 636 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
405 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 637 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
406 return type; 638 return type;
407 } 639 }
408 640
409 Type* OperationTyper::NumberAbs(Type* type) { 641 Type* OperationTyper::NumberBitwiseOr(Type* lhs, Type* rhs) {
410 DCHECK(type->Is(Type::Number())); 642 DCHECK(lhs->Is(Type::Number()));
411 643 DCHECK(rhs->Is(Type::Number()));
412 if (!type->IsInhabited()) { 644
413 return Type::None(); 645 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
414 } 646
415 647 lhs = NumberToInt32(lhs);
416 bool const maybe_nan = type->Maybe(Type::NaN()); 648 rhs = NumberToInt32(rhs);
417 bool const maybe_minuszero = type->Maybe(Type::MinusZero()); 649
418 type = Type::Intersect(type, Type::PlainNumber(), zone()); 650 double lmin = lhs->Min();
419 double const max = type->Max(); 651 double rmin = rhs->Min();
420 double const min = type->Min(); 652 double lmax = lhs->Max();
421 if (min < 0) { 653 double rmax = rhs->Max();
422 if (type->Is(cache_.kInteger)) { 654 // Or-ing any two values results in a value no smaller than their minimum.
423 type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone()); 655 // Even no smaller than their maximum if both values are non-negative.
424 } else { 656 double min =
425 type = Type::PlainNumber(); 657 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
658 double max = kMaxInt;
659
660 // Or-ing with 0 is essentially a conversion to int32.
661 if (rmin == 0 && rmax == 0) {
662 min = lmin;
663 max = lmax;
664 }
665 if (lmin == 0 && lmax == 0) {
666 min = rmin;
667 max = rmax;
668 }
669
670 if (lmax < 0 || rmax < 0) {
671 // Or-ing two values of which at least one is negative results in a negative
672 // value.
673 max = std::min(max, -1.0);
674 }
675 return Type::Range(min, max, zone());
676 }
677
678 Type* OperationTyper::NumberBitwiseAnd(Type* lhs, Type* rhs) {
679 DCHECK(lhs->Is(Type::Number()));
680 DCHECK(rhs->Is(Type::Number()));
681
682 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
683
684 lhs = NumberToInt32(lhs);
685 rhs = NumberToInt32(rhs);
686
687 double lmin = lhs->Min();
688 double rmin = rhs->Min();
689 double lmax = lhs->Max();
690 double rmax = rhs->Max();
691 double min = kMinInt;
692 // And-ing any two values results in a value no larger than their maximum.
693 // Even no larger than their minimum if both values are non-negative.
694 double max =
695 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
696 // And-ing with a non-negative value x causes the result to be between
697 // zero and x.
698 if (lmin >= 0) {
699 min = 0;
700 max = std::min(max, lmax);
701 }
702 if (rmin >= 0) {
703 min = 0;
704 max = std::min(max, rmax);
705 }
706 return Type::Range(min, max, zone());
707 }
708
709 Type* OperationTyper::NumberBitwiseXor(Type* lhs, Type* rhs) {
710 DCHECK(lhs->Is(Type::Number()));
711 DCHECK(rhs->Is(Type::Number()));
712
713 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
714
715 lhs = NumberToInt32(lhs);
716 rhs = NumberToInt32(rhs);
717
718 double lmin = lhs->Min();
719 double rmin = rhs->Min();
720 double lmax = lhs->Max();
721 double rmax = rhs->Max();
722 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
723 // Xor-ing negative or non-negative values results in a non-negative value.
724 return Type::Unsigned31();
725 }
726 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
727 // Xor-ing a negative and a non-negative value results in a negative value.
728 // TODO(jarin) Use a range here.
729 return Type::Negative32();
730 }
731 return Type::Signed32();
732 }
733
734 Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) {
735 DCHECK(lhs->Is(Type::Number()));
736 DCHECK(rhs->Is(Type::Number()));
737
738 // TODO(turbofan): Infer a better type here.
739 return Type::Signed32();
740 }
741
742 Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
743 DCHECK(lhs->Is(Type::Number()));
744 DCHECK(rhs->Is(Type::Number()));
745
746 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
747
748 lhs = NumberToInt32(lhs);
749 rhs = NumberToUint32(rhs);
750
751 double min = kMinInt;
752 double max = kMaxInt;
753 if (lhs->Min() >= 0) {
754 // Right-shifting a non-negative value cannot make it negative, nor larger.
755 min = std::max(min, 0.0);
756 max = std::min(max, lhs->Max());
757 if (rhs->Min() > 0 && rhs->Max() <= 31) {
758 max = static_cast<int>(max) >> static_cast<int>(rhs->Min());
426 } 759 }
427 } 760 }
428 if (maybe_minuszero) { 761 if (lhs->Max() < 0) {
429 type = Type::Union(type, cache_.kSingletonZero, zone()); 762 // Right-shifting a negative value cannot make it non-negative, nor smaller.
430 } 763 min = std::max(min, lhs->Min());
431 if (maybe_nan) { 764 max = std::min(max, -1.0);
765 if (rhs->Min() > 0 && rhs->Max() <= 31) {
766 min = static_cast<int>(min) >> static_cast<int>(rhs->Min());
767 }
768 }
769 if (rhs->Min() > 0 && rhs->Max() <= 31) {
770 // Right-shifting by a positive value yields a small integer value.
771 double shift_min = kMinInt >> static_cast<int>(rhs->Min());
772 double shift_max = kMaxInt >> static_cast<int>(rhs->Min());
773 min = std::max(min, shift_min);
774 max = std::min(max, shift_max);
775 }
776 // TODO(jarin) Ideally, the following micro-optimization should be performed
777 // by the type constructor.
778 if (max == kMaxInt && min == kMinInt) return Type::Signed32();
779 return Type::Range(min, max, zone());
780 }
781
782 Type* OperationTyper::NumberShiftRightLogical(Type* lhs, Type* rhs) {
783 DCHECK(lhs->Is(Type::Number()));
784 DCHECK(rhs->Is(Type::Number()));
785
786 if (!lhs->IsInhabited()) return Type::None();
787
788 lhs = NumberToUint32(lhs);
789
790 // Logical right-shifting any value cannot make it larger.
791 return Type::Range(0.0, lhs->Max(), zone());
792 }
793
794 Type* OperationTyper::NumberAtan2(Type* lhs, Type* rhs) {
795 DCHECK(lhs->Is(Type::Number()));
796 DCHECK(rhs->Is(Type::Number()));
797 return Type::Number();
798 }
799
800 Type* OperationTyper::NumberImul(Type* lhs, Type* rhs) {
801 DCHECK(lhs->Is(Type::Number()));
802 DCHECK(rhs->Is(Type::Number()));
803 // TODO(turbofan): We should be able to do better here.
804 return Type::Signed32();
805 }
806
807 Type* OperationTyper::NumberMax(Type* lhs, Type* rhs) {
808 DCHECK(lhs->Is(Type::Number()));
809 DCHECK(rhs->Is(Type::Number()));
810 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) {
811 return Type::NaN();
812 }
813 Type* type = Type::None();
814 // TODO(turbofan): Improve minus zero handling here.
815 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
432 type = Type::Union(type, Type::NaN(), zone()); 816 type = Type::Union(type, Type::NaN(), zone());
433 } 817 }
818 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
819 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
820 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
821 double max = std::max(lhs->Max(), rhs->Max());
822 double min = std::max(lhs->Min(), rhs->Min());
823 type = Type::Union(type, Type::Range(min, max, zone()), zone());
824 } else {
825 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
826 }
434 return type; 827 return type;
435 } 828 }
436 829
830 Type* OperationTyper::NumberMin(Type* lhs, Type* rhs) {
831 DCHECK(lhs->Is(Type::Number()));
832 DCHECK(rhs->Is(Type::Number()));
833 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) {
834 return Type::NaN();
835 }
836 Type* type = Type::None();
837 // TODO(turbofan): Improve minus zero handling here.
838 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
839 type = Type::Union(type, Type::NaN(), zone());
840 }
841 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
842 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
843 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
844 double max = std::min(lhs->Max(), rhs->Max());
845 double min = std::min(lhs->Min(), rhs->Min());
846 type = Type::Union(type, Type::Range(min, max, zone()), zone());
847 } else {
848 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
849 }
850 return type;
851 }
852
853 Type* OperationTyper::NumberPow(Type* lhs, Type* rhs) {
854 DCHECK(lhs->Is(Type::Number()));
855 DCHECK(rhs->Is(Type::Number()));
856 // TODO(turbofan): We should be able to do better here.
857 return Type::Number();
858 }
859
860 #define SPECULATIVE_NUMBER_BINOP(Name) \
861 Type* OperationTyper::Speculative##Name(Type* lhs, Type* rhs) { \
862 lhs = ToNumber(Type::Intersect(lhs, Type::NumberOrOddball(), zone())); \
863 rhs = ToNumber(Type::Intersect(rhs, Type::NumberOrOddball(), zone())); \
864 return Name(lhs, rhs); \
865 }
866 SPECULATIVE_NUMBER_BINOP(NumberAdd)
867 SPECULATIVE_NUMBER_BINOP(NumberSubtract)
868 SPECULATIVE_NUMBER_BINOP(NumberMultiply)
869 SPECULATIVE_NUMBER_BINOP(NumberDivide)
870 SPECULATIVE_NUMBER_BINOP(NumberModulus)
871 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
872 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
873 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
874 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
875 SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
876 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
877 #undef SPECULATIVE_NUMBER_BINOP
878
437 Type* OperationTyper::ToPrimitive(Type* type) { 879 Type* OperationTyper::ToPrimitive(Type* type) {
438 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { 880 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
439 return type; 881 return type;
440 } 882 }
441 return Type::Primitive(); 883 return Type::Primitive();
442 } 884 }
443 885
444 Type* OperationTyper::Invert(Type* type) { 886 Type* OperationTyper::Invert(Type* type) {
445 DCHECK(type->Is(Type::Boolean())); 887 DCHECK(type->Is(Type::Boolean()));
446 DCHECK(type->IsInhabited()); 888 DCHECK(type->IsInhabited());
(...skipping 15 matching lines...) Expand all
462 if ((outcome & kComparisonFalse) != 0 || 904 if ((outcome & kComparisonFalse) != 0 ||
463 (outcome & kComparisonUndefined) != 0) { 905 (outcome & kComparisonUndefined) != 0) {
464 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() 906 return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
465 : singleton_false(); 907 : singleton_false();
466 } 908 }
467 // Type should be non empty, so we know it should be true. 909 // Type should be non empty, so we know it should be true.
468 DCHECK((outcome & kComparisonTrue) != 0); 910 DCHECK((outcome & kComparisonTrue) != 0);
469 return singleton_true(); 911 return singleton_true();
470 } 912 }
471 913
472 Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) {
473 lhs = ToPrimitive(lhs);
474 rhs = ToPrimitive(rhs);
475
476 if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
477 return Type::None();
478 }
479
480 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
481 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
482 return Type::String();
483 } else {
484 return Type::NumberOrString();
485 }
486 }
487 lhs = ToNumber(lhs);
488 rhs = ToNumber(rhs);
489 return NumberAdd(lhs, rhs);
490 }
491
492 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) {
493 return NumberSubtract(ToNumber(lhs), ToNumber(rhs));
494 }
495
496 } // namespace compiler 914 } // namespace compiler
497 } // namespace internal 915 } // namespace internal
498 } // namespace v8 916 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/operation-typer.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698