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 1391633 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20 1391633 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = broker->isolate()->factory();
22 1391632 : infinity_ = Type::NewConstant(V8_INFINITY, zone);
23 1391634 : minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24 1391634 : Type truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 :
27 : singleton_empty_string_ =
28 1391634 : Type::HeapConstant(broker, factory->empty_string(), zone);
29 : singleton_NaN_string_ =
30 1391633 : Type::HeapConstant(broker, factory->NaN_string(), zone);
31 : singleton_zero_string_ =
32 1391631 : Type::HeapConstant(broker, factory->zero_string(), zone);
33 1391631 : singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34 1391631 : singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35 : singleton_the_hole_ =
36 1391631 : Type::HeapConstant(broker, factory->the_hole_value(), zone);
37 1391632 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38 1391632 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 :
40 : falsish_ = Type::Union(
41 : Type::Undetectable(),
42 1391629 : Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
43 : Type::Union(singleton_empty_string_, Type::Hole(), zone),
44 : zone),
45 2783261 : zone);
46 : truish_ = Type::Union(
47 : singleton_true_,
48 1391634 : Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 1391635 : }
50 :
51 1200963 : Type OperationTyper::Merge(Type left, Type right) {
52 1200963 : return Type::Union(left, right, zone());
53 : }
54 :
55 448047 : 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 448047 : 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 448048 : if (current_min != previous_range.Min()) {
105 : new_min = -V8_INFINITY;
106 332340 : for (double const min : kWeakenMinLimits) {
107 169799 : if (min <= current_min) {
108 : new_min = min;
109 : break;
110 : }
111 : }
112 : }
113 :
114 448048 : 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 448046 : if (current_max != previous_range.Max()) {
119 : new_max = V8_INFINITY;
120 7097346 : for (double const max : kWeakenMaxLimits) {
121 3695722 : if (max >= current_max) {
122 : new_max = max;
123 : break;
124 : }
125 : }
126 : }
127 :
128 448048 : 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 1355684 : double x = +V8_INFINITY;
147 12200916 : for (size_t i = 0; i < n; ++i) {
148 5422616 : if (!std::isnan(a[i])) {
149 5422562 : x = std::min(a[i], x);
150 : }
151 : }
152 : DCHECK(!std::isnan(x));
153 1355684 : 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 1355684 : double x = -V8_INFINITY;
162 12200924 : for (size_t i = 0; i < n; ++i) {
163 5422620 : if (!std::isnan(a[i])) {
164 5422518 : x = std::max(a[i], x);
165 : }
166 : }
167 : DCHECK(!std::isnan(x));
168 1355684 : return x == 0 ? 0 : x; // -0 -> 0
169 : }
170 :
171 : } // namespace
172 :
173 1246073 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174 : double rhs_max) {
175 : double results[4];
176 1246073 : results[0] = lhs_min + rhs_min;
177 1246073 : results[1] = lhs_min + rhs_max;
178 1246073 : results[2] = lhs_max + rhs_min;
179 1246073 : 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 11213297 : for (int i = 0; i < 4; ++i) {
186 4983612 : if (std::isnan(results[i])) ++nans;
187 : }
188 1246073 : if (nans == 4) return Type::NaN();
189 1246067 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190 1246093 : 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 1246093 : return type;
197 : }
198 :
199 54340 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200 : double rhs_min, double rhs_max) {
201 : double results[4];
202 54340 : results[0] = lhs_min - rhs_min;
203 54340 : results[1] = lhs_min - rhs_max;
204 54340 : results[2] = lhs_max - rhs_min;
205 54340 : 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 489060 : for (int i = 0; i < 4; ++i) {
212 217360 : if (std::isnan(results[i])) ++nans;
213 : }
214 54340 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215 54334 : Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216 54334 : 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 55361 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225 : double rhs_min, double rhs_max) {
226 : double results[4];
227 55361 : results[0] = lhs_min * rhs_min;
228 55361 : results[1] = lhs_min * rhs_max;
229 55361 : results[2] = lhs_max * rhs_min;
230 55361 : 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 497735 : for (int i = 0; i < 4; ++i) {
236 221265 : if (std::isnan(results[i])) {
237 78 : return cache_->kIntegerOrMinusZeroOrNaN;
238 : }
239 : }
240 : double min = array_min(results, 4);
241 : double max = array_max(results, 4);
242 55283 : Type type = Type::Range(min, max, zone());
243 55283 : if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244 42769 : type = Type::Union(type, Type::MinusZero(), zone());
245 : }
246 : // 0 * V8_INFINITY is NaN, regardless of sign
247 94147 : if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248 74991 : (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249 55182 : ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250 127 : (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251 194 : type = Type::Union(type, Type::NaN(), zone());
252 : }
253 55283 : return type;
254 : }
255 :
256 80813 : Type OperationTyper::ConvertReceiver(Type type) {
257 80813 : if (type.Is(Type::Receiver())) return type;
258 80806 : bool const maybe_primitive = type.Maybe(Type::Primitive());
259 80806 : type = Type::Intersect(type, Type::Receiver(), zone());
260 80806 : 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 80806 : type = Type::Union(type, Type::OtherObject(), zone());
264 : }
265 80806 : return type;
266 : }
267 :
268 3303692 : Type OperationTyper::ToNumber(Type type) {
269 3303662 : 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 717121 : 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 438900 : 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 438922 : if (type.Maybe(Type::Null())) {
286 : // ToNumber(null) => +0
287 426258 : type = Type::Union(type, cache_->kSingletonZero, zone());
288 : }
289 438956 : if (type.Maybe(Type::Undefined())) {
290 : // ToNumber(undefined) => NaN
291 432878 : type = Type::Union(type, Type::NaN(), zone());
292 : }
293 438927 : if (type.Maybe(singleton_false_)) {
294 : // ToNumber(false) => +0
295 428198 : type = Type::Union(type, cache_->kSingletonZero, zone());
296 : }
297 438963 : if (type.Maybe(singleton_true_)) {
298 : // ToNumber(true) => +1
299 428741 : type = Type::Union(type, cache_->kSingletonOne, zone());
300 : }
301 438967 : 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 1168926 : Type OperationTyper::ToNumeric(Type type) {
316 : // If the {type} includes any receivers, then the callbacks
317 : // might actually produce BigInt primitive values here.
318 1168926 : if (type.Maybe(Type::Receiver())) {
319 59961 : type = Type::Union(type, Type::BigInt(), zone());
320 : }
321 : return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 1168926 : Type::Intersect(type, Type::BigInt(), zone()), zone());
323 : }
324 :
325 1280 : Type OperationTyper::NumberAbs(Type type) {
326 : DCHECK(type.Is(Type::Number()));
327 1280 : if (type.IsNone()) return type;
328 :
329 1245 : bool const maybe_nan = type.Maybe(Type::NaN());
330 1245 : bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 :
332 1245 : type = Type::Intersect(type, Type::PlainNumber(), zone());
333 1245 : if (!type.IsNone()) {
334 1192 : double const max = type.Max();
335 1192 : double const min = type.Min();
336 1192 : if (min < 0) {
337 2036 : if (type.Is(cache_->kInteger)) {
338 : type =
339 672 : Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
340 : } else {
341 682 : type = Type::PlainNumber();
342 : }
343 : }
344 : }
345 :
346 1245 : if (maybe_minuszero) {
347 676 : type = Type::Union(type, cache_->kSingletonZero, zone());
348 : }
349 1245 : if (maybe_nan) {
350 766 : type = Type::Union(type, Type::NaN(), zone());
351 : }
352 1245 : return type;
353 : }
354 :
355 101 : Type OperationTyper::NumberAcos(Type type) {
356 : DCHECK(type.Is(Type::Number()));
357 101 : return Type::Number();
358 : }
359 :
360 101 : Type OperationTyper::NumberAcosh(Type type) {
361 : DCHECK(type.Is(Type::Number()));
362 101 : return Type::Number();
363 : }
364 :
365 129 : Type OperationTyper::NumberAsin(Type type) {
366 : DCHECK(type.Is(Type::Number()));
367 129 : return Type::Number();
368 : }
369 :
370 101 : Type OperationTyper::NumberAsinh(Type type) {
371 : DCHECK(type.Is(Type::Number()));
372 101 : return Type::Number();
373 : }
374 :
375 101 : Type OperationTyper::NumberAtan(Type type) {
376 : DCHECK(type.Is(Type::Number()));
377 101 : return Type::Number();
378 : }
379 :
380 100 : Type OperationTyper::NumberAtanh(Type type) {
381 : DCHECK(type.Is(Type::Number()));
382 100 : return Type::Number();
383 : }
384 :
385 101 : Type OperationTyper::NumberCbrt(Type type) {
386 : DCHECK(type.Is(Type::Number()));
387 101 : return Type::Number();
388 : }
389 :
390 21858 : Type OperationTyper::NumberCeil(Type type) {
391 : DCHECK(type.Is(Type::Number()));
392 43716 : if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
393 21218 : type = Type::Intersect(type, Type::NaN(), zone());
394 21218 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
395 21218 : 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 86359 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427 86359 : type = Type::Union(type, cache_->kInteger, zone());
428 86359 : return type;
429 : }
430 :
431 4214 : Type OperationTyper::NumberFround(Type type) {
432 : DCHECK(type.Is(Type::Number()));
433 4214 : 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 4758 : type = Type::Intersect(type, Type::NaN(), zone());
460 4758 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
461 4758 : 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 176 : bool maybe_minuszero = type.Maybe(Type::MinusZero());
468 176 : bool maybe_nan = type.Maybe(Type::NaN());
469 176 : type = Type::Intersect(type, Type::PlainNumber(), zone());
470 176 : if (type.IsNone()) {
471 : // Do nothing.
472 176 : } else if (type.Max() < 0.0) {
473 3 : type = cache_->kSingletonMinusOne;
474 173 : } else if (type.Max() <= 0.0) {
475 0 : type = cache_->kMinusOneOrZero;
476 173 : } else if (type.Min() > 0.0) {
477 8 : type = cache_->kSingletonOne;
478 165 : } else if (type.Min() >= 0.0) {
479 0 : type = cache_->kZeroOrOne;
480 : } else {
481 165 : type = Type::Range(-1.0, 1.0, zone());
482 : }
483 176 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484 176 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485 : DCHECK(!type.IsNone());
486 176 : 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 21083 : type = Type::Intersect(type, Type::NaN(), zone());
518 21083 : type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
519 21083 : return type;
520 : }
521 :
522 46135 : Type OperationTyper::NumberToBoolean(Type type) {
523 : DCHECK(type.Is(Type::Number()));
524 46135 : if (type.IsNone()) return type;
525 92200 : if (type.Is(cache_->kZeroish)) return singleton_false_;
526 46098 : if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527 2130 : return singleton_true_; // Ruled out nan, -0 and +0.
528 : }
529 : return Type::Boolean();
530 : }
531 :
532 190939 : Type OperationTyper::NumberToInt32(Type type) {
533 : DCHECK(type.Is(Type::Number()));
534 :
535 190939 : if (type.Is(Type::Signed32())) return type;
536 105494 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
537 49364 : if (type.Is(signed32ish_)) {
538 6281 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
539 6281 : Type::Signed32(), zone());
540 : }
541 : return Type::Signed32();
542 : }
543 :
544 12602 : Type OperationTyper::NumberToString(Type type) {
545 : DCHECK(type.Is(Type::Number()));
546 12602 : if (type.IsNone()) return type;
547 12562 : if (type.Is(Type::NaN())) return singleton_NaN_string_;
548 25122 : if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
549 : return Type::String();
550 : }
551 :
552 54580 : Type OperationTyper::NumberToUint32(Type type) {
553 : DCHECK(type.Is(Type::Number()));
554 :
555 54580 : if (type.Is(Type::Unsigned32())) return type;
556 47896 : if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
557 22240 : if (type.Is(unsigned32ish_)) {
558 46 : return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
559 46 : Type::Unsigned32(), zone());
560 : }
561 : return Type::Unsigned32();
562 : }
563 :
564 1618 : Type OperationTyper::NumberToUint8Clamped(Type type) {
565 : DCHECK(type.Is(Type::Number()));
566 :
567 3236 : if (type.Is(cache_->kUint8)) return type;
568 1527 : return cache_->kUint8;
569 : }
570 :
571 3601 : 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 3601 : if (type.Maybe(Type::NaN())) return Type::Number();
577 989 : return type;
578 : }
579 :
580 1751109 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581 : DCHECK(lhs.Is(Type::Number()));
582 : DCHECK(rhs.Is(Type::Number()));
583 :
584 3501061 : 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 1749857 : 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 1749637 : if (lhs.Maybe(Type::MinusZero())) {
593 252003 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
594 : } else {
595 : maybe_minuszero = false;
596 : }
597 1749735 : if (rhs.Maybe(Type::MinusZero())) {
598 189008 : 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 1749852 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606 1749862 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607 3499581 : if (!lhs.IsNone() && !rhs.IsNone()) {
608 4862260 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
609 1246066 : type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610 : } else {
611 1311698 : if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 320391 : (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 1749861 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 1749856 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622 1749867 : return type;
623 : }
624 :
625 63500 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626 : DCHECK(lhs.Is(Type::Number()));
627 : DCHECK(rhs.Is(Type::Number()));
628 :
629 126580 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
630 :
631 : // Subtraction can return NaN if either input can be NaN or we try to
632 : // compute the sum of two infinities of opposite sign.
633 62996 : 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 62996 : if (lhs.Maybe(Type::MinusZero())) {
639 5979 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
640 5979 : maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
641 : }
642 62996 : if (rhs.Maybe(Type::MinusZero())) {
643 2430 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
644 : }
645 :
646 : // We can give more precise types for integers.
647 : Type type = Type::None();
648 62996 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649 62996 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650 125863 : if (!lhs.IsNone() && !rhs.IsNone()) {
651 181181 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
652 54340 : type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653 : } else {
654 23022 : if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 7016 : (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 62996 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 62996 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665 62996 : return type;
666 : }
667 :
668 509750 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669 509750 : 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 509667 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
676 : }
677 :
678 39727 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679 39727 : 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 39727 : return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
686 : }
687 :
688 80746 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689 : DCHECK(lhs.Is(Type::Number()));
690 : DCHECK(rhs.Is(Type::Number()));
691 :
692 161279 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693 160880 : 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 171159 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699 82216 : (lhs.Maybe(cache_->kZeroish) &&
700 199131 : (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701 47448 : (rhs.Maybe(cache_->kZeroish) &&
702 6254 : (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703 80314 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704 : DCHECK(!lhs.IsNone());
705 80314 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706 : DCHECK(!rhs.IsNone());
707 :
708 : // Try to rule out -0.
709 123736 : bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710 85018 : rhs.Maybe(Type::MinusZero()) ||
711 182474 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
712 27179 : (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
713 80314 : if (lhs.Maybe(Type::MinusZero())) {
714 36892 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
715 36892 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716 : }
717 80314 : if (rhs.Maybe(Type::MinusZero())) {
718 5056 : rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
719 5056 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720 : }
721 :
722 : // Compute the effective type, utilizing range information if possible.
723 197384 : Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
724 55361 : ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 135675 : : Type::OrderedNumber();
726 :
727 : // Take into account the -0 and NaN information computed earlier.
728 80314 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 80314 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730 80314 : return type;
731 : }
732 :
733 65503 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734 : DCHECK(lhs.Is(Type::Number()));
735 : DCHECK(rhs.Is(Type::Number()));
736 :
737 130945 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738 128593 : 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 93207 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
742 60094 : ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743 4216 : (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744 63600 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745 : DCHECK(!lhs.IsNone());
746 63601 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747 : DCHECK(!rhs.IsNone());
748 :
749 : // Try to rule out -0.
750 : bool maybe_minuszero =
751 110277 : !lhs.Is(cache_->kInteger) ||
752 117928 : (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
753 62562 : (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 63600 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758 63600 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759 63600 : return type;
760 : }
761 :
762 14545 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763 : DCHECK(lhs.Is(Type::Number()));
764 : DCHECK(rhs.Is(Type::Number()));
765 :
766 29029 : 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 36561 : bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
771 34740 : 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 14447 : if (lhs.Maybe(Type::MinusZero())) {
776 : maybe_minuszero = true;
777 3689 : lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
778 : }
779 14447 : if (rhs.Maybe(Type::MinusZero())) {
780 962 : 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 14447 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 14447 : 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 28774 : if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
791 : // Determine the bounds of {lhs} and {rhs}.
792 14182 : double const lmin = lhs.Min();
793 14182 : double const lmax = lhs.Max();
794 14182 : double const rmin = rhs.Min();
795 14182 : double const rmax = rhs.Max();
796 :
797 : // The sign of the result is the sign of the {lhs}.
798 14182 : if (lmin < 0.0) maybe_minuszero = true;
799 :
800 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
801 40076 : if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
802 33777 : double labs = std::max(std::abs(lmin), std::abs(lmax));
803 33777 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804 11259 : double abs = std::min(labs, rabs);
805 : double min = 0.0, max = 0.0;
806 11259 : if (lmin >= 0.0) {
807 : // {lhs} positive.
808 : min = 0.0;
809 : max = abs;
810 8235 : } else if (lmax <= 0.0) {
811 : // {lhs} negative.
812 730 : min = 0.0 - abs;
813 : max = 0.0;
814 : } else {
815 : // {lhs} positive or negative.
816 7505 : min = 0.0 - abs;
817 : max = abs;
818 : }
819 11259 : 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 14447 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 14447 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828 14447 : return type;
829 : }
830 :
831 45009 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832 : DCHECK(lhs.Is(Type::Number()));
833 : DCHECK(rhs.Is(Type::Number()));
834 :
835 45009 : lhs = NumberToInt32(lhs);
836 45009 : rhs = NumberToInt32(rhs);
837 :
838 89869 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 :
840 44823 : double lmin = lhs.Min();
841 44823 : double rmin = rhs.Min();
842 44823 : double lmax = lhs.Max();
843 44823 : 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 89646 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848 44823 : double max = kMaxInt;
849 :
850 : // Or-ing with 0 is essentially a conversion to int32.
851 44823 : if (rmin == 0 && rmax == 0) {
852 : min = lmin;
853 31847 : max = lmax;
854 : }
855 44823 : if (lmin == 0 && lmax == 0) {
856 : min = rmin;
857 595 : max = rmax;
858 : }
859 :
860 44823 : if (lmax < 0 || rmax < 0) {
861 : // Or-ing two values of which at least one is negative results in a negative
862 : // value.
863 514 : max = std::min(max, -1.0);
864 : }
865 44823 : return Type::Range(min, max, zone());
866 : }
867 :
868 28124 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869 : DCHECK(lhs.Is(Type::Number()));
870 : DCHECK(rhs.Is(Type::Number()));
871 :
872 28124 : lhs = NumberToInt32(lhs);
873 28124 : rhs = NumberToInt32(rhs);
874 :
875 56124 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 :
877 27963 : double lmin = lhs.Min();
878 27963 : double rmin = rhs.Min();
879 27963 : double lmax = lhs.Max();
880 27963 : 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 55926 : 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 27963 : if (lmin >= 0) {
889 : min = 0;
890 7483 : max = std::min(max, lmax);
891 : }
892 27963 : if (rmin >= 0) {
893 : min = 0;
894 25613 : max = std::min(max, rmax);
895 : }
896 27963 : return Type::Range(min, max, zone());
897 : }
898 :
899 4335 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900 : DCHECK(lhs.Is(Type::Number()));
901 : DCHECK(rhs.Is(Type::Number()));
902 :
903 4335 : lhs = NumberToInt32(lhs);
904 4335 : rhs = NumberToInt32(rhs);
905 :
906 8601 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 :
908 4229 : double lmin = lhs.Min();
909 4229 : double rmin = rhs.Min();
910 4229 : double lmax = lhs.Max();
911 4229 : double rmax = rhs.Max();
912 4229 : 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 9315 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925 : DCHECK(lhs.Is(Type::Number()));
926 : DCHECK(rhs.Is(Type::Number()));
927 :
928 9315 : lhs = NumberToInt32(lhs);
929 9315 : rhs = NumberToUint32(rhs);
930 :
931 18561 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 :
933 9209 : int32_t min_lhs = lhs.Min();
934 9209 : int32_t max_lhs = lhs.Max();
935 9209 : uint32_t min_rhs = rhs.Min();
936 9209 : uint32_t max_rhs = rhs.Max();
937 9209 : if (max_rhs > 31) {
938 : // rhs can be larger than the bitmask
939 : max_rhs = 31;
940 : min_rhs = 0;
941 : }
942 :
943 9209 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944 : // overflow possible
945 : return Type::Signed32();
946 : }
947 :
948 : double min =
949 2410 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950 3615 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951 : double max =
952 2410 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953 3615 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 :
955 1205 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956 950 : return Type::Range(min, max, zone());
957 : }
958 :
959 18299 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960 : DCHECK(lhs.Is(Type::Number()));
961 : DCHECK(rhs.Is(Type::Number()));
962 :
963 18299 : lhs = NumberToInt32(lhs);
964 18299 : rhs = NumberToUint32(rhs);
965 :
966 36505 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 :
968 18155 : int32_t min_lhs = lhs.Min();
969 18155 : int32_t max_lhs = lhs.Max();
970 18155 : uint32_t min_rhs = rhs.Min();
971 18155 : uint32_t max_rhs = rhs.Max();
972 18155 : if (max_rhs > 31) {
973 : // rhs can be larger than the bitmask
974 : max_rhs = 31;
975 : min_rhs = 0;
976 : }
977 36310 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978 36310 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 :
980 18155 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981 16663 : return Type::Range(min, max, zone());
982 : }
983 :
984 7954 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985 : DCHECK(lhs.Is(Type::Number()));
986 : DCHECK(rhs.Is(Type::Number()));
987 :
988 7954 : lhs = NumberToUint32(lhs);
989 7954 : rhs = NumberToUint32(rhs);
990 :
991 15823 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 :
993 7827 : uint32_t min_lhs = lhs.Min();
994 7827 : uint32_t max_lhs = lhs.Max();
995 7827 : uint32_t min_rhs = rhs.Min();
996 7827 : uint32_t max_rhs = rhs.Max();
997 7827 : if (max_rhs > 31) {
998 : // rhs can be larger than the bitmask
999 : max_rhs = 31;
1000 : min_rhs = 0;
1001 : }
1002 :
1003 7827 : double min = min_lhs >> max_rhs;
1004 7827 : double max = max_lhs >> min_rhs;
1005 : DCHECK_LE(0, min);
1006 : DCHECK_LE(max, kMaxUInt32);
1007 :
1008 7827 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009 7196 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010 2923 : return Type::Range(min, max, zone());
1011 : }
1012 :
1013 156 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014 : DCHECK(lhs.Is(Type::Number()));
1015 : DCHECK(rhs.Is(Type::Number()));
1016 156 : 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 10491 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027 : DCHECK(lhs.Is(Type::Number()));
1028 : DCHECK(rhs.Is(Type::Number()));
1029 :
1030 20944 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031 20866 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 :
1033 : Type type = Type::None();
1034 10421 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 266 : type = Type::Union(type, Type::NaN(), zone());
1036 : }
1037 10421 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038 : DCHECK(!lhs.IsNone());
1039 10421 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040 : DCHECK(!rhs.IsNone());
1041 31009 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1042 10167 : 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 20182 : double max = std::max(lhs.Max(), rhs.Max());
1046 20182 : double min = std::max(lhs.Min(), rhs.Min());
1047 10091 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048 28721 : if (min <= 0.0 && 0.0 <= max &&
1049 16969 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050 184 : type = Type::Union(type, Type::MinusZero(), zone());
1051 : }
1052 : } else {
1053 330 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054 : }
1055 10421 : return type;
1056 : }
1057 :
1058 12015 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059 : DCHECK(lhs.Is(Type::Number()));
1060 : DCHECK(rhs.Is(Type::Number()));
1061 :
1062 23992 : if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063 23914 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 :
1065 : Type type = Type::None();
1066 11945 : if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 527 : type = Type::Union(type, Type::NaN(), zone());
1068 : }
1069 11945 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070 : DCHECK(!lhs.IsNone());
1071 11945 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072 : DCHECK(!rhs.IsNone());
1073 35365 : if (lhs.Is(cache_->kIntegerOrMinusZero) &&
1074 11475 : rhs.Is(cache_->kIntegerOrMinusZero)) {
1075 22750 : double max = std::min(lhs.Max(), rhs.Max());
1076 22750 : double min = std::min(lhs.Min(), rhs.Min());
1077 11375 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078 33946 : if (min <= 0.0 && 0.0 <= max &&
1079 22296 : (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080 147 : type = Type::Union(type, Type::MinusZero(), zone());
1081 : }
1082 : } else {
1083 570 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084 : }
1085 11945 : return type;
1086 : }
1087 :
1088 3154 : 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 3154 : 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 606777 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 40808 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 48396 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 49875 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 9222 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 35251 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 14038 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 2512 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 4742 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 14952 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 3690 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 : #undef SPECULATIVE_NUMBER_BINOP
1113 :
1114 1794717 : Type OperationTyper::SpeculativeToNumber(Type type) {
1115 1794717 : 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 370408 : Type JSType(Type type) {
1156 370408 : if (type.Is(Type::Boolean())) return Type::Boolean();
1157 363108 : if (type.Is(Type::String())) return Type::String();
1158 281903 : if (type.Is(Type::Number())) return Type::Number();
1159 148733 : if (type.Is(Type::BigInt())) return Type::BigInt();
1160 148632 : if (type.Is(Type::Undefined())) return Type::Undefined();
1161 146188 : if (type.Is(Type::Null())) return Type::Null();
1162 145964 : if (type.Is(Type::Symbol())) return Type::Symbol();
1163 145924 : if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164 : return Type::Any();
1165 : }
1166 :
1167 : } // namespace
1168 :
1169 667 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170 667 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171 667 : 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 627 : } else if (rhs.Is(Type::NaN())) {
1175 16 : if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176 : }
1177 667 : 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 574 : } else if (rhs.Is(Type::MinusZero())) {
1181 44 : if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182 : }
1183 1599 : 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 203 : 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 203 : return SameValue(lhs, rhs);
1195 : }
1196 :
1197 184537 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1198 184537 : if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1199 358316 : if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1200 447940 : if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1201 89924 : (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1202 : return singleton_false();
1203 : }
1204 349856 : if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1205 : return singleton_false();
1206 : }
1207 176535 : 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 52936 : Type OperationTyper::StringConcat(Type length, Type first, Type second) {
1216 158801 : if (length.IsNone() || first.IsNone() || second.IsNone()) return Type::None();
1217 52910 : if (first.Is(Type::EmptyString())) return second;
1218 52669 : if (second.Is(Type::EmptyString())) return first;
1219 :
1220 52633 : first = Type::Intersect(first, Type::NonEmptyString(), zone());
1221 52633 : second = Type::Intersect(second, Type::NonEmptyString(), zone());
1222 :
1223 : Type type = Type::NonEmptyString();
1224 66619 : if (first.Is(Type::NonEmptyOneByteString()) &&
1225 : second.Is(Type::NonEmptyOneByteString())) {
1226 : type = Type::NonEmptyOneByteString();
1227 85766 : } else if (first.Is(Type::NonEmptyTwoByteString()) ||
1228 : second.Is(Type::NonEmptyTwoByteString())) {
1229 : type = Type::NonEmptyTwoByteString();
1230 : }
1231 :
1232 52633 : if (length.Min() == 0) {
1233 26329 : type = Type::Union(type, Type::EmptyString(), zone());
1234 : }
1235 52633 : return type;
1236 : }
1237 :
1238 135463 : Type OperationTyper::CheckBounds(Type index, Type length) {
1239 : DCHECK(length.Is(cache_->kPositiveSafeInteger));
1240 270926 : if (length.Is(cache_->kSingletonZero)) return Type::None();
1241 135405 : Type mask = Type::Range(0.0, length.Max() - 1, zone());
1242 135405 : if (index.Maybe(Type::MinusZero())) {
1243 6391 : index = Type::Union(index, cache_->kSingletonZero, zone());
1244 : }
1245 135405 : return Type::Intersect(index, mask, zone());
1246 : }
1247 :
1248 1249 : Type OperationTyper::CheckFloat64Hole(Type type) {
1249 1249 : if (type.Maybe(Type::Hole())) {
1250 : // Turn "the hole" into undefined.
1251 1185 : type = Type::Intersect(type, Type::Number(), zone());
1252 1185 : type = Type::Union(type, Type::Undefined(), zone());
1253 : }
1254 1249 : return type;
1255 : }
1256 :
1257 3765 : Type OperationTyper::CheckNumber(Type type) {
1258 3765 : return Type::Intersect(type, Type::Number(), zone());
1259 : }
1260 :
1261 5112 : Type OperationTyper::CheckInternalizedString(Type type) {
1262 5112 : return Type::Intersect(type, Type::InternalizedString(), zone());
1263 : }
1264 :
1265 36 : Type OperationTyper::CheckNonEmptyString(Type type) {
1266 36 : return Type::Intersect(type, Type::NonEmptyString(), zone());
1267 : }
1268 :
1269 3573 : Type OperationTyper::CheckNonEmptyOneByteString(Type type) {
1270 3573 : return Type::Intersect(type, Type::NonEmptyOneByteString(), zone());
1271 : }
1272 :
1273 452 : Type OperationTyper::CheckNonEmptyTwoByteString(Type type) {
1274 452 : return Type::Intersect(type, Type::NonEmptyTwoByteString(), zone());
1275 : }
1276 :
1277 29277 : Type OperationTyper::CheckString(Type type) {
1278 29277 : return Type::Intersect(type, Type::String(), zone());
1279 : }
1280 :
1281 99649 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1282 99649 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1283 : }
1284 :
1285 4666 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1286 4666 : if (input.Maybe(Type::Hole())) {
1287 : // Turn "the hole" into undefined.
1288 4617 : Type type = Type::Intersect(input, Type::NonInternal(), zone());
1289 4617 : return Type::Union(type, Type::Undefined(), zone());
1290 : }
1291 49 : return input;
1292 : }
1293 :
1294 210199 : Type OperationTyper::ToBoolean(Type type) {
1295 210199 : if (type.Is(Type::Boolean())) return type;
1296 175546 : if (type.Is(falsish_)) return singleton_false_;
1297 173009 : if (type.Is(truish_)) return singleton_true_;
1298 172885 : if (type.Is(Type::Number())) {
1299 45587 : return NumberToBoolean(type);
1300 : }
1301 : return Type::Boolean();
1302 : }
1303 :
1304 : } // namespace compiler
1305 : } // namespace internal
1306 122028 : } // namespace v8
|