Chromium Code Reviews| 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 |