| 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 "src/base/flags.h" | 7 #include "src/base/flags.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
| 11 #include "src/compiler/graph-reducer.h" | 11 #include "src/compiler/graph-reducer.h" |
| 12 #include "src/compiler/js-operator.h" | 12 #include "src/compiler/js-operator.h" |
| 13 #include "src/compiler/node-properties.h" |
| 13 #include "src/compiler/node.h" | 14 #include "src/compiler/node.h" |
| 14 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/operation-typer.h" |
| 15 #include "src/compiler/simplified-operator.h" | 16 #include "src/compiler/simplified-operator.h" |
| 16 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
| 17 #include "src/type-cache.h" | 18 #include "src/type-cache.h" |
| 18 | 19 |
| 19 namespace v8 { | 20 namespace v8 { |
| 20 namespace internal { | 21 namespace internal { |
| 21 namespace compiler { | 22 namespace compiler { |
| 22 | 23 |
| 23 class Typer::Decorator final : public GraphDecorator { | 24 class Typer::Decorator final : public GraphDecorator { |
| 24 public: | 25 public: |
| 25 explicit Decorator(Typer* typer) : typer_(typer) {} | 26 explicit Decorator(Typer* typer) : typer_(typer) {} |
| 26 void Decorate(Node* node) final; | 27 void Decorate(Node* node) final; |
| 27 | 28 |
| 28 private: | 29 private: |
| 29 Typer* const typer_; | 30 Typer* const typer_; |
| 30 }; | 31 }; |
| 31 | 32 |
| 32 Typer::Typer(Isolate* isolate, Graph* graph, Flags flags, | 33 Typer::Typer(Isolate* isolate, Graph* graph, Flags flags, |
| 33 CompilationDependencies* dependencies, FunctionType* function_type) | 34 CompilationDependencies* dependencies, FunctionType* function_type) |
| 34 : isolate_(isolate), | 35 : isolate_(isolate), |
| 35 graph_(graph), | 36 graph_(graph), |
| 36 flags_(flags), | 37 flags_(flags), |
| 37 dependencies_(dependencies), | 38 dependencies_(dependencies), |
| 38 function_type_(function_type), | 39 function_type_(function_type), |
| 39 decorator_(nullptr), | 40 decorator_(nullptr), |
| 40 cache_(TypeCache::Get()) { | 41 cache_(TypeCache::Get()), |
| 42 operation_typer_(isolate, zone()) { |
| 41 Zone* zone = this->zone(); | 43 Zone* zone = this->zone(); |
| 42 Factory* const factory = isolate->factory(); | 44 Factory* const factory = isolate->factory(); |
| 43 | 45 |
| 44 Type* infinity = Type::Constant(factory->infinity_value(), zone); | 46 Type* infinity = Type::Constant(factory->infinity_value(), zone); |
| 45 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); | 47 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); |
| 46 // Unfortunately, the infinities created in other places might be different | 48 // Unfortunately, the infinities created in other places might be different |
| 47 // ones (eg the result of NewNumber in TypeNumberConstant). | 49 // ones (eg the result of NewNumber in TypeNumberConstant). |
| 48 Type* truncating_to_zero = | 50 Type* truncating_to_zero = |
| 49 Type::Union(Type::Union(infinity, minus_infinity, zone), | 51 Type::Union(Type::Union(infinity, minus_infinity, zone), |
| 50 Type::MinusZeroOrNaN(), zone); | 52 Type::MinusZeroOrNaN(), zone); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 enum ComparisonOutcomeFlags { | 227 enum ComparisonOutcomeFlags { |
| 226 kComparisonTrue = 1, | 228 kComparisonTrue = 1, |
| 227 kComparisonFalse = 2, | 229 kComparisonFalse = 2, |
| 228 kComparisonUndefined = 4 | 230 kComparisonUndefined = 4 |
| 229 }; | 231 }; |
| 230 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; | 232 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome; |
| 231 | 233 |
| 232 static ComparisonOutcome Invert(ComparisonOutcome, Typer*); | 234 static ComparisonOutcome Invert(ComparisonOutcome, Typer*); |
| 233 static Type* Invert(Type*, Typer*); | 235 static Type* Invert(Type*, Typer*); |
| 234 static Type* FalsifyUndefined(ComparisonOutcome, Typer*); | 236 static Type* FalsifyUndefined(ComparisonOutcome, Typer*); |
| 235 static Type* Rangify(Type*, Typer*); | |
| 236 | 237 |
| 237 static Type* ToPrimitive(Type*, Typer*); | 238 static Type* ToPrimitive(Type*, Typer*); |
| 238 static Type* ToBoolean(Type*, Typer*); | 239 static Type* ToBoolean(Type*, Typer*); |
| 239 static Type* ToInteger(Type*, Typer*); | 240 static Type* ToInteger(Type*, Typer*); |
| 240 static Type* ToLength(Type*, Typer*); | 241 static Type* ToLength(Type*, Typer*); |
| 241 static Type* ToName(Type*, Typer*); | 242 static Type* ToName(Type*, Typer*); |
| 242 static Type* ToNumber(Type*, Typer*); | 243 static Type* ToNumber(Type*, Typer*); |
| 243 static Type* ToObject(Type*, Typer*); | 244 static Type* ToObject(Type*, Typer*); |
| 244 static Type* ToString(Type*, Typer*); | 245 static Type* ToString(Type*, Typer*); |
| 245 static Type* NumberCeil(Type*, Typer*); | 246 static Type* NumberCeil(Type*, Typer*); |
| 246 static Type* NumberFloor(Type*, Typer*); | 247 static Type* NumberFloor(Type*, Typer*); |
| 247 static Type* NumberRound(Type*, Typer*); | 248 static Type* NumberRound(Type*, Typer*); |
| 248 static Type* NumberTrunc(Type*, Typer*); | 249 static Type* NumberTrunc(Type*, Typer*); |
| 249 static Type* NumberToInt32(Type*, Typer*); | 250 static Type* NumberToInt32(Type*, Typer*); |
| 250 static Type* NumberToUint32(Type*, Typer*); | 251 static Type* NumberToUint32(Type*, Typer*); |
| 251 | 252 |
| 252 static Type* ObjectIsCallable(Type*, Typer*); | 253 static Type* ObjectIsCallable(Type*, Typer*); |
| 253 static Type* ObjectIsNumber(Type*, Typer*); | 254 static Type* ObjectIsNumber(Type*, Typer*); |
| 254 static Type* ObjectIsReceiver(Type*, Typer*); | 255 static Type* ObjectIsReceiver(Type*, Typer*); |
| 255 static Type* ObjectIsSmi(Type*, Typer*); | 256 static Type* ObjectIsSmi(Type*, Typer*); |
| 256 static Type* ObjectIsString(Type*, Typer*); | 257 static Type* ObjectIsString(Type*, Typer*); |
| 257 static Type* ObjectIsUndetectable(Type*, Typer*); | 258 static Type* ObjectIsUndetectable(Type*, Typer*); |
| 258 | 259 |
| 259 static Type* JSAddRanger(double lhs_min, double lhs_max, double rhs_min, | |
| 260 double rhs_max, Typer* t); | |
| 261 static Type* JSSubtractRanger(RangeType*, RangeType*, Typer*); | |
| 262 static Type* JSDivideRanger(RangeType*, RangeType*, Typer*); | |
| 263 static Type* JSModulusRanger(RangeType*, RangeType*, Typer*); | |
| 264 | |
| 265 static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*); | 260 static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*); |
| 266 | 261 |
| 267 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); | 262 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*); |
| 268 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) | 263 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD) |
| 269 #undef DECLARE_METHOD | 264 #undef DECLARE_METHOD |
| 270 | 265 |
| 271 static Type* JSTypeOfTyper(Type*, Typer*); | 266 static Type* JSTypeOfTyper(Type*, Typer*); |
| 272 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); | 267 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*); |
| 273 static Type* JSCallFunctionTyper(Type*, Typer*); | 268 static Type* JSCallFunctionTyper(Type*, Typer*); |
| 274 | 269 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 if ((outcome & kComparisonFalse) != 0 || | 370 if ((outcome & kComparisonFalse) != 0 || |
| 376 (outcome & kComparisonUndefined) != 0) { | 371 (outcome & kComparisonUndefined) != 0) { |
| 377 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() | 372 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() |
| 378 : t->singleton_false_; | 373 : t->singleton_false_; |
| 379 } | 374 } |
| 380 // Type should be non empty, so we know it should be true. | 375 // Type should be non empty, so we know it should be true. |
| 381 DCHECK((outcome & kComparisonTrue) != 0); | 376 DCHECK((outcome & kComparisonTrue) != 0); |
| 382 return t->singleton_true_; | 377 return t->singleton_true_; |
| 383 } | 378 } |
| 384 | 379 |
| 385 | |
| 386 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { | |
| 387 if (type->IsRange()) return type; // Shortcut. | |
| 388 if (!type->Is(t->cache_.kInteger)) { | |
| 389 return type; // Give up on non-integer types. | |
| 390 } | |
| 391 double min = type->Min(); | |
| 392 double max = type->Max(); | |
| 393 // Handle the degenerate case of empty bitset types (such as | |
| 394 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures). | |
| 395 if (std::isnan(min)) { | |
| 396 DCHECK(std::isnan(max)); | |
| 397 return type; | |
| 398 } | |
| 399 return Type::Range(min, max, t->zone()); | |
| 400 } | |
| 401 | |
| 402 | |
| 403 // Type conversion. | 380 // Type conversion. |
| 404 | 381 |
| 405 | |
| 406 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) { | 382 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) { |
| 407 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { | 383 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
| 408 return type; | 384 return type; |
| 409 } | 385 } |
| 410 return Type::Primitive(); | 386 return Type::Primitive(); |
| 411 } | 387 } |
| 412 | 388 |
| 413 | 389 |
| 414 Type* Typer::Visitor::ToBoolean(Type* type, Typer* t) { | 390 Type* Typer::Visitor::ToBoolean(Type* type, Typer* t) { |
| 415 if (type->Is(Type::Boolean())) return type; | 391 if (type->Is(Type::Boolean())) return type; |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 | 975 |
| 1000 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) { | 976 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1001 lhs = NumberToUint32(ToNumber(lhs, t), t); | 977 lhs = NumberToUint32(ToNumber(lhs, t), t); |
| 1002 // Logical right-shifting any value cannot make it larger. | 978 // Logical right-shifting any value cannot make it larger. |
| 1003 return Type::Range(0.0, lhs->Max(), t->zone()); | 979 return Type::Range(0.0, lhs->Max(), t->zone()); |
| 1004 } | 980 } |
| 1005 | 981 |
| 1006 | 982 |
| 1007 // JS arithmetic operators. | 983 // JS arithmetic operators. |
| 1008 | 984 |
| 1009 | |
| 1010 // Returns the array's least element, ignoring NaN. | |
| 1011 // There must be at least one non-NaN element. | |
| 1012 // Any -0 is converted to 0. | |
| 1013 static double array_min(double a[], size_t n) { | |
| 1014 DCHECK(n != 0); | |
| 1015 double x = +V8_INFINITY; | |
| 1016 for (size_t i = 0; i < n; ++i) { | |
| 1017 if (!std::isnan(a[i])) { | |
| 1018 x = std::min(a[i], x); | |
| 1019 } | |
| 1020 } | |
| 1021 DCHECK(!std::isnan(x)); | |
| 1022 return x == 0 ? 0 : x; // -0 -> 0 | |
| 1023 } | |
| 1024 | |
| 1025 | |
| 1026 // Returns the array's greatest element, ignoring NaN. | |
| 1027 // There must be at least one non-NaN element. | |
| 1028 // Any -0 is converted to 0. | |
| 1029 static double array_max(double a[], size_t n) { | |
| 1030 DCHECK(n != 0); | |
| 1031 double x = -V8_INFINITY; | |
| 1032 for (size_t i = 0; i < n; ++i) { | |
| 1033 if (!std::isnan(a[i])) { | |
| 1034 x = std::max(a[i], x); | |
| 1035 } | |
| 1036 } | |
| 1037 DCHECK(!std::isnan(x)); | |
| 1038 return x == 0 ? 0 : x; // -0 -> 0 | |
| 1039 } | |
| 1040 | |
| 1041 Type* Typer::Visitor::JSAddRanger(double lhs_min, double lhs_max, | |
| 1042 double rhs_min, double rhs_max, Typer* t) { | |
| 1043 double results[4]; | |
| 1044 results[0] = lhs_min + rhs_min; | |
| 1045 results[1] = lhs_min + rhs_max; | |
| 1046 results[2] = lhs_max + rhs_min; | |
| 1047 results[3] = lhs_max + rhs_max; | |
| 1048 // The results can be nan (the sum of two infinities of opposite sign). | |
| 1049 // On the other hand, if none of the "results" above is nan, then the actual | |
| 1050 // result cannot be nan either. | |
| 1051 int nans = 0; | |
| 1052 for (int i = 0; i < 4; ++i) { | |
| 1053 if (std::isnan(results[i])) ++nans; | |
| 1054 } | |
| 1055 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa | |
| 1056 Type* range = | |
| 1057 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); | |
| 1058 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone()); | |
| 1059 // Examples: | |
| 1060 // [-inf, -inf] + [+inf, +inf] = NaN | |
| 1061 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN | |
| 1062 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN | |
| 1063 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN | |
| 1064 } | |
| 1065 | |
| 1066 | |
| 1067 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { | 985 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1068 lhs = ToPrimitive(lhs, t); | 986 lhs = ToPrimitive(lhs, t); |
| 1069 rhs = ToPrimitive(rhs, t); | 987 rhs = ToPrimitive(rhs, t); |
| 1070 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { | 988 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { |
| 1071 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { | 989 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { |
| 1072 return Type::String(); | 990 return Type::String(); |
| 1073 } else { | 991 } else { |
| 1074 return Type::NumberOrString(); | 992 return Type::NumberOrString(); |
| 1075 } | 993 } |
| 1076 } | 994 } |
| 1077 // The addition must be numeric. | 995 // The addition must be numeric. |
| 1078 lhs = ToNumber(lhs, t); | 996 return t->operation_typer()->NumericAdd(ToNumber(lhs, t), ToNumber(rhs, t)); |
| 1079 rhs = ToNumber(rhs, t); | |
| 1080 // We can give more precise types for integers. | |
| 1081 if (!lhs->Is(t->cache_.kIntegerOrMinusZeroOrNaN) || | |
| 1082 !rhs->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) { | |
| 1083 return Type::Number(); | |
| 1084 } | |
| 1085 Type* int_lhs = Type::Intersect(lhs, t->cache_.kInteger, t->zone()); | |
| 1086 Type* int_rhs = Type::Intersect(rhs, t->cache_.kInteger, t->zone()); | |
| 1087 Type* result = JSAddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), | |
| 1088 int_rhs->Max(), t); | |
| 1089 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { | |
| 1090 result = Type::Union(result, Type::NaN(), t->zone()); | |
| 1091 } | |
| 1092 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { | |
| 1093 result = Type::Union(result, Type::MinusZero(), t->zone()); | |
| 1094 } | |
| 1095 return result; | |
| 1096 } | 997 } |
| 1097 | 998 |
| 1098 Type* Typer::Visitor::JSSubtractRanger(RangeType* lhs, RangeType* rhs, | 999 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1099 Typer* t) { | 1000 return t->operation_typer()->NumericSubtract(ToNumber(lhs, t), |
| 1100 double results[4]; | 1001 ToNumber(rhs, t)); |
| 1101 results[0] = lhs->Min() - rhs->Min(); | |
| 1102 results[1] = lhs->Min() - rhs->Max(); | |
| 1103 results[2] = lhs->Max() - rhs->Min(); | |
| 1104 results[3] = lhs->Max() - rhs->Max(); | |
| 1105 // Since none of the inputs can be -0, the result cannot be -0. | |
| 1106 // However, it can be nan (the subtraction of two infinities of same sign). | |
| 1107 // On the other hand, if none of the "results" above is nan, then the actual | |
| 1108 // result cannot be nan either. | |
| 1109 int nans = 0; | |
| 1110 for (int i = 0; i < 4; ++i) { | |
| 1111 if (std::isnan(results[i])) ++nans; | |
| 1112 } | |
| 1113 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign) | |
| 1114 Type* range = | |
| 1115 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); | |
| 1116 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone()); | |
| 1117 // Examples: | |
| 1118 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN | |
| 1119 // [-inf, -inf] - [-inf, -inf] = NaN | |
| 1120 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN | |
| 1121 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN | |
| 1122 } | 1002 } |
| 1123 | 1003 |
| 1124 | 1004 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1125 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) { | 1005 return t->operation_typer()->NumericMultiply(ToNumber(lhs, t), |
| 1126 lhs = Rangify(ToNumber(lhs, t), t); | 1006 ToNumber(rhs, t)); |
| 1127 rhs = Rangify(ToNumber(rhs, t), t); | |
| 1128 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | |
| 1129 if (lhs->IsRange() && rhs->IsRange()) { | |
| 1130 return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t); | |
| 1131 } | |
| 1132 return Type::Number(); | |
| 1133 } | 1007 } |
| 1134 | 1008 |
| 1135 | |
| 1136 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { | |
| 1137 lhs = Rangify(ToNumber(lhs, t), t); | |
| 1138 rhs = Rangify(ToNumber(rhs, t), t); | |
| 1139 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | |
| 1140 if (lhs->IsRange() && rhs->IsRange()) { | |
| 1141 double results[4]; | |
| 1142 double lmin = lhs->AsRange()->Min(); | |
| 1143 double lmax = lhs->AsRange()->Max(); | |
| 1144 double rmin = rhs->AsRange()->Min(); | |
| 1145 double rmax = rhs->AsRange()->Max(); | |
| 1146 results[0] = lmin * rmin; | |
| 1147 results[1] = lmin * rmax; | |
| 1148 results[2] = lmax * rmin; | |
| 1149 results[3] = lmax * rmax; | |
| 1150 // If the result may be nan, we give up on calculating a precise type, | |
| 1151 // because | |
| 1152 // the discontinuity makes it too complicated. Note that even if none of | |
| 1153 // the | |
| 1154 // "results" above is nan, the actual result may still be, so we have to do | |
| 1155 // a | |
| 1156 // different check: | |
| 1157 bool maybe_nan = (lhs->Maybe(t->cache_.kSingletonZero) && | |
| 1158 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || | |
| 1159 (rhs->Maybe(t->cache_.kSingletonZero) && | |
| 1160 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); | |
| 1161 if (maybe_nan) return t->cache_.kIntegerOrMinusZeroOrNaN; // Giving up. | |
| 1162 bool maybe_minuszero = (lhs->Maybe(t->cache_.kSingletonZero) && rmin < 0) || | |
| 1163 (rhs->Maybe(t->cache_.kSingletonZero) && lmin < 0); | |
| 1164 Type* range = | |
| 1165 Type::Range(array_min(results, 4), array_max(results, 4), t->zone()); | |
| 1166 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) | |
| 1167 : range; | |
| 1168 } | |
| 1169 return Type::Number(); | |
| 1170 } | |
| 1171 | |
| 1172 | |
| 1173 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { | 1009 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1010 return t->operation_typer()->NumericDivide(ToNumber(lhs, t), |
| 1011 ToNumber(rhs, t)); |
| 1174 lhs = ToNumber(lhs, t); | 1012 lhs = ToNumber(lhs, t); |
| 1175 rhs = ToNumber(rhs, t); | 1013 rhs = ToNumber(rhs, t); |
| 1176 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1014 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1177 // Division is tricky, so all we do is try ruling out nan. | 1015 // Division is tricky, so all we do is try ruling out nan. |
| 1178 bool maybe_nan = | 1016 bool maybe_nan = |
| 1179 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) || | 1017 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) || |
| 1180 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | 1018 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 1181 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | 1019 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 1182 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 1020 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 1183 } | 1021 } |
| 1184 | 1022 |
| 1185 Type* Typer::Visitor::JSModulusRanger(RangeType* lhs, RangeType* rhs, | 1023 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1186 Typer* t) { | 1024 return t->operation_typer()->NumericModulus(ToNumber(lhs, t), |
| 1187 double lmin = lhs->Min(); | 1025 ToNumber(rhs, t)); |
| 1188 double lmax = lhs->Max(); | |
| 1189 double rmin = rhs->Min(); | |
| 1190 double rmax = rhs->Max(); | |
| 1191 | |
| 1192 double labs = std::max(std::abs(lmin), std::abs(lmax)); | |
| 1193 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; | |
| 1194 double abs = std::min(labs, rabs); | |
| 1195 bool maybe_minus_zero = false; | |
| 1196 double omin = 0; | |
| 1197 double omax = 0; | |
| 1198 if (lmin >= 0) { // {lhs} positive. | |
| 1199 omin = 0; | |
| 1200 omax = abs; | |
| 1201 } else if (lmax <= 0) { // {lhs} negative. | |
| 1202 omin = 0 - abs; | |
| 1203 omax = 0; | |
| 1204 maybe_minus_zero = true; | |
| 1205 } else { | |
| 1206 omin = 0 - abs; | |
| 1207 omax = abs; | |
| 1208 maybe_minus_zero = true; | |
| 1209 } | |
| 1210 | |
| 1211 Type* result = Type::Range(omin, omax, t->zone()); | |
| 1212 if (maybe_minus_zero) | |
| 1213 result = Type::Union(result, Type::MinusZero(), t->zone()); | |
| 1214 return result; | |
| 1215 } | 1026 } |
| 1216 | 1027 |
| 1217 | 1028 |
| 1218 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { | |
| 1219 lhs = ToNumber(lhs, t); | |
| 1220 rhs = ToNumber(rhs, t); | |
| 1221 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | |
| 1222 | |
| 1223 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) || | |
| 1224 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { | |
| 1225 // Result maybe NaN. | |
| 1226 return Type::Number(); | |
| 1227 } | |
| 1228 | |
| 1229 lhs = Rangify(lhs, t); | |
| 1230 rhs = Rangify(rhs, t); | |
| 1231 if (lhs->IsRange() && rhs->IsRange()) { | |
| 1232 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); | |
| 1233 } | |
| 1234 return Type::OrderedNumber(); | |
| 1235 } | |
| 1236 | |
| 1237 | |
| 1238 // JS unary operators. | 1029 // JS unary operators. |
| 1239 | 1030 |
| 1240 | 1031 |
| 1241 Type* Typer::Visitor::JSTypeOfTyper(Type* type, Typer* t) { | 1032 Type* Typer::Visitor::JSTypeOfTyper(Type* type, Typer* t) { |
| 1242 Factory* const f = t->isolate()->factory(); | 1033 Factory* const f = t->isolate()->factory(); |
| 1243 if (type->Is(Type::Boolean())) { | 1034 if (type->Is(Type::Boolean())) { |
| 1244 return Type::Constant(f->boolean_string(), t->zone()); | 1035 return Type::Constant(f->boolean_string(), t->zone()); |
| 1245 } else if (type->Is(Type::Number())) { | 1036 } else if (type->Is(Type::Number())) { |
| 1246 return Type::Constant(f->number_string(), t->zone()); | 1037 return Type::Constant(f->number_string(), t->zone()); |
| 1247 } else if (type->Is(Type::String())) { | 1038 } else if (type->Is(Type::String())) { |
| (...skipping 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2797 } | 2588 } |
| 2798 if (Type::IsInteger(*value)) { | 2589 if (Type::IsInteger(*value)) { |
| 2799 return Type::Range(value->Number(), value->Number(), zone()); | 2590 return Type::Range(value->Number(), value->Number(), zone()); |
| 2800 } | 2591 } |
| 2801 return Type::Constant(value, zone()); | 2592 return Type::Constant(value, zone()); |
| 2802 } | 2593 } |
| 2803 | 2594 |
| 2804 } // namespace compiler | 2595 } // namespace compiler |
| 2805 } // namespace internal | 2596 } // namespace internal |
| 2806 } // namespace v8 | 2597 } // namespace v8 |
| OLD | NEW |