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 |