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
OperationTyper(Isolate * isolate,JSHeapBroker * js_heap_broker,Zone * zone)19 OperationTyper::OperationTyper(Isolate* isolate, JSHeapBroker* js_heap_broker,
20 Zone* zone)
21 : zone_(zone), cache_(TypeCache::Get()) {
22 Factory* factory = isolate->factory();
23 infinity_ =
24 Type::NewConstant(js_heap_broker, factory->infinity_value(), zone);
25 minus_infinity_ =
26 Type::NewConstant(js_heap_broker, factory->minus_infinity_value(), zone);
27 Type truncating_to_zero = Type::MinusZeroOrNaN();
28 DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
29
30 singleton_empty_string_ =
31 Type::HeapConstant(js_heap_broker, factory->empty_string(), zone);
32 singleton_NaN_string_ =
33 Type::HeapConstant(js_heap_broker, factory->NaN_string(), zone);
34 singleton_zero_string_ =
35 Type::HeapConstant(js_heap_broker, factory->zero_string(), zone);
36 singleton_false_ =
37 Type::HeapConstant(js_heap_broker, factory->false_value(), zone);
38 singleton_true_ =
39 Type::HeapConstant(js_heap_broker, factory->true_value(), zone);
40 singleton_the_hole_ =
41 Type::HeapConstant(js_heap_broker, factory->the_hole_value(), zone);
42 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
43 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
44
45 falsish_ = Type::Union(
46 Type::Undetectable(),
47 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
48 Type::Union(singleton_empty_string_, Type::Hole(), zone),
49 zone),
50 zone);
51 truish_ = Type::Union(
52 singleton_true_,
53 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
54 }
55
Merge(Type left,Type right)56 Type OperationTyper::Merge(Type left, Type right) {
57 return Type::Union(left, right, zone());
58 }
59
WeakenRange(Type previous_range,Type current_range)60 Type OperationTyper::WeakenRange(Type previous_range, Type current_range) {
61 static const double kWeakenMinLimits[] = {0.0,
62 -1073741824.0,
63 -2147483648.0,
64 -4294967296.0,
65 -8589934592.0,
66 -17179869184.0,
67 -34359738368.0,
68 -68719476736.0,
69 -137438953472.0,
70 -274877906944.0,
71 -549755813888.0,
72 -1099511627776.0,
73 -2199023255552.0,
74 -4398046511104.0,
75 -8796093022208.0,
76 -17592186044416.0,
77 -35184372088832.0,
78 -70368744177664.0,
79 -140737488355328.0,
80 -281474976710656.0,
81 -562949953421312.0};
82 static const double kWeakenMaxLimits[] = {0.0,
83 1073741823.0,
84 2147483647.0,
85 4294967295.0,
86 8589934591.0,
87 17179869183.0,
88 34359738367.0,
89 68719476735.0,
90 137438953471.0,
91 274877906943.0,
92 549755813887.0,
93 1099511627775.0,
94 2199023255551.0,
95 4398046511103.0,
96 8796093022207.0,
97 17592186044415.0,
98 35184372088831.0,
99 70368744177663.0,
100 140737488355327.0,
101 281474976710655.0,
102 562949953421311.0};
103 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
104
105 double current_min = current_range.Min();
106 double new_min = current_min;
107 // Find the closest lower entry in the list of allowed
108 // minima (or negative infinity if there is no such entry).
109 if (current_min != previous_range.Min()) {
110 new_min = -V8_INFINITY;
111 for (double const min : kWeakenMinLimits) {
112 if (min <= current_min) {
113 new_min = min;
114 break;
115 }
116 }
117 }
118
119 double current_max = current_range.Max();
120 double new_max = current_max;
121 // Find the closest greater entry in the list of allowed
122 // maxima (or infinity if there is no such entry).
123 if (current_max != previous_range.Max()) {
124 new_max = V8_INFINITY;
125 for (double const max : kWeakenMaxLimits) {
126 if (max >= current_max) {
127 new_max = max;
128 break;
129 }
130 }
131 }
132
133 return Type::Range(new_min, new_max, zone());
134 }
135
Rangify(Type type)136 Type OperationTyper::Rangify(Type type) {
137 if (type.IsRange()) return type; // Shortcut.
138 if (!type.Is(cache_.kInteger)) {
139 return type; // Give up on non-integer types.
140 }
141 return Type::Range(type.Min(), type.Max(), zone());
142 }
143
144 namespace {
145
146 // Returns the array's least element, ignoring NaN.
147 // There must be at least one non-NaN element.
148 // Any -0 is converted to 0.
array_min(double a[],size_t n)149 double array_min(double a[], size_t n) {
150 DCHECK_NE(0, n);
151 double x = +V8_INFINITY;
152 for (size_t i = 0; i < n; ++i) {
153 if (!std::isnan(a[i])) {
154 x = std::min(a[i], x);
155 }
156 }
157 DCHECK(!std::isnan(x));
158 return x == 0 ? 0 : x; // -0 -> 0
159 }
160
161 // Returns the array's greatest element, ignoring NaN.
162 // There must be at least one non-NaN element.
163 // Any -0 is converted to 0.
array_max(double a[],size_t n)164 double array_max(double a[], size_t n) {
165 DCHECK_NE(0, n);
166 double x = -V8_INFINITY;
167 for (size_t i = 0; i < n; ++i) {
168 if (!std::isnan(a[i])) {
169 x = std::max(a[i], x);
170 }
171 }
172 DCHECK(!std::isnan(x));
173 return x == 0 ? 0 : x; // -0 -> 0
174 }
175
176 } // namespace
177
AddRanger(double lhs_min,double lhs_max,double rhs_min,double rhs_max)178 Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
179 double rhs_max) {
180 double results[4];
181 results[0] = lhs_min + rhs_min;
182 results[1] = lhs_min + rhs_max;
183 results[2] = lhs_max + rhs_min;
184 results[3] = lhs_max + rhs_max;
185 // Since none of the inputs can be -0, the result cannot be -0 either.
186 // However, it can be nan (the sum of two infinities of opposite sign).
187 // On the other hand, if none of the "results" above is nan, then the
188 // actual result cannot be nan either.
189 int nans = 0;
190 for (int i = 0; i < 4; ++i) {
191 if (std::isnan(results[i])) ++nans;
192 }
193 if (nans == 4) return Type::NaN();
194 Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
195 if (nans > 0) type = Type::Union(type, Type::NaN(), zone());
196 // Examples:
197 // [-inf, -inf] + [+inf, +inf] = NaN
198 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
199 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
200 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
201 return type;
202 }
203
SubtractRanger(double lhs_min,double lhs_max,double rhs_min,double rhs_max)204 Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
205 double rhs_min, double rhs_max) {
206 double results[4];
207 results[0] = lhs_min - rhs_min;
208 results[1] = lhs_min - rhs_max;
209 results[2] = lhs_max - rhs_min;
210 results[3] = lhs_max - rhs_max;
211 // Since none of the inputs can be -0, the result cannot be -0.
212 // However, it can be nan (the subtraction of two infinities of same sign).
213 // On the other hand, if none of the "results" above is nan, then the actual
214 // result cannot be nan either.
215 int nans = 0;
216 for (int i = 0; i < 4; ++i) {
217 if (std::isnan(results[i])) ++nans;
218 }
219 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
220 Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
221 return nans == 0 ? type : Type::Union(type, Type::NaN(), zone());
222 // Examples:
223 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
224 // [-inf, -inf] - [-inf, -inf] = NaN
225 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
226 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
227 }
228
MultiplyRanger(Type lhs,Type rhs)229 Type OperationTyper::MultiplyRanger(Type lhs, Type rhs) {
230 double results[4];
231 double lmin = lhs.AsRange()->Min();
232 double lmax = lhs.AsRange()->Max();
233 double rmin = rhs.AsRange()->Min();
234 double rmax = rhs.AsRange()->Max();
235 results[0] = lmin * rmin;
236 results[1] = lmin * rmax;
237 results[2] = lmax * rmin;
238 results[3] = lmax * rmax;
239 // If the result may be nan, we give up on calculating a precise type, because
240 // the discontinuity makes it too complicated. Note that even if none of the
241 // "results" above is nan, the actual result may still be, so we have to do a
242 // different check:
243 bool maybe_nan = (lhs.Maybe(cache_.kSingletonZero) &&
244 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
245 (rhs.Maybe(cache_.kSingletonZero) &&
246 (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
247 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up.
248 bool maybe_minuszero = (lhs.Maybe(cache_.kSingletonZero) && rmin < 0) ||
249 (rhs.Maybe(cache_.kSingletonZero) && lmin < 0);
250 Type range =
251 Type::Range(array_min(results, 4), array_max(results, 4), zone());
252 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
253 : range;
254 }
255
ConvertReceiver(Type type)256 Type OperationTyper::ConvertReceiver(Type type) {
257 if (type.Is(Type::Receiver())) return type;
258 bool const maybe_primitive = type.Maybe(Type::Primitive());
259 type = Type::Intersect(type, Type::Receiver(), zone());
260 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 type = Type::Union(type, Type::OtherObject(), zone());
264 }
265 return type;
266 }
267
268 // Returns the result type of converting {type} to number, if the
269 // result does not depend on conversion options.
ToNumberCommon(Type type)270 base::Optional<Type> OperationTyper::ToNumberCommon(Type type) {
271 if (type.Is(Type::Number())) return type;
272 if (type.Is(Type::NullOrUndefined())) {
273 if (type.Is(Type::Null())) return cache_.kSingletonZero;
274 if (type.Is(Type::Undefined())) return Type::NaN();
275 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
276 }
277 if (type.Is(Type::Boolean())) {
278 if (type.Is(singleton_false_)) return cache_.kSingletonZero;
279 if (type.Is(singleton_true_)) return cache_.kSingletonOne;
280 return cache_.kZeroOrOne;
281 }
282 if (type.Is(Type::NumberOrOddball())) {
283 if (type.Is(Type::NumberOrUndefined())) {
284 type = Type::Union(type, Type::NaN(), zone());
285 } else if (type.Is(Type::NullOrNumber())) {
286 type = Type::Union(type, cache_.kSingletonZero, zone());
287 } else if (type.Is(Type::BooleanOrNullOrNumber())) {
288 type = Type::Union(type, cache_.kZeroOrOne, zone());
289 } else {
290 type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone());
291 }
292 return Type::Intersect(type, Type::Number(), zone());
293 }
294 return base::Optional<Type>();
295 }
296
ToNumberOrNumeric(Object::Conversion mode,Type type)297 Type OperationTyper::ToNumberOrNumeric(Object::Conversion mode, Type type) {
298 if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) {
299 return *maybe_result_type;
300 }
301 if (type.Is(Type::BigInt())) {
302 return mode == Object::Conversion::kToNumber ? Type::None() : type;
303 }
304 return mode == Object::Conversion::kToNumber ? Type::Number()
305 : Type::Numeric();
306 }
307
ToNumber(Type type)308 Type OperationTyper::ToNumber(Type type) {
309 return ToNumberOrNumeric(Object::Conversion::kToNumber, type);
310 }
311
ToNumberConvertBigInt(Type type)312 Type OperationTyper::ToNumberConvertBigInt(Type type) {
313 if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) {
314 return *maybe_result_type;
315 }
316 return Type::Number();
317 }
318
ToNumeric(Type type)319 Type OperationTyper::ToNumeric(Type type) {
320 return ToNumberOrNumeric(Object::Conversion::kToNumeric, type);
321 }
322
NumberAbs(Type type)323 Type OperationTyper::NumberAbs(Type type) {
324 DCHECK(type.Is(Type::Number()));
325 if (type.IsNone()) return type;
326
327 bool const maybe_nan = type.Maybe(Type::NaN());
328 bool const maybe_minuszero = type.Maybe(Type::MinusZero());
329
330 type = Type::Intersect(type, Type::PlainNumber(), zone());
331 if (!type.IsNone()) {
332 double const max = type.Max();
333 double const min = type.Min();
334 if (min < 0) {
335 if (type.Is(cache_.kInteger)) {
336 type =
337 Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
338 } else {
339 type = Type::PlainNumber();
340 }
341 }
342 }
343
344 if (maybe_minuszero) {
345 type = Type::Union(type, cache_.kSingletonZero, zone());
346 }
347 if (maybe_nan) {
348 type = Type::Union(type, Type::NaN(), zone());
349 }
350 return type;
351 }
352
NumberAcos(Type type)353 Type OperationTyper::NumberAcos(Type type) {
354 DCHECK(type.Is(Type::Number()));
355 return Type::Number();
356 }
357
NumberAcosh(Type type)358 Type OperationTyper::NumberAcosh(Type type) {
359 DCHECK(type.Is(Type::Number()));
360 return Type::Number();
361 }
362
NumberAsin(Type type)363 Type OperationTyper::NumberAsin(Type type) {
364 DCHECK(type.Is(Type::Number()));
365 return Type::Number();
366 }
367
NumberAsinh(Type type)368 Type OperationTyper::NumberAsinh(Type type) {
369 DCHECK(type.Is(Type::Number()));
370 return Type::Number();
371 }
372
NumberAtan(Type type)373 Type OperationTyper::NumberAtan(Type type) {
374 DCHECK(type.Is(Type::Number()));
375 return Type::Number();
376 }
377
NumberAtanh(Type type)378 Type OperationTyper::NumberAtanh(Type type) {
379 DCHECK(type.Is(Type::Number()));
380 return Type::Number();
381 }
382
NumberCbrt(Type type)383 Type OperationTyper::NumberCbrt(Type type) {
384 DCHECK(type.Is(Type::Number()));
385 return Type::Number();
386 }
387
NumberCeil(Type type)388 Type OperationTyper::NumberCeil(Type type) {
389 DCHECK(type.Is(Type::Number()));
390 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
391 type = Type::Intersect(type, Type::NaN(), zone());
392 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
393 return type;
394 }
395
NumberClz32(Type type)396 Type OperationTyper::NumberClz32(Type type) {
397 DCHECK(type.Is(Type::Number()));
398 return cache_.kZeroToThirtyTwo;
399 }
400
NumberCos(Type type)401 Type OperationTyper::NumberCos(Type type) {
402 DCHECK(type.Is(Type::Number()));
403 return Type::Number();
404 }
405
NumberCosh(Type type)406 Type OperationTyper::NumberCosh(Type type) {
407 DCHECK(type.Is(Type::Number()));
408 return Type::Number();
409 }
410
NumberExp(Type type)411 Type OperationTyper::NumberExp(Type type) {
412 DCHECK(type.Is(Type::Number()));
413 return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
414 }
415
NumberExpm1(Type type)416 Type OperationTyper::NumberExpm1(Type type) {
417 DCHECK(type.Is(Type::Number()));
418 return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
419 }
420
NumberFloor(Type type)421 Type OperationTyper::NumberFloor(Type type) {
422 DCHECK(type.Is(Type::Number()));
423 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
424 type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
425 type = Type::Union(type, cache_.kInteger, zone());
426 return type;
427 }
428
NumberFround(Type type)429 Type OperationTyper::NumberFround(Type type) {
430 DCHECK(type.Is(Type::Number()));
431 return Type::Number();
432 }
433
NumberLog(Type type)434 Type OperationTyper::NumberLog(Type type) {
435 DCHECK(type.Is(Type::Number()));
436 return Type::Number();
437 }
438
NumberLog1p(Type type)439 Type OperationTyper::NumberLog1p(Type type) {
440 DCHECK(type.Is(Type::Number()));
441 return Type::Number();
442 }
443
NumberLog2(Type type)444 Type OperationTyper::NumberLog2(Type type) {
445 DCHECK(type.Is(Type::Number()));
446 return Type::Number();
447 }
448
NumberLog10(Type type)449 Type OperationTyper::NumberLog10(Type type) {
450 DCHECK(type.Is(Type::Number()));
451 return Type::Number();
452 }
453
NumberRound(Type type)454 Type OperationTyper::NumberRound(Type type) {
455 DCHECK(type.Is(Type::Number()));
456 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
457 type = Type::Intersect(type, Type::NaN(), zone());
458 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
459 return type;
460 }
461
NumberSign(Type type)462 Type OperationTyper::NumberSign(Type type) {
463 DCHECK(type.Is(Type::Number()));
464 if (type.Is(cache_.kZeroish)) return type;
465 bool maybe_minuszero = type.Maybe(Type::MinusZero());
466 bool maybe_nan = type.Maybe(Type::NaN());
467 type = Type::Intersect(type, Type::PlainNumber(), zone());
468 if (type.IsNone()) {
469 // Do nothing.
470 } else if (type.Max() < 0.0) {
471 type = cache_.kSingletonMinusOne;
472 } else if (type.Max() <= 0.0) {
473 type = cache_.kMinusOneOrZero;
474 } else if (type.Min() > 0.0) {
475 type = cache_.kSingletonOne;
476 } else if (type.Min() >= 0.0) {
477 type = cache_.kZeroOrOne;
478 } else {
479 type = Type::Range(-1.0, 1.0, zone());
480 }
481 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
482 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
483 DCHECK(!type.IsNone());
484 return type;
485 }
486
NumberSin(Type type)487 Type OperationTyper::NumberSin(Type type) {
488 DCHECK(type.Is(Type::Number()));
489 return Type::Number();
490 }
491
NumberSinh(Type type)492 Type OperationTyper::NumberSinh(Type type) {
493 DCHECK(type.Is(Type::Number()));
494 return Type::Number();
495 }
496
NumberSqrt(Type type)497 Type OperationTyper::NumberSqrt(Type type) {
498 DCHECK(type.Is(Type::Number()));
499 return Type::Number();
500 }
501
NumberTan(Type type)502 Type OperationTyper::NumberTan(Type type) {
503 DCHECK(type.Is(Type::Number()));
504 return Type::Number();
505 }
506
NumberTanh(Type type)507 Type OperationTyper::NumberTanh(Type type) {
508 DCHECK(type.Is(Type::Number()));
509 return Type::Number();
510 }
511
NumberTrunc(Type type)512 Type OperationTyper::NumberTrunc(Type type) {
513 DCHECK(type.Is(Type::Number()));
514 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
515 type = Type::Intersect(type, Type::NaN(), zone());
516 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
517 return type;
518 }
519
NumberToBoolean(Type type)520 Type OperationTyper::NumberToBoolean(Type type) {
521 DCHECK(type.Is(Type::Number()));
522 if (type.IsNone()) return type;
523 if (type.Is(cache_.kZeroish)) return singleton_false_;
524 if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
525 return singleton_true_; // Ruled out nan, -0 and +0.
526 }
527 return Type::Boolean();
528 }
529
NumberToInt32(Type type)530 Type OperationTyper::NumberToInt32(Type type) {
531 DCHECK(type.Is(Type::Number()));
532
533 if (type.Is(Type::Signed32())) return type;
534 if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
535 if (type.Is(signed32ish_)) {
536 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
537 Type::Signed32(), zone());
538 }
539 return Type::Signed32();
540 }
541
NumberToString(Type type)542 Type OperationTyper::NumberToString(Type type) {
543 DCHECK(type.Is(Type::Number()));
544 if (type.IsNone()) return type;
545 if (type.Is(Type::NaN())) return singleton_NaN_string_;
546 if (type.Is(cache_.kZeroOrMinusZero)) return singleton_zero_string_;
547 return Type::String();
548 }
549
NumberToUint32(Type type)550 Type OperationTyper::NumberToUint32(Type type) {
551 DCHECK(type.Is(Type::Number()));
552
553 if (type.Is(Type::Unsigned32())) return type;
554 if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
555 if (type.Is(unsigned32ish_)) {
556 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
557 Type::Unsigned32(), zone());
558 }
559 return Type::Unsigned32();
560 }
561
NumberToUint8Clamped(Type type)562 Type OperationTyper::NumberToUint8Clamped(Type type) {
563 DCHECK(type.Is(Type::Number()));
564
565 if (type.Is(cache_.kUint8)) return type;
566 return cache_.kUint8;
567 }
568
NumberSilenceNaN(Type type)569 Type OperationTyper::NumberSilenceNaN(Type type) {
570 DCHECK(type.Is(Type::Number()));
571 // TODO(jarin): This is a terrible hack; we definitely need a dedicated type
572 // for the hole (tagged and/or double). Otherwise if the input is the hole
573 // NaN constant, we'd just eliminate this node in JSTypedLowering.
574 if (type.Maybe(Type::NaN())) return Type::Number();
575 return type;
576 }
577
NumberAdd(Type lhs,Type rhs)578 Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
579 DCHECK(lhs.Is(Type::Number()));
580 DCHECK(rhs.Is(Type::Number()));
581
582 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
583
584 // Addition can return NaN if either input can be NaN or we try to compute
585 // the sum of two infinities of opposite sign.
586 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
587
588 // Addition can yield minus zero only if both inputs can be minus zero.
589 bool maybe_minuszero = true;
590 if (lhs.Maybe(Type::MinusZero())) {
591 lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
592 } else {
593 maybe_minuszero = false;
594 }
595 if (rhs.Maybe(Type::MinusZero())) {
596 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
597 } else {
598 maybe_minuszero = false;
599 }
600
601 // We can give more precise types for integers.
602 Type type = Type::None();
603 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
604 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
605 if (!lhs.IsNone() && !rhs.IsNone()) {
606 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
607 type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
608 } else {
609 if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
610 (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) {
611 maybe_nan = true;
612 }
613 type = Type::PlainNumber();
614 }
615 }
616
617 // Take into account the -0 and NaN information computed earlier.
618 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
619 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
620 return type;
621 }
622
NumberSubtract(Type lhs,Type rhs)623 Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
624 DCHECK(lhs.Is(Type::Number()));
625 DCHECK(rhs.Is(Type::Number()));
626
627 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
628
629 // Subtraction can return NaN if either input can be NaN or we try to
630 // compute the sum of two infinities of opposite sign.
631 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
632
633 // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs}
634 // can be zero.
635 bool maybe_minuszero = false;
636 if (lhs.Maybe(Type::MinusZero())) {
637 lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
638 maybe_minuszero = rhs.Maybe(cache_.kSingletonZero);
639 }
640 if (rhs.Maybe(Type::MinusZero())) {
641 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
642 }
643
644 // We can give more precise types for integers.
645 Type type = Type::None();
646 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
647 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
648 if (!lhs.IsNone() && !rhs.IsNone()) {
649 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
650 type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
651 } else {
652 if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
653 (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) {
654 maybe_nan = true;
655 }
656 type = Type::PlainNumber();
657 }
658 }
659
660 // Take into account the -0 and NaN information computed earlier.
661 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
662 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
663 return type;
664 }
665
SpeculativeSafeIntegerAdd(Type lhs,Type rhs)666 Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
667 Type result = SpeculativeNumberAdd(lhs, rhs);
668 // If we have a Smi or Int32 feedback, the representation selection will
669 // either truncate or it will check the inputs (i.e., deopt if not int32).
670 // In either case the result will be in the safe integer range, so we
671 // can bake in the type here. This needs to be in sync with
672 // SimplifiedLowering::VisitSpeculativeAdditiveOp.
673 return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
674 }
675
SpeculativeSafeIntegerSubtract(Type lhs,Type rhs)676 Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
677 Type result = SpeculativeNumberSubtract(lhs, rhs);
678 // If we have a Smi or Int32 feedback, the representation selection will
679 // either truncate or it will check the inputs (i.e., deopt if not int32).
680 // In either case the result will be in the safe integer range, so we
681 // can bake in the type here. This needs to be in sync with
682 // SimplifiedLowering::VisitSpeculativeAdditiveOp.
683 return result = Type::Intersect(result, cache_.kSafeInteger, zone());
684 }
685
NumberMultiply(Type lhs,Type rhs)686 Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
687 DCHECK(lhs.Is(Type::Number()));
688 DCHECK(rhs.Is(Type::Number()));
689
690 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
691
692 lhs = Rangify(lhs);
693 rhs = Rangify(rhs);
694 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
695 if (lhs.IsRange() && rhs.IsRange()) {
696 return MultiplyRanger(lhs, rhs);
697 }
698 return Type::Number();
699 }
700
NumberDivide(Type lhs,Type rhs)701 Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
702 DCHECK(lhs.Is(Type::Number()));
703 DCHECK(rhs.Is(Type::Number()));
704
705 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
706 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
707
708 // Division is tricky, so all we do is try ruling out -0 and NaN.
709 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
710 ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
711 (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
712 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
713 DCHECK(!lhs.IsNone());
714 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
715 DCHECK(!rhs.IsNone());
716
717 // Try to rule out -0.
718 bool maybe_minuszero =
719 !lhs.Is(cache_.kInteger) ||
720 (lhs.Maybe(cache_.kZeroish) && rhs.Min() < 0.0) ||
721 (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY);
722
723 // Take into account the -0 and NaN information computed earlier.
724 Type type = Type::PlainNumber();
725 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
726 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
727 return type;
728 }
729
NumberModulus(Type lhs,Type rhs)730 Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
731 DCHECK(lhs.Is(Type::Number()));
732 DCHECK(rhs.Is(Type::Number()));
733
734 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
735
736 // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or
737 // {lhs} is not finite, or the {rhs} is a zero value.
738 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
739 lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY;
740
741 // Deal with -0 inputs, only the signbit of {lhs} matters for the result.
742 bool maybe_minuszero = false;
743 if (lhs.Maybe(Type::MinusZero())) {
744 maybe_minuszero = true;
745 lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
746 }
747 if (rhs.Maybe(Type::MinusZero())) {
748 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
749 }
750
751 // Rule out NaN and -0, and check what we can do with the remaining type info.
752 Type type = Type::None();
753 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
754 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
755
756 // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited,
757 // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}.
758 if (!lhs.IsNone() && !rhs.Is(cache_.kSingletonZero)) {
759 // Determine the bounds of {lhs} and {rhs}.
760 double const lmin = lhs.Min();
761 double const lmax = lhs.Max();
762 double const rmin = rhs.Min();
763 double const rmax = rhs.Max();
764
765 // The sign of the result is the sign of the {lhs}.
766 if (lmin < 0.0) maybe_minuszero = true;
767
768 // For integer inputs {lhs} and {rhs} we can infer a precise type.
769 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
770 double labs = std::max(std::abs(lmin), std::abs(lmax));
771 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
772 double abs = std::min(labs, rabs);
773 double min = 0.0, max = 0.0;
774 if (lmin >= 0.0) {
775 // {lhs} positive.
776 min = 0.0;
777 max = abs;
778 } else if (lmax <= 0.0) {
779 // {lhs} negative.
780 min = 0.0 - abs;
781 max = 0.0;
782 } else {
783 // {lhs} positive or negative.
784 min = 0.0 - abs;
785 max = abs;
786 }
787 type = Type::Range(min, max, zone());
788 } else {
789 type = Type::PlainNumber();
790 }
791 }
792
793 // Take into account the -0 and NaN information computed earlier.
794 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
795 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
796 return type;
797 }
798
NumberBitwiseOr(Type lhs,Type rhs)799 Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
800 DCHECK(lhs.Is(Type::Number()));
801 DCHECK(rhs.Is(Type::Number()));
802
803 lhs = NumberToInt32(lhs);
804 rhs = NumberToInt32(rhs);
805
806 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
807
808 double lmin = lhs.Min();
809 double rmin = rhs.Min();
810 double lmax = lhs.Max();
811 double rmax = rhs.Max();
812 // Or-ing any two values results in a value no smaller than their minimum.
813 // Even no smaller than their maximum if both values are non-negative.
814 double min =
815 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
816 double max = kMaxInt;
817
818 // Or-ing with 0 is essentially a conversion to int32.
819 if (rmin == 0 && rmax == 0) {
820 min = lmin;
821 max = lmax;
822 }
823 if (lmin == 0 && lmax == 0) {
824 min = rmin;
825 max = rmax;
826 }
827
828 if (lmax < 0 || rmax < 0) {
829 // Or-ing two values of which at least one is negative results in a negative
830 // value.
831 max = std::min(max, -1.0);
832 }
833 return Type::Range(min, max, zone());
834 }
835
NumberBitwiseAnd(Type lhs,Type rhs)836 Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
837 DCHECK(lhs.Is(Type::Number()));
838 DCHECK(rhs.Is(Type::Number()));
839
840 lhs = NumberToInt32(lhs);
841 rhs = NumberToInt32(rhs);
842
843 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
844
845 double lmin = lhs.Min();
846 double rmin = rhs.Min();
847 double lmax = lhs.Max();
848 double rmax = rhs.Max();
849 double min = kMinInt;
850 // And-ing any two values results in a value no larger than their maximum.
851 // Even no larger than their minimum if both values are non-negative.
852 double max =
853 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
854 // And-ing with a non-negative value x causes the result to be between
855 // zero and x.
856 if (lmin >= 0) {
857 min = 0;
858 max = std::min(max, lmax);
859 }
860 if (rmin >= 0) {
861 min = 0;
862 max = std::min(max, rmax);
863 }
864 return Type::Range(min, max, zone());
865 }
866
NumberBitwiseXor(Type lhs,Type rhs)867 Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
868 DCHECK(lhs.Is(Type::Number()));
869 DCHECK(rhs.Is(Type::Number()));
870
871 lhs = NumberToInt32(lhs);
872 rhs = NumberToInt32(rhs);
873
874 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
875
876 double lmin = lhs.Min();
877 double rmin = rhs.Min();
878 double lmax = lhs.Max();
879 double rmax = rhs.Max();
880 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
881 // Xor-ing negative or non-negative values results in a non-negative value.
882 return Type::Unsigned31();
883 }
884 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
885 // Xor-ing a negative and a non-negative value results in a negative value.
886 // TODO(jarin) Use a range here.
887 return Type::Negative32();
888 }
889 return Type::Signed32();
890 }
891
NumberShiftLeft(Type lhs,Type rhs)892 Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
893 DCHECK(lhs.Is(Type::Number()));
894 DCHECK(rhs.Is(Type::Number()));
895
896 lhs = NumberToInt32(lhs);
897 rhs = NumberToUint32(rhs);
898
899 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
900
901 int32_t min_lhs = lhs.Min();
902 int32_t max_lhs = lhs.Max();
903 uint32_t min_rhs = rhs.Min();
904 uint32_t max_rhs = rhs.Max();
905 if (max_rhs > 31) {
906 // rhs can be larger than the bitmask
907 max_rhs = 31;
908 min_rhs = 0;
909 }
910
911 if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
912 // overflow possible
913 return Type::Signed32();
914 }
915
916 double min =
917 std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
918 static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
919 double max =
920 std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
921 static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
922
923 if (max == kMaxInt && min == kMinInt) return Type::Signed32();
924 return Type::Range(min, max, zone());
925 }
926
NumberShiftRight(Type lhs,Type rhs)927 Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
928 DCHECK(lhs.Is(Type::Number()));
929 DCHECK(rhs.Is(Type::Number()));
930
931 lhs = NumberToInt32(lhs);
932 rhs = NumberToUint32(rhs);
933
934 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
935
936 int32_t min_lhs = lhs.Min();
937 int32_t max_lhs = lhs.Max();
938 uint32_t min_rhs = rhs.Min();
939 uint32_t max_rhs = rhs.Max();
940 if (max_rhs > 31) {
941 // rhs can be larger than the bitmask
942 max_rhs = 31;
943 min_rhs = 0;
944 }
945 double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
946 double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
947
948 if (max == kMaxInt && min == kMinInt) return Type::Signed32();
949 return Type::Range(min, max, zone());
950 }
951
NumberShiftRightLogical(Type lhs,Type rhs)952 Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
953 DCHECK(lhs.Is(Type::Number()));
954 DCHECK(rhs.Is(Type::Number()));
955
956 lhs = NumberToUint32(lhs);
957 rhs = NumberToUint32(rhs);
958
959 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
960
961 uint32_t min_lhs = lhs.Min();
962 uint32_t max_lhs = lhs.Max();
963 uint32_t min_rhs = rhs.Min();
964 uint32_t max_rhs = rhs.Max();
965 if (max_rhs > 31) {
966 // rhs can be larger than the bitmask
967 max_rhs = 31;
968 min_rhs = 0;
969 }
970
971 double min = min_lhs >> max_rhs;
972 double max = max_lhs >> min_rhs;
973 DCHECK_LE(0, min);
974 DCHECK_LE(max, kMaxUInt32);
975
976 if (min == 0 && max == kMaxInt) return Type::Unsigned31();
977 if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
978 return Type::Range(min, max, zone());
979 }
980
NumberAtan2(Type lhs,Type rhs)981 Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
982 DCHECK(lhs.Is(Type::Number()));
983 DCHECK(rhs.Is(Type::Number()));
984 return Type::Number();
985 }
986
NumberImul(Type lhs,Type rhs)987 Type OperationTyper::NumberImul(Type lhs, Type rhs) {
988 DCHECK(lhs.Is(Type::Number()));
989 DCHECK(rhs.Is(Type::Number()));
990 // TODO(turbofan): We should be able to do better here.
991 return Type::Signed32();
992 }
993
NumberMax(Type lhs,Type rhs)994 Type OperationTyper::NumberMax(Type lhs, Type rhs) {
995 DCHECK(lhs.Is(Type::Number()));
996 DCHECK(rhs.Is(Type::Number()));
997
998 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
999 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1000
1001 Type type = Type::None();
1002 // TODO(turbofan): Improve minus zero handling here.
1003 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1004 type = Type::Union(type, Type::NaN(), zone());
1005 }
1006 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1007 DCHECK(!lhs.IsNone());
1008 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1009 DCHECK(!rhs.IsNone());
1010 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
1011 double max = std::max(lhs.Max(), rhs.Max());
1012 double min = std::max(lhs.Min(), rhs.Min());
1013 type = Type::Union(type, Type::Range(min, max, zone()), zone());
1014 } else {
1015 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1016 }
1017 return type;
1018 }
1019
NumberMin(Type lhs,Type rhs)1020 Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1021 DCHECK(lhs.Is(Type::Number()));
1022 DCHECK(rhs.Is(Type::Number()));
1023
1024 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1025 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1026
1027 Type type = Type::None();
1028 // TODO(turbofan): Improve minus zero handling here.
1029 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1030 type = Type::Union(type, Type::NaN(), zone());
1031 }
1032 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1033 DCHECK(!lhs.IsNone());
1034 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1035 DCHECK(!rhs.IsNone());
1036 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
1037 double max = std::min(lhs.Max(), rhs.Max());
1038 double min = std::min(lhs.Min(), rhs.Min());
1039 type = Type::Union(type, Type::Range(min, max, zone()), zone());
1040 } else {
1041 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1042 }
1043 return type;
1044 }
1045
NumberPow(Type lhs,Type rhs)1046 Type OperationTyper::NumberPow(Type lhs, Type rhs) {
1047 DCHECK(lhs.Is(Type::Number()));
1048 DCHECK(rhs.Is(Type::Number()));
1049 // TODO(turbofan): We should be able to do better here.
1050 return Type::Number();
1051 }
1052
1053 #define SPECULATIVE_NUMBER_BINOP(Name) \
1054 Type OperationTyper::Speculative##Name(Type lhs, Type rhs) { \
1055 lhs = SpeculativeToNumber(lhs); \
1056 rhs = SpeculativeToNumber(rhs); \
1057 return Name(lhs, rhs); \
1058 }
1059 SPECULATIVE_NUMBER_BINOP(NumberAdd)
SPECULATIVE_NUMBER_BINOP(NumberSubtract)1060 SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1061 SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1062 SPECULATIVE_NUMBER_BINOP(NumberDivide)
1063 SPECULATIVE_NUMBER_BINOP(NumberModulus)
1064 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1065 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1066 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1067 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1068 SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1069 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1070 #undef SPECULATIVE_NUMBER_BINOP
1071
1072 Type OperationTyper::SpeculativeToNumber(Type type) {
1073 return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
1074 }
1075
ToPrimitive(Type type)1076 Type OperationTyper::ToPrimitive(Type type) {
1077 if (type.Is(Type::Primitive())) {
1078 return type;
1079 }
1080 return Type::Primitive();
1081 }
1082
Invert(Type type)1083 Type OperationTyper::Invert(Type type) {
1084 DCHECK(type.Is(Type::Boolean()));
1085 DCHECK(!type.IsNone());
1086 if (type.Is(singleton_false())) return singleton_true();
1087 if (type.Is(singleton_true())) return singleton_false();
1088 return type;
1089 }
1090
Invert(ComparisonOutcome outcome)1091 OperationTyper::ComparisonOutcome OperationTyper::Invert(
1092 ComparisonOutcome outcome) {
1093 ComparisonOutcome result(0);
1094 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
1095 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
1096 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
1097 return result;
1098 }
1099
FalsifyUndefined(ComparisonOutcome outcome)1100 Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
1101 if ((outcome & kComparisonFalse) != 0 ||
1102 (outcome & kComparisonUndefined) != 0) {
1103 return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
1104 : singleton_false();
1105 }
1106 // Type should be non empty, so we know it should be true.
1107 DCHECK_NE(0, outcome & kComparisonTrue);
1108 return singleton_true();
1109 }
1110
1111 namespace {
1112
JSType(Type type)1113 Type JSType(Type type) {
1114 if (type.Is(Type::Boolean())) return Type::Boolean();
1115 if (type.Is(Type::String())) return Type::String();
1116 if (type.Is(Type::Number())) return Type::Number();
1117 if (type.Is(Type::BigInt())) return Type::BigInt();
1118 if (type.Is(Type::Undefined())) return Type::Undefined();
1119 if (type.Is(Type::Null())) return Type::Null();
1120 if (type.Is(Type::Symbol())) return Type::Symbol();
1121 if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1122 return Type::Any();
1123 }
1124
1125 } // namespace
1126
SameValue(Type lhs,Type rhs)1127 Type OperationTyper::SameValue(Type lhs, Type rhs) {
1128 if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1129 if (lhs.Is(Type::NaN())) {
1130 if (rhs.Is(Type::NaN())) return singleton_true();
1131 if (!rhs.Maybe(Type::NaN())) return singleton_false();
1132 } else if (rhs.Is(Type::NaN())) {
1133 if (!lhs.Maybe(Type::NaN())) return singleton_false();
1134 }
1135 if (lhs.Is(Type::MinusZero())) {
1136 if (rhs.Is(Type::MinusZero())) return singleton_true();
1137 if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
1138 } else if (rhs.Is(Type::MinusZero())) {
1139 if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1140 }
1141 if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1142 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1143 return singleton_false();
1144 }
1145 return Type::Boolean();
1146 }
1147
StrictEqual(Type lhs,Type rhs)1148 Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1149 if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1150 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1151 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1152 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1153 return singleton_false();
1154 }
1155 if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1156 return singleton_false();
1157 }
1158 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1159 // Types are equal and are inhabited only by a single semantic value,
1160 // which is not nan due to the earlier check.
1161 return singleton_true();
1162 }
1163 return Type::Boolean();
1164 }
1165
CheckFloat64Hole(Type type)1166 Type OperationTyper::CheckFloat64Hole(Type type) {
1167 if (type.Maybe(Type::Hole())) {
1168 // Turn "the hole" into undefined.
1169 type = Type::Intersect(type, Type::Number(), zone());
1170 type = Type::Union(type, Type::Undefined(), zone());
1171 }
1172 return type;
1173 }
1174
CheckNumber(Type type)1175 Type OperationTyper::CheckNumber(Type type) {
1176 return Type::Intersect(type, Type::Number(), zone());
1177 }
1178
TypeTypeGuard(const Operator * sigma_op,Type input)1179 Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1180 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1181 }
1182
ConvertTaggedHoleToUndefined(Type input)1183 Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1184 if (input.Maybe(Type::Hole())) {
1185 // Turn "the hole" into undefined.
1186 Type type = Type::Intersect(input, Type::NonInternal(), zone());
1187 return Type::Union(type, Type::Undefined(), zone());
1188 }
1189 return input;
1190 }
1191
ToBoolean(Type type)1192 Type OperationTyper::ToBoolean(Type type) {
1193 if (type.Is(Type::Boolean())) return type;
1194 if (type.Is(falsish_)) return singleton_false_;
1195 if (type.Is(truish_)) return singleton_true_;
1196 if (type.Is(Type::Number())) {
1197 return NumberToBoolean(type);
1198 }
1199 return Type::Boolean();
1200 }
1201
1202 } // namespace compiler
1203 } // namespace internal
1204 } // namespace v8
1205