1 // Copyright 2015 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/representation-change.h"
6
7 #include <sstream>
8
9 #include "src/base/bits.h"
10 #include "src/codegen/code-factory.h"
11 #include "src/compiler/js-heap-broker.h"
12 #include "src/compiler/machine-operator.h"
13 #include "src/compiler/node-matchers.h"
14 #include "src/compiler/simplified-operator.h"
15 #include "src/compiler/type-cache.h"
16 #include "src/heap/factory-inl.h"
17
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21
description() const22 const char* Truncation::description() const {
23 switch (kind()) {
24 case TruncationKind::kNone:
25 return "no-value-use";
26 case TruncationKind::kBool:
27 return "truncate-to-bool";
28 case TruncationKind::kWord32:
29 return "truncate-to-word32";
30 case TruncationKind::kWord64:
31 return "truncate-to-word64";
32 case TruncationKind::kOddballAndBigIntToNumber:
33 switch (identify_zeros()) {
34 case kIdentifyZeros:
35 return "truncate-oddball&bigint-to-number (identify zeros)";
36 case kDistinguishZeros:
37 return "truncate-oddball&bigint-to-number (distinguish zeros)";
38 }
39 case TruncationKind::kAny:
40 switch (identify_zeros()) {
41 case kIdentifyZeros:
42 return "no-truncation (but identify zeros)";
43 case kDistinguishZeros:
44 return "no-truncation (but distinguish zeros)";
45 }
46 }
47 UNREACHABLE();
48 }
49
50 // Partial order for truncations:
51 //
52 // kAny <-------+
53 // ^ |
54 // | |
55 // kOddballAndBigIntToNumber |
56 // ^ |
57 // / |
58 // kWord64 |
59 // ^ |
60 // | |
61 // kWord32 kBool
62 // ^ ^
63 // \ /
64 // \ /
65 // \ /
66 // \ /
67 // \ /
68 // kNone
69 //
70 // TODO(jarin) We might consider making kBool < kOddballAndBigIntToNumber.
71
72 // static
Generalize(TruncationKind rep1,TruncationKind rep2)73 Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
74 TruncationKind rep2) {
75 if (LessGeneral(rep1, rep2)) return rep2;
76 if (LessGeneral(rep2, rep1)) return rep1;
77 // Handle the generalization of float64-representable values.
78 if (LessGeneral(rep1, TruncationKind::kOddballAndBigIntToNumber) &&
79 LessGeneral(rep2, TruncationKind::kOddballAndBigIntToNumber)) {
80 return TruncationKind::kOddballAndBigIntToNumber;
81 }
82 // Handle the generalization of any-representable values.
83 if (LessGeneral(rep1, TruncationKind::kAny) &&
84 LessGeneral(rep2, TruncationKind::kAny)) {
85 return TruncationKind::kAny;
86 }
87 // All other combinations are illegal.
88 FATAL("Tried to combine incompatible truncations");
89 return TruncationKind::kNone;
90 }
91
92 // static
GeneralizeIdentifyZeros(IdentifyZeros i1,IdentifyZeros i2)93 IdentifyZeros Truncation::GeneralizeIdentifyZeros(IdentifyZeros i1,
94 IdentifyZeros i2) {
95 if (i1 == i2) {
96 return i1;
97 } else {
98 return kDistinguishZeros;
99 }
100 }
101
102 // static
LessGeneral(TruncationKind rep1,TruncationKind rep2)103 bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
104 switch (rep1) {
105 case TruncationKind::kNone:
106 return true;
107 case TruncationKind::kBool:
108 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
109 case TruncationKind::kWord32:
110 return rep2 == TruncationKind::kWord32 ||
111 rep2 == TruncationKind::kWord64 ||
112 rep2 == TruncationKind::kOddballAndBigIntToNumber ||
113 rep2 == TruncationKind::kAny;
114 case TruncationKind::kWord64:
115 return rep2 == TruncationKind::kWord64 ||
116 rep2 == TruncationKind::kOddballAndBigIntToNumber ||
117 rep2 == TruncationKind::kAny;
118 case TruncationKind::kOddballAndBigIntToNumber:
119 return rep2 == TruncationKind::kOddballAndBigIntToNumber ||
120 rep2 == TruncationKind::kAny;
121 case TruncationKind::kAny:
122 return rep2 == TruncationKind::kAny;
123 }
124 UNREACHABLE();
125 }
126
127 // static
LessGeneralIdentifyZeros(IdentifyZeros i1,IdentifyZeros i2)128 bool Truncation::LessGeneralIdentifyZeros(IdentifyZeros i1, IdentifyZeros i2) {
129 return i1 == i2 || i1 == kIdentifyZeros;
130 }
131
132 namespace {
133
IsWord(MachineRepresentation rep)134 bool IsWord(MachineRepresentation rep) {
135 return rep == MachineRepresentation::kWord8 ||
136 rep == MachineRepresentation::kWord16 ||
137 rep == MachineRepresentation::kWord32;
138 }
139
140 } // namespace
141
RepresentationChanger(JSGraph * jsgraph,JSHeapBroker * broker)142 RepresentationChanger::RepresentationChanger(JSGraph* jsgraph,
143 JSHeapBroker* broker)
144 : cache_(TypeCache::Get()),
145 jsgraph_(jsgraph),
146 broker_(broker),
147 testing_type_errors_(false),
148 type_error_(false) {}
149
150 // Changes representation from {output_rep} to {use_rep}. The {truncation}
151 // parameter is only used for checking - if the changer cannot figure
152 // out signedness for the word32->float64 conversion, then we check that the
153 // uses truncate to word32 (so they do not care about signedness).
GetRepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)154 Node* RepresentationChanger::GetRepresentationFor(
155 Node* node, MachineRepresentation output_rep, Type output_type,
156 Node* use_node, UseInfo use_info) {
157 if (output_rep == MachineRepresentation::kNone && !output_type.IsNone()) {
158 // The output representation should be set if the type is inhabited (i.e.,
159 // if the value is possible).
160 return TypeError(node, output_rep, output_type, use_info.representation());
161 }
162
163 // Rematerialize any truncated BigInt if user is not expecting a BigInt.
164 if (output_type.Is(Type::BigInt()) &&
165 output_rep == MachineRepresentation::kWord64 &&
166 use_info.type_check() != TypeCheckKind::kBigInt) {
167 node =
168 InsertConversion(node, simplified()->ChangeUint64ToBigInt(), use_node);
169 output_rep = MachineRepresentation::kTaggedPointer;
170 }
171
172 // Handle the no-op shortcuts when no checking is necessary.
173 if (use_info.type_check() == TypeCheckKind::kNone ||
174 // TODO(nicohartmann@, chromium:1077804): Ignoring {use_info.type_check()}
175 // in case the representation already matches is not correct. For now,
176 // this behavior is disabled only for TypeCheckKind::kBigInt, but should
177 // be fixed for all other type checks.
178 (output_rep != MachineRepresentation::kWord32 &&
179 use_info.type_check() != TypeCheckKind::kBigInt)) {
180 if (use_info.representation() == output_rep) {
181 // Representations are the same. That's a no-op.
182 return node;
183 }
184 if (IsWord(use_info.representation()) && IsWord(output_rep)) {
185 // Both are words less than or equal to 32-bits.
186 // Since loads of integers from memory implicitly sign or zero extend the
187 // value to the full machine word size and stores implicitly truncate,
188 // no representation change is necessary.
189 return node;
190 }
191 }
192
193 switch (use_info.representation()) {
194 case MachineRepresentation::kTaggedSigned:
195 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
196 use_info.type_check() == TypeCheckKind::kSignedSmall);
197 return GetTaggedSignedRepresentationFor(node, output_rep, output_type,
198 use_node, use_info);
199 case MachineRepresentation::kTaggedPointer:
200 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
201 use_info.type_check() == TypeCheckKind::kHeapObject ||
202 use_info.type_check() == TypeCheckKind::kBigInt);
203 return GetTaggedPointerRepresentationFor(node, output_rep, output_type,
204 use_node, use_info);
205 case MachineRepresentation::kTagged:
206 DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
207 return GetTaggedRepresentationFor(node, output_rep, output_type,
208 use_info.truncation());
209 case MachineRepresentation::kFloat32:
210 DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
211 return GetFloat32RepresentationFor(node, output_rep, output_type,
212 use_info.truncation());
213 case MachineRepresentation::kFloat64:
214 DCHECK_NE(TypeCheckKind::kBigInt, use_info.type_check());
215 return GetFloat64RepresentationFor(node, output_rep, output_type,
216 use_node, use_info);
217 case MachineRepresentation::kBit:
218 DCHECK_EQ(TypeCheckKind::kNone, use_info.type_check());
219 return GetBitRepresentationFor(node, output_rep, output_type);
220 case MachineRepresentation::kWord8:
221 case MachineRepresentation::kWord16:
222 case MachineRepresentation::kWord32:
223 return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
224 use_info);
225 case MachineRepresentation::kWord64:
226 DCHECK(use_info.type_check() == TypeCheckKind::kNone ||
227 use_info.type_check() == TypeCheckKind::kSigned64 ||
228 use_info.type_check() == TypeCheckKind::kBigInt ||
229 use_info.type_check() == TypeCheckKind::kArrayIndex);
230 return GetWord64RepresentationFor(node, output_rep, output_type, use_node,
231 use_info);
232 case MachineRepresentation::kSimd128:
233 case MachineRepresentation::kNone:
234 return node;
235 case MachineRepresentation::kCompressed:
236 case MachineRepresentation::kCompressedPointer:
237 UNREACHABLE();
238 }
239 UNREACHABLE();
240 }
241
GetTaggedSignedRepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)242 Node* RepresentationChanger::GetTaggedSignedRepresentationFor(
243 Node* node, MachineRepresentation output_rep, Type output_type,
244 Node* use_node, UseInfo use_info) {
245 // Eagerly fold representation changes for constants.
246 switch (node->opcode()) {
247 case IrOpcode::kNumberConstant:
248 if (output_type.Is(Type::SignedSmall())) {
249 return node;
250 }
251 break;
252 default:
253 break;
254 }
255 // Select the correct X -> Tagged operator.
256 const Operator* op;
257 if (output_type.Is(Type::None())) {
258 // This is an impossible value; it should not be used at runtime.
259 return jsgraph()->graph()->NewNode(
260 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedSigned),
261 node);
262 } else if (IsWord(output_rep)) {
263 if (output_type.Is(Type::Signed31())) {
264 op = simplified()->ChangeInt31ToTaggedSigned();
265 } else if (output_type.Is(Type::Signed32())) {
266 if (SmiValuesAre32Bits()) {
267 op = simplified()->ChangeInt32ToTagged();
268 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
269 op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
270 } else {
271 return TypeError(node, output_rep, output_type,
272 MachineRepresentation::kTaggedSigned);
273 }
274 } else if (output_type.Is(Type::Unsigned32()) &&
275 use_info.type_check() == TypeCheckKind::kSignedSmall) {
276 op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
277 } else {
278 return TypeError(node, output_rep, output_type,
279 MachineRepresentation::kTaggedSigned);
280 }
281 } else if (output_rep == MachineRepresentation::kWord64) {
282 if (output_type.Is(Type::Signed31())) {
283 // int64 -> int32 -> tagged signed
284 node = InsertTruncateInt64ToInt32(node);
285 op = simplified()->ChangeInt31ToTaggedSigned();
286 } else if (output_type.Is(Type::Signed32()) && SmiValuesAre32Bits()) {
287 // int64 -> int32 -> tagged signed
288 node = InsertTruncateInt64ToInt32(node);
289 op = simplified()->ChangeInt32ToTagged();
290 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
291 if (output_type.Is(cache_->kPositiveSafeInteger)) {
292 op = simplified()->CheckedUint64ToTaggedSigned(use_info.feedback());
293 } else if (output_type.Is(cache_->kSafeInteger)) {
294 op = simplified()->CheckedInt64ToTaggedSigned(use_info.feedback());
295 } else {
296 return TypeError(node, output_rep, output_type,
297 MachineRepresentation::kTaggedSigned);
298 }
299 } else {
300 return TypeError(node, output_rep, output_type,
301 MachineRepresentation::kTaggedSigned);
302 }
303 } else if (output_rep == MachineRepresentation::kFloat64) {
304 if (output_type.Is(Type::Signed31())) {
305 // float64 -> int32 -> tagged signed
306 node = InsertChangeFloat64ToInt32(node);
307 op = simplified()->ChangeInt31ToTaggedSigned();
308 } else if (output_type.Is(Type::Signed32())) {
309 // float64 -> int32 -> tagged signed
310 node = InsertChangeFloat64ToInt32(node);
311 if (SmiValuesAre32Bits()) {
312 op = simplified()->ChangeInt32ToTagged();
313 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
314 op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
315 } else {
316 return TypeError(node, output_rep, output_type,
317 MachineRepresentation::kTaggedSigned);
318 }
319 } else if (output_type.Is(Type::Unsigned32()) &&
320 use_info.type_check() == TypeCheckKind::kSignedSmall) {
321 // float64 -> uint32 -> tagged signed
322 node = InsertChangeFloat64ToUint32(node);
323 op = simplified()->CheckedUint32ToTaggedSigned(use_info.feedback());
324 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
325 node = InsertCheckedFloat64ToInt32(
326 node,
327 output_type.Maybe(Type::MinusZero())
328 ? CheckForMinusZeroMode::kCheckForMinusZero
329 : CheckForMinusZeroMode::kDontCheckForMinusZero,
330 use_info.feedback(), use_node);
331 if (SmiValuesAre32Bits()) {
332 op = simplified()->ChangeInt32ToTagged();
333 } else {
334 op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
335 }
336 } else {
337 return TypeError(node, output_rep, output_type,
338 MachineRepresentation::kTaggedSigned);
339 }
340 } else if (output_rep == MachineRepresentation::kFloat32) {
341 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
342 node = InsertChangeFloat32ToFloat64(node);
343 node = InsertCheckedFloat64ToInt32(
344 node,
345 output_type.Maybe(Type::MinusZero())
346 ? CheckForMinusZeroMode::kCheckForMinusZero
347 : CheckForMinusZeroMode::kDontCheckForMinusZero,
348 use_info.feedback(), use_node);
349 if (SmiValuesAre32Bits()) {
350 op = simplified()->ChangeInt32ToTagged();
351 } else {
352 op = simplified()->CheckedInt32ToTaggedSigned(use_info.feedback());
353 }
354 } else {
355 return TypeError(node, output_rep, output_type,
356 MachineRepresentation::kTaggedSigned);
357 }
358 } else if (CanBeTaggedPointer(output_rep)) {
359 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
360 op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
361 } else if (output_type.Is(Type::SignedSmall())) {
362 op = simplified()->ChangeTaggedToTaggedSigned();
363 } else {
364 return TypeError(node, output_rep, output_type,
365 MachineRepresentation::kTaggedSigned);
366 }
367 } else if (output_rep == MachineRepresentation::kBit) {
368 if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
369 // TODO(turbofan): Consider adding a Bailout operator that just deopts.
370 // Also use that for MachineRepresentation::kPointer case above.
371 node = InsertChangeBitToTagged(node);
372 op = simplified()->CheckedTaggedToTaggedSigned(use_info.feedback());
373 } else {
374 return TypeError(node, output_rep, output_type,
375 MachineRepresentation::kTaggedSigned);
376 }
377 } else {
378 return TypeError(node, output_rep, output_type,
379 MachineRepresentation::kTaggedSigned);
380 }
381 return InsertConversion(node, op, use_node);
382 }
383
GetTaggedPointerRepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)384 Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
385 Node* node, MachineRepresentation output_rep, Type output_type,
386 Node* use_node, UseInfo use_info) {
387 // Eagerly fold representation changes for constants.
388 switch (node->opcode()) {
389 case IrOpcode::kHeapConstant:
390 case IrOpcode::kDelayedStringConstant:
391 if (use_info.type_check() == TypeCheckKind::kBigInt) break;
392 return node; // No change necessary.
393 case IrOpcode::kInt32Constant:
394 case IrOpcode::kFloat64Constant:
395 case IrOpcode::kFloat32Constant:
396 UNREACHABLE();
397 default:
398 break;
399 }
400 // Select the correct X -> TaggedPointer operator.
401 Operator const* op;
402 if (output_type.Is(Type::None())) {
403 // This is an impossible value; it should not be used at runtime.
404 return jsgraph()->graph()->NewNode(
405 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
406 node);
407 }
408
409 if (use_info.type_check() == TypeCheckKind::kBigInt &&
410 !output_type.Is(Type::BigInt())) {
411 // BigInt checks can only be performed on tagged representations. Note that
412 // a corresponding check is inserted down below.
413 if (!CanBeTaggedPointer(output_rep)) {
414 Node* unreachable =
415 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotABigInt);
416 return jsgraph()->graph()->NewNode(
417 jsgraph()->common()->DeadValue(MachineRepresentation::kTaggedPointer),
418 unreachable);
419 }
420 }
421
422 if (output_rep == MachineRepresentation::kBit) {
423 if (output_type.Is(Type::Boolean())) {
424 op = simplified()->ChangeBitToTagged();
425 } else {
426 return TypeError(node, output_rep, output_type,
427 MachineRepresentation::kTagged);
428 }
429 } else if (IsWord(output_rep)) {
430 if (output_type.Is(Type::Unsigned32())) {
431 // uint32 -> float64 -> tagged
432 node = InsertChangeUint32ToFloat64(node);
433 } else if (output_type.Is(Type::Signed32())) {
434 // int32 -> float64 -> tagged
435 node = InsertChangeInt32ToFloat64(node);
436 } else {
437 return TypeError(node, output_rep, output_type,
438 MachineRepresentation::kTaggedPointer);
439 }
440 op = simplified()->ChangeFloat64ToTaggedPointer();
441 } else if (output_rep == MachineRepresentation::kWord64) {
442 if (output_type.Is(cache_->kSafeInteger)) {
443 // int64 -> float64 -> tagged pointer
444 op = machine()->ChangeInt64ToFloat64();
445 node = jsgraph()->graph()->NewNode(op, node);
446 op = simplified()->ChangeFloat64ToTaggedPointer();
447 } else if (output_type.Is(Type::BigInt()) &&
448 use_info.type_check() == TypeCheckKind::kBigInt) {
449 op = simplified()->ChangeUint64ToBigInt();
450 } else {
451 return TypeError(node, output_rep, output_type,
452 MachineRepresentation::kTaggedPointer);
453 }
454 } else if (output_rep == MachineRepresentation::kFloat32) {
455 if (output_type.Is(Type::Number())) {
456 // float32 -> float64 -> tagged
457 node = InsertChangeFloat32ToFloat64(node);
458 op = simplified()->ChangeFloat64ToTaggedPointer();
459 } else {
460 return TypeError(node, output_rep, output_type,
461 MachineRepresentation::kTaggedPointer);
462 }
463 } else if (output_rep == MachineRepresentation::kFloat64) {
464 if (output_type.Is(Type::Number())) {
465 // float64 -> tagged
466 op = simplified()->ChangeFloat64ToTaggedPointer();
467 } else {
468 return TypeError(node, output_rep, output_type,
469 MachineRepresentation::kTaggedPointer);
470 }
471 } else if (CanBeTaggedSigned(output_rep) &&
472 use_info.type_check() == TypeCheckKind::kHeapObject) {
473 if (!output_type.Maybe(Type::SignedSmall())) {
474 return node;
475 }
476 // TODO(turbofan): Consider adding a Bailout operator that just deopts
477 // for TaggedSigned output representation.
478 op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
479 } else if (IsAnyTagged(output_rep) &&
480 (use_info.type_check() == TypeCheckKind::kBigInt ||
481 output_type.Is(Type::BigInt()))) {
482 if (output_type.Is(Type::BigInt())) {
483 return node;
484 }
485 op = simplified()->CheckBigInt(use_info.feedback());
486 } else {
487 return TypeError(node, output_rep, output_type,
488 MachineRepresentation::kTaggedPointer);
489 }
490 return InsertConversion(node, op, use_node);
491 }
492
GetTaggedRepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Truncation truncation)493 Node* RepresentationChanger::GetTaggedRepresentationFor(
494 Node* node, MachineRepresentation output_rep, Type output_type,
495 Truncation truncation) {
496 // Eagerly fold representation changes for constants.
497 switch (node->opcode()) {
498 case IrOpcode::kNumberConstant:
499 case IrOpcode::kHeapConstant:
500 case IrOpcode::kDelayedStringConstant:
501 return node; // No change necessary.
502 case IrOpcode::kInt32Constant:
503 case IrOpcode::kFloat64Constant:
504 case IrOpcode::kFloat32Constant:
505 UNREACHABLE();
506 default:
507 break;
508 }
509 if (output_rep == MachineRepresentation::kTaggedSigned ||
510 output_rep == MachineRepresentation::kTaggedPointer) {
511 // this is a no-op.
512 return node;
513 }
514 // Select the correct X -> Tagged operator.
515 const Operator* op;
516 if (output_type.Is(Type::None())) {
517 // This is an impossible value; it should not be used at runtime.
518 return jsgraph()->graph()->NewNode(
519 jsgraph()->common()->DeadValue(MachineRepresentation::kTagged), node);
520 } else if (output_rep == MachineRepresentation::kBit) {
521 if (output_type.Is(Type::Boolean())) {
522 op = simplified()->ChangeBitToTagged();
523 } else {
524 return TypeError(node, output_rep, output_type,
525 MachineRepresentation::kTagged);
526 }
527 } else if (IsWord(output_rep)) {
528 if (output_type.Is(Type::Signed31())) {
529 op = simplified()->ChangeInt31ToTaggedSigned();
530 } else if (output_type.Is(Type::Signed32()) ||
531 (output_type.Is(Type::Signed32OrMinusZero()) &&
532 truncation.IdentifiesZeroAndMinusZero())) {
533 op = simplified()->ChangeInt32ToTagged();
534 } else if (output_type.Is(Type::Unsigned32()) ||
535 (output_type.Is(Type::Unsigned32OrMinusZero()) &&
536 truncation.IdentifiesZeroAndMinusZero()) ||
537 truncation.IsUsedAsWord32()) {
538 // Either the output is uint32 or the uses only care about the
539 // low 32 bits (so we can pick uint32 safely).
540 op = simplified()->ChangeUint32ToTagged();
541 } else {
542 return TypeError(node, output_rep, output_type,
543 MachineRepresentation::kTagged);
544 }
545 } else if (output_rep == MachineRepresentation::kWord64) {
546 if (output_type.Is(Type::Signed31())) {
547 // int64 -> int32 -> tagged signed
548 node = InsertTruncateInt64ToInt32(node);
549 op = simplified()->ChangeInt31ToTaggedSigned();
550 } else if (output_type.Is(Type::Signed32())) {
551 // int64 -> int32 -> tagged
552 node = InsertTruncateInt64ToInt32(node);
553 op = simplified()->ChangeInt32ToTagged();
554 } else if (output_type.Is(Type::Unsigned32())) {
555 // int64 -> uint32 -> tagged
556 node = InsertTruncateInt64ToInt32(node);
557 op = simplified()->ChangeUint32ToTagged();
558 } else if (output_type.Is(cache_->kPositiveSafeInteger)) {
559 // uint64 -> tagged
560 op = simplified()->ChangeUint64ToTagged();
561 } else if (output_type.Is(cache_->kSafeInteger)) {
562 // int64 -> tagged
563 op = simplified()->ChangeInt64ToTagged();
564 } else if (output_type.Is(Type::BigInt())) {
565 // uint64 -> BigInt
566 op = simplified()->ChangeUint64ToBigInt();
567 } else {
568 return TypeError(node, output_rep, output_type,
569 MachineRepresentation::kTagged);
570 }
571 } else if (output_rep ==
572 MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
573 node = InsertChangeFloat32ToFloat64(node);
574 op = simplified()->ChangeFloat64ToTagged(
575 output_type.Maybe(Type::MinusZero())
576 ? CheckForMinusZeroMode::kCheckForMinusZero
577 : CheckForMinusZeroMode::kDontCheckForMinusZero);
578 } else if (output_rep == MachineRepresentation::kFloat64) {
579 if (output_type.Is(Type::Signed31())) { // float64 -> int32 -> tagged
580 node = InsertChangeFloat64ToInt32(node);
581 op = simplified()->ChangeInt31ToTaggedSigned();
582 } else if (output_type.Is(
583 Type::Signed32())) { // float64 -> int32 -> tagged
584 node = InsertChangeFloat64ToInt32(node);
585 op = simplified()->ChangeInt32ToTagged();
586 } else if (output_type.Is(
587 Type::Unsigned32())) { // float64 -> uint32 -> tagged
588 node = InsertChangeFloat64ToUint32(node);
589 op = simplified()->ChangeUint32ToTagged();
590 } else if (output_type.Is(Type::Number()) ||
591 (output_type.Is(Type::NumberOrOddball()) &&
592 truncation.TruncatesOddballAndBigIntToNumber())) {
593 op = simplified()->ChangeFloat64ToTagged(
594 output_type.Maybe(Type::MinusZero())
595 ? CheckForMinusZeroMode::kCheckForMinusZero
596 : CheckForMinusZeroMode::kDontCheckForMinusZero);
597 } else {
598 return TypeError(node, output_rep, output_type,
599 MachineRepresentation::kTagged);
600 }
601 } else {
602 return TypeError(node, output_rep, output_type,
603 MachineRepresentation::kTagged);
604 }
605 return jsgraph()->graph()->NewNode(op, node);
606 }
607
GetFloat32RepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Truncation truncation)608 Node* RepresentationChanger::GetFloat32RepresentationFor(
609 Node* node, MachineRepresentation output_rep, Type output_type,
610 Truncation truncation) {
611 // Eagerly fold representation changes for constants.
612 switch (node->opcode()) {
613 case IrOpcode::kNumberConstant:
614 return jsgraph()->Float32Constant(
615 DoubleToFloat32(OpParameter<double>(node->op())));
616 case IrOpcode::kInt32Constant:
617 case IrOpcode::kFloat64Constant:
618 case IrOpcode::kFloat32Constant:
619 UNREACHABLE();
620 default:
621 break;
622 }
623 // Select the correct X -> Float32 operator.
624 const Operator* op = nullptr;
625 if (output_type.Is(Type::None())) {
626 // This is an impossible value; it should not be used at runtime.
627 return jsgraph()->graph()->NewNode(
628 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat32), node);
629 } else if (IsWord(output_rep)) {
630 if (output_type.Is(Type::Signed32())) {
631 // int32 -> float64 -> float32
632 op = machine()->ChangeInt32ToFloat64();
633 node = jsgraph()->graph()->NewNode(op, node);
634 op = machine()->TruncateFloat64ToFloat32();
635 } else if (output_type.Is(Type::Unsigned32()) ||
636 truncation.IsUsedAsWord32()) {
637 // Either the output is uint32 or the uses only care about the
638 // low 32 bits (so we can pick uint32 safely).
639
640 // uint32 -> float64 -> float32
641 op = machine()->ChangeUint32ToFloat64();
642 node = jsgraph()->graph()->NewNode(op, node);
643 op = machine()->TruncateFloat64ToFloat32();
644 }
645 } else if (IsAnyTagged(output_rep)) {
646 if (output_type.Is(Type::NumberOrOddball())) {
647 // tagged -> float64 -> float32
648 if (output_type.Is(Type::Number())) {
649 op = simplified()->ChangeTaggedToFloat64();
650 } else {
651 op = simplified()->TruncateTaggedToFloat64();
652 }
653 node = jsgraph()->graph()->NewNode(op, node);
654 op = machine()->TruncateFloat64ToFloat32();
655 }
656 } else if (output_rep == MachineRepresentation::kFloat64) {
657 op = machine()->TruncateFloat64ToFloat32();
658 } else if (output_rep == MachineRepresentation::kWord64) {
659 if (output_type.Is(cache_->kSafeInteger)) {
660 // int64 -> float64 -> float32
661 op = machine()->ChangeInt64ToFloat64();
662 node = jsgraph()->graph()->NewNode(op, node);
663 op = machine()->TruncateFloat64ToFloat32();
664 }
665 }
666 if (op == nullptr) {
667 return TypeError(node, output_rep, output_type,
668 MachineRepresentation::kFloat32);
669 }
670 return jsgraph()->graph()->NewNode(op, node);
671 }
672
GetFloat64RepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)673 Node* RepresentationChanger::GetFloat64RepresentationFor(
674 Node* node, MachineRepresentation output_rep, Type output_type,
675 Node* use_node, UseInfo use_info) {
676 NumberMatcher m(node);
677 if (m.HasResolvedValue()) {
678 // BigInts are not used as number constants.
679 DCHECK(use_info.type_check() != TypeCheckKind::kBigInt);
680 switch (use_info.type_check()) {
681 case TypeCheckKind::kNone:
682 case TypeCheckKind::kNumber:
683 case TypeCheckKind::kNumberOrBoolean:
684 case TypeCheckKind::kNumberOrOddball:
685 return jsgraph()->Float64Constant(m.ResolvedValue());
686 case TypeCheckKind::kBigInt:
687 case TypeCheckKind::kHeapObject:
688 case TypeCheckKind::kSigned32:
689 case TypeCheckKind::kSigned64:
690 case TypeCheckKind::kSignedSmall:
691 case TypeCheckKind::kArrayIndex:
692 break;
693 }
694 }
695 // Select the correct X -> Float64 operator.
696 const Operator* op = nullptr;
697 if (output_type.Is(Type::None())) {
698 // This is an impossible value; it should not be used at runtime.
699 return jsgraph()->graph()->NewNode(
700 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64), node);
701 } else if (IsWord(output_rep)) {
702 if (output_type.Is(Type::Signed32()) ||
703 (output_type.Is(Type::Signed32OrMinusZero()) &&
704 use_info.truncation().IdentifiesZeroAndMinusZero())) {
705 op = machine()->ChangeInt32ToFloat64();
706 } else if (output_type.Is(Type::Unsigned32()) ||
707 (output_type.Is(Type::Unsigned32OrMinusZero()) &&
708 use_info.truncation().IdentifiesZeroAndMinusZero()) ||
709 use_info.truncation().IsUsedAsWord32()) {
710 // Either the output is uint32 or the uses only care about the
711 // low 32 bits (so we can pick uint32 safely).
712 op = machine()->ChangeUint32ToFloat64();
713 }
714 } else if (output_rep == MachineRepresentation::kBit) {
715 CHECK(output_type.Is(Type::Boolean()));
716 if (use_info.truncation().TruncatesOddballAndBigIntToNumber() ||
717 use_info.type_check() == TypeCheckKind::kNumberOrBoolean ||
718 use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
719 op = machine()->ChangeUint32ToFloat64();
720 } else {
721 CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
722 Node* unreachable =
723 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotAHeapNumber);
724 return jsgraph()->graph()->NewNode(
725 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
726 unreachable);
727 }
728 } else if (IsAnyTagged(output_rep)) {
729 if (output_type.Is(Type::Undefined())) {
730 if (use_info.type_check() == TypeCheckKind::kNumberOrBoolean) {
731 Node* unreachable = InsertUnconditionalDeopt(
732 use_node, DeoptimizeReason::kNotANumberOrBoolean);
733 return jsgraph()->graph()->NewNode(
734 jsgraph()->common()->DeadValue(MachineRepresentation::kFloat64),
735 unreachable);
736 } else {
737 return jsgraph()->Float64Constant(
738 std::numeric_limits<double>::quiet_NaN());
739 }
740 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
741 node = InsertChangeTaggedSignedToInt32(node);
742 op = machine()->ChangeInt32ToFloat64();
743 } else if (output_type.Is(Type::Number())) {
744 op = simplified()->ChangeTaggedToFloat64();
745 } else if ((output_type.Is(Type::NumberOrOddball()) &&
746 use_info.truncation().TruncatesOddballAndBigIntToNumber()) ||
747 output_type.Is(Type::NumberOrHole())) {
748 // JavaScript 'null' is an Oddball that results in +0 when truncated to
749 // Number. In a context like -0 == null, which must evaluate to false,
750 // this truncation must not happen. For this reason we restrict this case
751 // to when either the user explicitly requested a float (and thus wants
752 // +0 if null is the input) or we know from the types that the input can
753 // only be Number | Hole. The latter is necessary to handle the operator
754 // CheckFloat64Hole. We did not put in the type (Number | Oddball \ Null)
755 // to discover more bugs related to this conversion via crashes.
756 op = simplified()->TruncateTaggedToFloat64();
757 } else if (use_info.type_check() == TypeCheckKind::kNumber ||
758 (use_info.type_check() == TypeCheckKind::kNumberOrOddball &&
759 !output_type.Maybe(Type::BooleanOrNullOrNumber()))) {
760 op = simplified()->CheckedTaggedToFloat64(CheckTaggedInputMode::kNumber,
761 use_info.feedback());
762 } else if (use_info.type_check() == TypeCheckKind::kNumberOrBoolean) {
763 op = simplified()->CheckedTaggedToFloat64(
764 CheckTaggedInputMode::kNumberOrBoolean, use_info.feedback());
765 } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
766 op = simplified()->CheckedTaggedToFloat64(
767 CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
768 }
769 } else if (output_rep == MachineRepresentation::kFloat32) {
770 op = machine()->ChangeFloat32ToFloat64();
771 } else if (output_rep == MachineRepresentation::kWord64) {
772 if (output_type.Is(cache_->kSafeInteger)) {
773 op = machine()->ChangeInt64ToFloat64();
774 }
775 }
776 if (op == nullptr) {
777 return TypeError(node, output_rep, output_type,
778 MachineRepresentation::kFloat64);
779 }
780 return InsertConversion(node, op, use_node);
781 }
782
MakeTruncatedInt32Constant(double value)783 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
784 return jsgraph()->Int32Constant(DoubleToInt32(value));
785 }
786
InsertUnconditionalDeopt(Node * node,DeoptimizeReason reason)787 Node* RepresentationChanger::InsertUnconditionalDeopt(Node* node,
788 DeoptimizeReason reason) {
789 Node* effect = NodeProperties::GetEffectInput(node);
790 Node* control = NodeProperties::GetControlInput(node);
791 effect =
792 jsgraph()->graph()->NewNode(simplified()->CheckIf(reason),
793 jsgraph()->Int32Constant(0), effect, control);
794 Node* unreachable = effect = jsgraph()->graph()->NewNode(
795 jsgraph()->common()->Unreachable(), effect, control);
796 NodeProperties::ReplaceEffectInput(node, effect);
797 return unreachable;
798 }
799
GetWord32RepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)800 Node* RepresentationChanger::GetWord32RepresentationFor(
801 Node* node, MachineRepresentation output_rep, Type output_type,
802 Node* use_node, UseInfo use_info) {
803 // Eagerly fold representation changes for constants.
804 switch (node->opcode()) {
805 case IrOpcode::kInt32Constant:
806 case IrOpcode::kInt64Constant:
807 case IrOpcode::kFloat32Constant:
808 case IrOpcode::kFloat64Constant:
809 UNREACHABLE();
810 case IrOpcode::kNumberConstant: {
811 double const fv = OpParameter<double>(node->op());
812 if (use_info.type_check() == TypeCheckKind::kNone ||
813 ((use_info.type_check() == TypeCheckKind::kSignedSmall ||
814 use_info.type_check() == TypeCheckKind::kSigned32 ||
815 use_info.type_check() == TypeCheckKind::kNumber ||
816 use_info.type_check() == TypeCheckKind::kNumberOrOddball ||
817 use_info.type_check() == TypeCheckKind::kArrayIndex) &&
818 IsInt32Double(fv))) {
819 return MakeTruncatedInt32Constant(fv);
820 }
821 break;
822 }
823 default:
824 break;
825 }
826
827 // Select the correct X -> Word32 operator.
828 const Operator* op = nullptr;
829 if (output_type.Is(Type::None())) {
830 // This is an impossible value; it should not be used at runtime.
831 return jsgraph()->graph()->NewNode(
832 jsgraph()->common()->DeadValue(MachineRepresentation::kWord32), node);
833 } else if (output_rep == MachineRepresentation::kBit) {
834 CHECK(output_type.Is(Type::Boolean()));
835 if (use_info.truncation().IsUsedAsWord32()) {
836 return node;
837 } else {
838 CHECK(Truncation::Any(kIdentifyZeros)
839 .IsLessGeneralThan(use_info.truncation()));
840 CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
841 CHECK_NE(use_info.type_check(), TypeCheckKind::kNumberOrOddball);
842 Node* unreachable =
843 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
844 return jsgraph()->graph()->NewNode(
845 jsgraph()->common()->DeadValue(MachineRepresentation::kWord32),
846 unreachable);
847 }
848 } else if (output_rep == MachineRepresentation::kFloat64) {
849 if (output_type.Is(Type::Signed32())) {
850 op = machine()->ChangeFloat64ToInt32();
851 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
852 use_info.type_check() == TypeCheckKind::kSigned32 ||
853 use_info.type_check() == TypeCheckKind::kArrayIndex) {
854 op = simplified()->CheckedFloat64ToInt32(
855 output_type.Maybe(Type::MinusZero())
856 ? use_info.minus_zero_check()
857 : CheckForMinusZeroMode::kDontCheckForMinusZero,
858 use_info.feedback());
859 } else if (output_type.Is(Type::Unsigned32())) {
860 op = machine()->ChangeFloat64ToUint32();
861 } else if (use_info.truncation().IsUsedAsWord32()) {
862 op = machine()->TruncateFloat64ToWord32();
863 } else {
864 return TypeError(node, output_rep, output_type,
865 MachineRepresentation::kWord32);
866 }
867 } else if (output_rep == MachineRepresentation::kFloat32) {
868 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
869 if (output_type.Is(Type::Signed32())) {
870 op = machine()->ChangeFloat64ToInt32();
871 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
872 use_info.type_check() == TypeCheckKind::kSigned32 ||
873 use_info.type_check() == TypeCheckKind::kArrayIndex) {
874 op = simplified()->CheckedFloat64ToInt32(
875 output_type.Maybe(Type::MinusZero())
876 ? use_info.minus_zero_check()
877 : CheckForMinusZeroMode::kDontCheckForMinusZero,
878 use_info.feedback());
879 } else if (output_type.Is(Type::Unsigned32())) {
880 op = machine()->ChangeFloat64ToUint32();
881 } else if (use_info.truncation().IsUsedAsWord32()) {
882 op = machine()->TruncateFloat64ToWord32();
883 } else {
884 return TypeError(node, output_rep, output_type,
885 MachineRepresentation::kWord32);
886 }
887 } else if (IsAnyTagged(output_rep)) {
888 if (output_rep == MachineRepresentation::kTaggedSigned &&
889 output_type.Is(Type::SignedSmall())) {
890 op = simplified()->ChangeTaggedSignedToInt32();
891 } else if (output_type.Is(Type::Signed32())) {
892 op = simplified()->ChangeTaggedToInt32();
893 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) {
894 op = simplified()->CheckedTaggedSignedToInt32(use_info.feedback());
895 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
896 op = simplified()->CheckedTaggedToInt32(
897 output_type.Maybe(Type::MinusZero())
898 ? use_info.minus_zero_check()
899 : CheckForMinusZeroMode::kDontCheckForMinusZero,
900 use_info.feedback());
901 } else if (use_info.type_check() == TypeCheckKind::kArrayIndex) {
902 op = simplified()->CheckedTaggedToArrayIndex(use_info.feedback());
903 } else if (output_type.Is(Type::Unsigned32())) {
904 op = simplified()->ChangeTaggedToUint32();
905 } else if (use_info.truncation().IsUsedAsWord32()) {
906 if (output_type.Is(Type::NumberOrOddball())) {
907 op = simplified()->TruncateTaggedToWord32();
908 } else if (use_info.type_check() == TypeCheckKind::kNumber) {
909 op = simplified()->CheckedTruncateTaggedToWord32(
910 CheckTaggedInputMode::kNumber, use_info.feedback());
911 } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
912 op = simplified()->CheckedTruncateTaggedToWord32(
913 CheckTaggedInputMode::kNumberOrOddball, use_info.feedback());
914 } else {
915 return TypeError(node, output_rep, output_type,
916 MachineRepresentation::kWord32);
917 }
918 } else {
919 return TypeError(node, output_rep, output_type,
920 MachineRepresentation::kWord32);
921 }
922 } else if (output_rep == MachineRepresentation::kWord32) {
923 // Only the checked case should get here, the non-checked case is
924 // handled in GetRepresentationFor.
925 if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
926 use_info.type_check() == TypeCheckKind::kSigned32 ||
927 use_info.type_check() == TypeCheckKind::kArrayIndex) {
928 bool identify_zeros = use_info.truncation().IdentifiesZeroAndMinusZero();
929 if (output_type.Is(Type::Signed32()) ||
930 (identify_zeros && output_type.Is(Type::Signed32OrMinusZero()))) {
931 return node;
932 } else if (output_type.Is(Type::Unsigned32()) ||
933 (identify_zeros &&
934 output_type.Is(Type::Unsigned32OrMinusZero()))) {
935 op = simplified()->CheckedUint32ToInt32(use_info.feedback());
936 } else {
937 return TypeError(node, output_rep, output_type,
938 MachineRepresentation::kWord32);
939 }
940 } else if (use_info.type_check() == TypeCheckKind::kNumber ||
941 use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
942 return node;
943 }
944 } else if (output_rep == MachineRepresentation::kWord8 ||
945 output_rep == MachineRepresentation::kWord16) {
946 DCHECK_EQ(MachineRepresentation::kWord32, use_info.representation());
947 DCHECK(use_info.type_check() == TypeCheckKind::kSignedSmall ||
948 use_info.type_check() == TypeCheckKind::kSigned32);
949 return node;
950 } else if (output_rep == MachineRepresentation::kWord64) {
951 if (output_type.Is(Type::Signed32()) ||
952 output_type.Is(Type::Unsigned32())) {
953 op = machine()->TruncateInt64ToInt32();
954 } else if (output_type.Is(cache_->kSafeInteger) &&
955 use_info.truncation().IsUsedAsWord32()) {
956 op = machine()->TruncateInt64ToInt32();
957 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall ||
958 use_info.type_check() == TypeCheckKind::kSigned32 ||
959 use_info.type_check() == TypeCheckKind::kArrayIndex) {
960 if (output_type.Is(cache_->kPositiveSafeInteger)) {
961 op = simplified()->CheckedUint64ToInt32(use_info.feedback());
962 } else if (output_type.Is(cache_->kSafeInteger)) {
963 op = simplified()->CheckedInt64ToInt32(use_info.feedback());
964 } else {
965 return TypeError(node, output_rep, output_type,
966 MachineRepresentation::kWord32);
967 }
968 } else {
969 return TypeError(node, output_rep, output_type,
970 MachineRepresentation::kWord32);
971 }
972 }
973
974 if (op == nullptr) {
975 return TypeError(node, output_rep, output_type,
976 MachineRepresentation::kWord32);
977 }
978 return InsertConversion(node, op, use_node);
979 }
980
InsertConversion(Node * node,const Operator * op,Node * use_node)981 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
982 Node* use_node) {
983 if (op->ControlInputCount() > 0) {
984 // If the operator can deoptimize (which means it has control
985 // input), we need to connect it to the effect and control chains.
986 Node* effect = NodeProperties::GetEffectInput(use_node);
987 Node* control = NodeProperties::GetControlInput(use_node);
988 Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
989 NodeProperties::ReplaceEffectInput(use_node, conversion);
990 return conversion;
991 }
992 return jsgraph()->graph()->NewNode(op, node);
993 }
994
GetBitRepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type)995 Node* RepresentationChanger::GetBitRepresentationFor(
996 Node* node, MachineRepresentation output_rep, Type output_type) {
997 // Eagerly fold representation changes for constants.
998 switch (node->opcode()) {
999 case IrOpcode::kHeapConstant: {
1000 HeapObjectMatcher m(node);
1001 if (m.Is(factory()->false_value())) {
1002 return jsgraph()->Int32Constant(0);
1003 } else if (m.Is(factory()->true_value())) {
1004 return jsgraph()->Int32Constant(1);
1005 }
1006 break;
1007 }
1008 default:
1009 break;
1010 }
1011 // Select the correct X -> Bit operator.
1012 const Operator* op;
1013 if (output_type.Is(Type::None())) {
1014 // This is an impossible value; it should not be used at runtime.
1015 return jsgraph()->graph()->NewNode(
1016 jsgraph()->common()->DeadValue(MachineRepresentation::kBit), node);
1017 } else if (output_rep == MachineRepresentation::kTagged ||
1018 output_rep == MachineRepresentation::kTaggedPointer) {
1019 if (output_type.Is(Type::BooleanOrNullOrUndefined())) {
1020 // true is the only trueish Oddball.
1021 op = simplified()->ChangeTaggedToBit();
1022 } else {
1023 if (output_rep == MachineRepresentation::kTagged &&
1024 output_type.Maybe(Type::SignedSmall())) {
1025 op = simplified()->TruncateTaggedToBit();
1026 } else {
1027 // The {output_type} either doesn't include the Smi range,
1028 // or the {output_rep} is known to be TaggedPointer.
1029 op = simplified()->TruncateTaggedPointerToBit();
1030 }
1031 }
1032 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1033 if (COMPRESS_POINTERS_BOOL) {
1034 node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1035 jsgraph()->Int32Constant(0));
1036 } else {
1037 node = jsgraph()->graph()->NewNode(machine()->WordEqual(), node,
1038 jsgraph()->IntPtrConstant(0));
1039 }
1040 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1041 jsgraph()->Int32Constant(0));
1042 } else if (IsWord(output_rep)) {
1043 node = jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1044 jsgraph()->Int32Constant(0));
1045 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1046 jsgraph()->Int32Constant(0));
1047 } else if (output_rep == MachineRepresentation::kWord64) {
1048 node = jsgraph()->graph()->NewNode(machine()->Word64Equal(), node,
1049 jsgraph()->Int64Constant(0));
1050 return jsgraph()->graph()->NewNode(machine()->Word32Equal(), node,
1051 jsgraph()->Int32Constant(0));
1052 } else if (output_rep == MachineRepresentation::kFloat32) {
1053 node = jsgraph()->graph()->NewNode(machine()->Float32Abs(), node);
1054 return jsgraph()->graph()->NewNode(machine()->Float32LessThan(),
1055 jsgraph()->Float32Constant(0.0), node);
1056 } else if (output_rep == MachineRepresentation::kFloat64) {
1057 node = jsgraph()->graph()->NewNode(machine()->Float64Abs(), node);
1058 return jsgraph()->graph()->NewNode(machine()->Float64LessThan(),
1059 jsgraph()->Float64Constant(0.0), node);
1060 } else {
1061 return TypeError(node, output_rep, output_type,
1062 MachineRepresentation::kBit);
1063 }
1064 return jsgraph()->graph()->NewNode(op, node);
1065 }
1066
GetWord64RepresentationFor(Node * node,MachineRepresentation output_rep,Type output_type,Node * use_node,UseInfo use_info)1067 Node* RepresentationChanger::GetWord64RepresentationFor(
1068 Node* node, MachineRepresentation output_rep, Type output_type,
1069 Node* use_node, UseInfo use_info) {
1070 // Eagerly fold representation changes for constants.
1071 switch (node->opcode()) {
1072 case IrOpcode::kInt32Constant:
1073 case IrOpcode::kInt64Constant:
1074 case IrOpcode::kFloat32Constant:
1075 case IrOpcode::kFloat64Constant:
1076 UNREACHABLE();
1077 case IrOpcode::kNumberConstant: {
1078 if (use_info.type_check() != TypeCheckKind::kBigInt) {
1079 double const fv = OpParameter<double>(node->op());
1080 using limits = std::numeric_limits<int64_t>;
1081 if (fv <= limits::max() && fv >= limits::min()) {
1082 int64_t const iv = static_cast<int64_t>(fv);
1083 if (static_cast<double>(iv) == fv) {
1084 return jsgraph()->Int64Constant(iv);
1085 }
1086 }
1087 }
1088 break;
1089 }
1090 case IrOpcode::kHeapConstant: {
1091 HeapObjectMatcher m(node);
1092 if (m.HasResolvedValue() && m.Ref(broker_).IsBigInt() &&
1093 use_info.truncation().IsUsedAsWord64()) {
1094 auto bigint = m.Ref(broker_).AsBigInt();
1095 return jsgraph()->Int64Constant(
1096 static_cast<int64_t>(bigint.AsUint64()));
1097 }
1098 break;
1099 }
1100 default:
1101 break;
1102 }
1103
1104 if (use_info.type_check() == TypeCheckKind::kBigInt) {
1105 // BigInts are only represented as tagged pointer and word64.
1106 if (!CanBeTaggedPointer(output_rep) &&
1107 output_rep != MachineRepresentation::kWord64) {
1108 DCHECK(!output_type.Is(Type::BigInt()));
1109 Node* unreachable =
1110 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotABigInt);
1111 return jsgraph()->graph()->NewNode(
1112 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1113 unreachable);
1114 }
1115 }
1116
1117 // Select the correct X -> Word64 operator.
1118 const Operator* op;
1119 if (output_type.Is(Type::None())) {
1120 // This is an impossible value; it should not be used at runtime.
1121 return jsgraph()->graph()->NewNode(
1122 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64), node);
1123 } else if (output_rep == MachineRepresentation::kBit) {
1124 CHECK(output_type.Is(Type::Boolean()));
1125 CHECK_NE(use_info.type_check(), TypeCheckKind::kNone);
1126 CHECK_NE(use_info.type_check(), TypeCheckKind::kNumberOrOddball);
1127 CHECK_NE(use_info.type_check(), TypeCheckKind::kBigInt);
1128 Node* unreachable =
1129 InsertUnconditionalDeopt(use_node, DeoptimizeReason::kNotASmi);
1130 return jsgraph()->graph()->NewNode(
1131 jsgraph()->common()->DeadValue(MachineRepresentation::kWord64),
1132 unreachable);
1133 } else if (IsWord(output_rep)) {
1134 if (output_type.Is(Type::Unsigned32OrMinusZero())) {
1135 // uint32 -> uint64
1136 CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
1137 use_info.truncation().IdentifiesZeroAndMinusZero());
1138 op = machine()->ChangeUint32ToUint64();
1139 } else if (output_type.Is(Type::Signed32OrMinusZero())) {
1140 // int32 -> int64
1141 CHECK_IMPLIES(output_type.Maybe(Type::MinusZero()),
1142 use_info.truncation().IdentifiesZeroAndMinusZero());
1143 op = machine()->ChangeInt32ToInt64();
1144 } else {
1145 return TypeError(node, output_rep, output_type,
1146 MachineRepresentation::kWord64);
1147 }
1148 } else if (output_rep == MachineRepresentation::kFloat32) {
1149 if (output_type.Is(cache_->kInt64)) {
1150 // float32 -> float64 -> int64
1151 node = InsertChangeFloat32ToFloat64(node);
1152 op = machine()->ChangeFloat64ToInt64();
1153 } else if (output_type.Is(cache_->kUint64)) {
1154 // float32 -> float64 -> uint64
1155 node = InsertChangeFloat32ToFloat64(node);
1156 op = machine()->ChangeFloat64ToUint64();
1157 } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
1158 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1159 // float32 -> float64 -> int64
1160 node = InsertChangeFloat32ToFloat64(node);
1161 op = simplified()->CheckedFloat64ToInt64(
1162 output_type.Maybe(Type::MinusZero())
1163 ? use_info.minus_zero_check()
1164 : CheckForMinusZeroMode::kDontCheckForMinusZero,
1165 use_info.feedback());
1166 } else {
1167 return TypeError(node, output_rep, output_type,
1168 MachineRepresentation::kWord64);
1169 }
1170 } else if (output_rep == MachineRepresentation::kFloat64) {
1171 if (output_type.Is(cache_->kInt64)) {
1172 op = machine()->ChangeFloat64ToInt64();
1173 } else if (output_type.Is(cache_->kUint64)) {
1174 op = machine()->ChangeFloat64ToUint64();
1175 } else if (use_info.type_check() == TypeCheckKind::kSigned64 ||
1176 use_info.type_check() == TypeCheckKind::kArrayIndex) {
1177 op = simplified()->CheckedFloat64ToInt64(
1178 output_type.Maybe(Type::MinusZero())
1179 ? use_info.minus_zero_check()
1180 : CheckForMinusZeroMode::kDontCheckForMinusZero,
1181 use_info.feedback());
1182 } else {
1183 return TypeError(node, output_rep, output_type,
1184 MachineRepresentation::kWord64);
1185 }
1186 } else if (output_rep == MachineRepresentation::kTaggedSigned) {
1187 if (output_type.Is(Type::SignedSmall())) {
1188 op = simplified()->ChangeTaggedSignedToInt64();
1189 } else {
1190 return TypeError(node, output_rep, output_type,
1191 MachineRepresentation::kWord64);
1192 }
1193 } else if (IsAnyTagged(output_rep) &&
1194 use_info.truncation().IsUsedAsWord64() &&
1195 (use_info.type_check() == TypeCheckKind::kBigInt ||
1196 output_type.Is(Type::BigInt()))) {
1197 node = GetTaggedPointerRepresentationFor(node, output_rep, output_type,
1198 use_node, use_info);
1199 op = simplified()->TruncateBigIntToUint64();
1200 } else if (CanBeTaggedPointer(output_rep)) {
1201 if (output_type.Is(cache_->kInt64)) {
1202 op = simplified()->ChangeTaggedToInt64();
1203 } else if (use_info.type_check() == TypeCheckKind::kSigned64) {
1204 op = simplified()->CheckedTaggedToInt64(
1205 output_type.Maybe(Type::MinusZero())
1206 ? use_info.minus_zero_check()
1207 : CheckForMinusZeroMode::kDontCheckForMinusZero,
1208 use_info.feedback());
1209 } else if (use_info.type_check() == TypeCheckKind::kArrayIndex) {
1210 op = simplified()->CheckedTaggedToArrayIndex(use_info.feedback());
1211 } else {
1212 return TypeError(node, output_rep, output_type,
1213 MachineRepresentation::kWord64);
1214 }
1215 } else if (output_rep == MachineRepresentation::kWord64) {
1216 DCHECK_EQ(use_info.type_check(), TypeCheckKind::kBigInt);
1217 if (output_type.Is(Type::BigInt())) {
1218 return node;
1219 } else {
1220 return TypeError(node, output_rep, output_type,
1221 MachineRepresentation::kWord64);
1222 }
1223 } else {
1224 return TypeError(node, output_rep, output_type,
1225 MachineRepresentation::kWord64);
1226 }
1227 return InsertConversion(node, op, use_node);
1228 }
1229
Int32OperatorFor(IrOpcode::Value opcode)1230 const Operator* RepresentationChanger::Int32OperatorFor(
1231 IrOpcode::Value opcode) {
1232 switch (opcode) {
1233 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1234 case IrOpcode::kSpeculativeSafeIntegerAdd:
1235 case IrOpcode::kNumberAdd:
1236 return machine()->Int32Add();
1237 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1238 case IrOpcode::kSpeculativeSafeIntegerSubtract:
1239 case IrOpcode::kNumberSubtract:
1240 return machine()->Int32Sub();
1241 case IrOpcode::kSpeculativeNumberMultiply:
1242 case IrOpcode::kNumberMultiply:
1243 return machine()->Int32Mul();
1244 case IrOpcode::kSpeculativeNumberDivide:
1245 case IrOpcode::kNumberDivide:
1246 return machine()->Int32Div();
1247 case IrOpcode::kSpeculativeNumberModulus:
1248 case IrOpcode::kNumberModulus:
1249 return machine()->Int32Mod();
1250 case IrOpcode::kSpeculativeNumberBitwiseOr: // Fall through.
1251 case IrOpcode::kNumberBitwiseOr:
1252 return machine()->Word32Or();
1253 case IrOpcode::kSpeculativeNumberBitwiseXor: // Fall through.
1254 case IrOpcode::kNumberBitwiseXor:
1255 return machine()->Word32Xor();
1256 case IrOpcode::kSpeculativeNumberBitwiseAnd: // Fall through.
1257 case IrOpcode::kNumberBitwiseAnd:
1258 return machine()->Word32And();
1259 case IrOpcode::kNumberEqual:
1260 case IrOpcode::kSpeculativeNumberEqual:
1261 return machine()->Word32Equal();
1262 case IrOpcode::kNumberLessThan:
1263 case IrOpcode::kSpeculativeNumberLessThan:
1264 return machine()->Int32LessThan();
1265 case IrOpcode::kNumberLessThanOrEqual:
1266 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1267 return machine()->Int32LessThanOrEqual();
1268 default:
1269 UNREACHABLE();
1270 }
1271 }
1272
Int32OverflowOperatorFor(IrOpcode::Value opcode)1273 const Operator* RepresentationChanger::Int32OverflowOperatorFor(
1274 IrOpcode::Value opcode) {
1275 switch (opcode) {
1276 case IrOpcode::kSpeculativeSafeIntegerAdd:
1277 return simplified()->CheckedInt32Add();
1278 case IrOpcode::kSpeculativeSafeIntegerSubtract:
1279 return simplified()->CheckedInt32Sub();
1280 case IrOpcode::kSpeculativeNumberDivide:
1281 return simplified()->CheckedInt32Div();
1282 case IrOpcode::kSpeculativeNumberModulus:
1283 return simplified()->CheckedInt32Mod();
1284 default:
1285 UNREACHABLE();
1286 }
1287 }
1288
Int64OperatorFor(IrOpcode::Value opcode)1289 const Operator* RepresentationChanger::Int64OperatorFor(
1290 IrOpcode::Value opcode) {
1291 switch (opcode) {
1292 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
1293 case IrOpcode::kSpeculativeSafeIntegerAdd:
1294 case IrOpcode::kNumberAdd:
1295 return machine()->Int64Add();
1296 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
1297 case IrOpcode::kSpeculativeSafeIntegerSubtract:
1298 case IrOpcode::kNumberSubtract:
1299 return machine()->Int64Sub();
1300 default:
1301 UNREACHABLE();
1302 }
1303 }
1304
TaggedSignedOperatorFor(IrOpcode::Value opcode)1305 const Operator* RepresentationChanger::TaggedSignedOperatorFor(
1306 IrOpcode::Value opcode) {
1307 switch (opcode) {
1308 case IrOpcode::kSpeculativeNumberLessThan:
1309 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1310 ? machine()->Int32LessThan()
1311 : machine()->Int64LessThan();
1312 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1313 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1314 ? machine()->Int32LessThanOrEqual()
1315 : machine()->Int64LessThanOrEqual();
1316 case IrOpcode::kSpeculativeNumberEqual:
1317 return (COMPRESS_POINTERS_BOOL || machine()->Is32())
1318 ? machine()->Word32Equal()
1319 : machine()->Word64Equal();
1320 default:
1321 UNREACHABLE();
1322 }
1323 }
1324
Uint32OperatorFor(IrOpcode::Value opcode)1325 const Operator* RepresentationChanger::Uint32OperatorFor(
1326 IrOpcode::Value opcode) {
1327 switch (opcode) {
1328 case IrOpcode::kNumberAdd:
1329 return machine()->Int32Add();
1330 case IrOpcode::kNumberSubtract:
1331 return machine()->Int32Sub();
1332 case IrOpcode::kSpeculativeNumberMultiply:
1333 case IrOpcode::kNumberMultiply:
1334 return machine()->Int32Mul();
1335 case IrOpcode::kSpeculativeNumberDivide:
1336 case IrOpcode::kNumberDivide:
1337 return machine()->Uint32Div();
1338 case IrOpcode::kSpeculativeNumberModulus:
1339 case IrOpcode::kNumberModulus:
1340 return machine()->Uint32Mod();
1341 case IrOpcode::kNumberEqual:
1342 case IrOpcode::kSpeculativeNumberEqual:
1343 return machine()->Word32Equal();
1344 case IrOpcode::kNumberLessThan:
1345 case IrOpcode::kSpeculativeNumberLessThan:
1346 return machine()->Uint32LessThan();
1347 case IrOpcode::kNumberLessThanOrEqual:
1348 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1349 return machine()->Uint32LessThanOrEqual();
1350 case IrOpcode::kNumberClz32:
1351 return machine()->Word32Clz();
1352 case IrOpcode::kNumberImul:
1353 return machine()->Int32Mul();
1354 default:
1355 UNREACHABLE();
1356 }
1357 }
1358
Uint32OverflowOperatorFor(IrOpcode::Value opcode)1359 const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
1360 IrOpcode::Value opcode) {
1361 switch (opcode) {
1362 case IrOpcode::kSpeculativeNumberDivide:
1363 return simplified()->CheckedUint32Div();
1364 case IrOpcode::kSpeculativeNumberModulus:
1365 return simplified()->CheckedUint32Mod();
1366 default:
1367 UNREACHABLE();
1368 }
1369 }
1370
Float64OperatorFor(IrOpcode::Value opcode)1371 const Operator* RepresentationChanger::Float64OperatorFor(
1372 IrOpcode::Value opcode) {
1373 switch (opcode) {
1374 case IrOpcode::kSpeculativeNumberAdd:
1375 case IrOpcode::kSpeculativeSafeIntegerAdd:
1376 case IrOpcode::kNumberAdd:
1377 return machine()->Float64Add();
1378 case IrOpcode::kSpeculativeNumberSubtract:
1379 case IrOpcode::kSpeculativeSafeIntegerSubtract:
1380 case IrOpcode::kNumberSubtract:
1381 return machine()->Float64Sub();
1382 case IrOpcode::kSpeculativeNumberMultiply:
1383 case IrOpcode::kNumberMultiply:
1384 return machine()->Float64Mul();
1385 case IrOpcode::kSpeculativeNumberDivide:
1386 case IrOpcode::kNumberDivide:
1387 return machine()->Float64Div();
1388 case IrOpcode::kSpeculativeNumberModulus:
1389 case IrOpcode::kNumberModulus:
1390 return machine()->Float64Mod();
1391 case IrOpcode::kNumberEqual:
1392 case IrOpcode::kSpeculativeNumberEqual:
1393 return machine()->Float64Equal();
1394 case IrOpcode::kNumberLessThan:
1395 case IrOpcode::kSpeculativeNumberLessThan:
1396 return machine()->Float64LessThan();
1397 case IrOpcode::kNumberLessThanOrEqual:
1398 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1399 return machine()->Float64LessThanOrEqual();
1400 case IrOpcode::kNumberAbs:
1401 return machine()->Float64Abs();
1402 case IrOpcode::kNumberAcos:
1403 return machine()->Float64Acos();
1404 case IrOpcode::kNumberAcosh:
1405 return machine()->Float64Acosh();
1406 case IrOpcode::kNumberAsin:
1407 return machine()->Float64Asin();
1408 case IrOpcode::kNumberAsinh:
1409 return machine()->Float64Asinh();
1410 case IrOpcode::kNumberAtan:
1411 return machine()->Float64Atan();
1412 case IrOpcode::kNumberAtanh:
1413 return machine()->Float64Atanh();
1414 case IrOpcode::kNumberAtan2:
1415 return machine()->Float64Atan2();
1416 case IrOpcode::kNumberCbrt:
1417 return machine()->Float64Cbrt();
1418 case IrOpcode::kNumberCeil:
1419 return machine()->Float64RoundUp().placeholder();
1420 case IrOpcode::kNumberCos:
1421 return machine()->Float64Cos();
1422 case IrOpcode::kNumberCosh:
1423 return machine()->Float64Cosh();
1424 case IrOpcode::kNumberExp:
1425 return machine()->Float64Exp();
1426 case IrOpcode::kNumberExpm1:
1427 return machine()->Float64Expm1();
1428 case IrOpcode::kNumberFloor:
1429 return machine()->Float64RoundDown().placeholder();
1430 case IrOpcode::kNumberFround:
1431 return machine()->TruncateFloat64ToFloat32();
1432 case IrOpcode::kNumberLog:
1433 return machine()->Float64Log();
1434 case IrOpcode::kNumberLog1p:
1435 return machine()->Float64Log1p();
1436 case IrOpcode::kNumberLog2:
1437 return machine()->Float64Log2();
1438 case IrOpcode::kNumberLog10:
1439 return machine()->Float64Log10();
1440 case IrOpcode::kNumberMax:
1441 return machine()->Float64Max();
1442 case IrOpcode::kNumberMin:
1443 return machine()->Float64Min();
1444 case IrOpcode::kNumberPow:
1445 return machine()->Float64Pow();
1446 case IrOpcode::kNumberSin:
1447 return machine()->Float64Sin();
1448 case IrOpcode::kNumberSinh:
1449 return machine()->Float64Sinh();
1450 case IrOpcode::kNumberSqrt:
1451 return machine()->Float64Sqrt();
1452 case IrOpcode::kNumberTan:
1453 return machine()->Float64Tan();
1454 case IrOpcode::kNumberTanh:
1455 return machine()->Float64Tanh();
1456 case IrOpcode::kNumberTrunc:
1457 return machine()->Float64RoundTruncate().placeholder();
1458 case IrOpcode::kNumberSilenceNaN:
1459 return machine()->Float64SilenceNaN();
1460 default:
1461 UNREACHABLE();
1462 }
1463 }
1464
TypeError(Node * node,MachineRepresentation output_rep,Type output_type,MachineRepresentation use)1465 Node* RepresentationChanger::TypeError(Node* node,
1466 MachineRepresentation output_rep,
1467 Type output_type,
1468 MachineRepresentation use) {
1469 type_error_ = true;
1470 if (!testing_type_errors_) {
1471 std::ostringstream out_str;
1472 out_str << output_rep << " (";
1473 output_type.PrintTo(out_str);
1474 out_str << ")";
1475
1476 std::ostringstream use_str;
1477 use_str << use;
1478
1479 FATAL(
1480 "RepresentationChangerError: node #%d:%s of "
1481 "%s cannot be changed to %s",
1482 node->id(), node->op()->mnemonic(), out_str.str().c_str(),
1483 use_str.str().c_str());
1484 }
1485 return node;
1486 }
1487
InsertChangeBitToTagged(Node * node)1488 Node* RepresentationChanger::InsertChangeBitToTagged(Node* node) {
1489 return jsgraph()->graph()->NewNode(simplified()->ChangeBitToTagged(), node);
1490 }
1491
InsertChangeFloat32ToFloat64(Node * node)1492 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
1493 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
1494 }
1495
InsertChangeFloat64ToUint32(Node * node)1496 Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
1497 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
1498 }
1499
InsertChangeFloat64ToInt32(Node * node)1500 Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
1501 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
1502 }
1503
InsertChangeInt32ToFloat64(Node * node)1504 Node* RepresentationChanger::InsertChangeInt32ToFloat64(Node* node) {
1505 return jsgraph()->graph()->NewNode(machine()->ChangeInt32ToFloat64(), node);
1506 }
1507
InsertChangeTaggedSignedToInt32(Node * node)1508 Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
1509 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
1510 node);
1511 }
1512
InsertChangeTaggedToFloat64(Node * node)1513 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
1514 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
1515 node);
1516 }
1517
InsertChangeUint32ToFloat64(Node * node)1518 Node* RepresentationChanger::InsertChangeUint32ToFloat64(Node* node) {
1519 return jsgraph()->graph()->NewNode(machine()->ChangeUint32ToFloat64(), node);
1520 }
1521
InsertTruncateInt64ToInt32(Node * node)1522 Node* RepresentationChanger::InsertTruncateInt64ToInt32(Node* node) {
1523 return jsgraph()->graph()->NewNode(machine()->TruncateInt64ToInt32(), node);
1524 }
1525
InsertCheckedFloat64ToInt32(Node * node,CheckForMinusZeroMode check,const FeedbackSource & feedback,Node * use_node)1526 Node* RepresentationChanger::InsertCheckedFloat64ToInt32(
1527 Node* node, CheckForMinusZeroMode check, const FeedbackSource& feedback,
1528 Node* use_node) {
1529 return InsertConversion(
1530 node, simplified()->CheckedFloat64ToInt32(check, feedback), use_node);
1531 }
1532
isolate() const1533 Isolate* RepresentationChanger::isolate() const { return broker_->isolate(); }
1534
1535 } // namespace compiler
1536 } // namespace internal
1537 } // namespace v8
1538