OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/base/flags.h" | |
5 #include "src/bootstrapper.h" | 6 #include "src/bootstrapper.h" |
6 #include "src/compiler/graph-reducer.h" | 7 #include "src/compiler/graph-reducer.h" |
7 #include "src/compiler/js-operator.h" | 8 #include "src/compiler/js-operator.h" |
8 #include "src/compiler/node.h" | 9 #include "src/compiler/node.h" |
9 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
10 #include "src/compiler/simplified-operator.h" | 11 #include "src/compiler/simplified-operator.h" |
11 #include "src/compiler/typer.h" | 12 #include "src/compiler/typer.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 Isolate* isolate() { return typer_->isolate(); } | 319 Isolate* isolate() { return typer_->isolate(); } |
319 Graph* graph() { return typer_->graph(); } | 320 Graph* graph() { return typer_->graph(); } |
320 MaybeHandle<Context> context() { return typer_->context(); } | 321 MaybeHandle<Context> context() { return typer_->context(); } |
321 | 322 |
322 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); | 323 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); |
323 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); | 324 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); |
324 | 325 |
325 Bounds TypeUnaryOp(Node* node, UnaryTyperFun); | 326 Bounds TypeUnaryOp(Node* node, UnaryTyperFun); |
326 Bounds TypeBinaryOp(Node* node, BinaryTyperFun); | 327 Bounds TypeBinaryOp(Node* node, BinaryTyperFun); |
327 | 328 |
329 enum ComparisonOutcomeFlags { | |
330 kComparisonTrue = 1, | |
331 kComparisonFalse = 2, | |
332 kComparisonUndefined = 4 | |
333 }; | |
334 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; | |
Benedikt Meurer
2015/02/19 10:32:57
You should also DEFINE_OPERATOR_FOR_FLAGS here.
Jarin
2015/02/19 10:50:21
Unfortunately, the macro does not work with privat
| |
335 | |
336 static ComparisonOutcome Invert(ComparisonOutcome, Typer*); | |
328 static Type* Invert(Type*, Typer*); | 337 static Type* Invert(Type*, Typer*); |
329 static Type* FalsifyUndefined(Type*, Typer*); | 338 static Type* FalsifyUndefined(ComparisonOutcome, Typer*); |
330 static Type* Rangify(Type*, Typer*); | 339 static Type* Rangify(Type*, Typer*); |
331 | 340 |
332 static Type* ToPrimitive(Type*, Typer*); | 341 static Type* ToPrimitive(Type*, Typer*); |
333 static Type* ToBoolean(Type*, Typer*); | 342 static Type* ToBoolean(Type*, Typer*); |
334 static Type* ToNumber(Type*, Typer*); | 343 static Type* ToNumber(Type*, Typer*); |
335 static Type* ToString(Type*, Typer*); | 344 static Type* ToString(Type*, Typer*); |
336 static Type* NumberToInt32(Type*, Typer*); | 345 static Type* NumberToInt32(Type*, Typer*); |
337 static Type* NumberToUint32(Type*, Typer*); | 346 static Type* NumberToUint32(Type*, Typer*); |
338 | 347 |
339 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); | 348 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); |
340 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); | 349 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); |
341 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*); | 350 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*); |
342 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*); | 351 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*); |
343 static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*); | 352 static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*); |
344 | 353 |
345 static Type* JSCompareTyper(Type*, Type*, Typer*); | 354 static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*); |
346 | 355 |
347 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); | 356 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); |
348 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) | 357 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) |
349 #undef DECLARE_METHOD | 358 #undef DECLARE_METHOD |
350 | 359 |
351 static Type* JSUnaryNotTyper(Type*, Typer*); | 360 static Type* JSUnaryNotTyper(Type*, Typer*); |
352 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); | 361 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); |
353 static Type* JSCallFunctionTyper(Type*, Typer*); | 362 static Type* JSCallFunctionTyper(Type*, Typer*); |
354 | 363 |
355 Reduction UpdateBounds(Node* node, Bounds current) { | 364 Reduction UpdateBounds(Node* node, Bounds current) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 upper->IsConstant()) | 470 upper->IsConstant()) |
462 ? upper | 471 ? upper |
463 : f(left.lower, right.lower, typer_)) | 472 : f(left.lower, right.lower, typer_)) |
464 : Type::None(); | 473 : Type::None(); |
465 // TODO(neis): Figure out what to do with lower bound. | 474 // TODO(neis): Figure out what to do with lower bound. |
466 return Bounds(lower, upper); | 475 return Bounds(lower, upper); |
467 } | 476 } |
468 | 477 |
469 | 478 |
470 Type* Typer::Visitor::Invert(Type* type, Typer* t) { | 479 Type* Typer::Visitor::Invert(Type* type, Typer* t) { |
480 DCHECK(type->Is(Type::Boolean())); | |
481 DCHECK(type->IsInhabited()); | |
471 if (type->Is(t->singleton_false)) return t->singleton_true; | 482 if (type->Is(t->singleton_false)) return t->singleton_true; |
472 if (type->Is(t->singleton_true)) return t->singleton_false; | 483 if (type->Is(t->singleton_true)) return t->singleton_false; |
473 return type; | 484 return type; |
474 } | 485 } |
475 | 486 |
476 | 487 |
477 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) { | 488 Typer::Visitor::ComparisonOutcome Typer::Visitor::Invert( |
478 if (type->Is(Type::Undefined())) return t->singleton_false; | 489 ComparisonOutcome outcome, Typer* t) { |
479 return type; | 490 ComparisonOutcome result(0); |
491 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined; | |
492 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse; | |
493 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue; | |
494 return result; | |
480 } | 495 } |
481 | 496 |
482 | 497 |
498 Type* Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer* t) { | |
499 if ((outcome & kComparisonFalse) != 0 || | |
500 (outcome & kComparisonUndefined) != 0) { | |
501 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() | |
502 : t->singleton_false; | |
503 } | |
504 // Type should be non empty, so we know it should be true. | |
505 DCHECK((outcome & kComparisonTrue) != 0); | |
506 return t->singleton_true; | |
507 } | |
508 | |
509 | |
483 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { | 510 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { |
484 if (type->IsRange()) return type; // Shortcut. | 511 if (type->IsRange()) return type; // Shortcut. |
485 if (!type->Is(t->integer) && !type->Is(Type::Integral32())) { | 512 if (!type->Is(t->integer) && !type->Is(Type::Integral32())) { |
486 return type; // Give up on non-integer types. | 513 return type; // Give up on non-integer types. |
487 } | 514 } |
488 double min = type->Min(); | 515 double min = type->Min(); |
489 double max = type->Max(); | 516 double max = type->Max(); |
490 // Handle the degenerate case of empty bitset types (such as | 517 // Handle the degenerate case of empty bitset types (such as |
491 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). | 518 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). |
492 if (std::isnan(min)) { | 519 if (std::isnan(min)) { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
766 | 793 |
767 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { | 794 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
768 return Invert(JSStrictEqualTyper(lhs, rhs, t), t); | 795 return Invert(JSStrictEqualTyper(lhs, rhs, t), t); |
769 } | 796 } |
770 | 797 |
771 | 798 |
772 // The EcmaScript specification defines the four relational comparison operators | 799 // The EcmaScript specification defines the four relational comparison operators |
773 // (<, <=, >=, >) with the help of a single abstract one. It behaves like < | 800 // (<, <=, >=, >) with the help of a single abstract one. It behaves like < |
774 // but returns undefined when the inputs cannot be compared. | 801 // but returns undefined when the inputs cannot be compared. |
775 // We implement the typing analogously. | 802 // We implement the typing analogously. |
776 Type* Typer::Visitor::JSCompareTyper(Type* lhs, Type* rhs, Typer* t) { | 803 Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs, |
804 Type* rhs, | |
805 Typer* t) { | |
777 lhs = ToPrimitive(lhs, t); | 806 lhs = ToPrimitive(lhs, t); |
778 rhs = ToPrimitive(rhs, t); | 807 rhs = ToPrimitive(rhs, t); |
779 if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) { | 808 if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) { |
780 return Type::Boolean(); | 809 return ComparisonOutcome(kComparisonTrue) | |
810 ComparisonOutcome(kComparisonFalse); | |
781 } | 811 } |
782 lhs = ToNumber(lhs, t); | 812 lhs = ToNumber(lhs, t); |
783 rhs = ToNumber(rhs, t); | 813 rhs = ToNumber(rhs, t); |
784 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::Undefined(); | 814 |
815 // Shortcut for NaNs. | |
816 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined; | |
817 | |
818 ComparisonOutcome result; | |
785 if (lhs->IsConstant() && rhs->Is(lhs)) { | 819 if (lhs->IsConstant() && rhs->Is(lhs)) { |
786 // Types are equal and are inhabited only by a single semantic value, | 820 // Types are equal and are inhabited only by a single semantic value. |
787 // which is not NaN due to the previous check. | 821 result = kComparisonFalse; |
788 return t->singleton_false; | 822 } else if (lhs->Min() >= rhs->Max()) { |
823 result = kComparisonFalse; | |
824 } else if (lhs->Max() < rhs->Min()) { | |
825 result = kComparisonTrue; | |
826 } else { | |
827 // We cannot figure out the result, return both true and false. (We do not | |
828 // have to return undefined because that cannot affect the result of | |
829 // FalsifyUndefined.) | |
830 return ComparisonOutcome(kComparisonTrue) | | |
831 ComparisonOutcome(kComparisonFalse); | |
789 } | 832 } |
790 if (lhs->Min() >= rhs->Max()) return t->singleton_false; | 833 // Add the undefined if we could see NaN. |
791 if (lhs->Max() < rhs->Min() && | 834 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
792 !lhs->Maybe(Type::NaN()) && !rhs->Maybe(Type::NaN())) { | 835 result |= kComparisonUndefined; |
793 return t->singleton_true; | |
794 } | 836 } |
795 return Type::Boolean(); | 837 return result; |
796 } | 838 } |
797 | 839 |
798 | 840 |
799 Type* Typer::Visitor::JSLessThanTyper(Type* lhs, Type* rhs, Typer* t) { | 841 Type* Typer::Visitor::JSLessThanTyper(Type* lhs, Type* rhs, Typer* t) { |
800 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t); | 842 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t); |
801 } | 843 } |
802 | 844 |
803 | 845 |
804 Type* Typer::Visitor::JSGreaterThanTyper(Type* lhs, Type* rhs, Typer* t) { | 846 Type* Typer::Visitor::JSGreaterThanTyper(Type* lhs, Type* rhs, Typer* t) { |
805 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t); | 847 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t); |
(...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2137 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 2179 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
2138 #undef TYPED_ARRAY_CASE | 2180 #undef TYPED_ARRAY_CASE |
2139 } | 2181 } |
2140 } | 2182 } |
2141 return Type::Constant(value, zone()); | 2183 return Type::Constant(value, zone()); |
2142 } | 2184 } |
2143 | 2185 |
2144 } // namespace compiler | 2186 } // namespace compiler |
2145 } // namespace internal | 2187 } // namespace internal |
2146 } // namespace v8 | 2188 } // namespace v8 |
OLD | NEW |