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 1392351 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20 1392351 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = broker->isolate()->factory();
22 1392352 : infinity_ = Type::NewConstant(V8_INFINITY, zone);
23 1392350 : minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24 1392356 : Type truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 :
27 : singleton_empty_string_ =
28 1392356 : Type::HeapConstant(broker, factory->empty_string(), zone);
29 : singleton_NaN_string_ =
30 1392348 : Type::HeapConstant(broker, factory->NaN_string(), zone);
31 : singleton_zero_string_ =
32 1392354 : Type::HeapConstant(broker, factory->zero_string(), zone);
33 1392358 : singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34 1392360 : singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35 : singleton_the_hole_ =
36 1392357 : Type::HeapConstant(broker, factory->the_hole_value(), zone);
37 1392361 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38 1392358 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 :
40 : falsish_ = Type::Union(
41 : Type::Undetectable(),
42 1392352 : Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
43 : Type::Union(singleton_empty_string_, Type::Hole(), zone),
44 : zone),
45 2784709 : zone);
46 : truish_ = Type::Union(
47 : singleton_true_,
48 1392361 : Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 1392360 : }
50 :
51 1200443 : Type OperationTyper::Merge(Type left, Type right) {
52 1200443 : return Type::Union(left, right, zone());
53 : }
54 :
55 447965 : 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 447965 : 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 447965 : if (current_min != previous_range.Min()) {
105 : new_min = -V8_INFINITY;
106 329385 : for (double const min : kWeakenMinLimits) {
107 168336 : if (min <= current_min) {
108 : new_min = min;
109 : break;
110 : }
111 : }
112 : }
113 :
114 447965 : 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 447965 : if (current_max != previous_range.Max()) {
119 : new_max = V8_INFINITY;
120 7100930 : for (double const max : kWeakenMaxLimits) {
121 3697645 : if (max >= current_max) {
122 : new_max = max;
123 : break;
124 : }
125 : }
126 : }
127 :
128 447965 : 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 1354862 : double x = +V8_INFINITY;
147 12193590 : for (size_t i = 0; i < n; ++i) {
148 5419364 : if (!std::isnan(a[i])) {
149 5419290 : x = std::min(a[i], x);
150 : }
151 : }
152 : DCHECK(!std::isnan(x));
153 1354862 : 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 1354862 : double x = -V8_INFINITY;
162 12193534 : for (size_t i = 0; i < n; ++i) {
163 5419336 : if (!std::isnan(a[i])) {
164 5419218 : x = std::max(a[i], x);
165 : }
166 : }
167 : DCHECK(!std::isnan(x));
168 1354862 : return x == 0 ? 0 : x; // -0 -> 0
169 : }
170 :
171 : } // namespace
172 :
173 1245843 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174 : double rhs_max) {
175 : double results[4];
176 1245843 : results[0] = lhs_min + rhs_min;
177 1245843 : results[1] = lhs_min + rhs_max;
178 1245843 : results[2] = lhs_max + rhs_min;
179 1245843 : 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 11212331 : for (int i = 0; i < 4; ++i) {
186 4983244 : if (std::isnan(results[i])) ++nans;
187 : }
188 1245843 : if (nans == 4) return Type::NaN();
189 1245837 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190 1245852 : 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 1245853 : return type;
197 : }
198 :
199 54020 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200 : double rhs_min, double rhs_max) {
201 : double results[4];
202 54020 : results[0] = lhs_min - rhs_min;
203 54020 : results[1] = lhs_min - rhs_max;
204 54020 : results[2] = lhs_max - rhs_min;
205 54020 : 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 486180 : for (int i = 0; i < 4; ++i) {
212 216080 : if (std::isnan(results[i])) ++nans;
213 : }
214 54020 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215 54014 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216 54014 : 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 55084 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225 : double rhs_min, double rhs_max) {
226 : double results[4];
227 55084 : results[0] = lhs_min * rhs_min;
228 55084 : results[1] = lhs_min * rhs_max;
229 55084 : results[2] = lhs_max * rhs_min;
230 55084 : 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 495276 : for (int i = 0; i < 4; ++i) {
236 220169 : if (std::isnan(results[i])) {
237 73 : return cache_->kIntegerOrMinusZeroOrNaN;
238 : }
239 : }
240 : double min = array_min(results, 4);
241 : double max = array_max(results, 4);
242 55011 : Type type = Type::Range(min, max, zone());
243 55011 : if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244 42743 : type = Type::Union(type, Type::MinusZero(), zone());
245 : }
246 : // 0 * V8_INFINITY is NaN, regardless of sign
247 93597 : if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248 74727 : (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249 54906 : ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250 115 : (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251 183 : type = Type::Union(type, Type::NaN(), zone());
252 : }
253 55011 : return type;
254 : }
255 :
256 80832 : Type OperationTyper::ConvertReceiver(Type type) {
257 80832 : if (type.Is(Type::Receiver())) return type;
258 80825 : bool const maybe_primitive = type.Maybe(Type::Primitive());
259 80825 : type = Type::Intersect(type, Type::Receiver(), zone());
260 80825 : 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 80825 : type = Type::Union(type, Type::OtherObject(), zone());
264 : }
265 80825 : return type;
266 : }
267 :
268 3296424 : Type OperationTyper::ToNumber(Type type) {
269 3296429 : 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 717161 : 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 438631 : 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 438651 : if (type.Maybe(Type::Null())) {
286 : // ToNumber(null) => +0
287 425932 : type = Type::Union(type, cache_->kSingletonZero, zone());
288 : }
289 438676 : if (type.Maybe(Type::Undefined())) {
290 : // ToNumber(undefined) => NaN
291 432626 : type = Type::Union(type, Type::NaN(), zone());
292 : }
293 438660 : if (type.Maybe(singleton_false_)) {
294 : // ToNumber(false) => +0
295 427950 : type = Type::Union(type, cache_->kSingletonZero, zone());
296 : }
297 438722 : if (type.Maybe(singleton_true_)) {
298 : // ToNumber(true) => +1
299 428527 : type = Type::Union(type, cache_->kSingletonOne, zone());
300 : }
301 438722 : 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 1169842 : Type OperationTyper::ToNumeric(Type type) {
316 : // If the {type} includes any receivers, then the callbacks
317 : // might actually produce BigInt primitive values here.
318 1169842 : if (type.Maybe(Type::Receiver())) {
319 60013 : type = Type::Union(type, Type::BigInt(), zone());
320 : }
321 : return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 1169842 : Type::Intersect(type, Type::BigInt(), zone()), zone());
323 : }
324 :
325 1284 : Type OperationTyper::NumberAbs(Type type) {
326 : DCHECK(type.Is(Type::Number()));
327 1284 : if (type.IsNone()) return type;
328 :
329 1252 : bool const maybe_nan = type.Maybe(Type::NaN());
330 1252 : bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 :
332 1252 : type = Type::Intersect(type, Type::PlainNumber(), zone());
333 1252 : if (!type.IsNone()) {
334 1200 : double const max = type.Max();
335 1200 : double const min = type.Min();
336 1200 : if (min < 0) {
337 2040 : 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 688 : type = Type::PlainNumber();
342 : }
343 : }
344 : }
345 :
346 1252 : if (maybe_minuszero) {
347 677 : type = Type::Union(type, cache_->kSingletonZero, zone());
348 : }
349 1252 : if (maybe_nan) {
350 767 : type = Type::Union(type, Type::NaN(), zone());
351 : }
352 1252 : 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 21906 : Type OperationTyper::NumberCeil(Type type) {
391 : DCHECK(type.Is(Type::Number()));
392 43812 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
393 21267 : type = Type::Intersect(type, Type::NaN(), zone());
394 21267 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
395 21267 : 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 86360 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427 86360 : type = Type::Union(type, cache_->kInteger, zone());
428 86360 : return type;
429 : }
430 :
431 4358 : Type OperationTyper::NumberFround(Type type) {
432 : DCHECK(type.Is(Type::Number()));
433 4358 : 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 4759 : type = Type::Intersect(type, Type::NaN(), zone());
460 4759 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
461 4759 : 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 180 : bool maybe_minuszero = type.Maybe(Type::MinusZero());
468 180 : bool maybe_nan = type.Maybe(Type::NaN());
469 180 : type = Type::Intersect(type, Type::PlainNumber(), zone());
470 180 : if (type.IsNone()) {
471 : // Do nothing.
472 180 : } else if (type.Max() < 0.0) {
473 6 : type = cache_->kSingletonMinusOne;
474 174 : } else if (type.Max() <= 0.0) {
475 0 : type = cache_->kMinusOneOrZero;
476 174 : } else if (type.Min() > 0.0) {
477 13 : type = cache_->kSingletonOne;
478 161 : } else if (type.Min() >= 0.0) {
479 1 : type = cache_->kZeroOrOne;
480 : } else {
481 160 : type = Type::Range(-1.0, 1.0, zone());
482 : }
483 180 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484 180 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485 : DCHECK(!type.IsNone());
486 180 : 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 21084 : type = Type::Intersect(type, Type::NaN(), zone());
518 21084 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
519 21084 : return type;
520 : }
521 :
522 46101 : Type OperationTyper::NumberToBoolean(Type type) {
523 : DCHECK(type.Is(Type::Number()));
524 46101 : if (type.IsNone()) return type;
525 92138 : if (type.Is(cache_->kZeroish)) return singleton_false_;
526 46068 : if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527 2141 : return singleton_true_; // Ruled out nan, -0 and +0.
528 : }
529 : return Type::Boolean();
530 : }
531 :
532 191205 : Type OperationTyper::NumberToInt32(Type type) {
533 : DCHECK(type.Is(Type::Number()));
534 :
535 191205 : if (type.Is(Type::Signed32())) return type;
536 105114 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
537 49186 : if (type.Is(signed32ish_)) {
538 6304 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
539 6304 : Type::Signed32(), zone());
540 : }
541 : return Type::Signed32();
542 : }
543 :
544 12621 : Type OperationTyper::NumberToString(Type type) {
545 : DCHECK(type.Is(Type::Number()));
546 12621 : if (type.IsNone()) return type;
547 12585 : if (type.Is(Type::NaN())) return singleton_NaN_string_;
548 25168 : if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
549 : return Type::String();
550 : }
551 :
552 54372 : Type OperationTyper::NumberToUint32(Type type) {
553 : DCHECK(type.Is(Type::Number()));
554 :
555 54372 : if (type.Is(Type::Unsigned32())) return type;
556 47734 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
557 22167 : if (type.Is(unsigned32ish_)) {
558 40 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
559 40 : 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 1530 : return cache_->kUint8;
569 : }
570 :
571 3556 : 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 3556 : if (type.Maybe(Type::NaN())) return Type::Number();
577 992 : return type;
578 : }
579 :
580 1751048 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581 : DCHECK(lhs.Is(Type::Number()));
582 : DCHECK(rhs.Is(Type::Number()));
583 :
584 3500928 : 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 1749792 : 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 1749612 : if (lhs.Maybe(Type::MinusZero())) {
593 252249 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
594 : } else {
595 : maybe_minuszero = false;
596 : }
597 1749763 : if (rhs.Maybe(Type::MinusZero())) {
598 188906 : 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 1749866 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606 1749866 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607 3499601 : if (!lhs.IsNone() && !rhs.IsNone()) {
608 4861950 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
609 1245835 : type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610 : } else {
611 1312218 : if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 320376 : (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 1749858 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 1749859 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622 1749853 : return type;
623 : }
624 :
625 63172 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626 : DCHECK(lhs.Is(Type::Number()));
627 : DCHECK(rhs.Is(Type::Number()));
628 :
629 125912 : 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 62664 : 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 62664 : if (lhs.Maybe(Type::MinusZero())) {
639 5973 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
640 5973 : maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
641 : }
642 62664 : if (rhs.Maybe(Type::MinusZero())) {
643 2392 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
644 : }
645 :
646 : // We can give more precise types for integers.
647 : Type type = Type::None();
648 62664 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649 62664 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650 125199 : if (!lhs.IsNone() && !rhs.IsNone()) {
651 180213 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
652 54020 : type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653 : } else {
654 23010 : if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 7026 : (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 62664 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 62664 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665 62664 : return type;
666 : }
667 :
668 509294 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669 509294 : 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 509335 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
676 : }
677 :
678 39430 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679 39430 : 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 39430 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
686 : }
687 :
688 80023 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689 : DCHECK(lhs.Is(Type::Number()));
690 : DCHECK(rhs.Is(Type::Number()));
691 :
692 159831 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693 159428 : 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 169767 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699 81637 : (lhs.Maybe(cache_->kZeroish) &&
700 197543 : (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701 47150 : (rhs.Maybe(cache_->kZeroish) &&
702 6223 : (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703 79588 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704 : DCHECK(!lhs.IsNone());
705 79588 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706 : DCHECK(!rhs.IsNone());
707 :
708 : // Try to rule out -0.
709 122647 : bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710 84374 : rhs.Maybe(Type::MinusZero()) ||
711 180896 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
712 26876 : (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
713 79588 : if (lhs.Maybe(Type::MinusZero())) {
714 36529 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
715 36529 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716 : }
717 79588 : if (rhs.Maybe(Type::MinusZero())) {
718 4936 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
719 4936 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720 : }
721 :
722 : // Compute the effective type, utilizing range information if possible.
723 195736 : Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
724 55084 : ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 134672 : : Type::OrderedNumber();
726 :
727 : // Take into account the -0 and NaN information computed earlier.
728 79588 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 79588 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730 79588 : return type;
731 : }
732 :
733 65629 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734 : DCHECK(lhs.Is(Type::Number()));
735 : DCHECK(rhs.Is(Type::Number()));
736 :
737 131193 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738 128843 : 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 93379 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
742 60185 : ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743 4217 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744 63726 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745 : DCHECK(!lhs.IsNone());
746 63726 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747 : DCHECK(!rhs.IsNone());
748 :
749 : // Try to rule out -0.
750 : bool maybe_minuszero =
751 110505 : !lhs.Is(cache_->kInteger) ||
752 118160 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
753 62693 : (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 63726 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758 63726 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759 63726 : return type;
760 : }
761 :
762 14224 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763 : DCHECK(lhs.Is(Type::Number()));
764 : DCHECK(rhs.Is(Type::Number()));
765 :
766 28383 : 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 35874 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
771 34064 : 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 14121 : if (lhs.Maybe(Type::MinusZero())) {
776 : maybe_minuszero = true;
777 3548 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
778 : }
779 14121 : if (rhs.Maybe(Type::MinusZero())) {
780 940 : 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 14121 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 14121 : 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 28122 : if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
791 : // Determine the bounds of {lhs} and {rhs}.
792 13863 : double const lmin = lhs.Min();
793 13863 : double const lmax = lhs.Max();
794 13863 : double const rmin = rhs.Min();
795 13863 : double const rmax = rhs.Max();
796 :
797 : // The sign of the result is the sign of the {lhs}.
798 13863 : if (lmin < 0.0) maybe_minuszero = true;
799 :
800 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
801 39264 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
802 33201 : double labs = std::max(std::abs(lmin), std::abs(lmax));
803 33201 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804 11067 : double abs = std::min(labs, rabs);
805 : double min = 0.0, max = 0.0;
806 11067 : if (lmin >= 0.0) {
807 : // {lhs} positive.
808 : min = 0.0;
809 : max = abs;
810 8087 : } else if (lmax <= 0.0) {
811 : // {lhs} negative.
812 739 : min = 0.0 - abs;
813 : max = 0.0;
814 : } else {
815 : // {lhs} positive or negative.
816 7348 : min = 0.0 - abs;
817 : max = abs;
818 : }
819 11067 : 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 14121 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 14121 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828 14121 : return type;
829 : }
830 :
831 44969 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832 : DCHECK(lhs.Is(Type::Number()));
833 : DCHECK(rhs.Is(Type::Number()));
834 :
835 44969 : lhs = NumberToInt32(lhs);
836 44969 : rhs = NumberToInt32(rhs);
837 :
838 89787 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 :
840 44780 : double lmin = lhs.Min();
841 44780 : double rmin = rhs.Min();
842 44780 : double lmax = lhs.Max();
843 44780 : 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 89560 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848 44780 : double max = kMaxInt;
849 :
850 : // Or-ing with 0 is essentially a conversion to int32.
851 44780 : if (rmin == 0 && rmax == 0) {
852 : min = lmin;
853 31810 : max = lmax;
854 : }
855 44780 : if (lmin == 0 && lmax == 0) {
856 : min = rmin;
857 590 : max = rmax;
858 : }
859 :
860 44780 : if (lmax < 0 || rmax < 0) {
861 : // Or-ing two values of which at least one is negative results in a negative
862 : // value.
863 490 : max = std::min(max, -1.0);
864 : }
865 44780 : return Type::Range(min, max, zone());
866 : }
867 :
868 28295 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869 : DCHECK(lhs.Is(Type::Number()));
870 : DCHECK(rhs.Is(Type::Number()));
871 :
872 28295 : lhs = NumberToInt32(lhs);
873 28295 : rhs = NumberToInt32(rhs);
874 :
875 56464 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 :
877 28131 : double lmin = lhs.Min();
878 28131 : double rmin = rhs.Min();
879 28131 : double lmax = lhs.Max();
880 28131 : 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 56262 : 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 28131 : if (lmin >= 0) {
889 : min = 0;
890 7759 : max = std::min(max, lmax);
891 : }
892 28131 : if (rmin >= 0) {
893 : min = 0;
894 25781 : max = std::min(max, rmax);
895 : }
896 28131 : return Type::Range(min, max, zone());
897 : }
898 :
899 4339 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900 : DCHECK(lhs.Is(Type::Number()));
901 : DCHECK(rhs.Is(Type::Number()));
902 :
903 4339 : lhs = NumberToInt32(lhs);
904 4339 : rhs = NumberToInt32(rhs);
905 :
906 8605 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 :
908 4228 : double lmin = lhs.Min();
909 4228 : double rmin = rhs.Min();
910 4228 : double lmax = lhs.Max();
911 4228 : double rmax = rhs.Max();
912 4228 : 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 3985 : 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 9319 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925 : DCHECK(lhs.Is(Type::Number()));
926 : DCHECK(rhs.Is(Type::Number()));
927 :
928 9319 : lhs = NumberToInt32(lhs);
929 9319 : rhs = NumberToUint32(rhs);
930 :
931 18565 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 :
933 9208 : int32_t min_lhs = lhs.Min();
934 9208 : int32_t max_lhs = lhs.Max();
935 9208 : uint32_t min_rhs = rhs.Min();
936 9208 : uint32_t max_rhs = rhs.Max();
937 9208 : if (max_rhs > 31) {
938 : // rhs can be larger than the bitmask
939 : max_rhs = 31;
940 : min_rhs = 0;
941 : }
942 :
943 9208 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944 : // overflow possible
945 : return Type::Signed32();
946 : }
947 :
948 : double min =
949 2388 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950 3582 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951 : double max =
952 2388 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953 3582 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 :
955 1194 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956 945 : return Type::Range(min, max, zone());
957 : }
958 :
959 18291 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960 : DCHECK(lhs.Is(Type::Number()));
961 : DCHECK(rhs.Is(Type::Number()));
962 :
963 18291 : lhs = NumberToInt32(lhs);
964 18291 : rhs = NumberToUint32(rhs);
965 :
966 36485 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 :
968 18142 : int32_t min_lhs = lhs.Min();
969 18142 : int32_t max_lhs = lhs.Max();
970 18142 : uint32_t min_rhs = rhs.Min();
971 18142 : uint32_t max_rhs = rhs.Max();
972 18142 : if (max_rhs > 31) {
973 : // rhs can be larger than the bitmask
974 : max_rhs = 31;
975 : min_rhs = 0;
976 : }
977 36284 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978 36284 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 :
980 18142 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981 16677 : return Type::Range(min, max, zone());
982 : }
983 :
984 7852 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985 : DCHECK(lhs.Is(Type::Number()));
986 : DCHECK(rhs.Is(Type::Number()));
987 :
988 7852 : lhs = NumberToUint32(lhs);
989 7852 : rhs = NumberToUint32(rhs);
990 :
991 15619 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 :
993 7721 : uint32_t min_lhs = lhs.Min();
994 7721 : uint32_t max_lhs = lhs.Max();
995 7721 : uint32_t min_rhs = rhs.Min();
996 7721 : uint32_t max_rhs = rhs.Max();
997 7721 : if (max_rhs > 31) {
998 : // rhs can be larger than the bitmask
999 : max_rhs = 31;
1000 : min_rhs = 0;
1001 : }
1002 :
1003 7721 : double min = min_lhs >> max_rhs;
1004 7721 : double max = max_lhs >> min_rhs;
1005 : DCHECK_LE(0, min);
1006 : DCHECK_LE(max, kMaxUInt32);
1007 :
1008 7721 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009 7090 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010 2869 : return Type::Range(min, max, zone());
1011 : }
1012 :
1013 148 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014 : DCHECK(lhs.Is(Type::Number()));
1015 : DCHECK(rhs.Is(Type::Number()));
1016 148 : return Type::Number();
1017 : }
1018 :
1019 2764 : 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 2764 : return Type::Signed32();
1024 : }
1025 :
1026 10304 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027 : DCHECK(lhs.Is(Type::Number()));
1028 : DCHECK(rhs.Is(Type::Number()));
1029 :
1030 20576 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031 20492 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 :
1033 : Type type = Type::None();
1034 10234 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 264 : type = Type::Union(type, Type::NaN(), zone());
1036 : }
1037 10234 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038 : DCHECK(!lhs.IsNone());
1039 10234 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040 : DCHECK(!rhs.IsNone());
1041 30462 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1042 9994 : 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 19812 : double max = std::max(lhs.Max(), rhs.Max());
1046 19812 : double min = std::max(lhs.Min(), rhs.Min());
1047 9906 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048 28211 : if (min <= 0.0 && 0.0 <= max &&
1049 16689 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050 184 : type = Type::Union(type, Type::MinusZero(), zone());
1051 : }
1052 : } else {
1053 328 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054 : }
1055 10234 : return type;
1056 : }
1057 :
1058 11851 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059 : DCHECK(lhs.Is(Type::Number()));
1060 : DCHECK(rhs.Is(Type::Number()));
1061 :
1062 23670 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063 23586 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 :
1065 : Type type = Type::None();
1066 11781 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 528 : type = Type::Union(type, Type::NaN(), zone());
1068 : }
1069 11781 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070 : DCHECK(!lhs.IsNone());
1071 11781 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072 : DCHECK(!rhs.IsNone());
1073 34884 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1074 11322 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1075 22420 : double max = std::min(lhs.Max(), rhs.Max());
1076 22420 : double min = std::min(lhs.Min(), rhs.Min());
1077 11210 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078 33503 : if (min <= 0.0 && 0.0 <= max &&
1079 22072 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080 145 : type = Type::Union(type, Type::MinusZero(), zone());
1081 : }
1082 : } else {
1083 571 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084 : }
1085 11781 : return type;
1086 : }
1087 :
1088 3066 : 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 3066 : 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 606402 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 40516 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 47837 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 49997 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 8902 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 35214 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 13965 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 2517 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 4749 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 14945 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 3579 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 : #undef SPECULATIVE_NUMBER_BINOP
1113 :
1114 1791430 : Type OperationTyper::SpeculativeToNumber(Type type) {
1115 1791430 : 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 370614 : Type JSType(Type type) {
1156 370614 : if (type.Is(Type::Boolean())) return Type::Boolean();
1157 363186 : if (type.Is(Type::String())) return Type::String();
1158 282060 : if (type.Is(Type::Number())) return Type::Number();
1159 148777 : if (type.Is(Type::BigInt())) return Type::BigInt();
1160 148676 : if (type.Is(Type::Undefined())) return Type::Undefined();
1161 146232 : if (type.Is(Type::Null())) return Type::Null();
1162 146009 : if (type.Is(Type::Symbol())) return Type::Symbol();
1163 145969 : if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164 : return Type::Any();
1165 : }
1166 :
1167 : } // namespace
1168 :
1169 666 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170 666 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171 666 : 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 626 : } else if (rhs.Is(Type::NaN())) {
1175 16 : if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176 : }
1177 666 : 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 573 : } else if (rhs.Is(Type::MinusZero())) {
1181 44 : if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182 : }
1183 1597 : 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 199 : 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 199 : return SameValue(lhs, rhs);
1195 : }
1196 :
1197 184641 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1198 184641 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1199 358436 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1200 448093 : if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1201 89949 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1202 : return singleton_false();
1203 : }
1204 349966 : if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1205 : return singleton_false();
1206 : }
1207 176620 : 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 135372 : Type OperationTyper::CheckBounds(Type index, Type length) {
1216 : DCHECK(length.Is(cache_->kPositiveSafeInteger));
1217 270744 : if (length.Is(cache_->kSingletonZero)) return Type::None();
1218 135309 : Type mask = Type::Range(0.0, length.Max() - 1, zone());
1219 135309 : if (index.Maybe(Type::MinusZero())) {
1220 6410 : index = Type::Union(index, cache_->kSingletonZero, zone());
1221 : }
1222 135309 : return Type::Intersect(index, mask, zone());
1223 : }
1224 :
1225 1243 : Type OperationTyper::CheckFloat64Hole(Type type) {
1226 1243 : if (type.Maybe(Type::Hole())) {
1227 : // Turn "the hole" into undefined.
1228 1179 : type = Type::Intersect(type, Type::Number(), zone());
1229 1179 : type = Type::Union(type, Type::Undefined(), zone());
1230 : }
1231 1243 : return type;
1232 : }
1233 :
1234 3733 : Type OperationTyper::CheckNumber(Type type) {
1235 3733 : return Type::Intersect(type, Type::Number(), zone());
1236 : }
1237 :
1238 90630 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1239 90630 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1240 : }
1241 :
1242 4651 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1243 4651 : if (input.Maybe(Type::Hole())) {
1244 : // Turn "the hole" into undefined.
1245 4601 : Type type = Type::Intersect(input, Type::NonInternal(), zone());
1246 4601 : return Type::Union(type, Type::Undefined(), zone());
1247 : }
1248 50 : return input;
1249 : }
1250 :
1251 210116 : Type OperationTyper::ToBoolean(Type type) {
1252 210117 : if (type.Is(Type::Boolean())) return type;
1253 175415 : if (type.Is(falsish_)) return singleton_false_;
1254 172881 : if (type.Is(truish_)) return singleton_true_;
1255 172756 : if (type.Is(Type::Number())) {
1256 45557 : return NumberToBoolean(type);
1257 : }
1258 : return Type::Boolean();
1259 : }
1260 :
1261 : } // namespace compiler
1262 : } // namespace internal
1263 122036 : } // namespace v8
|