Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/operation-typer.h"
6 :
7 : #include "src/compiler/common-operator.h"
8 : #include "src/compiler/type-cache.h"
9 : #include "src/compiler/types.h"
10 : #include "src/heap/factory.h"
11 : #include "src/isolate.h"
12 :
13 : #include "src/objects-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 : namespace compiler {
18 :
19 1393161 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20 1393161 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = broker->isolate()->factory();
22 1393162 : infinity_ = Type::NewConstant(V8_INFINITY, zone);
23 1393161 : minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24 1393162 : Type truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 :
27 : singleton_empty_string_ =
28 1393162 : Type::HeapConstant(broker, factory->empty_string(), zone);
29 : singleton_NaN_string_ =
30 1393162 : Type::HeapConstant(broker, factory->NaN_string(), zone);
31 : singleton_zero_string_ =
32 1393163 : Type::HeapConstant(broker, factory->zero_string(), zone);
33 1393165 : singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34 1393165 : singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35 : singleton_the_hole_ =
36 1393165 : Type::HeapConstant(broker, factory->the_hole_value(), zone);
37 1393163 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38 1393162 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 :
40 : falsish_ = Type::Union(
41 : Type::Undetectable(),
42 1393162 : Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
43 : Type::Union(singleton_empty_string_, Type::Hole(), zone),
44 : zone),
45 2786327 : zone);
46 : truish_ = Type::Union(
47 : singleton_true_,
48 1393166 : Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 1393165 : }
50 :
51 1202102 : Type OperationTyper::Merge(Type left, Type right) {
52 1202102 : return Type::Union(left, right, zone());
53 : }
54 :
55 447884 : Type OperationTyper::WeakenRange(Type previous_range, Type current_range) {
56 : static const double kWeakenMinLimits[] = {0.0,
57 : -1073741824.0,
58 : -2147483648.0,
59 : -4294967296.0,
60 : -8589934592.0,
61 : -17179869184.0,
62 : -34359738368.0,
63 : -68719476736.0,
64 : -137438953472.0,
65 : -274877906944.0,
66 : -549755813888.0,
67 : -1099511627776.0,
68 : -2199023255552.0,
69 : -4398046511104.0,
70 : -8796093022208.0,
71 : -17592186044416.0,
72 : -35184372088832.0,
73 : -70368744177664.0,
74 : -140737488355328.0,
75 : -281474976710656.0,
76 : -562949953421312.0};
77 : static const double kWeakenMaxLimits[] = {0.0,
78 : 1073741823.0,
79 : 2147483647.0,
80 : 4294967295.0,
81 : 8589934591.0,
82 : 17179869183.0,
83 : 34359738367.0,
84 : 68719476735.0,
85 : 137438953471.0,
86 : 274877906943.0,
87 : 549755813887.0,
88 : 1099511627775.0,
89 : 2199023255551.0,
90 : 4398046511103.0,
91 : 8796093022207.0,
92 : 17592186044415.0,
93 : 35184372088831.0,
94 : 70368744177663.0,
95 : 140737488355327.0,
96 : 281474976710655.0,
97 : 562949953421311.0};
98 : STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
99 :
100 447884 : double current_min = current_range.Min();
101 : double new_min = current_min;
102 : // Find the closest lower entry in the list of allowed
103 : // minima (or negative infinity if there is no such entry).
104 447883 : if (current_min != previous_range.Min()) {
105 : new_min = -V8_INFINITY;
106 328270 : for (double const min : kWeakenMinLimits) {
107 167807 : if (min <= current_min) {
108 : new_min = min;
109 : break;
110 : }
111 : }
112 : }
113 :
114 447883 : double current_max = current_range.Max();
115 : double new_max = current_max;
116 : // Find the closest greater entry in the list of allowed
117 : // maxima (or infinity if there is no such entry).
118 447884 : if (current_max != previous_range.Max()) {
119 : new_max = V8_INFINITY;
120 7106442 : for (double const max : kWeakenMaxLimits) {
121 3700467 : if (max >= current_max) {
122 : new_max = max;
123 : break;
124 : }
125 : }
126 : }
127 :
128 447885 : return Type::Range(new_min, new_max, zone());
129 : }
130 :
131 0 : Type OperationTyper::Rangify(Type type) {
132 0 : if (type.IsRange()) return type; // Shortcut.
133 0 : if (!type.Is(cache_->kInteger)) {
134 0 : return type; // Give up on non-integer types.
135 : }
136 0 : return Type::Range(type.Min(), type.Max(), zone());
137 : }
138 :
139 : namespace {
140 :
141 : // Returns the array's least element, ignoring NaN.
142 : // There must be at least one non-NaN element.
143 : // Any -0 is converted to 0.
144 : double array_min(double a[], size_t n) {
145 : DCHECK_NE(0, n);
146 1355269 : double x = +V8_INFINITY;
147 12197165 : for (size_t i = 0; i < n; ++i) {
148 5420948 : if (!std::isnan(a[i])) {
149 5420847 : x = std::min(a[i], x);
150 : }
151 : }
152 : DCHECK(!std::isnan(x));
153 1355269 : return x == 0 ? 0 : x; // -0 -> 0
154 : }
155 :
156 : // Returns the array's greatest element, ignoring NaN.
157 : // There must be at least one non-NaN element.
158 : // Any -0 is converted to 0.
159 : double array_max(double a[], size_t n) {
160 : DCHECK_NE(0, n);
161 1355269 : double x = -V8_INFINITY;
162 12197085 : for (size_t i = 0; i < n; ++i) {
163 5420908 : if (!std::isnan(a[i])) {
164 5420815 : x = std::max(a[i], x);
165 : }
166 : }
167 : DCHECK(!std::isnan(x));
168 1355269 : return x == 0 ? 0 : x; // -0 -> 0
169 : }
170 :
171 : } // namespace
172 :
173 1245023 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174 : double rhs_max) {
175 : double results[4];
176 1245023 : results[0] = lhs_min + rhs_min;
177 1245023 : results[1] = lhs_min + rhs_max;
178 1245023 : results[2] = lhs_max + rhs_min;
179 1245023 : results[3] = lhs_max + rhs_max;
180 : // Since none of the inputs can be -0, the result cannot be -0 either.
181 : // However, it can be nan (the sum of two infinities of opposite sign).
182 : // On the other hand, if none of the "results" above is nan, then the
183 : // actual result cannot be nan either.
184 : int nans = 0;
185 11204479 : for (int i = 0; i < 4; ++i) {
186 4979728 : if (std::isnan(results[i])) ++nans;
187 : }
188 1245023 : if (nans == 4) return Type::NaN();
189 1245017 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190 1245049 : if (nans > 0) type = Type::Union(type, Type::NaN(), zone());
191 : // Examples:
192 : // [-inf, -inf] + [+inf, +inf] = NaN
193 : // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
194 : // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
195 : // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
196 1245051 : return type;
197 : }
198 :
199 54449 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200 : double rhs_min, double rhs_max) {
201 : double results[4];
202 54449 : results[0] = lhs_min - rhs_min;
203 54449 : results[1] = lhs_min - rhs_max;
204 54449 : results[2] = lhs_max - rhs_min;
205 54449 : results[3] = lhs_max - rhs_max;
206 : // Since none of the inputs can be -0, the result cannot be -0.
207 : // However, it can be nan (the subtraction of two infinities of same sign).
208 : // On the other hand, if none of the "results" above is nan, then the actual
209 : // result cannot be nan either.
210 : int nans = 0;
211 490041 : for (int i = 0; i < 4; ++i) {
212 217796 : if (std::isnan(results[i])) ++nans;
213 : }
214 54449 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215 54443 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216 54443 : return nans == 0 ? type : Type::Union(type, Type::NaN(), zone());
217 : // Examples:
218 : // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
219 : // [-inf, -inf] - [-inf, -inf] = NaN
220 : // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
221 : // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
222 : }
223 :
224 55881 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225 : double rhs_min, double rhs_max) {
226 : double results[4];
227 55881 : results[0] = lhs_min * rhs_min;
228 55881 : results[1] = lhs_min * rhs_max;
229 55881 : results[2] = lhs_max * rhs_min;
230 55881 : results[3] = lhs_max * rhs_max;
231 : // If the result may be nan, we give up on calculating a precise type,
232 : // because the discontinuity makes it too complicated. Note that even if
233 : // none of the "results" above is nan, the actual result may still be, so we
234 : // have to do a different check:
235 502453 : for (int i = 0; i < 4; ++i) {
236 223358 : if (std::isnan(results[i])) {
237 72 : return cache_->kIntegerOrMinusZeroOrNaN;
238 : }
239 : }
240 : double min = array_min(results, 4);
241 : double max = array_max(results, 4);
242 55809 : Type type = Type::Range(min, max, zone());
243 55809 : if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244 42766 : type = Type::Union(type, Type::MinusZero(), zone());
245 : }
246 : // 0 * V8_INFINITY is NaN, regardless of sign
247 95197 : if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248 75509 : (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249 55718 : ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250 118 : (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251 182 : type = Type::Union(type, Type::NaN(), zone());
252 : }
253 55809 : return type;
254 : }
255 :
256 80785 : Type OperationTyper::ConvertReceiver(Type type) {
257 80785 : if (type.Is(Type::Receiver())) return type;
258 80776 : bool const maybe_primitive = type.Maybe(Type::Primitive());
259 80776 : type = Type::Intersect(type, Type::Receiver(), zone());
260 80776 : if (maybe_primitive) {
261 : // ConvertReceiver maps null and undefined to the JSGlobalProxy of the
262 : // target function, and all other primitives are wrapped into a JSValue.
263 80776 : type = Type::Union(type, Type::OtherObject(), zone());
264 : }
265 80776 : return type;
266 : }
267 :
268 3296772 : Type OperationTyper::ToNumber(Type type) {
269 3296729 : if (type.Is(Type::Number())) return type;
270 :
271 : // If {type} includes any receivers, we cannot tell what kind of
272 : // Number their callbacks might produce. Similarly in the case
273 : // where {type} includes String, it's not possible at this point
274 : // to tell which exact numbers are going to be produced.
275 714012 : if (type.Maybe(Type::StringOrReceiver())) return Type::Number();
276 :
277 : // Both Symbol and BigInt primitives will cause exceptions
278 : // to be thrown from ToNumber conversions, so they don't
279 : // contribute to the resulting type anyways.
280 436060 : type = Type::Intersect(type, Type::PlainPrimitive(), zone());
281 :
282 : // This leaves us with Number\/Oddball, so deal with the individual
283 : // Oddball primitives below.
284 : DCHECK(type.Is(Type::NumberOrOddball()));
285 436071 : if (type.Maybe(Type::Null())) {
286 : // ToNumber(null) => +0
287 423301 : type = Type::Union(type, cache_->kSingletonZero, zone());
288 : }
289 436115 : if (type.Maybe(Type::Undefined())) {
290 : // ToNumber(undefined) => NaN
291 430000 : type = Type::Union(type, Type::NaN(), zone());
292 : }
293 436090 : if (type.Maybe(singleton_false_)) {
294 : // ToNumber(false) => +0
295 425326 : type = Type::Union(type, cache_->kSingletonZero, zone());
296 : }
297 436175 : if (type.Maybe(singleton_true_)) {
298 : // ToNumber(true) => +1
299 425907 : type = Type::Union(type, cache_->kSingletonOne, zone());
300 : }
301 436194 : return Type::Intersect(type, Type::Number(), zone());
302 : }
303 :
304 360 : Type OperationTyper::ToNumberConvertBigInt(Type type) {
305 : // If the {type} includes any receivers, then the callbacks
306 : // might actually produce BigInt primitive values here.
307 : bool maybe_bigint =
308 360 : type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
309 360 : type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
310 :
311 : // Any BigInt is rounded to an integer Number in the range [-inf, inf].
312 360 : return maybe_bigint ? Type::Union(type, cache_->kInteger, zone()) : type;
313 : }
314 :
315 1169893 : Type OperationTyper::ToNumeric(Type type) {
316 : // If the {type} includes any receivers, then the callbacks
317 : // might actually produce BigInt primitive values here.
318 1169893 : if (type.Maybe(Type::Receiver())) {
319 59725 : type = Type::Union(type, Type::BigInt(), zone());
320 : }
321 : return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 1169893 : Type::Intersect(type, Type::BigInt(), zone()), zone());
323 : }
324 :
325 1281 : Type OperationTyper::NumberAbs(Type type) {
326 : DCHECK(type.Is(Type::Number()));
327 1281 : if (type.IsNone()) return type;
328 :
329 1238 : bool const maybe_nan = type.Maybe(Type::NaN());
330 1238 : bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 :
332 1238 : type = Type::Intersect(type, Type::PlainNumber(), zone());
333 1238 : if (!type.IsNone()) {
334 1186 : double const max = type.Max();
335 1186 : double const min = type.Min();
336 1186 : if (min < 0) {
337 2016 : if (type.Is(cache_->kInteger)) {
338 : type =
339 662 : Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
340 : } else {
341 677 : type = Type::PlainNumber();
342 : }
343 : }
344 : }
345 :
346 1238 : if (maybe_minuszero) {
347 667 : type = Type::Union(type, cache_->kSingletonZero, zone());
348 : }
349 1238 : if (maybe_nan) {
350 757 : type = Type::Union(type, Type::NaN(), zone());
351 : }
352 1238 : return type;
353 : }
354 :
355 101 : Type OperationTyper::NumberAcos(Type type) {
356 : DCHECK(type.Is(Type::Number()));
357 101 : return Type::Number();
358 : }
359 :
360 101 : Type OperationTyper::NumberAcosh(Type type) {
361 : DCHECK(type.Is(Type::Number()));
362 101 : return Type::Number();
363 : }
364 :
365 129 : Type OperationTyper::NumberAsin(Type type) {
366 : DCHECK(type.Is(Type::Number()));
367 129 : return Type::Number();
368 : }
369 :
370 101 : Type OperationTyper::NumberAsinh(Type type) {
371 : DCHECK(type.Is(Type::Number()));
372 101 : return Type::Number();
373 : }
374 :
375 101 : Type OperationTyper::NumberAtan(Type type) {
376 : DCHECK(type.Is(Type::Number()));
377 101 : return Type::Number();
378 : }
379 :
380 100 : Type OperationTyper::NumberAtanh(Type type) {
381 : DCHECK(type.Is(Type::Number()));
382 100 : return Type::Number();
383 : }
384 :
385 101 : Type OperationTyper::NumberCbrt(Type type) {
386 : DCHECK(type.Is(Type::Number()));
387 101 : return Type::Number();
388 : }
389 :
390 21858 : Type OperationTyper::NumberCeil(Type type) {
391 : DCHECK(type.Is(Type::Number()));
392 43716 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
393 21213 : type = Type::Intersect(type, Type::NaN(), zone());
394 21213 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
395 21213 : return type;
396 : }
397 :
398 201 : Type OperationTyper::NumberClz32(Type type) {
399 : DCHECK(type.Is(Type::Number()));
400 201 : return cache_->kZeroToThirtyTwo;
401 : }
402 :
403 157 : Type OperationTyper::NumberCos(Type type) {
404 : DCHECK(type.Is(Type::Number()));
405 157 : return Type::Number();
406 : }
407 :
408 122 : Type OperationTyper::NumberCosh(Type type) {
409 : DCHECK(type.Is(Type::Number()));
410 122 : return Type::Number();
411 : }
412 :
413 210 : Type OperationTyper::NumberExp(Type type) {
414 : DCHECK(type.Is(Type::Number()));
415 210 : return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
416 : }
417 :
418 143 : Type OperationTyper::NumberExpm1(Type type) {
419 : DCHECK(type.Is(Type::Number()));
420 143 : return Type::Number();
421 : }
422 :
423 86982 : Type OperationTyper::NumberFloor(Type type) {
424 : DCHECK(type.Is(Type::Number()));
425 173964 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
426 86354 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427 86354 : type = Type::Union(type, cache_->kInteger, zone());
428 86354 : return type;
429 : }
430 :
431 4221 : Type OperationTyper::NumberFround(Type type) {
432 : DCHECK(type.Is(Type::Number()));
433 4221 : return Type::Number();
434 : }
435 :
436 507 : Type OperationTyper::NumberLog(Type type) {
437 : DCHECK(type.Is(Type::Number()));
438 507 : return Type::Number();
439 : }
440 :
441 101 : Type OperationTyper::NumberLog1p(Type type) {
442 : DCHECK(type.Is(Type::Number()));
443 101 : return Type::Number();
444 : }
445 :
446 101 : Type OperationTyper::NumberLog2(Type type) {
447 : DCHECK(type.Is(Type::Number()));
448 101 : return Type::Number();
449 : }
450 :
451 101 : Type OperationTyper::NumberLog10(Type type) {
452 : DCHECK(type.Is(Type::Number()));
453 101 : return Type::Number();
454 : }
455 :
456 4846 : Type OperationTyper::NumberRound(Type type) {
457 : DCHECK(type.Is(Type::Number()));
458 9692 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
459 4753 : type = Type::Intersect(type, Type::NaN(), zone());
460 4753 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
461 4753 : return type;
462 : }
463 :
464 212 : Type OperationTyper::NumberSign(Type type) {
465 : DCHECK(type.Is(Type::Number()));
466 424 : if (type.Is(cache_->kZeroish)) return type;
467 169 : bool maybe_minuszero = type.Maybe(Type::MinusZero());
468 169 : bool maybe_nan = type.Maybe(Type::NaN());
469 169 : type = Type::Intersect(type, Type::PlainNumber(), zone());
470 169 : if (type.IsNone()) {
471 : // Do nothing.
472 169 : } else if (type.Max() < 0.0) {
473 3 : type = cache_->kSingletonMinusOne;
474 166 : } else if (type.Max() <= 0.0) {
475 0 : type = cache_->kMinusOneOrZero;
476 166 : } else if (type.Min() > 0.0) {
477 11 : type = cache_->kSingletonOne;
478 155 : } else if (type.Min() >= 0.0) {
479 1 : type = cache_->kZeroOrOne;
480 : } else {
481 154 : type = Type::Range(-1.0, 1.0, zone());
482 : }
483 169 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484 169 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485 : DCHECK(!type.IsNone());
486 169 : return type;
487 : }
488 :
489 194 : Type OperationTyper::NumberSin(Type type) {
490 : DCHECK(type.Is(Type::Number()));
491 194 : return Type::Number();
492 : }
493 :
494 122 : Type OperationTyper::NumberSinh(Type type) {
495 : DCHECK(type.Is(Type::Number()));
496 122 : return Type::Number();
497 : }
498 :
499 260 : Type OperationTyper::NumberSqrt(Type type) {
500 : DCHECK(type.Is(Type::Number()));
501 260 : return Type::Number();
502 : }
503 :
504 185 : Type OperationTyper::NumberTan(Type type) {
505 : DCHECK(type.Is(Type::Number()));
506 185 : return Type::Number();
507 : }
508 :
509 122 : Type OperationTyper::NumberTanh(Type type) {
510 : DCHECK(type.Is(Type::Number()));
511 122 : return Type::Number();
512 : }
513 :
514 21298 : Type OperationTyper::NumberTrunc(Type type) {
515 : DCHECK(type.Is(Type::Number()));
516 42596 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
517 21078 : type = Type::Intersect(type, Type::NaN(), zone());
518 21078 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
519 21078 : return type;
520 : }
521 :
522 46126 : Type OperationTyper::NumberToBoolean(Type type) {
523 : DCHECK(type.Is(Type::Number()));
524 46126 : if (type.IsNone()) return type;
525 92166 : if (type.Is(cache_->kZeroish)) return singleton_false_;
526 46082 : if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527 2137 : return singleton_true_; // Ruled out nan, -0 and +0.
528 : }
529 : return Type::Boolean();
530 : }
531 :
532 191018 : Type OperationTyper::NumberToInt32(Type type) {
533 : DCHECK(type.Is(Type::Number()));
534 :
535 191018 : if (type.Is(Type::Signed32())) return type;
536 104676 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
537 48971 : if (type.Is(signed32ish_)) {
538 6283 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
539 6283 : Type::Signed32(), zone());
540 : }
541 : return Type::Signed32();
542 : }
543 :
544 12502 : Type OperationTyper::NumberToString(Type type) {
545 : DCHECK(type.Is(Type::Number()));
546 12502 : if (type.IsNone()) return type;
547 12455 : if (type.Is(Type::NaN())) return singleton_NaN_string_;
548 24908 : if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
549 : return Type::String();
550 : }
551 :
552 54415 : Type OperationTyper::NumberToUint32(Type type) {
553 : DCHECK(type.Is(Type::Number()));
554 :
555 54415 : if (type.Is(Type::Unsigned32())) return type;
556 47368 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
557 21976 : if (type.Is(unsigned32ish_)) {
558 46 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
559 46 : Type::Unsigned32(), zone());
560 : }
561 : return Type::Unsigned32();
562 : }
563 :
564 1618 : Type OperationTyper::NumberToUint8Clamped(Type type) {
565 : DCHECK(type.Is(Type::Number()));
566 :
567 3236 : if (type.Is(cache_->kUint8)) return type;
568 1518 : return cache_->kUint8;
569 : }
570 :
571 3569 : Type OperationTyper::NumberSilenceNaN(Type type) {
572 : DCHECK(type.Is(Type::Number()));
573 : // TODO(jarin): This is a terrible hack; we definitely need a dedicated type
574 : // for the hole (tagged and/or double). Otherwise if the input is the hole
575 : // NaN constant, we'd just eliminate this node in JSTypedLowering.
576 3569 : if (type.Maybe(Type::NaN())) return Type::Number();
577 995 : return type;
578 : }
579 :
580 1747548 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581 : DCHECK(lhs.Is(Type::Number()));
582 : DCHECK(rhs.Is(Type::Number()));
583 :
584 3493911 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
585 :
586 : // Addition can return NaN if either input can be NaN or we try to compute
587 : // the sum of two infinities of opposite sign.
588 1746243 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
589 :
590 : // Addition can yield minus zero only if both inputs can be minus zero.
591 : bool maybe_minuszero = true;
592 1746000 : if (lhs.Maybe(Type::MinusZero())) {
593 250662 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
594 : } else {
595 : maybe_minuszero = false;
596 : }
597 1746085 : if (rhs.Maybe(Type::MinusZero())) {
598 187649 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
599 : } else {
600 : maybe_minuszero = false;
601 : }
602 :
603 : // We can give more precise types for integers.
604 : Type type = Type::None();
605 1746265 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606 1746256 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607 3492431 : if (!lhs.IsNone() && !rhs.IsNone()) {
608 4853700 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
609 1245004 : type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610 : } else {
611 1305459 : if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 319151 : (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) {
613 : maybe_nan = true;
614 : }
615 : type = Type::PlainNumber();
616 : }
617 : }
618 :
619 : // Take into account the -0 and NaN information computed earlier.
620 1746264 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 1746257 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622 1746270 : return type;
623 : }
624 :
625 63522 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626 : DCHECK(lhs.Is(Type::Number()));
627 : DCHECK(rhs.Is(Type::Number()));
628 :
629 126580 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
630 :
631 : // Subtraction can return NaN if either input can be NaN or we try to
632 : // compute the sum of two infinities of opposite sign.
633 62962 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
634 :
635 : // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs}
636 : // can be zero.
637 : bool maybe_minuszero = false;
638 62962 : if (lhs.Maybe(Type::MinusZero())) {
639 5854 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
640 5854 : maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
641 : }
642 62962 : if (rhs.Maybe(Type::MinusZero())) {
643 2299 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
644 : }
645 :
646 : // We can give more precise types for integers.
647 : Type type = Type::None();
648 62962 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649 62962 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650 125799 : if (!lhs.IsNone() && !rhs.IsNone()) {
651 181220 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
652 54449 : type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653 : } else {
654 22690 : if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 6926 : (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) {
656 : maybe_nan = true;
657 : }
658 : type = Type::PlainNumber();
659 : }
660 : }
661 :
662 : // Take into account the -0 and NaN information computed earlier.
663 62962 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 62962 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665 62962 : return type;
666 : }
667 :
668 506172 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669 506172 : Type result = SpeculativeNumberAdd(lhs, rhs);
670 : // If we have a Smi or Int32 feedback, the representation selection will
671 : // either truncate or it will check the inputs (i.e., deopt if not int32).
672 : // In either case the result will be in the safe integer range, so we
673 : // can bake in the type here. This needs to be in sync with
674 : // SimplifiedLowering::VisitSpeculativeAdditiveOp.
675 506265 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
676 : }
677 :
678 39847 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679 39847 : Type result = SpeculativeNumberSubtract(lhs, rhs);
680 : // If we have a Smi or Int32 feedback, the representation selection will
681 : // either truncate or it will check the inputs (i.e., deopt if not int32).
682 : // In either case the result will be in the safe integer range, so we
683 : // can bake in the type here. This needs to be in sync with
684 : // SimplifiedLowering::VisitSpeculativeAdditiveOp.
685 39847 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
686 : }
687 :
688 81100 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689 : DCHECK(lhs.Is(Type::Number()));
690 : DCHECK(rhs.Is(Type::Number()));
691 :
692 161964 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693 161518 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
694 :
695 : // Multiplication propagates NaN:
696 : // NaN * x = NaN (regardless of sign of x)
697 : // 0 * Infinity = NaN (regardless of signs)
698 172410 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699 83193 : (lhs.Maybe(cache_->kZeroish) &&
700 200927 : (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701 47949 : (rhs.Maybe(cache_->kZeroish) &&
702 6278 : (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703 80634 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704 : DCHECK(!lhs.IsNone());
705 80634 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706 : DCHECK(!rhs.IsNone());
707 :
708 : // Try to rule out -0.
709 124510 : bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710 85969 : rhs.Maybe(Type::MinusZero()) ||
711 184269 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
712 27666 : (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
713 80634 : if (lhs.Maybe(Type::MinusZero())) {
714 36758 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
715 36758 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716 : }
717 80634 : if (rhs.Maybe(Type::MinusZero())) {
718 4970 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
719 4970 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720 : }
721 :
722 : // Compute the effective type, utilizing range information if possible.
723 198658 : Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
724 55881 : ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 136515 : : Type::OrderedNumber();
726 :
727 : // Take into account the -0 and NaN information computed earlier.
728 80634 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 80634 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730 80634 : return type;
731 : }
732 :
733 65461 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734 : DCHECK(lhs.Is(Type::Number()));
735 : DCHECK(rhs.Is(Type::Number()));
736 :
737 130841 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738 128373 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
739 :
740 : // Division is tricky, so all we do is try ruling out -0 and NaN.
741 93131 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
742 60163 : ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743 4223 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744 63490 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745 : DCHECK(!lhs.IsNone());
746 63490 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747 : DCHECK(!rhs.IsNone());
748 :
749 : // Try to rule out -0.
750 : bool maybe_minuszero =
751 110021 : !lhs.Is(cache_->kInteger) ||
752 117697 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
753 62535 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY);
754 :
755 : // Take into account the -0 and NaN information computed earlier.
756 : Type type = Type::PlainNumber();
757 63490 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758 63490 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759 63490 : return type;
760 : }
761 :
762 14618 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763 : DCHECK(lhs.Is(Type::Number()));
764 : DCHECK(rhs.Is(Type::Number()));
765 :
766 29155 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
767 :
768 : // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or
769 : // {lhs} is not finite, or the {rhs} is a zero value.
770 36552 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
771 34751 : lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY;
772 :
773 : // Deal with -0 inputs, only the signbit of {lhs} matters for the result.
774 : bool maybe_minuszero = false;
775 14487 : if (lhs.Maybe(Type::MinusZero())) {
776 : maybe_minuszero = true;
777 3759 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
778 : }
779 14487 : if (rhs.Maybe(Type::MinusZero())) {
780 898 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
781 : }
782 :
783 : // Rule out NaN and -0, and check what we can do with the remaining type info.
784 : Type type = Type::None();
785 14487 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 14487 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
787 :
788 : // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited,
789 : // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}.
790 28856 : if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
791 : // Determine the bounds of {lhs} and {rhs}.
792 14228 : double const lmin = lhs.Min();
793 14228 : double const lmax = lhs.Max();
794 14228 : double const rmin = rhs.Min();
795 14228 : double const rmax = rhs.Max();
796 :
797 : // The sign of the result is the sign of the {lhs}.
798 14228 : if (lmin < 0.0) maybe_minuszero = true;
799 :
800 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
801 40134 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
802 33669 : double labs = std::max(std::abs(lmin), std::abs(lmax));
803 33669 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804 11223 : double abs = std::min(labs, rabs);
805 : double min = 0.0, max = 0.0;
806 11223 : if (lmin >= 0.0) {
807 : // {lhs} positive.
808 : min = 0.0;
809 : max = abs;
810 8222 : } else if (lmax <= 0.0) {
811 : // {lhs} negative.
812 725 : min = 0.0 - abs;
813 : max = 0.0;
814 : } else {
815 : // {lhs} positive or negative.
816 7497 : min = 0.0 - abs;
817 : max = abs;
818 : }
819 11223 : type = Type::Range(min, max, zone());
820 : } else {
821 : type = Type::PlainNumber();
822 : }
823 : }
824 :
825 : // Take into account the -0 and NaN information computed earlier.
826 14487 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 14487 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828 14487 : return type;
829 : }
830 :
831 45066 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832 : DCHECK(lhs.Is(Type::Number()));
833 : DCHECK(rhs.Is(Type::Number()));
834 :
835 45066 : lhs = NumberToInt32(lhs);
836 45066 : rhs = NumberToInt32(rhs);
837 :
838 89965 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 :
840 44849 : double lmin = lhs.Min();
841 44849 : double rmin = rhs.Min();
842 44849 : double lmax = lhs.Max();
843 44849 : double rmax = rhs.Max();
844 : // Or-ing any two values results in a value no smaller than their minimum.
845 : // Even no smaller than their maximum if both values are non-negative.
846 : double min =
847 89698 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848 44849 : double max = kMaxInt;
849 :
850 : // Or-ing with 0 is essentially a conversion to int32.
851 44849 : if (rmin == 0 && rmax == 0) {
852 : min = lmin;
853 31891 : max = lmax;
854 : }
855 44849 : if (lmin == 0 && lmax == 0) {
856 : min = rmin;
857 591 : max = rmax;
858 : }
859 :
860 44849 : if (lmax < 0 || rmax < 0) {
861 : // Or-ing two values of which at least one is negative results in a negative
862 : // value.
863 458 : max = std::min(max, -1.0);
864 : }
865 44849 : return Type::Range(min, max, zone());
866 : }
867 :
868 28173 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869 : DCHECK(lhs.Is(Type::Number()));
870 : DCHECK(rhs.Is(Type::Number()));
871 :
872 28173 : lhs = NumberToInt32(lhs);
873 28173 : rhs = NumberToInt32(rhs);
874 :
875 56206 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 :
877 27983 : double lmin = lhs.Min();
878 27983 : double rmin = rhs.Min();
879 27983 : double lmax = lhs.Max();
880 27983 : double rmax = rhs.Max();
881 : double min = kMinInt;
882 : // And-ing any two values results in a value no larger than their maximum.
883 : // Even no larger than their minimum if both values are non-negative.
884 : double max =
885 55966 : lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
886 : // And-ing with a non-negative value x causes the result to be between
887 : // zero and x.
888 27983 : if (lmin >= 0) {
889 : min = 0;
890 7593 : max = std::min(max, lmax);
891 : }
892 27983 : if (rmin >= 0) {
893 : min = 0;
894 25700 : max = std::min(max, rmax);
895 : }
896 27983 : return Type::Range(min, max, zone());
897 : }
898 :
899 4317 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900 : DCHECK(lhs.Is(Type::Number()));
901 : DCHECK(rhs.Is(Type::Number()));
902 :
903 4317 : lhs = NumberToInt32(lhs);
904 4317 : rhs = NumberToInt32(rhs);
905 :
906 8545 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 :
908 4178 : double lmin = lhs.Min();
909 4178 : double rmin = rhs.Min();
910 4178 : double lmax = lhs.Max();
911 4178 : double rmax = rhs.Max();
912 4178 : if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
913 : // Xor-ing negative or non-negative values results in a non-negative value.
914 : return Type::Unsigned31();
915 : }
916 3930 : if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
917 : // Xor-ing a negative and a non-negative value results in a negative value.
918 : // TODO(jarin) Use a range here.
919 : return Type::Negative32();
920 : }
921 : return Type::Signed32();
922 : }
923 :
924 9295 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925 : DCHECK(lhs.Is(Type::Number()));
926 : DCHECK(rhs.Is(Type::Number()));
927 :
928 9295 : lhs = NumberToInt32(lhs);
929 9295 : rhs = NumberToUint32(rhs);
930 :
931 18502 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 :
933 9157 : int32_t min_lhs = lhs.Min();
934 9157 : int32_t max_lhs = lhs.Max();
935 9157 : uint32_t min_rhs = rhs.Min();
936 9157 : uint32_t max_rhs = rhs.Max();
937 9157 : if (max_rhs > 31) {
938 : // rhs can be larger than the bitmask
939 : max_rhs = 31;
940 : min_rhs = 0;
941 : }
942 :
943 9157 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944 : // overflow possible
945 : return Type::Signed32();
946 : }
947 :
948 : double min =
949 2380 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950 3570 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951 : double max =
952 2380 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953 3570 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 :
955 1190 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956 941 : return Type::Range(min, max, zone());
957 : }
958 :
959 18222 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960 : DCHECK(lhs.Is(Type::Number()));
961 : DCHECK(rhs.Is(Type::Number()));
962 :
963 18222 : lhs = NumberToInt32(lhs);
964 18222 : rhs = NumberToUint32(rhs);
965 :
966 36334 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 :
968 18048 : int32_t min_lhs = lhs.Min();
969 18048 : int32_t max_lhs = lhs.Max();
970 18048 : uint32_t min_rhs = rhs.Min();
971 18048 : uint32_t max_rhs = rhs.Max();
972 18048 : if (max_rhs > 31) {
973 : // rhs can be larger than the bitmask
974 : max_rhs = 31;
975 : min_rhs = 0;
976 : }
977 36096 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978 36096 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 :
980 18048 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981 16624 : return Type::Range(min, max, zone());
982 : }
983 :
984 7924 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985 : DCHECK(lhs.Is(Type::Number()));
986 : DCHECK(rhs.Is(Type::Number()));
987 :
988 7924 : lhs = NumberToUint32(lhs);
989 7924 : rhs = NumberToUint32(rhs);
990 :
991 15742 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 :
993 7761 : uint32_t min_lhs = lhs.Min();
994 7761 : uint32_t max_lhs = lhs.Max();
995 7761 : uint32_t min_rhs = rhs.Min();
996 7761 : uint32_t max_rhs = rhs.Max();
997 7761 : if (max_rhs > 31) {
998 : // rhs can be larger than the bitmask
999 : max_rhs = 31;
1000 : min_rhs = 0;
1001 : }
1002 :
1003 7761 : double min = min_lhs >> max_rhs;
1004 7761 : double max = max_lhs >> min_rhs;
1005 : DCHECK_LE(0, min);
1006 : DCHECK_LE(max, kMaxUInt32);
1007 :
1008 7761 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009 7130 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010 2936 : return Type::Range(min, max, zone());
1011 : }
1012 :
1013 138 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014 : DCHECK(lhs.Is(Type::Number()));
1015 : DCHECK(rhs.Is(Type::Number()));
1016 138 : return Type::Number();
1017 : }
1018 :
1019 2754 : Type OperationTyper::NumberImul(Type lhs, Type rhs) {
1020 : DCHECK(lhs.Is(Type::Number()));
1021 : DCHECK(rhs.Is(Type::Number()));
1022 : // TODO(turbofan): We should be able to do better here.
1023 2754 : return Type::Signed32();
1024 : }
1025 :
1026 10319 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027 : DCHECK(lhs.Is(Type::Number()));
1028 : DCHECK(rhs.Is(Type::Number()));
1029 :
1030 20600 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031 20502 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 :
1033 : Type type = Type::None();
1034 10239 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 250 : type = Type::Union(type, Type::NaN(), zone());
1036 : }
1037 10239 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038 : DCHECK(!lhs.IsNone());
1039 10239 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040 : DCHECK(!rhs.IsNone());
1041 30487 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1042 10009 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1043 : // TODO(turbofan): This could still be improved in ruling out -0 when
1044 : // one of the inputs' min is 0.
1045 19858 : double max = std::max(lhs.Max(), rhs.Max());
1046 19858 : double min = std::max(lhs.Min(), rhs.Min());
1047 9929 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048 28246 : if (min <= 0.0 && 0.0 <= max &&
1049 16669 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050 182 : type = Type::Union(type, Type::MinusZero(), zone());
1051 : }
1052 : } else {
1053 310 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054 : }
1055 10239 : return type;
1056 : }
1057 :
1058 11854 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059 : DCHECK(lhs.Is(Type::Number()));
1060 : DCHECK(rhs.Is(Type::Number()));
1061 :
1062 23670 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063 23572 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 :
1065 : Type type = Type::None();
1066 11774 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 511 : type = Type::Union(type, Type::NaN(), zone());
1068 : }
1069 11774 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070 : DCHECK(!lhs.IsNone());
1071 11774 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072 : DCHECK(!rhs.IsNone());
1073 34876 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1074 11328 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1075 22448 : double max = std::min(lhs.Max(), rhs.Max());
1076 22448 : double min = std::min(lhs.Min(), rhs.Min());
1077 11224 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078 33493 : if (min <= 0.0 && 0.0 <= max &&
1079 21996 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080 147 : type = Type::Union(type, Type::MinusZero(), zone());
1081 : }
1082 : } else {
1083 550 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084 : }
1085 11774 : return type;
1086 : }
1087 :
1088 3098 : Type OperationTyper::NumberPow(Type lhs, Type rhs) {
1089 : DCHECK(lhs.Is(Type::Number()));
1090 : DCHECK(rhs.Is(Type::Number()));
1091 : // TODO(turbofan): We should be able to do better here.
1092 3098 : return Type::Number();
1093 : }
1094 :
1095 : #define SPECULATIVE_NUMBER_BINOP(Name) \
1096 : Type OperationTyper::Speculative##Name(Type lhs, Type rhs) { \
1097 : lhs = SpeculativeToNumber(lhs); \
1098 : rhs = SpeculativeToNumber(rhs); \
1099 : return Name(lhs, rhs); \
1100 : }
1101 602654 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 40913 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 48854 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 49788 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 9304 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 35313 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 14024 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 2503 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 4727 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 14884 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 3680 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 : #undef SPECULATIVE_NUMBER_BINOP
1113 :
1114 1787527 : Type OperationTyper::SpeculativeToNumber(Type type) {
1115 1787527 : return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
1116 : }
1117 :
1118 0 : Type OperationTyper::ToPrimitive(Type type) {
1119 0 : if (type.Is(Type::Primitive())) {
1120 0 : return type;
1121 : }
1122 : return Type::Primitive();
1123 : }
1124 :
1125 0 : Type OperationTyper::Invert(Type type) {
1126 : DCHECK(type.Is(Type::Boolean()));
1127 : DCHECK(!type.IsNone());
1128 0 : if (type.Is(singleton_false())) return singleton_true();
1129 0 : if (type.Is(singleton_true())) return singleton_false();
1130 0 : return type;
1131 : }
1132 :
1133 0 : OperationTyper::ComparisonOutcome OperationTyper::Invert(
1134 : ComparisonOutcome outcome) {
1135 : ComparisonOutcome result(0);
1136 0 : if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
1137 0 : if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
1138 0 : if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
1139 0 : return result;
1140 : }
1141 :
1142 0 : Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
1143 0 : if ((outcome & kComparisonFalse) != 0 ||
1144 : (outcome & kComparisonUndefined) != 0) {
1145 : return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
1146 0 : : singleton_false();
1147 : }
1148 : // Type should be non empty, so we know it should be true.
1149 : DCHECK_NE(0, outcome & kComparisonTrue);
1150 : return singleton_true();
1151 : }
1152 :
1153 : namespace {
1154 :
1155 369612 : Type JSType(Type type) {
1156 369612 : if (type.Is(Type::Boolean())) return Type::Boolean();
1157 362159 : if (type.Is(Type::String())) return Type::String();
1158 281152 : if (type.Is(Type::Number())) return Type::Number();
1159 148203 : if (type.Is(Type::BigInt())) return Type::BigInt();
1160 148101 : if (type.Is(Type::Undefined())) return Type::Undefined();
1161 145658 : if (type.Is(Type::Null())) return Type::Null();
1162 145435 : if (type.Is(Type::Symbol())) return Type::Symbol();
1163 145394 : if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164 : return Type::Any();
1165 : }
1166 :
1167 : } // namespace
1168 :
1169 467 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170 467 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171 467 : if (lhs.Is(Type::NaN())) {
1172 40 : if (rhs.Is(Type::NaN())) return singleton_true();
1173 40 : if (!rhs.Maybe(Type::NaN())) return singleton_false();
1174 427 : } else if (rhs.Is(Type::NaN())) {
1175 16 : if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176 : }
1177 467 : if (lhs.Is(Type::MinusZero())) {
1178 93 : if (rhs.Is(Type::MinusZero())) return singleton_true();
1179 93 : if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
1180 374 : } else if (rhs.Is(Type::MinusZero())) {
1181 44 : if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182 : }
1183 1048 : if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1184 60 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1185 : return singleton_false();
1186 : }
1187 : return Type::Boolean();
1188 : }
1189 :
1190 184339 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1191 184339 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1192 357814 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1193 447340 : if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1194 89809 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1195 : return singleton_false();
1196 : }
1197 349322 : if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1198 : return singleton_false();
1199 : }
1200 176290 : if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1201 : // Types are equal and are inhabited only by a single semantic value,
1202 : // which is not nan due to the earlier check.
1203 : return singleton_true();
1204 : }
1205 : return Type::Boolean();
1206 : }
1207 :
1208 53008 : Type OperationTyper::StringConcat(Type length, Type first, Type second) {
1209 159020 : if (length.IsNone() || first.IsNone() || second.IsNone()) return Type::None();
1210 52987 : if (first.Is(Type::EmptyString())) return second;
1211 52743 : if (second.Is(Type::EmptyString())) return first;
1212 :
1213 52708 : first = Type::Intersect(first, Type::NonEmptyString(), zone());
1214 52708 : second = Type::Intersect(second, Type::NonEmptyString(), zone());
1215 :
1216 : Type type = Type::NonEmptyString();
1217 66829 : if (first.Is(Type::NonEmptyOneByteString()) &&
1218 : second.Is(Type::NonEmptyOneByteString())) {
1219 : type = Type::NonEmptyOneByteString();
1220 85624 : } else if (first.Is(Type::NonEmptyTwoByteString()) ||
1221 : second.Is(Type::NonEmptyTwoByteString())) {
1222 : type = Type::NonEmptyTwoByteString();
1223 : }
1224 :
1225 52708 : if (length.Min() == 0) {
1226 26285 : type = Type::Union(type, Type::EmptyString(), zone());
1227 : }
1228 52708 : return type;
1229 : }
1230 :
1231 135673 : Type OperationTyper::CheckBounds(Type index, Type length) {
1232 : DCHECK(length.Is(cache_->kPositiveSafeInteger));
1233 271346 : if (length.Is(cache_->kSingletonZero)) return Type::None();
1234 135608 : Type mask = Type::Range(0.0, length.Max() - 1, zone());
1235 135608 : if (index.Maybe(Type::MinusZero())) {
1236 6236 : index = Type::Union(index, cache_->kSingletonZero, zone());
1237 : }
1238 135608 : return Type::Intersect(index, mask, zone());
1239 : }
1240 :
1241 1249 : Type OperationTyper::CheckFloat64Hole(Type type) {
1242 1249 : if (type.Maybe(Type::Hole())) {
1243 : // Turn "the hole" into undefined.
1244 1185 : type = Type::Intersect(type, Type::Number(), zone());
1245 1185 : type = Type::Union(type, Type::Undefined(), zone());
1246 : }
1247 1249 : return type;
1248 : }
1249 :
1250 3741 : Type OperationTyper::CheckNumber(Type type) {
1251 3741 : return Type::Intersect(type, Type::Number(), zone());
1252 : }
1253 :
1254 5075 : Type OperationTyper::CheckInternalizedString(Type type) {
1255 5075 : return Type::Intersect(type, Type::InternalizedString(), zone());
1256 : }
1257 :
1258 36 : Type OperationTyper::CheckNonEmptyString(Type type) {
1259 36 : return Type::Intersect(type, Type::NonEmptyString(), zone());
1260 : }
1261 :
1262 3645 : Type OperationTyper::CheckNonEmptyOneByteString(Type type) {
1263 3645 : return Type::Intersect(type, Type::NonEmptyOneByteString(), zone());
1264 : }
1265 :
1266 474 : Type OperationTyper::CheckNonEmptyTwoByteString(Type type) {
1267 474 : return Type::Intersect(type, Type::NonEmptyTwoByteString(), zone());
1268 : }
1269 :
1270 29215 : Type OperationTyper::CheckString(Type type) {
1271 29215 : return Type::Intersect(type, Type::String(), zone());
1272 : }
1273 :
1274 100081 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1275 100081 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1276 : }
1277 :
1278 4673 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1279 4673 : if (input.Maybe(Type::Hole())) {
1280 : // Turn "the hole" into undefined.
1281 4623 : Type type = Type::Intersect(input, Type::NonInternal(), zone());
1282 4623 : return Type::Union(type, Type::Undefined(), zone());
1283 : }
1284 50 : return input;
1285 : }
1286 :
1287 210594 : Type OperationTyper::ToBoolean(Type type) {
1288 210594 : if (type.Is(Type::Boolean())) return type;
1289 175773 : if (type.Is(falsish_)) return singleton_false_;
1290 173270 : if (type.Is(truish_)) return singleton_true_;
1291 173147 : if (type.Is(Type::Number())) {
1292 45578 : return NumberToBoolean(type);
1293 : }
1294 : return Type::Boolean();
1295 : }
1296 :
1297 : } // namespace compiler
1298 : } // namespace internal
1299 122004 : } // namespace v8
|