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 2737996 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20 1368995 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = broker->isolate()->factory();
22 1369001 : infinity_ = Type::NewConstant(V8_INFINITY, zone);
23 1368995 : minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24 1368995 : Type truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 :
27 : singleton_empty_string_ =
28 1368995 : Type::HeapConstant(broker, factory->empty_string(), zone);
29 : singleton_NaN_string_ =
30 1369001 : Type::HeapConstant(broker, factory->NaN_string(), zone);
31 : singleton_zero_string_ =
32 1369009 : Type::HeapConstant(broker, factory->zero_string(), zone);
33 1369006 : singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34 1369009 : singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35 : singleton_the_hole_ =
36 1369006 : Type::HeapConstant(broker, factory->the_hole_value(), zone);
37 1369011 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38 1369009 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 :
40 : falsish_ = Type::Union(
41 : Type::Undetectable(),
42 : Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
43 : Type::Union(singleton_empty_string_, Type::Hole(), zone),
44 : zone),
45 1369008 : zone);
46 : truish_ = Type::Union(
47 : singleton_true_,
48 1369012 : Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 1369014 : }
50 :
51 1140711 : Type OperationTyper::Merge(Type left, Type right) {
52 1140711 : return Type::Union(left, right, zone());
53 : }
54 :
55 867994 : 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 433996 : 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 433996 : if (current_min != previous_range.Min()) {
105 : new_min = -V8_INFINITY;
106 323339 : for (double const min : kWeakenMinLimits) {
107 167596 : if (min <= current_min) {
108 : new_min = min;
109 : break;
110 : }
111 : }
112 : }
113 :
114 433998 : 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 433997 : if (current_max != previous_range.Max()) {
119 : new_max = V8_INFINITY;
120 6714287 : for (double const max : kWeakenMaxLimits) {
121 3506063 : if (max >= current_max) {
122 : new_max = max;
123 : break;
124 : }
125 : }
126 : }
127 :
128 433998 : 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 1335398 : double array_min(double a[], size_t n) {
145 : DCHECK_NE(0, n);
146 1335398 : double x = +V8_INFINITY;
147 6676966 : for (size_t i = 0; i < n; ++i) {
148 5341568 : if (!std::isnan(a[i])) {
149 5341427 : x = std::min(a[i], x);
150 : }
151 : }
152 : DCHECK(!std::isnan(x));
153 1335398 : 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 1335396 : double array_max(double a[], size_t n) {
160 : DCHECK_NE(0, n);
161 1335396 : double x = -V8_INFINITY;
162 6675892 : for (size_t i = 0; i < n; ++i) {
163 5340496 : if (!std::isnan(a[i])) {
164 5340359 : x = std::max(a[i], x);
165 : }
166 : }
167 : DCHECK(!std::isnan(x));
168 1335396 : return x == 0 ? 0 : x; // -0 -> 0
169 : }
170 :
171 : } // namespace
172 :
173 1221076 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174 1221125 : double rhs_max) {
175 : double results[4];
176 1221076 : results[0] = lhs_min + rhs_min;
177 1221076 : results[1] = lhs_min + rhs_max;
178 1221076 : results[2] = lhs_max + rhs_min;
179 1221076 : 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 6105356 : for (int i = 0; i < 4; ++i) {
186 4884280 : if (std::isnan(results[i])) ++nans;
187 : }
188 1221076 : if (nans == 4) return Type::NaN();
189 1221067 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190 1221111 : 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 1221051 : return type;
197 : }
198 :
199 55806 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200 55845 : double rhs_min, double rhs_max) {
201 : double results[4];
202 55806 : results[0] = lhs_min - rhs_min;
203 55806 : results[1] = lhs_min - rhs_max;
204 55806 : results[2] = lhs_max - rhs_min;
205 55806 : 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 279030 : for (int i = 0; i < 4; ++i) {
212 223224 : if (std::isnan(results[i])) ++nans;
213 : }
214 55806 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215 55797 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216 55845 : 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 58608 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225 105432 : double rhs_min, double rhs_max) {
226 : double results[4];
227 58608 : results[0] = lhs_min * rhs_min;
228 58608 : results[1] = lhs_min * rhs_max;
229 58608 : results[2] = lhs_max * rhs_min;
230 58608 : 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 292785 : for (int i = 0; i < 4; ++i) {
236 234254 : if (std::isnan(results[i])) {
237 77 : return cache_->kIntegerOrMinusZeroOrNaN;
238 : }
239 : }
240 58531 : double min = array_min(results, 4);
241 58531 : double max = array_max(results, 4);
242 58531 : Type type = Type::Range(min, max, zone());
243 58531 : if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244 46704 : type = Type::Union(type, Type::MinusZero(), zone());
245 : }
246 : // 0 * V8_INFINITY is NaN, regardless of sign
247 100636 : if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248 79478 : (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249 58426 : ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250 125 : (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251 197 : type = Type::Union(type, Type::NaN(), zone());
252 : }
253 58531 : return type;
254 : }
255 :
256 527223 : Type OperationTyper::ConvertReceiver(Type type) {
257 175751 : if (type.Is(Type::Receiver())) return type;
258 175736 : bool const maybe_primitive = type.Maybe(Type::Primitive());
259 175736 : type = Type::Intersect(type, Type::Receiver(), zone());
260 175736 : 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 175736 : type = Type::Union(type, Type::OtherObject(), zone());
264 : }
265 175736 : return type;
266 : }
267 :
268 6020015 : Type OperationTyper::ToNumber(Type type) {
269 3328314 : 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 712887 : 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 454914 : 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 454927 : if (type.Maybe(Type::Null())) {
286 : // ToNumber(null) => +0
287 442789 : type = Type::Union(type, cache_->kSingletonZero, zone());
288 : }
289 454941 : if (type.Maybe(Type::Undefined())) {
290 : // ToNumber(undefined) => NaN
291 448802 : type = Type::Union(type, Type::NaN(), zone());
292 : }
293 454917 : if (type.Maybe(singleton_false_)) {
294 : // ToNumber(false) => +0
295 444820 : type = Type::Union(type, cache_->kSingletonZero, zone());
296 : }
297 454978 : if (type.Maybe(singleton_true_)) {
298 : // ToNumber(true) => +1
299 445390 : type = Type::Union(type, cache_->kSingletonOne, zone());
300 : }
301 454965 : return Type::Intersect(type, Type::Number(), zone());
302 : }
303 :
304 1185 : 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 506 : type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
309 506 : type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
310 :
311 : // Any BigInt is rounded to an integer Number in the range [-inf, inf].
312 679 : return maybe_bigint ? Type::Union(type, cache_->kInteger, zone()) : type;
313 : }
314 :
315 3534609 : Type OperationTyper::ToNumeric(Type type) {
316 : // If the {type} includes any receivers, then the callbacks
317 : // might actually produce BigInt primitive values here.
318 1160903 : if (type.Maybe(Type::Receiver())) {
319 51898 : type = Type::Union(type, Type::BigInt(), zone());
320 : }
321 : return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 2321808 : Type::Intersect(type, Type::BigInt(), zone()), zone());
323 : }
324 :
325 4322 : Type OperationTyper::NumberAbs(Type type) {
326 : DCHECK(type.Is(Type::Number()));
327 1292 : if (type.IsNone()) return type;
328 :
329 1255 : bool const maybe_nan = type.Maybe(Type::NaN());
330 1255 : bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 :
332 1255 : type = Type::Intersect(type, Type::PlainNumber(), zone());
333 1255 : if (!type.IsNone()) {
334 1191 : double const max = type.Max();
335 1191 : double const min = type.Min();
336 1191 : if (min < 0) {
337 2018 : if (type.Is(cache_->kInteger)) {
338 : type =
339 654 : 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 1255 : if (maybe_minuszero) {
347 675 : type = Type::Union(type, cache_->kSingletonZero, zone());
348 : }
349 1255 : if (maybe_nan) {
350 773 : type = Type::Union(type, Type::NaN(), zone());
351 : }
352 1255 : 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 101 : Type OperationTyper::NumberAsin(Type type) {
366 : DCHECK(type.Is(Type::Number()));
367 101 : 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 64296 : Type OperationTyper::NumberCeil(Type type) {
391 : DCHECK(type.Is(Type::Number()));
392 43728 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
393 21216 : type = Type::Intersect(type, Type::NaN(), zone());
394 21216 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
395 21216 : return type;
396 : }
397 :
398 216 : Type OperationTyper::NumberClz32(Type type) {
399 : DCHECK(type.Is(Type::Number()));
400 216 : return cache_->kZeroToThirtyTwo;
401 : }
402 :
403 144 : Type OperationTyper::NumberCos(Type type) {
404 : DCHECK(type.Is(Type::Number()));
405 144 : 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 233 : Type OperationTyper::NumberExp(Type type) {
414 : DCHECK(type.Is(Type::Number()));
415 233 : 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 251768 : Type OperationTyper::NumberFloor(Type type) {
424 : DCHECK(type.Is(Type::Number()));
425 168692 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
426 83711 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427 83711 : type = Type::Union(type, cache_->kInteger, zone());
428 83711 : return type;
429 : }
430 :
431 4399 : Type OperationTyper::NumberFround(Type type) {
432 : DCHECK(type.Is(Type::Number()));
433 4399 : return Type::Number();
434 : }
435 :
436 617 : Type OperationTyper::NumberLog(Type type) {
437 : DCHECK(type.Is(Type::Number()));
438 617 : 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 14381 : Type OperationTyper::NumberRound(Type type) {
457 : DCHECK(type.Is(Type::Number()));
458 9710 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
459 4763 : type = Type::Intersect(type, Type::NaN(), zone());
460 4763 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
461 4763 : return type;
462 : }
463 :
464 808 : Type OperationTyper::NumberSign(Type type) {
465 : DCHECK(type.Is(Type::Number()));
466 424 : if (type.Is(cache_->kZeroish)) return type;
467 173 : bool maybe_minuszero = type.Maybe(Type::MinusZero());
468 173 : bool maybe_nan = type.Maybe(Type::NaN());
469 173 : type = Type::Intersect(type, Type::PlainNumber(), zone());
470 173 : if (type.IsNone()) {
471 : // Do nothing.
472 173 : } else if (type.Max() < 0.0) {
473 1 : type = cache_->kSingletonMinusOne;
474 172 : } else if (type.Max() <= 0.0) {
475 0 : type = cache_->kMinusOneOrZero;
476 172 : } else if (type.Min() > 0.0) {
477 14 : type = cache_->kSingletonOne;
478 158 : } else if (type.Min() >= 0.0) {
479 0 : type = cache_->kZeroOrOne;
480 : } else {
481 158 : type = Type::Range(-1.0, 1.0, zone());
482 : }
483 306 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484 305 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485 : DCHECK(!type.IsNone());
486 173 : return type;
487 : }
488 :
489 203 : Type OperationTyper::NumberSin(Type type) {
490 : DCHECK(type.Is(Type::Number()));
491 203 : 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 295 : Type OperationTyper::NumberSqrt(Type type) {
500 : DCHECK(type.Is(Type::Number()));
501 295 : return Type::Number();
502 : }
503 :
504 188 : Type OperationTyper::NumberTan(Type type) {
505 : DCHECK(type.Is(Type::Number()));
506 188 : 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 63447 : Type OperationTyper::NumberTrunc(Type type) {
515 : DCHECK(type.Is(Type::Number()));
516 42582 : 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 46171 : Type OperationTyper::NumberToBoolean(Type type) {
523 : DCHECK(type.Is(Type::Number()));
524 46171 : if (type.IsNone()) return type;
525 92268 : if (type.Is(cache_->kZeroish)) return singleton_false_;
526 46131 : if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527 2149 : return singleton_true_; // Ruled out nan, -0 and +0.
528 : }
529 : return Type::Boolean();
530 : }
531 :
532 230790 : Type OperationTyper::NumberToInt32(Type type) {
533 : DCHECK(type.Is(Type::Number()));
534 :
535 224778 : if (type.Is(Type::Signed32())) return type;
536 145654 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
537 69400 : if (type.Is(signed32ish_)) {
538 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
539 6012 : Type::Signed32(), zone());
540 : }
541 : return Type::Signed32();
542 : }
543 :
544 12820 : Type OperationTyper::NumberToString(Type type) {
545 : DCHECK(type.Is(Type::Number()));
546 12820 : if (type.IsNone()) return type;
547 12783 : if (type.Is(Type::NaN())) return singleton_NaN_string_;
548 25564 : if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
549 : return Type::String();
550 : }
551 :
552 85202 : Type OperationTyper::NumberToUint32(Type type) {
553 : DCHECK(type.Is(Type::Number()));
554 :
555 85052 : if (type.Is(Type::Unsigned32())) return type;
556 81422 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
557 38994 : if (type.Is(unsigned32ish_)) {
558 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
559 150 : 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 3573 : 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 3573 : if (type.Maybe(Type::NaN())) return Type::Number();
577 892 : return type;
578 : }
579 :
580 6153941 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581 : DCHECK(lhs.Is(Type::Number()));
582 : DCHECK(rhs.Is(Type::Number()));
583 :
584 3466103 : 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 1732375 : 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 1732219 : if (lhs.Maybe(Type::MinusZero())) {
593 255459 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
594 : } else {
595 : maybe_minuszero = false;
596 : }
597 1732272 : if (rhs.Maybe(Type::MinusZero())) {
598 191578 : 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 1732370 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606 1732382 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607 3464552 : if (!lhs.IsNone() && !rhs.IsNone()) {
608 4804246 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
609 1221073 : type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610 : } else {
611 1331262 : if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 326502 : (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 1906115 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 2066912 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622 1732265 : return type;
623 : }
624 :
625 225393 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626 : DCHECK(lhs.Is(Type::Number()));
627 : DCHECK(rhs.Is(Type::Number()));
628 :
629 135144 : 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 67276 : 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 67276 : if (lhs.Maybe(Type::MinusZero())) {
639 6990 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
640 6990 : maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
641 : }
642 67276 : if (rhs.Maybe(Type::MinusZero())) {
643 2991 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
644 : }
645 :
646 : // We can give more precise types for integers.
647 : Type type = Type::None();
648 67276 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649 67276 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650 134406 : if (!lhs.IsNone() && !rhs.IsNone()) {
651 192118 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
652 55806 : type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653 : } else {
654 30996 : if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 9904 : (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 69382 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 78249 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665 67276 : return type;
666 : }
667 :
668 1027374 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669 513691 : 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 513683 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
676 : }
677 :
678 77454 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679 38727 : 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 38727 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
686 : }
687 :
688 444147 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689 : DCHECK(lhs.Is(Type::Number()));
690 : DCHECK(rhs.Is(Type::Number()));
691 :
692 173962 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693 173538 : 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 188619 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699 90941 : (lhs.Maybe(cache_->kZeroish) &&
700 217056 : (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701 53968 : (rhs.Maybe(cache_->kZeroish) &&
702 8614 : (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703 86631 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704 : DCHECK(!lhs.IsNone());
705 86631 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706 : DCHECK(!rhs.IsNone());
707 :
708 : // Try to rule out -0.
709 135480 : bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710 95491 : rhs.Maybe(Type::MinusZero()) ||
711 197949 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
712 28961 : (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
713 86631 : if (lhs.Maybe(Type::MinusZero())) {
714 37782 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
715 37782 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716 : }
717 86631 : if (rhs.Maybe(Type::MinusZero())) {
718 5610 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
719 5610 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720 : }
721 :
722 : // Compute the effective type, utilizing range information if possible.
723 212903 : Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
724 58608 : ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 145239 : : Type::OrderedNumber();
726 :
727 : // Take into account the -0 and NaN information computed earlier.
728 146386 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 123893 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730 86631 : return type;
731 : }
732 :
733 293454 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734 : DCHECK(lhs.Is(Type::Number()));
735 : DCHECK(rhs.Is(Type::Number()));
736 :
737 143391 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738 141070 : 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 103003 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
742 67436 : ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743 5213 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744 69825 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745 : DCHECK(!lhs.IsNone());
746 69825 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747 : DCHECK(!rhs.IsNone());
748 :
749 : // Try to rule out -0.
750 : bool maybe_minuszero =
751 120307 : !lhs.Is(cache_->kInteger) ||
752 128824 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
753 66822 : (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 115234 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758 106494 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759 69825 : return type;
760 : }
761 :
762 92594 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763 : DCHECK(lhs.Is(Type::Number()));
764 : DCHECK(rhs.Is(Type::Number()));
765 :
766 35789 : 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 43558 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
771 39569 : 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 17823 : if (lhs.Maybe(Type::MinusZero())) {
776 : maybe_minuszero = true;
777 4394 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
778 : }
779 17823 : if (rhs.Maybe(Type::MinusZero())) {
780 1501 : 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 17823 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 17823 : 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 35526 : if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
791 : // Determine the bounds of {lhs} and {rhs}.
792 17563 : double const lmin = lhs.Min();
793 17563 : double const lmax = lhs.Max();
794 17563 : double const rmin = rhs.Min();
795 17563 : double const rmax = rhs.Max();
796 :
797 : // The sign of the result is the sign of the {lhs}.
798 17563 : if (lmin < 0.0) maybe_minuszero = true;
799 :
800 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
801 48840 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
802 37077 : double labs = std::max(std::abs(lmin), std::abs(lmax));
803 37077 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804 12359 : double abs = std::min(labs, rabs);
805 : double min = 0.0, max = 0.0;
806 12359 : if (lmin >= 0.0) {
807 : // {lhs} positive.
808 : min = 0.0;
809 : max = abs;
810 8955 : } else if (lmax <= 0.0) {
811 : // {lhs} negative.
812 948 : min = 0.0 - abs;
813 : max = 0.0;
814 : } else {
815 : // {lhs} positive or negative.
816 8007 : min = 0.0 - abs;
817 : max = abs;
818 : }
819 12359 : 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 31366 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 25049 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828 17823 : return type;
829 : }
830 :
831 86454 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832 : DCHECK(lhs.Is(Type::Number()));
833 : DCHECK(rhs.Is(Type::Number()));
834 :
835 43345 : lhs = NumberToInt32(lhs);
836 43345 : rhs = NumberToInt32(rhs);
837 :
838 86495 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 :
840 43109 : double lmin = lhs.Min();
841 43109 : double rmin = rhs.Min();
842 43109 : double lmax = lhs.Max();
843 43109 : 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 86218 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848 43109 : double max = kMaxInt;
849 :
850 : // Or-ing with 0 is essentially a conversion to int32.
851 43109 : if (rmin == 0 && rmax == 0) {
852 : min = lmin;
853 29299 : max = lmax;
854 : }
855 43109 : if (lmin == 0 && lmax == 0) {
856 : min = rmin;
857 620 : max = rmax;
858 : }
859 :
860 43109 : if (lmax < 0 || rmax < 0) {
861 : // Or-ing two values of which at least one is negative results in a negative
862 : // value.
863 1336 : max = std::min(max, -1.0);
864 : }
865 43109 : return Type::Range(min, max, zone());
866 : }
867 :
868 60912 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869 : DCHECK(lhs.Is(Type::Number()));
870 : DCHECK(rhs.Is(Type::Number()));
871 :
872 30564 : lhs = NumberToInt32(lhs);
873 30564 : rhs = NumberToInt32(rhs);
874 :
875 60953 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 :
877 30348 : double lmin = lhs.Min();
878 30348 : double rmin = rhs.Min();
879 30348 : double lmax = lhs.Max();
880 30348 : 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 60696 : 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 30348 : if (lmin >= 0) {
889 : min = 0;
890 9831 : max = std::min(max, lmax);
891 : }
892 30348 : if (rmin >= 0) {
893 : min = 0;
894 24642 : max = std::min(max, rmax);
895 : }
896 30348 : return Type::Range(min, max, zone());
897 : }
898 :
899 8439 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900 : DCHECK(lhs.Is(Type::Number()));
901 : DCHECK(rhs.Is(Type::Number()));
902 :
903 8439 : lhs = NumberToInt32(lhs);
904 8439 : rhs = NumberToInt32(rhs);
905 :
906 16809 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 :
908 8329 : double lmin = lhs.Min();
909 8329 : double rmin = rhs.Min();
910 8329 : double lmax = lhs.Max();
911 8329 : double rmax = rhs.Max();
912 8329 : 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 7994 : 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 13966 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925 : DCHECK(lhs.Is(Type::Number()));
926 : DCHECK(rhs.Is(Type::Number()));
927 :
928 13040 : lhs = NumberToInt32(lhs);
929 13040 : rhs = NumberToUint32(rhs);
930 :
931 26010 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 :
933 12929 : int32_t min_lhs = lhs.Min();
934 12929 : int32_t max_lhs = lhs.Max();
935 12929 : uint32_t min_rhs = rhs.Min();
936 12929 : uint32_t max_rhs = rhs.Max();
937 12929 : if (max_rhs > 31) {
938 : // rhs can be larger than the bitmask
939 : max_rhs = 31;
940 : min_rhs = 0;
941 : }
942 :
943 12929 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944 : // overflow possible
945 : return Type::Signed32();
946 : }
947 :
948 : double min =
949 1175 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950 3525 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951 : double max =
952 1175 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953 3525 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 :
955 1175 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956 926 : return Type::Range(min, max, zone());
957 : }
958 :
959 38997 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960 : DCHECK(lhs.Is(Type::Number()));
961 : DCHECK(rhs.Is(Type::Number()));
962 :
963 21984 : lhs = NumberToInt32(lhs);
964 21984 : rhs = NumberToUint32(rhs);
965 :
966 43878 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 :
968 21839 : int32_t min_lhs = lhs.Min();
969 21839 : int32_t max_lhs = lhs.Max();
970 21839 : uint32_t min_rhs = rhs.Min();
971 21839 : uint32_t max_rhs = rhs.Max();
972 21839 : if (max_rhs > 31) {
973 : // rhs can be larger than the bitmask
974 : max_rhs = 31;
975 : min_rhs = 0;
976 : }
977 43678 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978 43678 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 :
980 21839 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981 17013 : return Type::Range(min, max, zone());
982 : }
983 :
984 17950 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985 : DCHECK(lhs.Is(Type::Number()));
986 : DCHECK(rhs.Is(Type::Number()));
987 :
988 13288 : lhs = NumberToUint32(lhs);
989 13288 : rhs = NumberToUint32(rhs);
990 :
991 26441 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 :
993 13105 : uint32_t min_lhs = lhs.Min();
994 13105 : uint32_t max_lhs = lhs.Max();
995 13105 : uint32_t min_rhs = rhs.Min();
996 13105 : uint32_t max_rhs = rhs.Max();
997 13105 : if (max_rhs > 31) {
998 : // rhs can be larger than the bitmask
999 : max_rhs = 31;
1000 : min_rhs = 0;
1001 : }
1002 :
1003 13105 : double min = min_lhs >> max_rhs;
1004 13105 : double max = max_lhs >> min_rhs;
1005 : DCHECK_LE(0, min);
1006 : DCHECK_LE(max, kMaxUInt32);
1007 :
1008 13105 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009 12443 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010 4662 : return Type::Range(min, max, zone());
1011 : }
1012 :
1013 158 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014 : DCHECK(lhs.Is(Type::Number()));
1015 : DCHECK(rhs.Is(Type::Number()));
1016 158 : return Type::Number();
1017 : }
1018 :
1019 2703 : 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 2703 : return Type::Signed32();
1024 : }
1025 :
1026 40737 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027 : DCHECK(lhs.Is(Type::Number()));
1028 : DCHECK(rhs.Is(Type::Number()));
1029 :
1030 20219 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031 20141 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 :
1033 : Type type = Type::None();
1034 10058 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 270 : type = Type::Union(type, Type::NaN(), zone());
1036 : }
1037 10058 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038 : DCHECK(!lhs.IsNone());
1039 10058 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040 : DCHECK(!rhs.IsNone());
1041 29915 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1042 9799 : 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 19434 : double max = std::max(lhs.Max(), rhs.Max());
1046 19434 : double min = std::max(lhs.Min(), rhs.Min());
1047 9717 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048 27723 : if (min <= 0.0 && 0.0 <= max &&
1049 16487 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050 166 : type = Type::Union(type, Type::MinusZero(), zone());
1051 : }
1052 : } else {
1053 341 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054 : }
1055 10058 : return type;
1056 : }
1057 :
1058 47297 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059 : DCHECK(lhs.Is(Type::Number()));
1060 : DCHECK(rhs.Is(Type::Number()));
1061 :
1062 23387 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063 23300 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 :
1065 : Type type = Type::None();
1066 11633 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 537 : type = Type::Union(type, Type::NaN(), zone());
1068 : }
1069 11633 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070 : DCHECK(!lhs.IsNone());
1071 11633 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072 : DCHECK(!rhs.IsNone());
1073 34424 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1074 11158 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1075 22092 : double max = std::min(lhs.Max(), rhs.Max());
1076 22092 : double min = std::min(lhs.Min(), rhs.Min());
1077 11046 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078 33015 : if (min <= 0.0 && 0.0 <= max &&
1079 21750 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080 150 : type = Type::Union(type, Type::MinusZero(), zone());
1081 : }
1082 : } else {
1083 587 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084 : }
1085 11633 : return type;
1086 : }
1087 :
1088 3303 : 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 3303 : 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 611359 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 39897 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 46049 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 48855 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 8497 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 33629 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 15923 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 2667 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 4696 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 14722 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 5204 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 : #undef SPECULATIVE_NUMBER_BINOP
1113 :
1114 1811831 : Type OperationTyper::SpeculativeToNumber(Type type) {
1115 1811831 : 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 363568 : Type JSType(Type type) {
1156 363568 : if (type.Is(Type::Boolean())) return Type::Boolean();
1157 355913 : if (type.Is(Type::String())) return Type::String();
1158 277888 : if (type.Is(Type::Number())) return Type::Number();
1159 143215 : if (type.Is(Type::BigInt())) return Type::BigInt();
1160 143107 : if (type.Is(Type::Undefined())) return Type::Undefined();
1161 140398 : if (type.Is(Type::Null())) return Type::Null();
1162 140173 : if (type.Is(Type::Symbol())) return Type::Symbol();
1163 140130 : if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164 : return Type::Any();
1165 : }
1166 :
1167 : } // namespace
1168 :
1169 247 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170 247 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171 247 : if (lhs.Is(Type::NaN())) {
1172 35 : if (rhs.Is(Type::NaN())) return singleton_true();
1173 35 : if (!rhs.Maybe(Type::NaN())) return singleton_false();
1174 212 : } else if (rhs.Is(Type::NaN())) {
1175 14 : if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176 : }
1177 247 : if (lhs.Is(Type::MinusZero())) {
1178 85 : if (rhs.Is(Type::MinusZero())) return singleton_true();
1179 85 : if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
1180 162 : } else if (rhs.Is(Type::MinusZero())) {
1181 42 : if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182 : }
1183 601 : if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1184 58 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1185 : return singleton_false();
1186 : }
1187 : return Type::Boolean();
1188 : }
1189 :
1190 181537 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1191 181537 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1192 351504 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1193 442410 : if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1194 91731 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1195 : return singleton_false();
1196 : }
1197 341676 : if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1198 : return singleton_false();
1199 : }
1200 172635 : 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 387910 : Type OperationTyper::CheckBounds(Type index, Type length) {
1209 : DCHECK(length.Is(cache_->kPositiveSafeInteger));
1210 254218 : if (length.Is(cache_->kSingletonZero)) return Type::None();
1211 127027 : Type mask = Type::Range(0.0, length.Max() - 1, zone());
1212 127027 : if (index.Maybe(Type::MinusZero())) {
1213 6747 : index = Type::Union(index, cache_->kSingletonZero, zone());
1214 : }
1215 127027 : return Type::Intersect(index, mask, zone());
1216 : }
1217 :
1218 3509 : Type OperationTyper::CheckFloat64Hole(Type type) {
1219 1213 : if (type.Maybe(Type::Hole())) {
1220 : // Turn "the hole" into undefined.
1221 1148 : type = Type::Intersect(type, Type::Number(), zone());
1222 1148 : type = Type::Union(type, Type::Undefined(), zone());
1223 : }
1224 1213 : return type;
1225 : }
1226 :
1227 4114 : Type OperationTyper::CheckNumber(Type type) {
1228 4114 : return Type::Intersect(type, Type::Number(), zone());
1229 : }
1230 :
1231 95008 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1232 95008 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1233 : }
1234 :
1235 12238 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1236 4110 : if (input.Maybe(Type::Hole())) {
1237 : // Turn "the hole" into undefined.
1238 4064 : Type type = Type::Intersect(input, Type::NonInternal(), zone());
1239 4064 : return Type::Union(type, Type::Undefined(), zone());
1240 : }
1241 46 : return input;
1242 : }
1243 :
1244 203298 : Type OperationTyper::ToBoolean(Type type) {
1245 203298 : if (type.Is(Type::Boolean())) return type;
1246 162026 : if (type.Is(falsish_)) return singleton_false_;
1247 159370 : if (type.Is(truish_)) return singleton_true_;
1248 159133 : if (type.Is(Type::Number())) {
1249 45617 : return NumberToBoolean(type);
1250 : }
1251 : return Type::Boolean();
1252 : }
1253 :
1254 : } // namespace compiler
1255 : } // namespace internal
1256 183867 : } // namespace v8
|