| 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" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "src/bootstrapper.h" | 5 #include "src/bootstrapper.h" |
| 10 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
| 11 #include "src/compiler/graph-reducer.h" | 7 #include "src/compiler/graph-reducer.h" |
| 12 #include "src/compiler/js-operator.h" | 8 #include "src/compiler/js-operator.h" |
| 13 #include "src/compiler/node.h" | 9 #include "src/compiler/node.h" |
| 14 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
| 15 #include "src/compiler/node-properties.h" | 11 #include "src/compiler/node-properties.h" |
| 16 #include "src/compiler/simplified-operator.h" | 12 #include "src/compiler/simplified-operator.h" |
| 13 #include "src/compiler/typer.h" |
| 17 | 14 |
| 18 namespace v8 { | 15 namespace v8 { |
| 19 namespace internal { | 16 namespace internal { |
| 20 namespace compiler { | 17 namespace compiler { |
| 21 | 18 |
| 22 #define NATIVE_TYPES(V) \ | 19 #define NATIVE_TYPES(V) \ |
| 23 V(Int8) \ | 20 V(Int8) \ |
| 24 V(Uint8) \ | 21 V(Uint8) \ |
| 25 V(Int16) \ | 22 V(Int16) \ |
| 26 V(Uint16) \ | 23 V(Uint16) \ |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 context_(context), | 153 context_(context), |
| 157 decorator_(NULL), | 154 decorator_(NULL), |
| 158 cache_(new (graph->zone()) LazyTypeCache(graph->zone())), | 155 cache_(new (graph->zone()) LazyTypeCache(graph->zone())), |
| 159 weaken_min_limits_(graph->zone()), | 156 weaken_min_limits_(graph->zone()), |
| 160 weaken_max_limits_(graph->zone()) { | 157 weaken_max_limits_(graph->zone()) { |
| 161 Zone* zone = this->zone(); | 158 Zone* zone = this->zone(); |
| 162 Factory* f = zone->isolate()->factory(); | 159 Factory* f = zone->isolate()->factory(); |
| 163 | 160 |
| 164 Handle<Object> zero = f->NewNumber(0); | 161 Handle<Object> zero = f->NewNumber(0); |
| 165 Handle<Object> one = f->NewNumber(1); | 162 Handle<Object> one = f->NewNumber(1); |
| 166 Handle<Object> infinity = | 163 Handle<Object> infinity = f->NewNumber(+V8_INFINITY); |
| 167 f->NewNumber(+std::numeric_limits<double>::infinity()); | 164 Handle<Object> minusinfinity = f->NewNumber(-V8_INFINITY); |
| 168 Handle<Object> minusinfinity = | |
| 169 f->NewNumber(-std::numeric_limits<double>::infinity()); | |
| 170 | 165 |
| 171 Type* number = Type::Number(); | 166 Type* number = Type::Number(); |
| 172 Type* signed32 = Type::Signed32(); | 167 Type* signed32 = Type::Signed32(); |
| 173 Type* unsigned32 = Type::Unsigned32(); | 168 Type* unsigned32 = Type::Unsigned32(); |
| 174 Type* nan_or_minuszero = Type::Union(Type::NaN(), Type::MinusZero(), zone); | 169 Type* nan_or_minuszero = Type::Union(Type::NaN(), Type::MinusZero(), zone); |
| 175 Type* truncating_to_zero = | 170 Type* truncating_to_zero = |
| 176 Type::Union(Type::Union(Type::Constant(infinity, zone), | 171 Type::Union(Type::Union(Type::Constant(infinity, zone), |
| 177 Type::Constant(minusinfinity, zone), zone), | 172 Type::Constant(minusinfinity, zone), zone), |
| 178 nan_or_minuszero, zone); | 173 nan_or_minuszero, zone); |
| 179 | 174 |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 | 929 |
| 935 | 930 |
| 936 // JS arithmetic operators. | 931 // JS arithmetic operators. |
| 937 | 932 |
| 938 | 933 |
| 939 // Returns the array's least element, ignoring NaN. | 934 // Returns the array's least element, ignoring NaN. |
| 940 // There must be at least one non-NaN element. | 935 // There must be at least one non-NaN element. |
| 941 // Any -0 is converted to 0. | 936 // Any -0 is converted to 0. |
| 942 static double array_min(double a[], size_t n) { | 937 static double array_min(double a[], size_t n) { |
| 943 DCHECK(n != 0); | 938 DCHECK(n != 0); |
| 944 double x = +std::numeric_limits<double>::infinity(); | 939 double x = +V8_INFINITY; |
| 945 for (size_t i = 0; i < n; ++i) { | 940 for (size_t i = 0; i < n; ++i) { |
| 946 if (!std::isnan(a[i])) { | 941 if (!std::isnan(a[i])) { |
| 947 x = std::min(a[i], x); | 942 x = std::min(a[i], x); |
| 948 } | 943 } |
| 949 } | 944 } |
| 950 DCHECK(!std::isnan(x)); | 945 DCHECK(!std::isnan(x)); |
| 951 return x == 0 ? 0 : x; // -0 -> 0 | 946 return x == 0 ? 0 : x; // -0 -> 0 |
| 952 } | 947 } |
| 953 | 948 |
| 954 | 949 |
| 955 // Returns the array's greatest element, ignoring NaN. | 950 // Returns the array's greatest element, ignoring NaN. |
| 956 // There must be at least one non-NaN element. | 951 // There must be at least one non-NaN element. |
| 957 // Any -0 is converted to 0. | 952 // Any -0 is converted to 0. |
| 958 static double array_max(double a[], size_t n) { | 953 static double array_max(double a[], size_t n) { |
| 959 DCHECK(n != 0); | 954 DCHECK(n != 0); |
| 960 double x = -std::numeric_limits<double>::infinity(); | 955 double x = -V8_INFINITY; |
| 961 for (size_t i = 0; i < n; ++i) { | 956 for (size_t i = 0; i < n; ++i) { |
| 962 if (!std::isnan(a[i])) { | 957 if (!std::isnan(a[i])) { |
| 963 x = std::max(a[i], x); | 958 x = std::max(a[i], x); |
| 964 } | 959 } |
| 965 } | 960 } |
| 966 DCHECK(!std::isnan(x)); | 961 DCHECK(!std::isnan(x)); |
| 967 return x == 0 ? 0 : x; // -0 -> 0 | 962 return x == 0 ? 0 : x; // -0 -> 0 |
| 968 } | 963 } |
| 969 | 964 |
| 970 | 965 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 double rmax = rhs->Max()->Number(); | 1060 double rmax = rhs->Max()->Number(); |
| 1066 results[0] = lmin * rmin; | 1061 results[0] = lmin * rmin; |
| 1067 results[1] = lmin * rmax; | 1062 results[1] = lmin * rmax; |
| 1068 results[2] = lmax * rmin; | 1063 results[2] = lmax * rmin; |
| 1069 results[3] = lmax * rmax; | 1064 results[3] = lmax * rmax; |
| 1070 // If the result may be nan, we give up on calculating a precise type, because | 1065 // If the result may be nan, we give up on calculating a precise type, because |
| 1071 // the discontinuity makes it too complicated. Note that even if none of the | 1066 // the discontinuity makes it too complicated. Note that even if none of the |
| 1072 // "results" above is nan, the actual result may still be, so we have to do a | 1067 // "results" above is nan, the actual result may still be, so we have to do a |
| 1073 // different check: | 1068 // different check: |
| 1074 bool maybe_nan = (lhs->Maybe(t->singleton_zero) && | 1069 bool maybe_nan = (lhs->Maybe(t->singleton_zero) && |
| 1075 (rmin == -std::numeric_limits<double>::infinity() || | 1070 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
| 1076 rmax == +std::numeric_limits<double>::infinity())) || | |
| 1077 (rhs->Maybe(t->singleton_zero) && | 1071 (rhs->Maybe(t->singleton_zero) && |
| 1078 (lmin == -std::numeric_limits<double>::infinity() || | 1072 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
| 1079 lmax == +std::numeric_limits<double>::infinity())); | |
| 1080 if (maybe_nan) return t->weakint; // Giving up. | 1073 if (maybe_nan) return t->weakint; // Giving up. |
| 1081 bool maybe_minuszero = (lhs->Maybe(t->singleton_zero) && rmin < 0) || | 1074 bool maybe_minuszero = (lhs->Maybe(t->singleton_zero) && rmin < 0) || |
| 1082 (rhs->Maybe(t->singleton_zero) && lmin < 0); | 1075 (rhs->Maybe(t->singleton_zero) && lmin < 0); |
| 1083 Factory* f = t->isolate()->factory(); | 1076 Factory* f = t->isolate()->factory(); |
| 1084 Type* range = Type::Range(f->NewNumber(array_min(results, 4)), | 1077 Type* range = Type::Range(f->NewNumber(array_min(results, 4)), |
| 1085 f->NewNumber(array_max(results, 4)), t->zone()); | 1078 f->NewNumber(array_max(results, 4)), t->zone()); |
| 1086 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) | 1079 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) |
| 1087 : range; | 1080 : range; |
| 1088 } | 1081 } |
| 1089 | 1082 |
| 1090 | 1083 |
| 1091 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { | 1084 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1092 lhs = Rangify(ToNumber(lhs, t), t); | 1085 lhs = Rangify(ToNumber(lhs, t), t); |
| 1093 rhs = Rangify(ToNumber(rhs, t), t); | 1086 rhs = Rangify(ToNumber(rhs, t), t); |
| 1094 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1087 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1095 if (lhs->IsRange() && rhs->IsRange()) { | 1088 if (lhs->IsRange() && rhs->IsRange()) { |
| 1096 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t); | 1089 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t); |
| 1097 } | 1090 } |
| 1098 return Type::Number(); | 1091 return Type::Number(); |
| 1099 } | 1092 } |
| 1100 | 1093 |
| 1101 | 1094 |
| 1102 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { | 1095 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1103 lhs = ToNumber(lhs, t); | 1096 lhs = ToNumber(lhs, t); |
| 1104 rhs = ToNumber(rhs, t); | 1097 rhs = ToNumber(rhs, t); |
| 1105 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1098 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1106 // Division is tricky, so all we do is try ruling out nan. | 1099 // Division is tricky, so all we do is try ruling out nan. |
| 1107 // TODO(neis): try ruling out -0 as well? | 1100 // TODO(neis): try ruling out -0 as well? |
| 1108 bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) || | 1101 bool maybe_nan = |
| 1109 ((lhs->Min() == -std::numeric_limits<double>::infinity() || | 1102 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) || |
| 1110 lhs->Max() == +std::numeric_limits<double>::infinity()) && | 1103 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 1111 (rhs->Min() == -std::numeric_limits<double>::infinity() || | 1104 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 1112 rhs->Max() == +std::numeric_limits<double>::infinity())); | |
| 1113 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 1105 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 1114 } | 1106 } |
| 1115 | 1107 |
| 1116 | 1108 |
| 1117 Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs, | 1109 Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs, |
| 1118 Type::RangeType* rhs, Typer* t) { | 1110 Type::RangeType* rhs, Typer* t) { |
| 1119 double lmin = lhs->Min()->Number(); | 1111 double lmin = lhs->Min()->Number(); |
| 1120 double lmax = lhs->Max()->Number(); | 1112 double lmax = lhs->Max()->Number(); |
| 1121 double rmin = rhs->Min()->Number(); | 1113 double rmin = rhs->Min()->Number(); |
| 1122 double rmax = rhs->Max()->Number(); | 1114 double rmax = rhs->Max()->Number(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1147 return result; | 1139 return result; |
| 1148 } | 1140 } |
| 1149 | 1141 |
| 1150 | 1142 |
| 1151 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { | 1143 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { |
| 1152 lhs = ToNumber(lhs, t); | 1144 lhs = ToNumber(lhs, t); |
| 1153 rhs = ToNumber(rhs, t); | 1145 rhs = ToNumber(rhs, t); |
| 1154 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 1146 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 1155 | 1147 |
| 1156 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) || | 1148 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) || |
| 1157 lhs->Min() == -std::numeric_limits<double>::infinity() || | 1149 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
| 1158 lhs->Max() == +std::numeric_limits<double>::infinity()) { | |
| 1159 // Result maybe NaN. | 1150 // Result maybe NaN. |
| 1160 return Type::Number(); | 1151 return Type::Number(); |
| 1161 } | 1152 } |
| 1162 | 1153 |
| 1163 lhs = Rangify(lhs, t); | 1154 lhs = Rangify(lhs, t); |
| 1164 rhs = Rangify(rhs, t); | 1155 rhs = Rangify(rhs, t); |
| 1165 if (lhs->IsRange() && rhs->IsRange()) { | 1156 if (lhs->IsRange() && rhs->IsRange()) { |
| 1166 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); | 1157 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); |
| 1167 } | 1158 } |
| 1168 return Type::OrderedNumber(); | 1159 return Type::OrderedNumber(); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2101 // TODO(rossberg): Do we want some ClampedArray type to express this? | 2092 // TODO(rossberg): Do we want some ClampedArray type to express this? |
| 2102 break; | 2093 break; |
| 2103 } | 2094 } |
| 2104 } | 2095 } |
| 2105 return Type::Constant(value, zone()); | 2096 return Type::Constant(value, zone()); |
| 2106 } | 2097 } |
| 2107 | 2098 |
| 2108 } // namespace compiler | 2099 } // namespace compiler |
| 2109 } // namespace internal | 2100 } // namespace internal |
| 2110 } // namespace v8 | 2101 } // namespace v8 |
| OLD | NEW |