OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/operation-typer.h" | 5 #include "src/compiler/operation-typer.h" |
6 | 6 |
7 #include "src/factory.h" | 7 #include "src/factory.h" |
8 #include "src/isolate.h" | 8 #include "src/isolate.h" |
9 #include "src/type-cache.h" | 9 #include "src/type-cache.h" |
10 #include "src/types.h" | 10 #include "src/types.h" |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 if (!std::isnan(a[i])) { | 146 if (!std::isnan(a[i])) { |
147 x = std::max(a[i], x); | 147 x = std::max(a[i], x); |
148 } | 148 } |
149 } | 149 } |
150 DCHECK(!std::isnan(x)); | 150 DCHECK(!std::isnan(x)); |
151 return x == 0 ? 0 : x; // -0 -> 0 | 151 return x == 0 ? 0 : x; // -0 -> 0 |
152 } | 152 } |
153 | 153 |
154 } // namespace | 154 } // namespace |
155 | 155 |
156 Type* OperationTyper::AddRanger(RangeType* lhs, RangeType* rhs) { | 156 Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min, |
| 157 double rhs_max) { |
157 double results[4]; | 158 double results[4]; |
158 results[0] = lhs->Min() + rhs->Min(); | 159 results[0] = lhs_min + rhs_min; |
159 results[1] = lhs->Min() + rhs->Max(); | 160 results[1] = lhs_min + rhs_max; |
160 results[2] = lhs->Max() + rhs->Min(); | 161 results[2] = lhs_max + rhs_min; |
161 results[3] = lhs->Max() + rhs->Max(); | 162 results[3] = lhs_max + rhs_max; |
162 // Since none of the inputs can be -0, the result cannot be -0 either. | 163 // Since none of the inputs can be -0, the result cannot be -0 either. |
163 // However, it can be nan (the sum of two infinities of opposite sign). | 164 // However, it can be nan (the sum of two infinities of opposite sign). |
164 // On the other hand, if none of the "results" above is nan, then the actual | 165 // On the other hand, if none of the "results" above is nan, then the actual |
165 // result cannot be nan either. | 166 // result cannot be nan either. |
166 int nans = 0; | 167 int nans = 0; |
167 for (int i = 0; i < 4; ++i) { | 168 for (int i = 0; i < 4; ++i) { |
168 if (std::isnan(results[i])) ++nans; | 169 if (std::isnan(results[i])) ++nans; |
169 } | 170 } |
170 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa | 171 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa |
171 Type* range = | 172 Type* range = |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 282 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
282 cache_.kZeroOrOne, zone()); | 283 cache_.kZeroOrOne, zone()); |
283 } | 284 } |
284 return Type::Number(); | 285 return Type::Number(); |
285 } | 286 } |
286 | 287 |
287 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { | 288 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { |
288 DCHECK(lhs->Is(Type::Number())); | 289 DCHECK(lhs->Is(Type::Number())); |
289 DCHECK(rhs->Is(Type::Number())); | 290 DCHECK(rhs->Is(Type::Number())); |
290 | 291 |
291 lhs = Rangify(lhs); | 292 // We can give more precise types for integers. |
292 rhs = Rangify(rhs); | 293 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || |
293 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 294 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { |
294 if (lhs->IsRange() && rhs->IsRange()) { | 295 return Type::Number(); |
295 return AddRanger(lhs->AsRange(), rhs->AsRange()); | |
296 } | 296 } |
297 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 297 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); |
298 return Type::Number(); | 298 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); |
| 299 Type* result = |
| 300 AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max()); |
| 301 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
| 302 result = Type::Union(result, Type::NaN(), zone()); |
| 303 } |
| 304 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { |
| 305 result = Type::Union(result, Type::MinusZero(), zone()); |
| 306 } |
| 307 return result; |
299 } | 308 } |
300 | 309 |
301 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { | 310 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { |
302 DCHECK(lhs->Is(Type::Number())); | 311 DCHECK(lhs->Is(Type::Number())); |
303 DCHECK(rhs->Is(Type::Number())); | 312 DCHECK(rhs->Is(Type::Number())); |
304 | 313 |
305 lhs = Rangify(lhs); | 314 lhs = Rangify(lhs); |
306 rhs = Rangify(rhs); | 315 rhs = Rangify(rhs); |
307 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 316 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
308 if (lhs->IsRange() && rhs->IsRange()) { | 317 if (lhs->IsRange() && rhs->IsRange()) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 return NumericAdd(lhs, rhs); | 415 return NumericAdd(lhs, rhs); |
407 } | 416 } |
408 | 417 |
409 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 418 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
410 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); | 419 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); |
411 } | 420 } |
412 | 421 |
413 } // namespace compiler | 422 } // namespace compiler |
414 } // namespace internal | 423 } // namespace internal |
415 } // namespace v8 | 424 } // namespace v8 |
OLD | NEW |