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