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 |