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 |