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/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 790117 : OperationTyper::OperationTyper(Isolate* isolate, Zone* zone)
20 790117 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = isolate->factory();
22 790119 : infinity_ = Type::NewConstant(factory->infinity_value(), zone);
23 790119 : minus_infinity_ = Type::NewConstant(factory->minus_infinity_value(), zone);
24 : Type* truncating_to_zero = Type::MinusZeroOrNaN();
25 : DCHECK(!truncating_to_zero->Maybe(Type::Integral32()));
26 :
27 790118 : singleton_false_ = Type::HeapConstant(factory->false_value(), zone);
28 790120 : singleton_true_ = Type::HeapConstant(factory->true_value(), zone);
29 790120 : singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone);
30 790120 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
31 790119 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
32 790120 : }
33 :
34 1607382 : Type* OperationTyper::Merge(Type* left, Type* right) {
35 1607382 : return Type::Union(left, right, zone());
36 : }
37 :
38 810817 : Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) {
39 : static const double kWeakenMinLimits[] = {0.0,
40 : -1073741824.0,
41 : -2147483648.0,
42 : -4294967296.0,
43 : -8589934592.0,
44 : -17179869184.0,
45 : -34359738368.0,
46 : -68719476736.0,
47 : -137438953472.0,
48 : -274877906944.0,
49 : -549755813888.0,
50 : -1099511627776.0,
51 : -2199023255552.0,
52 : -4398046511104.0,
53 : -8796093022208.0,
54 : -17592186044416.0,
55 : -35184372088832.0,
56 : -70368744177664.0,
57 : -140737488355328.0,
58 : -281474976710656.0,
59 : -562949953421312.0};
60 : static const double kWeakenMaxLimits[] = {0.0,
61 : 1073741823.0,
62 : 2147483647.0,
63 : 4294967295.0,
64 : 8589934591.0,
65 : 17179869183.0,
66 : 34359738367.0,
67 : 68719476735.0,
68 : 137438953471.0,
69 : 274877906943.0,
70 : 549755813887.0,
71 : 1099511627775.0,
72 : 2199023255551.0,
73 : 4398046511103.0,
74 : 8796093022207.0,
75 : 17592186044415.0,
76 : 35184372088831.0,
77 : 70368744177663.0,
78 : 140737488355327.0,
79 : 281474976710655.0,
80 : 562949953421311.0};
81 : STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
82 :
83 405411 : double current_min = current_range->Min();
84 : double new_min = current_min;
85 : // Find the closest lower entry in the list of allowed
86 : // minima (or negative infinity if there is no such entry).
87 405411 : if (current_min != previous_range->Min()) {
88 : new_min = -V8_INFINITY;
89 655611 : for (double const min : kWeakenMinLimits) {
90 338722 : if (min <= current_min) {
91 : new_min = min;
92 : break;
93 : }
94 : }
95 : }
96 :
97 405408 : double current_max = current_range->Max();
98 : double new_max = current_max;
99 : // Find the closest greater entry in the list of allowed
100 : // maxima (or infinity if there is no such entry).
101 405410 : if (current_max != previous_range->Max()) {
102 : new_max = V8_INFINITY;
103 5523877 : for (double const max : kWeakenMaxLimits) {
104 2884331 : if (max >= current_max) {
105 : new_max = max;
106 : break;
107 : }
108 : }
109 : }
110 :
111 405408 : return Type::Range(new_min, new_max, zone());
112 : }
113 :
114 229242 : Type* OperationTyper::Rangify(Type* type) {
115 218563 : if (type->IsRange()) return type; // Shortcut.
116 200020 : if (!type->Is(cache_.kInteger)) {
117 : return type; // Give up on non-integer types.
118 : }
119 10679 : double min = type->Min();
120 10679 : double max = type->Max();
121 : // Handle the degenerate case of empty bitset types (such as
122 : // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
123 10679 : if (std::isnan(min)) {
124 : DCHECK(std::isnan(max));
125 : return type;
126 : }
127 10679 : return Type::Range(min, max, zone());
128 : }
129 :
130 : namespace {
131 :
132 : // Returns the array's least element, ignoring NaN.
133 : // There must be at least one non-NaN element.
134 : // Any -0 is converted to 0.
135 698554 : double array_min(double a[], size_t n) {
136 : DCHECK(n != 0);
137 698554 : double x = +V8_INFINITY;
138 3492766 : for (size_t i = 0; i < n; ++i) {
139 2794212 : if (!std::isnan(a[i])) {
140 2794172 : x = std::min(a[i], x);
141 : }
142 : }
143 : DCHECK(!std::isnan(x));
144 698554 : return x == 0 ? 0 : x; // -0 -> 0
145 : }
146 :
147 : // Returns the array's greatest element, ignoring NaN.
148 : // There must be at least one non-NaN element.
149 : // Any -0 is converted to 0.
150 698551 : double array_max(double a[], size_t n) {
151 : DCHECK(n != 0);
152 698551 : double x = -V8_INFINITY;
153 3492743 : for (size_t i = 0; i < n; ++i) {
154 2794192 : if (!std::isnan(a[i])) {
155 2794148 : x = std::max(a[i], x);
156 : }
157 : }
158 : DCHECK(!std::isnan(x));
159 698551 : return x == 0 ? 0 : x; // -0 -> 0
160 : }
161 :
162 : } // namespace
163 :
164 336313 : Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
165 336322 : double rhs_max) {
166 : double results[4];
167 336313 : results[0] = lhs_min + rhs_min;
168 336313 : results[1] = lhs_min + rhs_max;
169 336313 : results[2] = lhs_max + rhs_min;
170 336313 : results[3] = lhs_max + rhs_max;
171 : // Since none of the inputs can be -0, the result cannot be -0 either.
172 : // However, it can be nan (the sum of two infinities of opposite sign).
173 : // On the other hand, if none of the "results" above is nan, then the
174 : // actual result cannot be nan either.
175 : int nans = 0;
176 1681561 : for (int i = 0; i < 4; ++i) {
177 1345248 : if (std::isnan(results[i])) ++nans;
178 : }
179 336313 : if (nans == 4) return Type::NaN();
180 : Type* type =
181 336314 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
182 336324 : if (nans > 0) type = Type::Union(type, Type::NaN(), zone());
183 : // Examples:
184 : // [-inf, -inf] + [+inf, +inf] = NaN
185 : // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
186 : // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
187 : // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
188 336316 : return type;
189 : }
190 :
191 331712 : Type* OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
192 331727 : double rhs_min, double rhs_max) {
193 : double results[4];
194 331712 : results[0] = lhs_min - rhs_min;
195 331712 : results[1] = lhs_min - rhs_max;
196 331712 : results[2] = lhs_max - rhs_min;
197 331712 : results[3] = lhs_max - rhs_max;
198 : // Since none of the inputs can be -0, the result cannot be -0.
199 : // However, it can be nan (the subtraction of two infinities of same sign).
200 : // On the other hand, if none of the "results" above is nan, then the actual
201 : // result cannot be nan either.
202 : int nans = 0;
203 1658560 : for (int i = 0; i < 4; ++i) {
204 1326848 : if (std::isnan(results[i])) ++nans;
205 : }
206 331712 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
207 : Type* type =
208 331707 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
209 331727 : return nans == 0 ? type : Type::Union(type, Type::NaN(), zone());
210 : // Examples:
211 : // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
212 : // [-inf, -inf] - [-inf, -inf] = NaN
213 : // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
214 : // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
215 : }
216 :
217 68284 : Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) {
218 : double results[4];
219 30622 : double lmin = lhs->AsRange()->Min();
220 30622 : double lmax = lhs->AsRange()->Max();
221 30622 : double rmin = rhs->AsRange()->Min();
222 30622 : double rmax = rhs->AsRange()->Max();
223 30622 : results[0] = lmin * rmin;
224 30622 : results[1] = lmin * rmax;
225 30622 : results[2] = lmax * rmin;
226 30622 : results[3] = lmax * rmax;
227 : // If the result may be nan, we give up on calculating a precise type, because
228 : // the discontinuity makes it too complicated. Note that even if none of the
229 : // "results" above is nan, the actual result may still be, so we have to do a
230 : // different check:
231 53901 : bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) &&
232 84437 : (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
233 33365 : (rhs->Maybe(cache_.kSingletonZero) &&
234 2810 : (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
235 30622 : if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up.
236 54253 : bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) ||
237 24569 : (rhs->Maybe(cache_.kSingletonZero) && lmin < 0);
238 : Type* range =
239 30530 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
240 : return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
241 37662 : : range;
242 : }
243 :
244 2903567 : Type* OperationTyper::ToNumber(Type* type) {
245 2250757 : if (type->Is(Type::Number())) return type;
246 468998 : if (type->Is(Type::NullOrUndefined())) {
247 3370 : if (type->Is(Type::Null())) return cache_.kSingletonZero;
248 1955 : if (type->Is(Type::Undefined())) return Type::NaN();
249 0 : return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
250 : }
251 465619 : if (type->Is(Type::Boolean())) {
252 15592 : if (type->Is(singleton_false_)) return cache_.kSingletonZero;
253 14358 : if (type->Is(singleton_true_)) return cache_.kSingletonOne;
254 4464 : return cache_.kZeroOrOne;
255 : }
256 457819 : if (type->Is(Type::NumberOrOddball())) {
257 326409 : if (type->Is(Type::NumberOrUndefined())) {
258 13735 : type = Type::Union(type, Type::NaN(), zone());
259 312677 : } else if (type->Is(Type::NullOrNumber())) {
260 111 : type = Type::Union(type, cache_.kSingletonZero, zone());
261 312561 : } else if (type->Is(Type::BooleanOrNullOrNumber())) {
262 696 : type = Type::Union(type, cache_.kZeroOrOne, zone());
263 : } else {
264 311865 : type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone());
265 : }
266 326430 : return Type::Intersect(type, Type::Number(), zone());
267 : }
268 : return Type::Number();
269 : }
270 :
271 1334 : Type* OperationTyper::NumberAbs(Type* type) {
272 : DCHECK(type->Is(Type::Number()));
273 :
274 496 : if (!type->IsInhabited()) {
275 : return Type::None();
276 : }
277 :
278 463 : bool const maybe_nan = type->Maybe(Type::NaN());
279 463 : bool const maybe_minuszero = type->Maybe(Type::MinusZero());
280 463 : type = Type::Intersect(type, Type::PlainNumber(), zone());
281 463 : double const max = type->Max();
282 463 : double const min = type->Min();
283 463 : if (min < 0) {
284 574 : if (type->Is(cache_.kInteger)) {
285 396 : type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
286 : } else {
287 : type = Type::PlainNumber();
288 : }
289 : }
290 463 : if (maybe_minuszero) {
291 74 : type = Type::Union(type, cache_.kSingletonZero, zone());
292 : }
293 463 : if (maybe_nan) {
294 169 : type = Type::Union(type, Type::NaN(), zone());
295 : }
296 463 : return type;
297 : }
298 :
299 115 : Type* OperationTyper::NumberAcos(Type* type) {
300 : DCHECK(type->Is(Type::Number()));
301 115 : return Type::Number();
302 : }
303 :
304 113 : Type* OperationTyper::NumberAcosh(Type* type) {
305 : DCHECK(type->Is(Type::Number()));
306 113 : return Type::Number();
307 : }
308 :
309 115 : Type* OperationTyper::NumberAsin(Type* type) {
310 : DCHECK(type->Is(Type::Number()));
311 115 : return Type::Number();
312 : }
313 :
314 113 : Type* OperationTyper::NumberAsinh(Type* type) {
315 : DCHECK(type->Is(Type::Number()));
316 113 : return Type::Number();
317 : }
318 :
319 115 : Type* OperationTyper::NumberAtan(Type* type) {
320 : DCHECK(type->Is(Type::Number()));
321 115 : return Type::Number();
322 : }
323 :
324 113 : Type* OperationTyper::NumberAtanh(Type* type) {
325 : DCHECK(type->Is(Type::Number()));
326 113 : return Type::Number();
327 : }
328 :
329 100 : Type* OperationTyper::NumberCbrt(Type* type) {
330 : DCHECK(type->Is(Type::Number()));
331 100 : return Type::Number();
332 : }
333 :
334 11472 : Type* OperationTyper::NumberCeil(Type* type) {
335 : DCHECK(type->Is(Type::Number()));
336 22944 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
337 : // TODO(bmeurer): We could infer a more precise type here.
338 10800 : return cache_.kIntegerOrMinusZeroOrNaN;
339 : }
340 :
341 156 : Type* OperationTyper::NumberClz32(Type* type) {
342 : DCHECK(type->Is(Type::Number()));
343 156 : return cache_.kZeroToThirtyTwo;
344 : }
345 :
346 205 : Type* OperationTyper::NumberCos(Type* type) {
347 : DCHECK(type->Is(Type::Number()));
348 205 : return Type::Number();
349 : }
350 :
351 131 : Type* OperationTyper::NumberCosh(Type* type) {
352 : DCHECK(type->Is(Type::Number()));
353 131 : return Type::Number();
354 : }
355 :
356 167 : Type* OperationTyper::NumberExp(Type* type) {
357 : DCHECK(type->Is(Type::Number()));
358 167 : return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
359 : }
360 :
361 100 : Type* OperationTyper::NumberExpm1(Type* type) {
362 : DCHECK(type->Is(Type::Number()));
363 100 : return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
364 : }
365 :
366 53908 : Type* OperationTyper::NumberFloor(Type* type) {
367 : DCHECK(type->Is(Type::Number()));
368 36804 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
369 17753 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
370 17753 : type = Type::Union(type, cache_.kInteger, zone());
371 17753 : return type;
372 : }
373 :
374 1424 : Type* OperationTyper::NumberFround(Type* type) {
375 : DCHECK(type->Is(Type::Number()));
376 1424 : return Type::Number();
377 : }
378 :
379 363 : Type* OperationTyper::NumberLog(Type* type) {
380 : DCHECK(type->Is(Type::Number()));
381 363 : return Type::Number();
382 : }
383 :
384 113 : Type* OperationTyper::NumberLog1p(Type* type) {
385 : DCHECK(type->Is(Type::Number()));
386 113 : return Type::Number();
387 : }
388 :
389 100 : Type* OperationTyper::NumberLog2(Type* type) {
390 : DCHECK(type->Is(Type::Number()));
391 100 : return Type::Number();
392 : }
393 :
394 100 : Type* OperationTyper::NumberLog10(Type* type) {
395 : DCHECK(type->Is(Type::Number()));
396 100 : return Type::Number();
397 : }
398 :
399 268 : Type* OperationTyper::NumberRound(Type* type) {
400 : DCHECK(type->Is(Type::Number()));
401 536 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
402 : // TODO(bmeurer): We could infer a more precise type here.
403 170 : return cache_.kIntegerOrMinusZeroOrNaN;
404 : }
405 :
406 505 : Type* OperationTyper::NumberSign(Type* type) {
407 : DCHECK(type->Is(Type::Number()));
408 310 : if (type->Is(cache_.kZeroish)) return type;
409 120 : bool maybe_minuszero = type->Maybe(Type::MinusZero());
410 120 : bool maybe_nan = type->Maybe(Type::NaN());
411 120 : type = Type::Intersect(type, Type::PlainNumber(), zone());
412 120 : if (type->Max() < 0.0) {
413 7 : type = cache_.kSingletonMinusOne;
414 113 : } else if (type->Max() <= 0.0) {
415 0 : type = cache_.kMinusOneOrZero;
416 113 : } else if (type->Min() > 0.0) {
417 13 : type = cache_.kSingletonOne;
418 100 : } else if (type->Min() >= 0.0) {
419 4 : type = cache_.kZeroOrOne;
420 : } else {
421 : type = Type::Range(-1.0, 1.0, zone());
422 : }
423 189 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
424 185 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
425 120 : return type;
426 : }
427 :
428 265 : Type* OperationTyper::NumberSin(Type* type) {
429 : DCHECK(type->Is(Type::Number()));
430 265 : return Type::Number();
431 : }
432 :
433 131 : Type* OperationTyper::NumberSinh(Type* type) {
434 : DCHECK(type->Is(Type::Number()));
435 131 : return Type::Number();
436 : }
437 :
438 234 : Type* OperationTyper::NumberSqrt(Type* type) {
439 : DCHECK(type->Is(Type::Number()));
440 234 : return Type::Number();
441 : }
442 :
443 122 : Type* OperationTyper::NumberTan(Type* type) {
444 : DCHECK(type->Is(Type::Number()));
445 122 : return Type::Number();
446 : }
447 :
448 129 : Type* OperationTyper::NumberTanh(Type* type) {
449 : DCHECK(type->Is(Type::Number()));
450 129 : return Type::Number();
451 : }
452 :
453 2975 : Type* OperationTyper::NumberTrunc(Type* type) {
454 : DCHECK(type->Is(Type::Number()));
455 5950 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
456 : // TODO(bmeurer): We could infer a more precise type here.
457 2748 : return cache_.kIntegerOrMinusZeroOrNaN;
458 : }
459 :
460 3533 : Type* OperationTyper::NumberToBoolean(Type* type) {
461 : DCHECK(type->Is(Type::Number()));
462 3533 : if (!type->IsInhabited()) return Type::None();
463 7000 : if (type->Is(cache_.kZeroish)) return singleton_false_;
464 3497 : if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) {
465 221 : return singleton_true_; // Ruled out nan, -0 and +0.
466 : }
467 : return Type::Boolean();
468 : }
469 :
470 442794 : Type* OperationTyper::NumberToInt32(Type* type) {
471 : DCHECK(type->Is(Type::Number()));
472 :
473 428081 : if (type->Is(Type::Signed32())) return type;
474 326752 : if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
475 317358 : if (type->Is(signed32ish_)) {
476 : return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
477 14713 : Type::Signed32(), zone());
478 : }
479 : return Type::Signed32();
480 : }
481 :
482 140008 : Type* OperationTyper::NumberToUint32(Type* type) {
483 : DCHECK(type->Is(Type::Number()));
484 :
485 139852 : if (type->Is(Type::Unsigned32())) return type;
486 84675 : if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
487 79943 : if (type->Is(unsigned32ish_)) {
488 : return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
489 156 : Type::Unsigned32(), zone());
490 : }
491 : return Type::Unsigned32();
492 : }
493 :
494 1038 : Type* OperationTyper::NumberToUint8Clamped(Type* type) {
495 : DCHECK(type->Is(Type::Number()));
496 :
497 2076 : if (type->Is(cache_.kUint8)) return type;
498 963 : return cache_.kUint8;
499 : }
500 :
501 1807 : Type* OperationTyper::NumberSilenceNaN(Type* type) {
502 : DCHECK(type->Is(Type::Number()));
503 : // TODO(jarin): This is a terrible hack; we definitely need a dedicated type
504 : // for the hole (tagged and/or double). Otherwise if the input is the hole
505 : // NaN constant, we'd just eliminate this node in JSTypedLowering.
506 1807 : if (type->Maybe(Type::NaN())) return Type::Number();
507 497 : return type;
508 : }
509 :
510 2618333 : Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) {
511 : DCHECK(lhs->Is(Type::Number()));
512 : DCHECK(rhs->Is(Type::Number()));
513 :
514 1301215 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
515 : return Type::None();
516 : }
517 :
518 : // Addition can return NaN if either input can be NaN or we try to compute
519 : // the sum of two infinities of opposite sign.
520 649342 : bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN());
521 :
522 : // Addition can yield minus zero only if both inputs can be minus zero.
523 : bool maybe_minuszero = true;
524 649343 : if (lhs->Maybe(Type::MinusZero())) {
525 169298 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
526 : } else {
527 : maybe_minuszero = false;
528 : }
529 649342 : if (rhs->Maybe(Type::MinusZero())) {
530 135587 : rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
531 : } else {
532 : maybe_minuszero = false;
533 : }
534 :
535 : // We can give more precise types for integers.
536 : Type* type = Type::None();
537 649369 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
538 649354 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
539 1298499 : if (lhs->IsInhabited() && rhs->IsInhabited()) {
540 1674610 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
541 336316 : type = AddRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max());
542 : } else {
543 797867 : if ((lhs->Maybe(minus_infinity_) && rhs->Maybe(infinity_)) ||
544 186118 : (rhs->Maybe(minus_infinity_) && lhs->Maybe(infinity_))) {
545 : maybe_nan = true;
546 : }
547 : type = Type::PlainNumber();
548 : }
549 : }
550 :
551 : // Take into account the -0 and NaN information computed earlier.
552 775281 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
553 886477 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
554 649312 : return type;
555 : }
556 :
557 1253005 : Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) {
558 : DCHECK(lhs->Is(Type::Number()));
559 : DCHECK(rhs->Is(Type::Number()));
560 :
561 764953 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
562 : return Type::None();
563 : }
564 :
565 : // Subtraction can return NaN if either input can be NaN or we try to
566 : // compute the sum of two infinities of opposite sign.
567 380992 : bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN());
568 :
569 : // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs}
570 : // can be zero.
571 : bool maybe_minuszero = false;
572 380992 : if (lhs->Maybe(Type::MinusZero())) {
573 41344 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
574 41344 : maybe_minuszero = rhs->Maybe(cache_.kSingletonZero);
575 : }
576 380992 : if (rhs->Maybe(Type::MinusZero())) {
577 9419 : rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
578 : }
579 :
580 : // We can give more precise types for integers.
581 : Type* type = Type::None();
582 380992 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
583 380992 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
584 761827 : if (lhs->IsInhabited() && rhs->IsInhabited()) {
585 1095118 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
586 331712 : type = SubtractRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max());
587 : } else {
588 138283 : if ((lhs->Maybe(infinity_) && rhs->Maybe(infinity_)) ||
589 41656 : (rhs->Maybe(minus_infinity_) && lhs->Maybe(minus_infinity_))) {
590 : maybe_nan = true;
591 : }
592 : type = Type::PlainNumber();
593 : }
594 : }
595 :
596 : // Take into account the -0 and NaN information computed earlier.
597 389588 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
598 428941 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
599 380992 : return type;
600 : }
601 :
602 109793 : Type* OperationTyper::NumberMultiply(Type* lhs, Type* rhs) {
603 : DCHECK(lhs->Is(Type::Number()));
604 : DCHECK(rhs->Is(Type::Number()));
605 :
606 219238 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
607 : return Type::None();
608 : }
609 :
610 109282 : lhs = Rangify(lhs);
611 109282 : rhs = Rangify(rhs);
612 218383 : if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
613 142071 : if (lhs->IsRange() && rhs->IsRange()) {
614 30622 : return MultiplyRanger(lhs, rhs);
615 : }
616 : return Type::Number();
617 : }
618 :
619 296790 : Type* OperationTyper::NumberDivide(Type* lhs, Type* rhs) {
620 : DCHECK(lhs->Is(Type::Number()));
621 : DCHECK(rhs->Is(Type::Number()));
622 :
623 138954 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
624 : return Type::None();
625 : }
626 :
627 137737 : if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
628 :
629 : // Division is tricky, so all we do is try ruling out -0 and NaN.
630 : bool maybe_nan =
631 91263 : lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
632 46853 : ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
633 3205 : (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
634 68223 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
635 68223 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
636 :
637 : // Try to rule out -0.
638 : bool maybe_minuszero =
639 120341 : !lhs->Is(cache_.kInteger) ||
640 126360 : (lhs->Maybe(cache_.kZeroish) && rhs->Min() < 0.0) ||
641 69149 : (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY);
642 :
643 : // Take into account the -0 and NaN information computed earlier.
644 : Type* type = Type::PlainNumber();
645 113858 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
646 113418 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
647 68223 : return type;
648 : }
649 :
650 89244 : Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) {
651 : DCHECK(lhs->Is(Type::Number()));
652 : DCHECK(rhs->Is(Type::Number()));
653 :
654 : // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or
655 : // {lhs} is not finite, or the {rhs} is a zero value.
656 41541 : bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
657 38139 : lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY;
658 :
659 : // Deal with -0 inputs, only the signbit of {lhs} matters for the result.
660 : bool maybe_minuszero = false;
661 17207 : if (lhs->Maybe(Type::MinusZero())) {
662 : maybe_minuszero = true;
663 4065 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
664 : }
665 17207 : if (rhs->Maybe(Type::MinusZero())) {
666 1512 : rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
667 : }
668 :
669 : // Rule out NaN and -0, and check what we can do with the remaining type info.
670 : Type* type = Type::None();
671 17207 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
672 17207 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
673 :
674 : // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited,
675 : // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}.
676 34228 : if (lhs->IsInhabited() && !rhs->Is(cache_.kSingletonZero)) {
677 : // Determine the bounds of {lhs} and {rhs}.
678 16763 : double const lmin = lhs->Min();
679 16763 : double const lmax = lhs->Max();
680 16763 : double const rmin = rhs->Min();
681 16763 : double const rmax = rhs->Max();
682 :
683 : // The sign of the result is the sign of the {lhs}.
684 16763 : if (lmin < 0.0) maybe_minuszero = true;
685 :
686 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
687 46418 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
688 35535 : double labs = std::max(std::abs(lmin), std::abs(lmax));
689 35535 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
690 11845 : double abs = std::min(labs, rabs);
691 : double min = 0.0, max = 0.0;
692 11845 : if (lmin >= 0.0) {
693 : // {lhs} positive.
694 : min = 0.0;
695 : max = abs;
696 8866 : } else if (lmax <= 0.0) {
697 : // {lhs} negative.
698 627 : min = 0.0 - abs;
699 : max = 0.0;
700 : } else {
701 : // {lhs} positive or negative.
702 8239 : min = 0.0 - abs;
703 : max = abs;
704 : }
705 : type = Type::Range(min, max, zone());
706 : } else {
707 : type = Type::PlainNumber();
708 : }
709 : }
710 :
711 : // Take into account the -0 and NaN information computed earlier.
712 30571 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
713 24044 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
714 17207 : return type;
715 : }
716 :
717 197143 : Type* OperationTyper::NumberBitwiseOr(Type* lhs, Type* rhs) {
718 : DCHECK(lhs->Is(Type::Number()));
719 : DCHECK(rhs->Is(Type::Number()));
720 :
721 197172 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
722 :
723 98196 : lhs = NumberToInt32(lhs);
724 98194 : rhs = NumberToInt32(rhs);
725 :
726 98196 : double lmin = lhs->Min();
727 98196 : double rmin = rhs->Min();
728 98196 : double lmax = lhs->Max();
729 98194 : double rmax = rhs->Max();
730 : // Or-ing any two values results in a value no smaller than their minimum.
731 : // Even no smaller than their maximum if both values are non-negative.
732 : double min =
733 196388 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
734 98194 : double max = kMaxInt;
735 :
736 : // Or-ing with 0 is essentially a conversion to int32.
737 98194 : if (rmin == 0 && rmax == 0) {
738 : min = lmin;
739 88466 : max = lmax;
740 : }
741 98194 : if (lmin == 0 && lmax == 0) {
742 : min = rmin;
743 1464 : max = rmax;
744 : }
745 :
746 98194 : if (lmax < 0 || rmax < 0) {
747 : // Or-ing two values of which at least one is negative results in a negative
748 : // value.
749 960 : max = std::min(max, -1.0);
750 : }
751 196387 : return Type::Range(min, max, zone());
752 : }
753 :
754 48268 : Type* OperationTyper::NumberBitwiseAnd(Type* lhs, Type* rhs) {
755 : DCHECK(lhs->Is(Type::Number()));
756 : DCHECK(rhs->Is(Type::Number()));
757 :
758 48308 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
759 :
760 24023 : lhs = NumberToInt32(lhs);
761 24023 : rhs = NumberToInt32(rhs);
762 :
763 24023 : double lmin = lhs->Min();
764 24023 : double rmin = rhs->Min();
765 24023 : double lmax = lhs->Max();
766 24023 : double rmax = rhs->Max();
767 : double min = kMinInt;
768 : // And-ing any two values results in a value no larger than their maximum.
769 : // Even no larger than their minimum if both values are non-negative.
770 : double max =
771 48046 : lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
772 : // And-ing with a non-negative value x causes the result to be between
773 : // zero and x.
774 24023 : if (lmin >= 0) {
775 : min = 0;
776 5915 : max = std::min(max, lmax);
777 : }
778 24023 : if (rmin >= 0) {
779 : min = 0;
780 17175 : max = std::min(max, rmax);
781 : }
782 48046 : return Type::Range(min, max, zone());
783 : }
784 :
785 15109 : Type* OperationTyper::NumberBitwiseXor(Type* lhs, Type* rhs) {
786 : DCHECK(lhs->Is(Type::Number()));
787 : DCHECK(rhs->Is(Type::Number()));
788 :
789 30136 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
790 :
791 14998 : lhs = NumberToInt32(lhs);
792 14998 : rhs = NumberToInt32(rhs);
793 :
794 14998 : double lmin = lhs->Min();
795 14998 : double rmin = rhs->Min();
796 14998 : double lmax = lhs->Max();
797 14998 : double rmax = rhs->Max();
798 14998 : if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
799 : // Xor-ing negative or non-negative values results in a non-negative value.
800 : return Type::Unsigned31();
801 : }
802 14598 : if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
803 : // Xor-ing a negative and a non-negative value results in a negative value.
804 : // TODO(jarin) Use a range here.
805 : return Type::Negative32();
806 : }
807 14412 : return Type::Signed32();
808 : }
809 :
810 55580 : Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) {
811 : DCHECK(lhs->Is(Type::Number()));
812 : DCHECK(rhs->Is(Type::Number()));
813 :
814 71760 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
815 :
816 35645 : lhs = NumberToInt32(lhs);
817 35645 : rhs = NumberToUint32(rhs);
818 :
819 35645 : int32_t min_lhs = lhs->Min();
820 35645 : int32_t max_lhs = lhs->Max();
821 35645 : uint32_t min_rhs = rhs->Min();
822 35645 : uint32_t max_rhs = rhs->Max();
823 35645 : if (max_rhs > 31) {
824 : // rhs can be larger than the bitmask
825 : max_rhs = 31;
826 : min_rhs = 0;
827 : }
828 :
829 35645 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
830 : // overflow possible
831 : return Type::Signed32();
832 : }
833 :
834 : double min =
835 19794 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
836 59382 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
837 : double max =
838 19794 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
839 59382 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
840 :
841 19794 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
842 19535 : return Type::Range(min, max, zone());
843 : }
844 :
845 74439 : Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
846 : DCHECK(lhs->Is(Type::Number()));
847 : DCHECK(rhs->Is(Type::Number()));
848 :
849 78059 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
850 :
851 38850 : lhs = NumberToInt32(lhs);
852 38851 : rhs = NumberToUint32(rhs);
853 :
854 38851 : int32_t min_lhs = lhs->Min();
855 38851 : int32_t max_lhs = lhs->Max();
856 38851 : uint32_t min_rhs = rhs->Min();
857 38849 : uint32_t max_rhs = rhs->Max();
858 38849 : if (max_rhs > 31) {
859 : // rhs can be larger than the bitmask
860 : max_rhs = 31;
861 : min_rhs = 0;
862 : }
863 77698 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
864 77698 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
865 :
866 38849 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
867 35257 : return Type::Range(min, max, zone());
868 : }
869 :
870 29873 : Type* OperationTyper::NumberShiftRightLogical(Type* lhs, Type* rhs) {
871 : DCHECK(lhs->Is(Type::Number()));
872 : DCHECK(rhs->Is(Type::Number()));
873 :
874 39633 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
875 :
876 19666 : lhs = NumberToUint32(lhs);
877 19667 : rhs = NumberToUint32(rhs);
878 :
879 19667 : uint32_t min_lhs = lhs->Min();
880 19667 : uint32_t max_lhs = lhs->Max();
881 19667 : uint32_t min_rhs = rhs->Min();
882 19667 : uint32_t max_rhs = rhs->Max();
883 19667 : if (max_rhs > 31) {
884 : // rhs can be larger than the bitmask
885 : max_rhs = 31;
886 : min_rhs = 0;
887 : }
888 :
889 19667 : double min = min_lhs >> max_rhs;
890 19667 : double max = max_lhs >> min_rhs;
891 : DCHECK_LE(0, min);
892 : DCHECK_LE(max, kMaxUInt32);
893 :
894 19667 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
895 18730 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
896 9943 : return Type::Range(min, max, zone());
897 : }
898 :
899 329 : Type* OperationTyper::NumberAtan2(Type* lhs, Type* rhs) {
900 : DCHECK(lhs->Is(Type::Number()));
901 : DCHECK(rhs->Is(Type::Number()));
902 329 : return Type::Number();
903 : }
904 :
905 282 : Type* OperationTyper::NumberImul(Type* lhs, Type* rhs) {
906 : DCHECK(lhs->Is(Type::Number()));
907 : DCHECK(rhs->Is(Type::Number()));
908 : // TODO(turbofan): We should be able to do better here.
909 282 : return Type::Signed32();
910 : }
911 :
912 2011 : Type* OperationTyper::NumberMax(Type* lhs, Type* rhs) {
913 : DCHECK(lhs->Is(Type::Number()));
914 : DCHECK(rhs->Is(Type::Number()));
915 1020 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
916 : return Type::None();
917 : }
918 951 : if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) {
919 : return Type::NaN();
920 : }
921 : Type* type = Type::None();
922 : // TODO(turbofan): Improve minus zero handling here.
923 463 : if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
924 95 : type = Type::Union(type, Type::NaN(), zone());
925 : }
926 463 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
927 463 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
928 1224 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
929 504 : double max = std::max(lhs->Max(), rhs->Max());
930 504 : double min = std::max(lhs->Min(), rhs->Min());
931 252 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
932 : } else {
933 211 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
934 : }
935 463 : return type;
936 : }
937 :
938 2343 : Type* OperationTyper::NumberMin(Type* lhs, Type* rhs) {
939 : DCHECK(lhs->Is(Type::Number()));
940 : DCHECK(rhs->Is(Type::Number()));
941 1137 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
942 : return Type::None();
943 : }
944 1061 : if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) {
945 : return Type::NaN();
946 : }
947 : Type* type = Type::None();
948 : // TODO(turbofan): Improve minus zero handling here.
949 518 : if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
950 200 : type = Type::Union(type, Type::NaN(), zone());
951 : }
952 518 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
953 518 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
954 1329 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
955 422 : double max = std::min(lhs->Max(), rhs->Max());
956 422 : double min = std::min(lhs->Min(), rhs->Min());
957 211 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
958 : } else {
959 307 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
960 : }
961 518 : return type;
962 : }
963 :
964 2215 : Type* OperationTyper::NumberPow(Type* lhs, Type* rhs) {
965 : DCHECK(lhs->Is(Type::Number()));
966 : DCHECK(rhs->Is(Type::Number()));
967 : // TODO(turbofan): We should be able to do better here.
968 2215 : return Type::Number();
969 : }
970 :
971 : #define SPECULATIVE_NUMBER_BINOP(Name) \
972 : Type* OperationTyper::Speculative##Name(Type* lhs, Type* rhs) { \
973 : lhs = SpeculativeToNumber(lhs); \
974 : rhs = SpeculativeToNumber(rhs); \
975 : return Name(lhs, rhs); \
976 : }
977 462861 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
978 87549 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
979 53018 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
980 24839 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
981 8129 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
982 34405 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
983 11332 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
984 3067 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
985 4490 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
986 12434 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
987 4095 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
988 : #undef SPECULATIVE_NUMBER_BINOP
989 :
990 1426043 : Type* OperationTyper::SpeculativeToNumber(Type* type) {
991 1426043 : return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
992 : }
993 :
994 0 : Type* OperationTyper::ToPrimitive(Type* type) {
995 0 : if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
996 0 : return type;
997 : }
998 : return Type::Primitive();
999 : }
1000 :
1001 0 : Type* OperationTyper::Invert(Type* type) {
1002 : DCHECK(type->Is(Type::Boolean()));
1003 : DCHECK(type->IsInhabited());
1004 0 : if (type->Is(singleton_false())) return singleton_true();
1005 0 : if (type->Is(singleton_true())) return singleton_false();
1006 : return type;
1007 : }
1008 :
1009 0 : OperationTyper::ComparisonOutcome OperationTyper::Invert(
1010 : ComparisonOutcome outcome) {
1011 : ComparisonOutcome result(0);
1012 0 : if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
1013 0 : if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
1014 0 : if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
1015 0 : return result;
1016 : }
1017 :
1018 0 : Type* OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
1019 0 : if ((outcome & kComparisonFalse) != 0 ||
1020 : (outcome & kComparisonUndefined) != 0) {
1021 : return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
1022 0 : : singleton_false();
1023 : }
1024 : // Type should be non empty, so we know it should be true.
1025 : DCHECK((outcome & kComparisonTrue) != 0);
1026 0 : return singleton_true();
1027 : }
1028 :
1029 4560 : Type* OperationTyper::CheckFloat64Hole(Type* type) {
1030 1552 : if (type->Maybe(Type::Hole())) {
1031 : // Turn "the hole" into undefined.
1032 1504 : type = Type::Intersect(type, Type::Number(), zone());
1033 1504 : type = Type::Union(type, Type::Undefined(), zone());
1034 : }
1035 1552 : return type;
1036 : }
1037 :
1038 4985 : Type* OperationTyper::CheckNumber(Type* type) {
1039 4985 : return Type::Intersect(type, Type::Number(), zone());
1040 : }
1041 :
1042 32455 : Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) {
1043 32455 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1044 : }
1045 :
1046 : } // namespace compiler
1047 : } // namespace internal
1048 : } // namespace v8
|