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 791544 : OperationTyper::OperationTyper(Isolate* isolate, Zone* zone)
20 791544 : : zone_(zone), cache_(TypeCache::Get()) {
21 : Factory* factory = isolate->factory();
22 791541 : infinity_ = Type::NewConstant(factory->infinity_value(), zone);
23 791533 : 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 791537 : singleton_false_ = Type::HeapConstant(factory->false_value(), zone);
28 791540 : singleton_true_ = Type::HeapConstant(factory->true_value(), zone);
29 791540 : singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone);
30 791540 : signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
31 791540 : unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
32 791544 : }
33 :
34 1605096 : Type* OperationTyper::Merge(Type* left, Type* right) {
35 1605096 : return Type::Union(left, right, zone());
36 : }
37 :
38 811557 : 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 405780 : 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 405779 : if (current_min != previous_range->Min()) {
88 : new_min = -V8_INFINITY;
89 656822 : for (double const min : kWeakenMinLimits) {
90 339323 : if (min <= current_min) {
91 : new_min = min;
92 : break;
93 : }
94 : }
95 : }
96 :
97 405778 : 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 405778 : if (current_max != previous_range->Max()) {
102 : new_max = V8_INFINITY;
103 5534623 : for (double const max : kWeakenMaxLimits) {
104 2889882 : if (max >= current_max) {
105 : new_max = max;
106 : break;
107 : }
108 : }
109 : }
110 :
111 405778 : return Type::Range(new_min, new_max, zone());
112 : }
113 :
114 228693 : Type* OperationTyper::Rangify(Type* type) {
115 218150 : if (type->IsRange()) return type; // Shortcut.
116 199490 : if (!type->Is(cache_.kInteger)) {
117 : return type; // Give up on non-integer types.
118 : }
119 10543 : double min = type->Min();
120 10543 : double max = type->Max();
121 : // Handle the degenerate case of empty bitset types (such as
122 : // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
123 10543 : if (std::isnan(min)) {
124 : DCHECK(std::isnan(max));
125 : return type;
126 : }
127 10543 : 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 700421 : double array_min(double a[], size_t n) {
136 : DCHECK(n != 0);
137 700421 : double x = +V8_INFINITY;
138 3502097 : for (size_t i = 0; i < n; ++i) {
139 2801676 : if (!std::isnan(a[i])) {
140 2801614 : x = std::min(a[i], x);
141 : }
142 : }
143 : DCHECK(!std::isnan(x));
144 700421 : 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 700418 : double array_max(double a[], size_t n) {
151 : DCHECK(n != 0);
152 700418 : double x = -V8_INFINITY;
153 3502050 : for (size_t i = 0; i < n; ++i) {
154 2801632 : if (!std::isnan(a[i])) {
155 2801590 : x = std::max(a[i], x);
156 : }
157 : }
158 : DCHECK(!std::isnan(x));
159 700418 : return x == 0 ? 0 : x; // -0 -> 0
160 : }
161 :
162 : } // namespace
163 :
164 337745 : Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
165 337754 : double rhs_max) {
166 : double results[4];
167 337745 : results[0] = lhs_min + rhs_min;
168 337745 : results[1] = lhs_min + rhs_max;
169 337745 : results[2] = lhs_max + rhs_min;
170 337745 : 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 1688721 : for (int i = 0; i < 4; ++i) {
177 1350976 : if (std::isnan(results[i])) ++nans;
178 : }
179 337745 : if (nans == 4) return Type::NaN();
180 : Type* type =
181 337741 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
182 337751 : 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 337738 : return type;
189 : }
190 :
191 332271 : Type* OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
192 332283 : double rhs_min, double rhs_max) {
193 : double results[4];
194 332271 : results[0] = lhs_min - rhs_min;
195 332271 : results[1] = lhs_min - rhs_max;
196 332271 : results[2] = lhs_max - rhs_min;
197 332271 : 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 1661355 : for (int i = 0; i < 4; ++i) {
204 1329084 : if (std::isnan(results[i])) ++nans;
205 : }
206 332271 : if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
207 : Type* type =
208 332266 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
209 332284 : 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 68001 : Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) {
218 : double results[4];
219 30498 : double lmin = lhs->AsRange()->Min();
220 30498 : double lmax = lhs->AsRange()->Max();
221 30498 : double rmin = rhs->AsRange()->Min();
222 30498 : double rmax = rhs->AsRange()->Max();
223 30498 : results[0] = lmin * rmin;
224 30498 : results[1] = lmin * rmax;
225 30498 : results[2] = lmax * rmin;
226 30498 : 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 53666 : bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) &&
232 84088 : (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
233 33190 : (rhs->Maybe(cache_.kSingletonZero) &&
234 2755 : (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
235 30498 : if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up.
236 54042 : bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) ||
237 24467 : (rhs->Maybe(cache_.kSingletonZero) && lmin < 0);
238 : Type* range =
239 30407 : Type::Range(array_min(results, 4), array_max(results, 4), zone());
240 : return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
241 37503 : : range;
242 : }
243 :
244 2918494 : Type* OperationTyper::ToNumber(Type* type) {
245 2264705 : if (type->Is(Type::Number())) return type;
246 469731 : if (type->Is(Type::NullOrUndefined())) {
247 3312 : if (type->Is(Type::Null())) return cache_.kSingletonZero;
248 1988 : if (type->Is(Type::Undefined())) return Type::NaN();
249 0 : return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
250 : }
251 466421 : if (type->Is(Type::Boolean())) {
252 15698 : if (type->Is(singleton_false_)) return cache_.kSingletonZero;
253 14464 : if (type->Is(singleton_true_)) return cache_.kSingletonOne;
254 4507 : return cache_.kZeroOrOne;
255 : }
256 458567 : if (type->Is(Type::NumberOrOddball())) {
257 326912 : if (type->Is(Type::NumberOrUndefined())) {
258 13902 : type = Type::Union(type, Type::NaN(), zone());
259 312998 : } else if (type->Is(Type::NullOrNumber())) {
260 144 : type = Type::Union(type, cache_.kSingletonZero, zone());
261 312858 : } else if (type->Is(Type::BooleanOrNullOrNumber())) {
262 696 : type = Type::Union(type, cache_.kZeroOrOne, zone());
263 : } else {
264 312162 : type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone());
265 : }
266 326930 : return Type::Intersect(type, Type::Number(), zone());
267 : }
268 : return Type::Number();
269 : }
270 :
271 1315 : Type* OperationTyper::NumberAbs(Type* type) {
272 : DCHECK(type->Is(Type::Number()));
273 :
274 496 : if (!type->IsInhabited()) {
275 : return Type::None();
276 : }
277 :
278 454 : bool const maybe_nan = type->Maybe(Type::NaN());
279 454 : bool const maybe_minuszero = type->Maybe(Type::MinusZero());
280 454 : type = Type::Intersect(type, Type::PlainNumber(), zone());
281 454 : double const max = type->Max();
282 454 : double const min = type->Min();
283 454 : if (min < 0) {
284 554 : if (type->Is(cache_.kInteger)) {
285 372 : type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
286 : } else {
287 : type = Type::PlainNumber();
288 : }
289 : }
290 454 : if (maybe_minuszero) {
291 72 : type = Type::Union(type, cache_.kSingletonZero, zone());
292 : }
293 454 : if (maybe_nan) {
294 169 : type = Type::Union(type, Type::NaN(), zone());
295 : }
296 454 : 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 11546 : Type* OperationTyper::NumberCeil(Type* type) {
335 : DCHECK(type->Is(Type::Number()));
336 23092 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
337 : // TODO(bmeurer): We could infer a more precise type here.
338 10876 : return cache_.kIntegerOrMinusZeroOrNaN;
339 : }
340 :
341 157 : Type* OperationTyper::NumberClz32(Type* type) {
342 : DCHECK(type->Is(Type::Number()));
343 157 : 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 54078 : Type* OperationTyper::NumberFloor(Type* type) {
367 : DCHECK(type->Is(Type::Number()));
368 36916 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
369 17810 : type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
370 17810 : type = Type::Union(type, cache_.kInteger, zone());
371 17810 : return type;
372 : }
373 :
374 1434 : Type* OperationTyper::NumberFround(Type* type) {
375 : DCHECK(type->Is(Type::Number()));
376 1434 : 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 169 : return cache_.kIntegerOrMinusZeroOrNaN;
404 : }
405 :
406 477 : Type* OperationTyper::NumberSign(Type* type) {
407 : DCHECK(type->Is(Type::Number()));
408 310 : if (type->Is(cache_.kZeroish)) return type;
409 108 : bool maybe_minuszero = type->Maybe(Type::MinusZero());
410 108 : bool maybe_nan = type->Maybe(Type::NaN());
411 108 : type = Type::Intersect(type, Type::PlainNumber(), zone());
412 108 : if (type->Max() < 0.0) {
413 7 : type = cache_.kSingletonMinusOne;
414 101 : } else if (type->Max() <= 0.0) {
415 0 : type = cache_.kMinusOneOrZero;
416 101 : } else if (type->Min() > 0.0) {
417 12 : type = cache_.kSingletonOne;
418 89 : } else if (type->Min() >= 0.0) {
419 3 : type = cache_.kZeroOrOne;
420 : } else {
421 : type = Type::Range(-1.0, 1.0, zone());
422 : }
423 173 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
424 171 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
425 108 : 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 131 : Type* OperationTyper::NumberTanh(Type* type) {
449 : DCHECK(type->Is(Type::Number()));
450 131 : return Type::Number();
451 : }
452 :
453 2903 : Type* OperationTyper::NumberTrunc(Type* type) {
454 : DCHECK(type->Is(Type::Number()));
455 5806 : if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
456 : // TODO(bmeurer): We could infer a more precise type here.
457 2677 : return cache_.kIntegerOrMinusZeroOrNaN;
458 : }
459 :
460 3531 : Type* OperationTyper::NumberToBoolean(Type* type) {
461 : DCHECK(type->Is(Type::Number()));
462 3531 : if (!type->IsInhabited()) return Type::None();
463 6978 : if (type->Is(cache_.kZeroish)) return singleton_false_;
464 3483 : if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) {
465 219 : return singleton_true_; // Ruled out nan, -0 and +0.
466 : }
467 : return Type::Boolean();
468 : }
469 :
470 454597 : Type* OperationTyper::NumberToInt32(Type* type) {
471 : DCHECK(type->Is(Type::Number()));
472 :
473 439426 : if (type->Is(Type::Signed32())) return type;
474 329378 : if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
475 319949 : if (type->Is(signed32ish_)) {
476 : return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
477 15177 : Type::Signed32(), zone());
478 : }
479 : return Type::Signed32();
480 : }
481 :
482 143001 : Type* OperationTyper::NumberToUint32(Type* type) {
483 : DCHECK(type->Is(Type::Number()));
484 :
485 142851 : if (type->Is(Type::Unsigned32())) return type;
486 84537 : if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero;
487 79792 : if (type->Is(unsigned32ish_)) {
488 : return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
489 151 : 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 954 : return cache_.kUint8;
499 : }
500 :
501 1804 : 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 1804 : if (type->Maybe(Type::NaN())) return Type::Number();
507 497 : return type;
508 : }
509 :
510 2614249 : Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) {
511 : DCHECK(lhs->Is(Type::Number()));
512 : DCHECK(rhs->Is(Type::Number()));
513 :
514 1299352 : 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 648385 : 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 648377 : if (lhs->Maybe(Type::MinusZero())) {
525 169156 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
526 : } else {
527 : maybe_minuszero = false;
528 : }
529 648403 : if (rhs->Maybe(Type::MinusZero())) {
530 135349 : 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 648403 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
538 648385 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
539 1296636 : if (lhs->IsInhabited() && rhs->IsInhabited()) {
540 1674104 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
541 337753 : type = AddRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max());
542 : } else {
543 791256 : if ((lhs->Maybe(minus_infinity_) && rhs->Maybe(infinity_)) ||
544 183562 : (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 774188 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
553 884848 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
554 648362 : return type;
555 : }
556 :
557 1255073 : Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) {
558 : DCHECK(lhs->Is(Type::Number()));
559 : DCHECK(rhs->Is(Type::Number()));
560 :
561 766280 : 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 381636 : 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 381637 : if (lhs->Maybe(Type::MinusZero())) {
573 41437 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
574 41437 : maybe_minuszero = rhs->Maybe(cache_.kSingletonZero);
575 : }
576 381637 : if (rhs->Maybe(Type::MinusZero())) {
577 9369 : rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
578 : }
579 :
580 : // We can give more precise types for integers.
581 : Type* type = Type::None();
582 381637 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
583 381637 : rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
584 763114 : if (lhs->IsInhabited() && rhs->IsInhabited()) {
585 1096938 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
586 332271 : type = SubtractRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max());
587 : } else {
588 138561 : if ((lhs->Maybe(infinity_) && rhs->Maybe(infinity_)) ||
589 41748 : (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 390210 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
598 429672 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
599 381636 : return type;
600 : }
601 :
602 109607 : Type* OperationTyper::NumberMultiply(Type* lhs, Type* rhs) {
603 : DCHECK(lhs->Is(Type::Number()));
604 : DCHECK(rhs->Is(Type::Number()));
605 :
606 218858 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
607 : return Type::None();
608 : }
609 :
610 109075 : lhs = Rangify(lhs);
611 109075 : rhs = Rangify(rhs);
612 217966 : if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
613 141723 : if (lhs->IsRange() && rhs->IsRange()) {
614 30498 : return MultiplyRanger(lhs, rhs);
615 : }
616 : return Type::Number();
617 : }
618 :
619 296785 : Type* OperationTyper::NumberDivide(Type* lhs, Type* rhs) {
620 : DCHECK(lhs->Is(Type::Number()));
621 : DCHECK(rhs->Is(Type::Number()));
622 :
623 139114 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
624 : return Type::None();
625 : }
626 :
627 137816 : 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 91699 : lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
632 47643 : ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
633 3205 : (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
634 68260 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
635 68261 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
636 :
637 : // Try to rule out -0.
638 : bool maybe_minuszero =
639 120466 : !lhs->Is(cache_.kInteger) ||
640 126674 : (lhs->Maybe(cache_.kZeroish) && rhs->Min() < 0.0) ||
641 69030 : (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 114090 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
646 113097 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
647 68261 : return type;
648 : }
649 :
650 90204 : 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 42167 : bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) ||
657 38837 : 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 17407 : if (lhs->Maybe(Type::MinusZero())) {
662 : maybe_minuszero = true;
663 4080 : lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
664 : }
665 17409 : if (rhs->Maybe(Type::MinusZero())) {
666 1415 : 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 17409 : lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
672 17410 : 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 34620 : if (lhs->IsInhabited() && !rhs->Is(cache_.kSingletonZero)) {
677 : // Determine the bounds of {lhs} and {rhs}.
678 16952 : double const lmin = lhs->Min();
679 16952 : double const lmax = lhs->Max();
680 16950 : double const rmin = rhs->Min();
681 16948 : double const rmax = rhs->Max();
682 :
683 : // The sign of the result is the sign of the {lhs}.
684 16948 : if (lmin < 0.0) maybe_minuszero = true;
685 :
686 : // For integer inputs {lhs} and {rhs} we can infer a precise type.
687 46960 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
688 36228 : double labs = std::max(std::abs(lmin), std::abs(lmax));
689 36228 : double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
690 12076 : double abs = std::min(labs, rabs);
691 : double min = 0.0, max = 0.0;
692 12076 : if (lmin >= 0.0) {
693 : // {lhs} positive.
694 : min = 0.0;
695 : max = abs;
696 9130 : } else if (lmax <= 0.0) {
697 : // {lhs} negative.
698 633 : min = 0.0 - abs;
699 : max = 0.0;
700 : } else {
701 : // {lhs} positive or negative.
702 8497 : 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 31025 : if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
713 24195 : if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
714 17409 : return type;
715 : }
716 :
717 200785 : Type* OperationTyper::NumberBitwiseOr(Type* lhs, Type* rhs) {
718 : DCHECK(lhs->Is(Type::Number()));
719 : DCHECK(rhs->Is(Type::Number()));
720 :
721 200832 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
722 :
723 100013 : lhs = NumberToInt32(lhs);
724 100006 : rhs = NumberToInt32(rhs);
725 :
726 100009 : double lmin = lhs->Min();
727 100009 : double rmin = rhs->Min();
728 100008 : double lmax = lhs->Max();
729 100008 : 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 200012 : lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
734 100006 : double max = kMaxInt;
735 :
736 : // Or-ing with 0 is essentially a conversion to int32.
737 100006 : if (rmin == 0 && rmax == 0) {
738 : min = lmin;
739 89588 : max = lmax;
740 : }
741 100006 : if (lmin == 0 && lmax == 0) {
742 : min = rmin;
743 1467 : max = rmax;
744 : }
745 :
746 100006 : if (lmax < 0 || rmax < 0) {
747 : // Or-ing two values of which at least one is negative results in a negative
748 : // value.
749 942 : max = std::min(max, -1.0);
750 : }
751 200014 : return Type::Range(min, max, zone());
752 : }
753 :
754 52934 : Type* OperationTyper::NumberBitwiseAnd(Type* lhs, Type* rhs) {
755 : DCHECK(lhs->Is(Type::Number()));
756 : DCHECK(rhs->Is(Type::Number()));
757 :
758 52986 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
759 :
760 26346 : lhs = NumberToInt32(lhs);
761 26346 : rhs = NumberToInt32(rhs);
762 :
763 26346 : double lmin = lhs->Min();
764 26346 : double rmin = rhs->Min();
765 26346 : double lmax = lhs->Max();
766 26346 : 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 52692 : 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 26346 : if (lmin >= 0) {
775 : min = 0;
776 6751 : max = std::min(max, lmax);
777 : }
778 26346 : if (rmin >= 0) {
779 : min = 0;
780 19430 : max = std::min(max, rmax);
781 : }
782 52692 : return Type::Range(min, max, zone());
783 : }
784 :
785 15318 : Type* OperationTyper::NumberBitwiseXor(Type* lhs, Type* rhs) {
786 : DCHECK(lhs->Is(Type::Number()));
787 : DCHECK(rhs->Is(Type::Number()));
788 :
789 30544 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
790 :
791 15185 : lhs = NumberToInt32(lhs);
792 15185 : rhs = NumberToInt32(rhs);
793 :
794 15185 : double lmin = lhs->Min();
795 15185 : double rmin = rhs->Min();
796 15185 : double lmax = lhs->Max();
797 15185 : double rmax = rhs->Max();
798 15185 : 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 14772 : 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 14589 : return Type::Signed32();
808 : }
809 :
810 56167 : Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) {
811 : DCHECK(lhs->Is(Type::Number()));
812 : DCHECK(rhs->Is(Type::Number()));
813 :
814 72962 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
815 :
816 36229 : lhs = NumberToInt32(lhs);
817 36229 : rhs = NumberToUint32(rhs);
818 :
819 36229 : int32_t min_lhs = lhs->Min();
820 36229 : int32_t max_lhs = lhs->Max();
821 36229 : uint32_t min_rhs = rhs->Min();
822 36228 : uint32_t max_rhs = rhs->Max();
823 36228 : if (max_rhs > 31) {
824 : // rhs can be larger than the bitmask
825 : max_rhs = 31;
826 : min_rhs = 0;
827 : }
828 :
829 36228 : if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
830 : // overflow possible
831 : return Type::Signed32();
832 : }
833 :
834 : double min =
835 19769 : std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
836 59307 : static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
837 : double max =
838 19769 : std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
839 59307 : static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
840 :
841 19769 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
842 19516 : return Type::Range(min, max, zone());
843 : }
844 :
845 79023 : Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
846 : DCHECK(lhs->Is(Type::Number()));
847 : DCHECK(rhs->Is(Type::Number()));
848 :
849 82611 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
850 :
851 41109 : lhs = NumberToInt32(lhs);
852 41110 : rhs = NumberToUint32(rhs);
853 :
854 41110 : int32_t min_lhs = lhs->Min();
855 41110 : int32_t max_lhs = lhs->Max();
856 41110 : uint32_t min_rhs = rhs->Min();
857 41110 : uint32_t max_rhs = rhs->Max();
858 41110 : if (max_rhs > 31) {
859 : // rhs can be larger than the bitmask
860 : max_rhs = 31;
861 : min_rhs = 0;
862 : }
863 82220 : double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
864 82220 : double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
865 :
866 41110 : if (max == kMaxInt && min == kMinInt) return Type::Signed32();
867 37561 : return Type::Range(min, max, zone());
868 : }
869 :
870 30097 : Type* OperationTyper::NumberShiftRightLogical(Type* lhs, Type* rhs) {
871 : DCHECK(lhs->Is(Type::Number()));
872 : DCHECK(rhs->Is(Type::Number()));
873 :
874 39829 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
875 :
876 19748 : lhs = NumberToUint32(lhs);
877 19747 : rhs = NumberToUint32(rhs);
878 :
879 19747 : uint32_t min_lhs = lhs->Min();
880 19747 : uint32_t max_lhs = lhs->Max();
881 19747 : uint32_t min_rhs = rhs->Min();
882 19747 : uint32_t max_rhs = rhs->Max();
883 19747 : if (max_rhs > 31) {
884 : // rhs can be larger than the bitmask
885 : max_rhs = 31;
886 : min_rhs = 0;
887 : }
888 :
889 19747 : double min = min_lhs >> max_rhs;
890 19747 : double max = max_lhs >> min_rhs;
891 : DCHECK_LE(0, min);
892 : DCHECK_LE(max, kMaxUInt32);
893 :
894 19747 : if (min == 0 && max == kMaxInt) return Type::Unsigned31();
895 18811 : if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
896 10065 : return Type::Range(min, max, zone());
897 : }
898 :
899 318 : Type* OperationTyper::NumberAtan2(Type* lhs, Type* rhs) {
900 : DCHECK(lhs->Is(Type::Number()));
901 : DCHECK(rhs->Is(Type::Number()));
902 318 : return Type::Number();
903 : }
904 :
905 271 : 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 271 : return Type::Signed32();
910 : }
911 :
912 1938 : Type* OperationTyper::NumberMax(Type* lhs, Type* rhs) {
913 : DCHECK(lhs->Is(Type::Number()));
914 : DCHECK(rhs->Is(Type::Number()));
915 1001 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
916 : return Type::None();
917 : }
918 915 : 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 445 : if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
924 83 : type = Type::Union(type, Type::NaN(), zone());
925 : }
926 445 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
927 445 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
928 1180 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
929 496 : double max = std::max(lhs->Max(), rhs->Max());
930 496 : double min = std::max(lhs->Min(), rhs->Min());
931 248 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
932 : } else {
933 197 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
934 : }
935 445 : return type;
936 : }
937 :
938 2246 : Type* OperationTyper::NumberMin(Type* lhs, Type* rhs) {
939 : DCHECK(lhs->Is(Type::Number()));
940 : DCHECK(rhs->Is(Type::Number()));
941 1106 : if (!lhs->IsInhabited() || !rhs->IsInhabited()) {
942 : return Type::None();
943 : }
944 1013 : 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 494 : if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
950 188 : type = Type::Union(type, Type::NaN(), zone());
951 : }
952 494 : lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
953 494 : rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
954 1267 : if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) {
955 402 : double max = std::min(lhs->Max(), rhs->Max());
956 402 : double min = std::min(lhs->Min(), rhs->Min());
957 201 : type = Type::Union(type, Type::Range(min, max, zone()), zone());
958 : } else {
959 293 : type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
960 : }
961 494 : return type;
962 : }
963 :
964 2202 : 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 2202 : 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 462314 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
978 87763 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
979 52909 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
980 24651 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
981 8364 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
982 36574 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
983 13678 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
984 3239 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
985 5123 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
986 14774 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
987 4197 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
988 : #undef SPECULATIVE_NUMBER_BINOP
989 :
990 1440753 : Type* OperationTyper::SpeculativeToNumber(Type* type) {
991 1440753 : 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 4978 : Type* OperationTyper::CheckNumber(Type* type) {
1039 4978 : return Type::Intersect(type, Type::Number(), zone());
1040 : }
1041 :
1042 31591 : Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) {
1043 31591 : return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1044 : }
1045 :
1046 : } // namespace compiler
1047 : } // namespace internal
1048 : } // namespace v8
|