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 1393880 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20 1393880 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = broker->isolate()->factory();
22 1393877 : infinity_ = Type::NewConstant(V8_INFINITY, zone);
23 1393882 : minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24 1393886 : Type truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 :
27 : singleton_empty_string_ =
28 1393886 : Type::HeapConstant(broker, factory->empty_string(), zone);
29 : singleton_NaN_string_ =
30 1393878 : Type::HeapConstant(broker, factory->NaN_string(), zone);
31 : singleton_zero_string_ =
32 1393884 : Type::HeapConstant(broker, factory->zero_string(), zone);
33 1393886 : singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34 1393887 : singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35 : singleton_the_hole_ =
36 1393888 : Type::HeapConstant(broker, factory->the_hole_value(), zone);
37 1393886 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38 1393885 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 :
40 : falsish_ = Type::Union(
41 : Type::Undetectable(),
42 1393879 : Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
43 : Type::Union(singleton_empty_string_, Type::Hole(), zone),
44 : zone),
45 2787768 : zone);
46 : truish_ = Type::Union(
47 : singleton_true_,
48 1393888 : Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 1393888 : }
50 :
51 1201313 : Type OperationTyper::Merge(Type left, Type right) {
52 1201313 : return Type::Union(left, right, zone());
53 : }
54 :
55 448283 : 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 448283 : 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 448283 : if (current_min != previous_range.Min()) {
105 : new_min = -V8_INFINITY;
106 330643 : for (double const min : kWeakenMinLimits) {
107 168960 : if (min <= current_min) {
108 : new_min = min;
109 : break;
110 : }
111 : }
112 : }
113 :
114 448284 : 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 448284 : if (current_max != previous_range.Max()) {
119 : new_max = V8_INFINITY;
120 7102649 : for (double const max : kWeakenMaxLimits) {
121 3698506 : if (max >= current_max) {
122 : new_max = max;
123 : break;
124 : }
125 : }
126 : }
127 :
128 448284 : 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 1354724 : double x = +V8_INFINITY;
147 12192228 : for (size_t i = 0; i < n; ++i) {
148 5418752 : if (!std::isnan(a[i])) {
149 5418702 : x = std::min(a[i], x);
150 : }
151 : }
152 : DCHECK(!std::isnan(x));
153 1354724 : 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 1354724 : double x = -V8_INFINITY;
162 12192092 : for (size_t i = 0; i < n; ++i) {
163 5418684 : if (!std::isnan(a[i])) {
164 5418574 : x = std::max(a[i], x);
165 : }
166 : }
167 : DCHECK(!std::isnan(x));
168 1354724 : return x == 0 ? 0 : x; // -0 -> 0
169 : }
170 :
171 : } // namespace
172 :
173 1245264 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174 : double rhs_max) {
175 : double results[4];
176 1245264 : results[0] = lhs_min + rhs_min;
177 1245264 : results[1] = lhs_min + rhs_max;
178 1245264 : results[2] = lhs_max + rhs_min;
179 1245264 : 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 11206960 : for (int i = 0; i < 4; ++i) {
186 4980848 : if (std::isnan(results[i])) ++nans;
187 : }
188 1245264 : if (nans == 4) return Type::NaN();
189 1245258 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190 1245279 : 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 1245285 : return type;
197 : }
198 :
199 54199 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200 : double rhs_min, double rhs_max) {
201 : double results[4];
202 54199 : results[0] = lhs_min - rhs_min;
203 54199 : results[1] = lhs_min - rhs_max;
204 54199 : results[2] = lhs_max - rhs_min;
205 54199 : 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 487791 : for (int i = 0; i < 4; ++i) {
212 216796 : if (std::isnan(results[i])) ++nans;
213 : }
214 54199 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215 54193 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216 54193 : 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 55350 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225 : double rhs_min, double rhs_max) {
226 : double results[4];
227 55350 : results[0] = lhs_min * rhs_min;
228 55350 : results[1] = lhs_min * rhs_max;
229 55350 : results[2] = lhs_max * rhs_min;
230 55350 : 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 497656 : for (int i = 0; i < 4; ++i) {
236 221230 : if (std::isnan(results[i])) {
237 77 : return cache_->kIntegerOrMinusZeroOrNaN;
238 : }
239 : }
240 : double min = array_min(results, 4);
241 : double max = array_max(results, 4);
242 55273 : Type type = Type::Range(min, max, zone());
243 55273 : if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244 42718 : type = Type::Union(type, Type::MinusZero(), zone());
245 : }
246 : // 0 * V8_INFINITY is NaN, regardless of sign
247 94131 : if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248 74972 : (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249 55176 : ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250 116 : (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251 173 : type = Type::Union(type, Type::NaN(), zone());
252 : }
253 55273 : return type;
254 : }
255 :
256 80499 : Type OperationTyper::ConvertReceiver(Type type) {
257 80499 : if (type.Is(Type::Receiver())) return type;
258 80492 : bool const maybe_primitive = type.Maybe(Type::Primitive());
259 80492 : type = Type::Intersect(type, Type::Receiver(), zone());
260 80492 : 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 80492 : type = Type::Union(type, Type::OtherObject(), zone());
264 : }
265 80492 : return type;
266 : }
267 :
268 3299507 : Type OperationTyper::ToNumber(Type type) {
269 3299422 : 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 717071 : 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 438985 : 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 439016 : if (type.Maybe(Type::Null())) {
286 : // ToNumber(null) => +0
287 426337 : type = Type::Union(type, cache_->kSingletonZero, zone());
288 : }
289 439039 : if (type.Maybe(Type::Undefined())) {
290 : // ToNumber(undefined) => NaN
291 432976 : type = Type::Union(type, Type::NaN(), zone());
292 : }
293 439031 : if (type.Maybe(singleton_false_)) {
294 : // ToNumber(false) => +0
295 428295 : type = Type::Union(type, cache_->kSingletonZero, zone());
296 : }
297 439093 : if (type.Maybe(singleton_true_)) {
298 : // ToNumber(true) => +1
299 428890 : type = Type::Union(type, cache_->kSingletonOne, zone());
300 : }
301 439110 : return Type::Intersect(type, Type::Number(), zone());
302 : }
303 :
304 359 : 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 359 : type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
309 359 : type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
310 :
311 : // Any BigInt is rounded to an integer Number in the range [-inf, inf].
312 359 : return maybe_bigint ? Type::Union(type, cache_->kInteger, zone()) : type;
313 : }
314 :
315 1169516 : Type OperationTyper::ToNumeric(Type type) {
316 : // If the {type} includes any receivers, then the callbacks
317 : // might actually produce BigInt primitive values here.
318 1169516 : if (type.Maybe(Type::Receiver())) {
319 59807 : type = Type::Union(type, Type::BigInt(), zone());
320 : }
321 : return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 1169516 : 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 1245 : bool const maybe_nan = type.Maybe(Type::NaN());
330 1245 : bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 :
332 1245 : type = Type::Intersect(type, Type::PlainNumber(), zone());
333 1245 : if (!type.IsNone()) {
334 1193 : double const max = type.Max();
335 1193 : double const min = type.Min();
336 1193 : if (min < 0) {
337 2028 : if (type.Is(cache_->kInteger)) {
338 : type =
339 664 : Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
340 : } else {
341 682 : type = Type::PlainNumber();
342 : }
343 : }
344 : }
345 :
346 1245 : if (maybe_minuszero) {
347 673 : type = Type::Union(type, cache_->kSingletonZero, zone());
348 : }
349 1245 : if (maybe_nan) {
350 763 : type = Type::Union(type, Type::NaN(), zone());
351 : }
352 1245 : 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 21217 : type = Type::Intersect(type, Type::NaN(), zone());
394 21217 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
395 21217 : return type;
396 : }
397 :
398 207 : Type OperationTyper::NumberClz32(Type type) {
399 : DCHECK(type.Is(Type::Number()));
400 207 : 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 86358 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427 86358 : type = Type::Union(type, cache_->kInteger, zone());
428 86358 : 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 4757 : type = Type::Intersect(type, Type::NaN(), zone());
460 4757 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
461 4757 : 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 175 : bool maybe_minuszero = type.Maybe(Type::MinusZero());
468 175 : bool maybe_nan = type.Maybe(Type::NaN());
469 175 : type = Type::Intersect(type, Type::PlainNumber(), zone());
470 175 : if (type.IsNone()) {
471 : // Do nothing.
472 175 : } else if (type.Max() < 0.0) {
473 5 : type = cache_->kSingletonMinusOne;
474 170 : } else if (type.Max() <= 0.0) {
475 0 : type = cache_->kMinusOneOrZero;
476 170 : } else if (type.Min() > 0.0) {
477 9 : type = cache_->kSingletonOne;
478 161 : } else if (type.Min() >= 0.0) {
479 3 : type = cache_->kZeroOrOne;
480 : } else {
481 158 : type = Type::Range(-1.0, 1.0, zone());
482 : }
483 175 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484 175 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485 : DCHECK(!type.IsNone());
486 175 : 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 21082 : type = Type::Intersect(type, Type::NaN(), zone());
518 21082 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
519 21082 : return type;
520 : }
521 :
522 46142 : Type OperationTyper::NumberToBoolean(Type type) {
523 : DCHECK(type.Is(Type::Number()));
524 46142 : if (type.IsNone()) return type;
525 92212 : if (type.Is(cache_->kZeroish)) return singleton_false_;
526 46104 : if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527 2135 : return singleton_true_; // Ruled out nan, -0 and +0.
528 : }
529 : return Type::Boolean();
530 : }
531 :
532 191533 : Type OperationTyper::NumberToInt32(Type type) {
533 : DCHECK(type.Is(Type::Number()));
534 :
535 191534 : if (type.Is(Type::Signed32())) return type;
536 104855 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
537 49057 : if (type.Is(signed32ish_)) {
538 6293 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
539 6293 : Type::Signed32(), zone());
540 : }
541 : return Type::Signed32();
542 : }
543 :
544 12505 : Type OperationTyper::NumberToString(Type type) {
545 : DCHECK(type.Is(Type::Number()));
546 12505 : if (type.IsNone()) return type;
547 12465 : if (type.Is(Type::NaN())) return singleton_NaN_string_;
548 24928 : if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
549 : return Type::String();
550 : }
551 :
552 54476 : Type OperationTyper::NumberToUint32(Type type) {
553 : DCHECK(type.Is(Type::Number()));
554 :
555 54476 : if (type.Is(Type::Unsigned32())) return type;
556 47358 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
557 21977 : if (type.Is(unsigned32ish_)) {
558 43 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
559 43 : 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 1525 : return cache_->kUint8;
569 : }
570 :
571 3572 : 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 3572 : if (type.Maybe(Type::NaN())) return Type::Number();
577 991 : return type;
578 : }
579 :
580 1751666 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581 : DCHECK(lhs.Is(Type::Number()));
582 : DCHECK(rhs.Is(Type::Number()));
583 :
584 3502153 : 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 1750379 : 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 1750281 : if (lhs.Maybe(Type::MinusZero())) {
593 252848 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
594 : } else {
595 : maybe_minuszero = false;
596 : }
597 1750370 : if (rhs.Maybe(Type::MinusZero())) {
598 189451 : 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 1750490 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606 1750509 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607 3500856 : if (!lhs.IsNone() && !rhs.IsNone()) {
608 4863113 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
609 1245251 : type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610 : } else {
611 1315370 : if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 320980 : (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 1750489 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 1750482 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622 1750514 : return type;
623 : }
624 :
625 63300 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626 : DCHECK(lhs.Is(Type::Number()));
627 : DCHECK(rhs.Is(Type::Number()));
628 :
629 126168 : 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 62760 : 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 62760 : if (lhs.Maybe(Type::MinusZero())) {
639 5902 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
640 5902 : maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
641 : }
642 62760 : if (rhs.Maybe(Type::MinusZero())) {
643 2312 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
644 : }
645 :
646 : // We can give more precise types for integers.
647 : Type type = Type::None();
648 62760 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649 62760 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650 125391 : if (!lhs.IsNone() && !rhs.IsNone()) {
651 180576 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
652 54199 : type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653 : } else {
654 22842 : if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 7020 : (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 62760 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 62760 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665 62760 : return type;
666 : }
667 :
668 510430 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669 510430 : 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 510481 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
676 : }
677 :
678 39576 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679 39576 : 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 39576 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
686 : }
687 :
688 80272 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689 : DCHECK(lhs.Is(Type::Number()));
690 : DCHECK(rhs.Is(Type::Number()));
691 :
692 160327 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693 159892 : 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 170409 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699 82039 : (lhs.Maybe(cache_->kZeroish) &&
700 198389 : (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701 47355 : (rhs.Maybe(cache_->kZeroish) &&
702 6247 : (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703 79820 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704 : DCHECK(!lhs.IsNone());
705 79820 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706 : DCHECK(!rhs.IsNone());
707 :
708 : // Try to rule out -0.
709 123080 : bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710 84754 : rhs.Maybe(Type::MinusZero()) ||
711 181672 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
712 27046 : (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
713 79820 : if (lhs.Maybe(Type::MinusZero())) {
714 36560 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
715 36560 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716 : }
717 79820 : if (rhs.Maybe(Type::MinusZero())) {
718 4940 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
719 4940 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720 : }
721 :
722 : // Compute the effective type, utilizing range information if possible.
723 196582 : Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
724 55350 : ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 135170 : : Type::OrderedNumber();
726 :
727 : // Take into account the -0 and NaN information computed earlier.
728 79820 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 79820 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730 79820 : return type;
731 : }
732 :
733 65320 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734 : DCHECK(lhs.Is(Type::Number()));
735 : DCHECK(rhs.Is(Type::Number()));
736 :
737 130573 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738 128245 : 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 93033 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
742 60096 : ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743 4209 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744 63425 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745 : DCHECK(!lhs.IsNone());
746 63425 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747 : DCHECK(!rhs.IsNone());
748 :
749 : // Try to rule out -0.
750 : bool maybe_minuszero =
751 110029 : !lhs.Is(cache_->kInteger) ||
752 117653 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
753 62464 : (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 63425 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758 63425 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759 63425 : return type;
760 : }
761 :
762 14169 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763 : DCHECK(lhs.Is(Type::Number()));
764 : DCHECK(rhs.Is(Type::Number()));
765 :
766 28271 : 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 35801 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
771 33992 : 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 14049 : if (lhs.Maybe(Type::MinusZero())) {
776 : maybe_minuszero = true;
777 3477 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
778 : }
779 14049 : 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 14049 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 14049 : 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 27978 : if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
791 : // Determine the bounds of {lhs} and {rhs}.
792 13789 : double const lmin = lhs.Min();
793 13789 : double const lmax = lhs.Max();
794 13789 : double const rmin = rhs.Min();
795 13789 : double const rmax = rhs.Max();
796 :
797 : // The sign of the result is the sign of the {lhs}.
798 13789 : if (lmin < 0.0) maybe_minuszero = true;
799 :
800 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
801 39115 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
802 33234 : double labs = std::max(std::abs(lmin), std::abs(lmax));
803 33234 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804 11078 : double abs = std::min(labs, rabs);
805 : double min = 0.0, max = 0.0;
806 11078 : if (lmin >= 0.0) {
807 : // {lhs} positive.
808 : min = 0.0;
809 : max = abs;
810 8111 : } else if (lmax <= 0.0) {
811 : // {lhs} negative.
812 758 : min = 0.0 - abs;
813 : max = 0.0;
814 : } else {
815 : // {lhs} positive or negative.
816 7353 : min = 0.0 - abs;
817 : max = abs;
818 : }
819 11078 : 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 14049 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 14049 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828 14049 : return type;
829 : }
830 :
831 45012 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832 : DCHECK(lhs.Is(Type::Number()));
833 : DCHECK(rhs.Is(Type::Number()));
834 :
835 45012 : lhs = NumberToInt32(lhs);
836 45013 : rhs = NumberToInt32(rhs);
837 :
838 89870 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 :
840 44804 : double lmin = lhs.Min();
841 44804 : double rmin = rhs.Min();
842 44804 : double lmax = lhs.Max();
843 44804 : 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 89608 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848 44804 : double max = kMaxInt;
849 :
850 : // Or-ing with 0 is essentially a conversion to int32.
851 44804 : if (rmin == 0 && rmax == 0) {
852 : min = lmin;
853 31853 : max = lmax;
854 : }
855 44804 : if (lmin == 0 && lmax == 0) {
856 : min = rmin;
857 593 : max = rmax;
858 : }
859 :
860 44804 : if (lmax < 0 || rmax < 0) {
861 : // Or-ing two values of which at least one is negative results in a negative
862 : // value.
863 454 : max = std::min(max, -1.0);
864 : }
865 44804 : return Type::Range(min, max, zone());
866 : }
867 :
868 28442 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869 : DCHECK(lhs.Is(Type::Number()));
870 : DCHECK(rhs.Is(Type::Number()));
871 :
872 28442 : lhs = NumberToInt32(lhs);
873 28442 : rhs = NumberToInt32(rhs);
874 :
875 56753 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 :
877 28258 : double lmin = lhs.Min();
878 28258 : double rmin = rhs.Min();
879 28258 : double lmax = lhs.Max();
880 28258 : 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 56516 : 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 28258 : if (lmin >= 0) {
889 : min = 0;
890 7916 : max = std::min(max, lmax);
891 : }
892 28258 : if (rmin >= 0) {
893 : min = 0;
894 25984 : max = std::min(max, rmax);
895 : }
896 28258 : return Type::Range(min, max, zone());
897 : }
898 :
899 4332 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900 : DCHECK(lhs.Is(Type::Number()));
901 : DCHECK(rhs.Is(Type::Number()));
902 :
903 4332 : lhs = NumberToInt32(lhs);
904 4332 : rhs = NumberToInt32(rhs);
905 :
906 8589 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 :
908 4204 : double lmin = lhs.Min();
909 4204 : double rmin = rhs.Min();
910 4204 : double lmax = lhs.Max();
911 4204 : double rmax = rhs.Max();
912 4204 : 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 3952 : 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 9280 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925 : DCHECK(lhs.Is(Type::Number()));
926 : DCHECK(rhs.Is(Type::Number()));
927 :
928 9280 : lhs = NumberToInt32(lhs);
929 9280 : rhs = NumberToUint32(rhs);
930 :
931 18485 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 :
933 9152 : int32_t min_lhs = lhs.Min();
934 9152 : int32_t max_lhs = lhs.Max();
935 9152 : uint32_t min_rhs = rhs.Min();
936 9152 : uint32_t max_rhs = rhs.Max();
937 9152 : if (max_rhs > 31) {
938 : // rhs can be larger than the bitmask
939 : max_rhs = 31;
940 : min_rhs = 0;
941 : }
942 :
943 9152 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944 : // overflow possible
945 : return Type::Signed32();
946 : }
947 :
948 : double min =
949 2394 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950 3591 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951 : double max =
952 2394 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953 3591 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 :
955 1197 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956 948 : return Type::Range(min, max, zone());
957 : }
958 :
959 18292 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960 : DCHECK(lhs.Is(Type::Number()));
961 : DCHECK(rhs.Is(Type::Number()));
962 :
963 18292 : lhs = NumberToInt32(lhs);
964 18292 : rhs = NumberToUint32(rhs);
965 :
966 36485 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 :
968 18126 : int32_t min_lhs = lhs.Min();
969 18126 : int32_t max_lhs = lhs.Max();
970 18126 : uint32_t min_rhs = rhs.Min();
971 18126 : uint32_t max_rhs = rhs.Max();
972 18126 : if (max_rhs > 31) {
973 : // rhs can be larger than the bitmask
974 : max_rhs = 31;
975 : min_rhs = 0;
976 : }
977 36252 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978 36252 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 :
980 18126 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981 16681 : return Type::Range(min, max, zone());
982 : }
983 :
984 7923 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985 : DCHECK(lhs.Is(Type::Number()));
986 : DCHECK(rhs.Is(Type::Number()));
987 :
988 7923 : lhs = NumberToUint32(lhs);
989 7923 : rhs = NumberToUint32(rhs);
990 :
991 15754 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 :
993 7773 : uint32_t min_lhs = lhs.Min();
994 7773 : uint32_t max_lhs = lhs.Max();
995 7773 : uint32_t min_rhs = rhs.Min();
996 7773 : uint32_t max_rhs = rhs.Max();
997 7773 : if (max_rhs > 31) {
998 : // rhs can be larger than the bitmask
999 : max_rhs = 31;
1000 : min_rhs = 0;
1001 : }
1002 :
1003 7773 : double min = min_lhs >> max_rhs;
1004 7773 : double max = max_lhs >> min_rhs;
1005 : DCHECK_LE(0, min);
1006 : DCHECK_LE(max, kMaxUInt32);
1007 :
1008 7773 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009 7134 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010 2907 : return Type::Range(min, max, zone());
1011 : }
1012 :
1013 145 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014 : DCHECK(lhs.Is(Type::Number()));
1015 : DCHECK(rhs.Is(Type::Number()));
1016 145 : return Type::Number();
1017 : }
1018 :
1019 2761 : 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 2761 : return Type::Signed32();
1024 : }
1025 :
1026 10421 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027 : DCHECK(lhs.Is(Type::Number()));
1028 : DCHECK(rhs.Is(Type::Number()));
1029 :
1030 20805 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031 20720 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 :
1033 : Type type = Type::None();
1034 10348 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 260 : type = Type::Union(type, Type::NaN(), zone());
1036 : }
1037 10348 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038 : DCHECK(!lhs.IsNone());
1039 10348 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040 : DCHECK(!rhs.IsNone());
1041 30800 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1042 10104 : 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 20052 : double max = std::max(lhs.Max(), rhs.Max());
1046 20052 : double min = std::max(lhs.Min(), rhs.Min());
1047 10026 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048 28550 : if (min <= 0.0 && 0.0 <= max &&
1049 16887 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050 184 : type = Type::Union(type, Type::MinusZero(), zone());
1051 : }
1052 : } else {
1053 322 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054 : }
1055 10348 : return type;
1056 : }
1057 :
1058 11918 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059 : DCHECK(lhs.Is(Type::Number()));
1060 : DCHECK(rhs.Is(Type::Number()));
1061 :
1062 23799 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063 23714 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 :
1065 : Type type = Type::None();
1066 11845 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 521 : type = Type::Union(type, Type::NaN(), zone());
1068 : }
1069 11845 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070 : DCHECK(!lhs.IsNone());
1071 11845 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072 : DCHECK(!rhs.IsNone());
1073 35075 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1074 11385 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1075 22566 : double max = std::min(lhs.Max(), rhs.Max());
1076 22566 : double min = std::min(lhs.Min(), rhs.Min());
1077 11283 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078 33722 : if (min <= 0.0 && 0.0 <= max &&
1079 22218 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080 145 : type = Type::Union(type, Type::MinusZero(), zone());
1081 : }
1082 : } else {
1083 562 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084 : }
1085 11845 : return type;
1086 : }
1087 :
1088 3094 : 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 3094 : 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 607738 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 40645 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 48091 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 49713 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 8849 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 35259 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 13965 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 2512 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 4711 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 14948 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 3665 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 : #undef SPECULATIVE_NUMBER_BINOP
1113 :
1114 1794219 : Type OperationTyper::SpeculativeToNumber(Type type) {
1115 1794219 : 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 370004 : Type JSType(Type type) {
1156 370004 : if (type.Is(Type::Boolean())) return Type::Boolean();
1157 362647 : if (type.Is(Type::String())) return Type::String();
1158 281695 : if (type.Is(Type::Number())) return Type::Number();
1159 148578 : if (type.Is(Type::BigInt())) return Type::BigInt();
1160 148477 : if (type.Is(Type::Undefined())) return Type::Undefined();
1161 146029 : if (type.Is(Type::Null())) return Type::Null();
1162 145806 : if (type.Is(Type::Symbol())) return Type::Symbol();
1163 145766 : if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164 : return Type::Any();
1165 : }
1166 :
1167 : } // namespace
1168 :
1169 675 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170 675 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171 675 : 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 635 : } else if (rhs.Is(Type::NaN())) {
1175 16 : if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176 : }
1177 675 : 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 582 : } else if (rhs.Is(Type::MinusZero())) {
1181 44 : if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182 : }
1183 1615 : if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1184 190 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1185 : return singleton_false();
1186 : }
1187 : return Type::Boolean();
1188 : }
1189 :
1190 208 : Type OperationTyper::SameValueNumbersOnly(Type lhs, Type rhs) {
1191 : // SameValue and SamevalueNumbersOnly only differ in treatment of
1192 : // strings and biginits. Since the SameValue typer does not do anything
1193 : // special about strings or bigints, we can just use it here.
1194 208 : return SameValue(lhs, rhs);
1195 : }
1196 :
1197 184327 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1198 184327 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1199 357852 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1200 447397 : if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1201 89852 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1202 : return singleton_false();
1203 : }
1204 349388 : if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1205 : return singleton_false();
1206 : }
1207 176305 : if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1208 : // Types are equal and are inhabited only by a single semantic value,
1209 : // which is not nan due to the earlier check.
1210 : return singleton_true();
1211 : }
1212 : return Type::Boolean();
1213 : }
1214 :
1215 133824 : Type OperationTyper::CheckBounds(Type index, Type length) {
1216 : DCHECK(length.Is(cache_->kPositiveSafeInteger));
1217 267648 : if (length.Is(cache_->kSingletonZero)) return Type::None();
1218 133748 : Type mask = Type::Range(0.0, length.Max() - 1, zone());
1219 133748 : if (index.Maybe(Type::MinusZero())) {
1220 6241 : index = Type::Union(index, cache_->kSingletonZero, zone());
1221 : }
1222 133748 : return Type::Intersect(index, mask, zone());
1223 : }
1224 :
1225 1249 : Type OperationTyper::CheckFloat64Hole(Type type) {
1226 1249 : if (type.Maybe(Type::Hole())) {
1227 : // Turn "the hole" into undefined.
1228 1185 : type = Type::Intersect(type, Type::Number(), zone());
1229 1185 : type = Type::Union(type, Type::Undefined(), zone());
1230 : }
1231 1249 : return type;
1232 : }
1233 :
1234 3751 : Type OperationTyper::CheckNumber(Type type) {
1235 3751 : return Type::Intersect(type, Type::Number(), zone());
1236 : }
1237 :
1238 90710 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1239 90710 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1240 : }
1241 :
1242 4624 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1243 4624 : if (input.Maybe(Type::Hole())) {
1244 : // Turn "the hole" into undefined.
1245 4574 : Type type = Type::Intersect(input, Type::NonInternal(), zone());
1246 4574 : return Type::Union(type, Type::Undefined(), zone());
1247 : }
1248 50 : return input;
1249 : }
1250 :
1251 209988 : Type OperationTyper::ToBoolean(Type type) {
1252 209988 : if (type.Is(Type::Boolean())) return type;
1253 175391 : if (type.Is(falsish_)) return singleton_false_;
1254 172863 : if (type.Is(truish_)) return singleton_true_;
1255 172747 : if (type.Is(Type::Number())) {
1256 45588 : return NumberToBoolean(type);
1257 : }
1258 : return Type::Boolean();
1259 : }
1260 :
1261 : } // namespace compiler
1262 : } // namespace internal
1263 122036 : } // namespace v8
|