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/compiler/typer.h" | 5 #include "src/compiler/typer.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/base/flags.h" | 9 #include "src/base/flags.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 Typer::Typer(Isolate* isolate, Graph* graph) | 35 Typer::Typer(Isolate* isolate, Graph* graph) |
36 : isolate_(isolate), | 36 : isolate_(isolate), |
37 graph_(graph), | 37 graph_(graph), |
38 decorator_(nullptr), | 38 decorator_(nullptr), |
39 cache_(TypeCache::Get()), | 39 cache_(TypeCache::Get()), |
40 operation_typer_(isolate, zone()) { | 40 operation_typer_(isolate, zone()) { |
41 Zone* zone = this->zone(); | 41 Zone* zone = this->zone(); |
42 Factory* const factory = isolate->factory(); | 42 Factory* const factory = isolate->factory(); |
43 | 43 |
44 singleton_false_ = Type::Constant(factory->false_value(), zone); | 44 singleton_false_ = Type::HeapConstant(factory->false_value(), zone); |
45 singleton_true_ = Type::Constant(factory->true_value(), zone); | 45 singleton_true_ = Type::HeapConstant(factory->true_value(), zone); |
46 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); | 46 singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone); |
47 falsish_ = Type::Union( | 47 falsish_ = Type::Union( |
48 Type::Undetectable(), | 48 Type::Undetectable(), |
49 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone), | 49 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone), |
50 singleton_the_hole_, zone), | 50 singleton_the_hole_, zone), |
51 zone); | 51 zone); |
52 truish_ = Type::Union( | 52 truish_ = Type::Union( |
53 singleton_true_, | 53 singleton_true_, |
54 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone); | 54 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone); |
55 | 55 |
56 decorator_ = new (zone) Decorator(this); | 56 decorator_ = new (zone) Decorator(this); |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 } | 597 } |
598 | 598 |
599 | 599 |
600 Type* Typer::Visitor::TypeFloat64Constant(Node* node) { | 600 Type* Typer::Visitor::TypeFloat64Constant(Node* node) { |
601 UNREACHABLE(); | 601 UNREACHABLE(); |
602 return nullptr; | 602 return nullptr; |
603 } | 603 } |
604 | 604 |
605 | 605 |
606 Type* Typer::Visitor::TypeNumberConstant(Node* node) { | 606 Type* Typer::Visitor::TypeNumberConstant(Node* node) { |
607 Factory* f = isolate()->factory(); | |
608 double number = OpParameter<double>(node); | 607 double number = OpParameter<double>(node); |
609 if (Type::IsInteger(number)) { | 608 return Type::NewConstant(number, zone()); |
610 return Type::Range(number, number, zone()); | |
611 } | |
612 return Type::Constant(f->NewNumber(number), zone()); | |
613 } | 609 } |
614 | 610 |
615 | |
616 Type* Typer::Visitor::TypeHeapConstant(Node* node) { | 611 Type* Typer::Visitor::TypeHeapConstant(Node* node) { |
617 return TypeConstant(OpParameter<Handle<HeapObject>>(node)); | 612 return TypeConstant(OpParameter<Handle<HeapObject>>(node)); |
618 } | 613 } |
619 | 614 |
620 | 615 |
621 Type* Typer::Visitor::TypeExternalConstant(Node* node) { | 616 Type* Typer::Visitor::TypeExternalConstant(Node* node) { |
622 return Type::Internal(); | 617 return Type::Internal(); |
623 } | 618 } |
624 | 619 |
625 | 620 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 | 824 |
830 Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) { | 825 Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
831 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_; | 826 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_; |
832 if (lhs->Is(Type::NullOrUndefined()) && rhs->Is(Type::NullOrUndefined())) { | 827 if (lhs->Is(Type::NullOrUndefined()) && rhs->Is(Type::NullOrUndefined())) { |
833 return t->singleton_true_; | 828 return t->singleton_true_; |
834 } | 829 } |
835 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) && | 830 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) && |
836 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) { | 831 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) { |
837 return t->singleton_false_; | 832 return t->singleton_false_; |
838 } | 833 } |
839 if (lhs->IsConstant() && rhs->Is(lhs)) { | 834 if (lhs->IsHeapConstant() && rhs->Is(lhs)) { |
840 // Types are equal and are inhabited only by a single semantic value, | 835 // Types are equal and are inhabited only by a single semantic value, |
841 // which is not nan due to the earlier check. | 836 // which is not nan due to the earlier check. |
842 return t->singleton_true_; | 837 return t->singleton_true_; |
843 } | 838 } |
844 return Type::Boolean(); | 839 return Type::Boolean(); |
845 } | 840 } |
846 | 841 |
847 | 842 |
848 Type* Typer::Visitor::JSNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { | 843 Type* Typer::Visitor::JSNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
849 return Invert(JSEqualTyper(lhs, rhs, t), t); | 844 return Invert(JSEqualTyper(lhs, rhs, t), t); |
(...skipping 16 matching lines...) Expand all Loading... |
866 if (!JSType(lhs)->Maybe(JSType(rhs))) return t->singleton_false_; | 861 if (!JSType(lhs)->Maybe(JSType(rhs))) return t->singleton_false_; |
867 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_; | 862 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_; |
868 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) && | 863 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) && |
869 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) { | 864 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) { |
870 return t->singleton_false_; | 865 return t->singleton_false_; |
871 } | 866 } |
872 if ((lhs->Is(t->singleton_the_hole_) || rhs->Is(t->singleton_the_hole_)) && | 867 if ((lhs->Is(t->singleton_the_hole_) || rhs->Is(t->singleton_the_hole_)) && |
873 !lhs->Maybe(rhs)) { | 868 !lhs->Maybe(rhs)) { |
874 return t->singleton_false_; | 869 return t->singleton_false_; |
875 } | 870 } |
876 if (lhs->IsConstant() && rhs->Is(lhs)) { | 871 if (lhs->IsHeapConstant() && rhs->Is(lhs)) { |
877 // Types are equal and are inhabited only by a single semantic value, | 872 // Types are equal and are inhabited only by a single semantic value, |
878 // which is not nan due to the earlier check. | 873 // which is not nan due to the earlier check. |
879 return t->singleton_true_; | 874 return t->singleton_true_; |
880 } | 875 } |
881 return Type::Boolean(); | 876 return Type::Boolean(); |
882 } | 877 } |
883 | 878 |
884 | 879 |
885 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { | 880 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
886 return Invert(JSStrictEqualTyper(lhs, rhs, t), t); | 881 return Invert(JSStrictEqualTyper(lhs, rhs, t), t); |
(...skipping 13 matching lines...) Expand all Loading... |
900 return ComparisonOutcome(kComparisonTrue) | | 895 return ComparisonOutcome(kComparisonTrue) | |
901 ComparisonOutcome(kComparisonFalse); | 896 ComparisonOutcome(kComparisonFalse); |
902 } | 897 } |
903 lhs = ToNumber(lhs, t); | 898 lhs = ToNumber(lhs, t); |
904 rhs = ToNumber(rhs, t); | 899 rhs = ToNumber(rhs, t); |
905 | 900 |
906 // Shortcut for NaNs. | 901 // Shortcut for NaNs. |
907 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined; | 902 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined; |
908 | 903 |
909 ComparisonOutcome result; | 904 ComparisonOutcome result; |
910 if (lhs->IsConstant() && rhs->Is(lhs)) { | 905 if (lhs->IsHeapConstant() && rhs->Is(lhs)) { |
911 // Types are equal and are inhabited only by a single semantic value. | 906 // Types are equal and are inhabited only by a single semantic value. |
912 result = kComparisonFalse; | 907 result = kComparisonFalse; |
913 } else if (lhs->Min() >= rhs->Max()) { | 908 } else if (lhs->Min() >= rhs->Max()) { |
914 result = kComparisonFalse; | 909 result = kComparisonFalse; |
915 } else if (lhs->Max() < rhs->Min()) { | 910 } else if (lhs->Max() < rhs->Min()) { |
916 result = kComparisonTrue; | 911 result = kComparisonTrue; |
917 } else { | 912 } else { |
918 // We cannot figure out the result, return both true and false. (We do not | 913 // We cannot figure out the result, return both true and false. (We do not |
919 // have to return undefined because that cannot affect the result of | 914 // have to return undefined because that cannot affect the result of |
920 // FalsifyUndefined.) | 915 // FalsifyUndefined.) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 return NumberModulus(ToNumber(lhs, t), ToNumber(rhs, t), t); | 1009 return NumberModulus(ToNumber(lhs, t), ToNumber(rhs, t), t); |
1015 } | 1010 } |
1016 | 1011 |
1017 | 1012 |
1018 // JS unary operators. | 1013 // JS unary operators. |
1019 | 1014 |
1020 | 1015 |
1021 Type* Typer::Visitor::JSTypeOfTyper(Type* type, Typer* t) { | 1016 Type* Typer::Visitor::JSTypeOfTyper(Type* type, Typer* t) { |
1022 Factory* const f = t->isolate()->factory(); | 1017 Factory* const f = t->isolate()->factory(); |
1023 if (type->Is(Type::Boolean())) { | 1018 if (type->Is(Type::Boolean())) { |
1024 return Type::Constant(f->boolean_string(), t->zone()); | 1019 return Type::HeapConstant(f->boolean_string(), t->zone()); |
1025 } else if (type->Is(Type::Number())) { | 1020 } else if (type->Is(Type::Number())) { |
1026 return Type::Constant(f->number_string(), t->zone()); | 1021 return Type::HeapConstant(f->number_string(), t->zone()); |
1027 } else if (type->Is(Type::String())) { | 1022 } else if (type->Is(Type::String())) { |
1028 return Type::Constant(f->string_string(), t->zone()); | 1023 return Type::HeapConstant(f->string_string(), t->zone()); |
1029 } else if (type->Is(Type::Symbol())) { | 1024 } else if (type->Is(Type::Symbol())) { |
1030 return Type::Constant(f->symbol_string(), t->zone()); | 1025 return Type::HeapConstant(f->symbol_string(), t->zone()); |
1031 } else if (type->Is(Type::Union(Type::Undefined(), Type::OtherUndetectable(), | 1026 } else if (type->Is(Type::Union(Type::Undefined(), Type::OtherUndetectable(), |
1032 t->zone()))) { | 1027 t->zone()))) { |
1033 return Type::Constant(f->undefined_string(), t->zone()); | 1028 return Type::HeapConstant(f->undefined_string(), t->zone()); |
1034 } else if (type->Is(Type::Null())) { | 1029 } else if (type->Is(Type::Null())) { |
1035 return Type::Constant(f->object_string(), t->zone()); | 1030 return Type::HeapConstant(f->object_string(), t->zone()); |
1036 } else if (type->Is(Type::Function())) { | 1031 } else if (type->Is(Type::Function())) { |
1037 return Type::Constant(f->function_string(), t->zone()); | 1032 return Type::HeapConstant(f->function_string(), t->zone()); |
1038 } else if (type->IsConstant()) { | 1033 } else if (type->IsHeapConstant()) { |
1039 return Type::Constant( | 1034 return Type::HeapConstant( |
1040 Object::TypeOf(t->isolate(), type->AsConstant()->Value()), t->zone()); | 1035 Object::TypeOf(t->isolate(), type->AsHeapConstant()->Value()), |
| 1036 t->zone()); |
| 1037 } else if (type->IsOtherNumberConstant()) { |
| 1038 return Type::HeapConstant(f->number_string(), t->zone()); |
1041 } | 1039 } |
1042 return Type::InternalizedString(); | 1040 return Type::InternalizedString(); |
1043 } | 1041 } |
1044 | 1042 |
1045 | 1043 |
1046 Type* Typer::Visitor::TypeJSTypeOf(Node* node) { | 1044 Type* Typer::Visitor::TypeJSTypeOf(Node* node) { |
1047 return TypeUnaryOp(node, JSTypeOfTyper); | 1045 return TypeUnaryOp(node, JSTypeOfTyper); |
1048 } | 1046 } |
1049 | 1047 |
1050 | 1048 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 | 1283 |
1286 // JS other operators. | 1284 // JS other operators. |
1287 | 1285 |
1288 | 1286 |
1289 Type* Typer::Visitor::TypeJSCallConstruct(Node* node) { | 1287 Type* Typer::Visitor::TypeJSCallConstruct(Node* node) { |
1290 return Type::Receiver(); | 1288 return Type::Receiver(); |
1291 } | 1289 } |
1292 | 1290 |
1293 | 1291 |
1294 Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) { | 1292 Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) { |
1295 if (fun->IsConstant() && fun->AsConstant()->Value()->IsJSFunction()) { | 1293 if (fun->IsHeapConstant() && fun->AsHeapConstant()->Value()->IsJSFunction()) { |
1296 Handle<JSFunction> function = | 1294 Handle<JSFunction> function = |
1297 Handle<JSFunction>::cast(fun->AsConstant()->Value()); | 1295 Handle<JSFunction>::cast(fun->AsHeapConstant()->Value()); |
1298 if (function->shared()->HasBuiltinFunctionId()) { | 1296 if (function->shared()->HasBuiltinFunctionId()) { |
1299 switch (function->shared()->builtin_function_id()) { | 1297 switch (function->shared()->builtin_function_id()) { |
1300 case kMathRandom: | 1298 case kMathRandom: |
1301 return Type::PlainNumber(); | 1299 return Type::PlainNumber(); |
1302 case kMathFloor: | 1300 case kMathFloor: |
1303 case kMathCeil: | 1301 case kMathCeil: |
1304 case kMathRound: | 1302 case kMathRound: |
1305 case kMathTrunc: | 1303 case kMathTrunc: |
1306 return t->cache_.kIntegerOrMinusZeroOrNaN; | 1304 return t->cache_.kIntegerOrMinusZeroOrNaN; |
1307 // Unary math functions. | 1305 // Unary math functions. |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1530 Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) { | 1528 Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) { |
1531 return Type::Integral32(); | 1529 return Type::Integral32(); |
1532 } | 1530 } |
1533 | 1531 |
1534 Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) { | 1532 Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) { |
1535 return Type::Number(); | 1533 return Type::Number(); |
1536 } | 1534 } |
1537 | 1535 |
1538 // static | 1536 // static |
1539 Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) { | 1537 Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) { |
1540 if (lhs->IsConstant() && rhs->Is(lhs)) { | 1538 if (lhs->IsHeapConstant() && rhs->Is(lhs)) { |
1541 return t->singleton_true_; | 1539 return t->singleton_true_; |
1542 } | 1540 } |
1543 return Type::Boolean(); | 1541 return Type::Boolean(); |
1544 } | 1542 } |
1545 | 1543 |
1546 | 1544 |
1547 Type* Typer::Visitor::TypeReferenceEqual(Node* node) { | 1545 Type* Typer::Visitor::TypeReferenceEqual(Node* node) { |
1548 return TypeBinaryOp(node, ReferenceEqualTyper); | 1546 return TypeBinaryOp(node, ReferenceEqualTyper); |
1549 } | 1547 } |
1550 | 1548 |
1551 Type* Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); } | 1549 Type* Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); } |
1552 | 1550 |
1553 Type* Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); } | 1551 Type* Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); } |
1554 | 1552 |
1555 Type* Typer::Visitor::TypeStringLessThanOrEqual(Node* node) { | 1553 Type* Typer::Visitor::TypeStringLessThanOrEqual(Node* node) { |
1556 return Type::Boolean(); | 1554 return Type::Boolean(); |
1557 } | 1555 } |
1558 | 1556 |
1559 Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) { | 1557 Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) { |
1560 type = NumberToUint32(ToNumber(type, t), t); | 1558 type = NumberToUint32(ToNumber(type, t), t); |
1561 Factory* f = t->isolate()->factory(); | 1559 Factory* f = t->isolate()->factory(); |
1562 double min = type->Min(); | 1560 double min = type->Min(); |
1563 double max = type->Max(); | 1561 double max = type->Max(); |
1564 if (min == max) { | 1562 if (min == max) { |
1565 uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU; | 1563 uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU; |
1566 Handle<String> string = f->LookupSingleCharacterStringFromCode(code); | 1564 Handle<String> string = f->LookupSingleCharacterStringFromCode(code); |
1567 return Type::Constant(string, t->zone()); | 1565 return Type::HeapConstant(string, t->zone()); |
1568 } | 1566 } |
1569 return Type::String(); | 1567 return Type::String(); |
1570 } | 1568 } |
1571 | 1569 |
1572 Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) { | 1570 Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) { |
1573 type = NumberToUint32(ToNumber(type, t), t); | 1571 type = NumberToUint32(ToNumber(type, t), t); |
1574 Factory* f = t->isolate()->factory(); | 1572 Factory* f = t->isolate()->factory(); |
1575 double min = type->Min(); | 1573 double min = type->Min(); |
1576 double max = type->Max(); | 1574 double max = type->Max(); |
1577 if (min == max) { | 1575 if (min == max) { |
1578 uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU; | 1576 uint32_t code = static_cast<uint32_t>(min) & String::kMaxUtf16CodeUnitU; |
1579 Handle<String> string = f->LookupSingleCharacterStringFromCode(code); | 1577 Handle<String> string = f->LookupSingleCharacterStringFromCode(code); |
1580 return Type::Constant(string, t->zone()); | 1578 return Type::HeapConstant(string, t->zone()); |
1581 } | 1579 } |
1582 return Type::String(); | 1580 return Type::String(); |
1583 } | 1581 } |
1584 | 1582 |
1585 Type* Typer::Visitor::TypeStringCharCodeAt(Node* node) { | 1583 Type* Typer::Visitor::TypeStringCharCodeAt(Node* node) { |
1586 // TODO(bmeurer): We could do better here based on inputs. | 1584 // TODO(bmeurer): We could do better here based on inputs. |
1587 return Type::Range(0, kMaxUInt16, zone()); | 1585 return Type::Range(0, kMaxUInt16, zone()); |
1588 } | 1586 } |
1589 | 1587 |
1590 Type* Typer::Visitor::TypeStringFromCharCode(Node* node) { | 1588 Type* Typer::Visitor::TypeStringFromCharCode(Node* node) { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1745 Type* Typer::Visitor::TypeArrayBufferWasNeutered(Node* node) { | 1743 Type* Typer::Visitor::TypeArrayBufferWasNeutered(Node* node) { |
1746 return Type::Boolean(); | 1744 return Type::Boolean(); |
1747 } | 1745 } |
1748 | 1746 |
1749 // Heap constants. | 1747 // Heap constants. |
1750 | 1748 |
1751 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { | 1749 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { |
1752 if (Type::IsInteger(*value)) { | 1750 if (Type::IsInteger(*value)) { |
1753 return Type::Range(value->Number(), value->Number(), zone()); | 1751 return Type::Range(value->Number(), value->Number(), zone()); |
1754 } | 1752 } |
1755 return Type::Constant(value, zone()); | 1753 return Type::NewConstant(value, zone()); |
1756 } | 1754 } |
1757 | 1755 |
1758 } // namespace compiler | 1756 } // namespace compiler |
1759 } // namespace internal | 1757 } // namespace internal |
1760 } // namespace v8 | 1758 } // namespace v8 |
OLD | NEW |