| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/representation-change.h" | 5 #include "src/compiler/representation-change.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 namespace { | 98 namespace { |
| 99 | 99 |
| 100 bool IsWord(MachineRepresentation rep) { | 100 bool IsWord(MachineRepresentation rep) { |
| 101 return rep == MachineRepresentation::kWord8 || | 101 return rep == MachineRepresentation::kWord8 || |
| 102 rep == MachineRepresentation::kWord16 || | 102 rep == MachineRepresentation::kWord16 || |
| 103 rep == MachineRepresentation::kWord32; | 103 rep == MachineRepresentation::kWord32; |
| 104 } | 104 } |
| 105 | 105 |
| 106 } // namespace | 106 } // namespace |
| 107 | 107 |
| 108 | |
| 109 // Changes representation from {output_rep} to {use_rep}. The {truncation} | 108 // Changes representation from {output_rep} to {use_rep}. The {truncation} |
| 110 // parameter is only used for sanity checking - if the changer cannot figure | 109 // parameter is only used for sanity checking - if the changer cannot figure |
| 111 // out signedness for the word32->float64 conversion, then we check that the | 110 // out signedness for the word32->float64 conversion, then we check that the |
| 112 // uses truncate to word32 (so they do not care about signedness). | 111 // uses truncate to word32 (so they do not care about signedness). |
| 113 Node* RepresentationChanger::GetRepresentationFor( | 112 Node* RepresentationChanger::GetRepresentationFor( |
| 114 Node* node, MachineRepresentation output_rep, Type* output_type, | 113 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 115 MachineRepresentation use_rep, Truncation truncation) { | 114 Node* use_node, UseInfo use_info) { |
| 116 if (output_rep == MachineRepresentation::kNone) { | 115 if (output_rep == MachineRepresentation::kNone) { |
| 117 // The output representation should be set. | 116 // The output representation should be set. |
| 118 return TypeError(node, output_rep, output_type, use_rep); | 117 return TypeError(node, output_rep, output_type, use_info.representation()); |
| 119 } | 118 } |
| 120 if (use_rep == output_rep) { | 119 |
| 121 // Representations are the same. That's a no-op. | 120 // Handle the no-op shortcuts when no checking is necessary. |
| 122 return node; | 121 if (use_info.type_check() == TypeCheckKind::kNone || |
| 122 output_rep != MachineRepresentation::kWord32) { |
| 123 if (use_info.representation() == output_rep) { |
| 124 // Representations are the same. That's a no-op. |
| 125 return node; |
| 126 } |
| 127 if (IsWord(use_info.representation()) && IsWord(output_rep)) { |
| 128 // Both are words less than or equal to 32-bits. |
| 129 // Since loads of integers from memory implicitly sign or zero extend the |
| 130 // value to the full machine word size and stores implicitly truncate, |
| 131 // no representation change is necessary. |
| 132 return node; |
| 133 } |
| 123 } | 134 } |
| 124 if (IsWord(use_rep) && IsWord(output_rep)) { | 135 |
| 125 // Both are words less than or equal to 32-bits. | 136 switch (use_info.representation()) { |
| 126 // Since loads of integers from memory implicitly sign or zero extend the | |
| 127 // value to the full machine word size and stores implicitly truncate, | |
| 128 // no representation change is necessary. | |
| 129 return node; | |
| 130 } | |
| 131 switch (use_rep) { | |
| 132 case MachineRepresentation::kTagged: | 137 case MachineRepresentation::kTagged: |
| 138 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 133 return GetTaggedRepresentationFor(node, output_rep, output_type); | 139 return GetTaggedRepresentationFor(node, output_rep, output_type); |
| 134 case MachineRepresentation::kFloat32: | 140 case MachineRepresentation::kFloat32: |
| 141 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 135 return GetFloat32RepresentationFor(node, output_rep, output_type, | 142 return GetFloat32RepresentationFor(node, output_rep, output_type, |
| 136 truncation); | 143 use_info.truncation()); |
| 137 case MachineRepresentation::kFloat64: | 144 case MachineRepresentation::kFloat64: |
| 138 return GetFloat64RepresentationFor(node, output_rep, output_type, | 145 return GetFloat64RepresentationFor(node, output_rep, output_type, |
| 139 truncation); | 146 use_node, use_info); |
| 140 case MachineRepresentation::kBit: | 147 case MachineRepresentation::kBit: |
| 148 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 141 return GetBitRepresentationFor(node, output_rep, output_type); | 149 return GetBitRepresentationFor(node, output_rep, output_type); |
| 142 case MachineRepresentation::kWord8: | 150 case MachineRepresentation::kWord8: |
| 143 case MachineRepresentation::kWord16: | 151 case MachineRepresentation::kWord16: |
| 144 case MachineRepresentation::kWord32: | 152 case MachineRepresentation::kWord32: |
| 145 return GetWord32RepresentationFor(node, output_rep, output_type, | 153 return GetWord32RepresentationFor(node, output_rep, output_type, use_node, |
| 146 truncation); | 154 use_info); |
| 147 case MachineRepresentation::kWord64: | 155 case MachineRepresentation::kWord64: |
| 156 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 148 return GetWord64RepresentationFor(node, output_rep, output_type); | 157 return GetWord64RepresentationFor(node, output_rep, output_type); |
| 149 case MachineRepresentation::kSimd128: // Fall through. | 158 case MachineRepresentation::kSimd128: // Fall through. |
| 150 // TODO(bbudge) Handle conversions between tagged and untagged. | 159 // TODO(bbudge) Handle conversions between tagged and untagged. |
| 151 break; | 160 break; |
| 152 case MachineRepresentation::kNone: | 161 case MachineRepresentation::kNone: |
| 153 return node; | 162 return node; |
| 154 } | 163 } |
| 155 UNREACHABLE(); | 164 UNREACHABLE(); |
| 156 return nullptr; | 165 return nullptr; |
| 157 } | 166 } |
| 158 | 167 |
| 159 | |
| 160 Node* RepresentationChanger::GetTaggedRepresentationFor( | 168 Node* RepresentationChanger::GetTaggedRepresentationFor( |
| 161 Node* node, MachineRepresentation output_rep, Type* output_type) { | 169 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 162 // Eagerly fold representation changes for constants. | 170 // Eagerly fold representation changes for constants. |
| 163 switch (node->opcode()) { | 171 switch (node->opcode()) { |
| 164 case IrOpcode::kNumberConstant: | 172 case IrOpcode::kNumberConstant: |
| 165 case IrOpcode::kHeapConstant: | 173 case IrOpcode::kHeapConstant: |
| 166 return node; // No change necessary. | 174 return node; // No change necessary. |
| 167 case IrOpcode::kInt32Constant: | 175 case IrOpcode::kInt32Constant: |
| 168 if (output_type->Is(Type::Signed32())) { | 176 if (output_type->Is(Type::Signed32())) { |
| 169 int32_t value = OpParameter<int32_t>(node); | 177 int32_t value = OpParameter<int32_t>(node); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 } else if (output_rep == MachineRepresentation::kFloat64) { | 291 } else if (output_rep == MachineRepresentation::kFloat64) { |
| 284 op = machine()->TruncateFloat64ToFloat32(); | 292 op = machine()->TruncateFloat64ToFloat32(); |
| 285 } | 293 } |
| 286 if (op == nullptr) { | 294 if (op == nullptr) { |
| 287 return TypeError(node, output_rep, output_type, | 295 return TypeError(node, output_rep, output_type, |
| 288 MachineRepresentation::kFloat32); | 296 MachineRepresentation::kFloat32); |
| 289 } | 297 } |
| 290 return jsgraph()->graph()->NewNode(op, node); | 298 return jsgraph()->graph()->NewNode(op, node); |
| 291 } | 299 } |
| 292 | 300 |
| 293 | |
| 294 Node* RepresentationChanger::GetFloat64RepresentationFor( | 301 Node* RepresentationChanger::GetFloat64RepresentationFor( |
| 295 Node* node, MachineRepresentation output_rep, Type* output_type, | 302 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 296 Truncation truncation) { | 303 Node* use_node, UseInfo use_info) { |
| 297 // Eagerly fold representation changes for constants. | 304 // Eagerly fold representation changes for constants. |
| 298 switch (node->opcode()) { | 305 if ((use_info.type_check() == TypeCheckKind::kNone)) { |
| 299 case IrOpcode::kNumberConstant: | 306 // TODO(jarin) Handle checked constant conversions. |
| 300 return jsgraph()->Float64Constant(OpParameter<double>(node)); | 307 switch (node->opcode()) { |
| 301 case IrOpcode::kInt32Constant: | 308 case IrOpcode::kNumberConstant: |
| 302 if (output_type->Is(Type::Signed32())) { | 309 return jsgraph()->Float64Constant(OpParameter<double>(node)); |
| 303 int32_t value = OpParameter<int32_t>(node); | 310 case IrOpcode::kInt32Constant: |
| 304 return jsgraph()->Float64Constant(value); | 311 if (output_type->Is(Type::Signed32())) { |
| 305 } else { | 312 int32_t value = OpParameter<int32_t>(node); |
| 306 DCHECK(output_type->Is(Type::Unsigned32())); | 313 return jsgraph()->Float64Constant(value); |
| 307 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 314 } else { |
| 308 return jsgraph()->Float64Constant(static_cast<double>(value)); | 315 DCHECK(output_type->Is(Type::Unsigned32())); |
| 309 } | 316 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); |
| 310 case IrOpcode::kFloat64Constant: | 317 return jsgraph()->Float64Constant(static_cast<double>(value)); |
| 311 return node; // No change necessary. | 318 } |
| 312 case IrOpcode::kFloat32Constant: | 319 case IrOpcode::kFloat64Constant: |
| 313 return jsgraph()->Float64Constant(OpParameter<float>(node)); | 320 return node; // No change necessary. |
| 314 default: | 321 case IrOpcode::kFloat32Constant: |
| 315 break; | 322 return jsgraph()->Float64Constant(OpParameter<float>(node)); |
| 323 default: |
| 324 break; |
| 325 } |
| 316 } | 326 } |
| 317 // Select the correct X -> Float64 operator. | 327 // Select the correct X -> Float64 operator. |
| 318 const Operator* op = nullptr; | 328 const Operator* op = nullptr; |
| 319 if (IsWord(output_rep)) { | 329 if (IsWord(output_rep)) { |
| 320 if (output_type->Is(Type::Signed32())) { | 330 if (output_type->Is(Type::Signed32())) { |
| 321 op = machine()->ChangeInt32ToFloat64(); | 331 op = machine()->ChangeInt32ToFloat64(); |
| 322 } else if (output_type->Is(Type::Unsigned32()) || | 332 } else if (output_type->Is(Type::Unsigned32()) || |
| 323 truncation.TruncatesToWord32()) { | 333 use_info.truncation().TruncatesToWord32()) { |
| 324 // Either the output is uint32 or the uses only care about the | 334 // Either the output is uint32 or the uses only care about the |
| 325 // low 32 bits (so we can pick uint32 safely). | 335 // low 32 bits (so we can pick uint32 safely). |
| 326 op = machine()->ChangeUint32ToFloat64(); | 336 op = machine()->ChangeUint32ToFloat64(); |
| 327 } | 337 } |
| 328 } else if (output_rep == MachineRepresentation::kTagged) { | 338 } else if (output_rep == MachineRepresentation::kTagged) { |
| 329 if (output_type->Is(Type::Undefined())) { | 339 if (output_type->Is(Type::Undefined())) { |
| 330 return jsgraph()->Float64Constant( | 340 return jsgraph()->Float64Constant( |
| 331 std::numeric_limits<double>::quiet_NaN()); | 341 std::numeric_limits<double>::quiet_NaN()); |
| 332 } else if (output_type->Is(Type::TaggedSigned())) { | 342 } else if (output_type->Is(Type::TaggedSigned())) { |
| 333 node = InsertChangeTaggedSignedToInt32(node); | 343 node = InsertChangeTaggedSignedToInt32(node); |
| 334 op = machine()->ChangeInt32ToFloat64(); | 344 op = machine()->ChangeInt32ToFloat64(); |
| 335 } else if (output_type->Is(Type::Number())) { | 345 } else if (output_type->Is(Type::Number())) { |
| 336 op = simplified()->ChangeTaggedToFloat64(); | 346 op = simplified()->ChangeTaggedToFloat64(); |
| 337 } else if (output_type->Is(Type::NumberOrUndefined())) { | 347 } else if (output_type->Is(Type::NumberOrUndefined())) { |
| 348 // TODO(jarin) Here we should check that truncation is Number. |
| 338 op = simplified()->TruncateTaggedToFloat64(); | 349 op = simplified()->TruncateTaggedToFloat64(); |
| 350 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) { |
| 351 op = simplified()->CheckedTaggedToFloat64(); |
| 339 } | 352 } |
| 340 } else if (output_rep == MachineRepresentation::kFloat32) { | 353 } else if (output_rep == MachineRepresentation::kFloat32) { |
| 341 op = machine()->ChangeFloat32ToFloat64(); | 354 op = machine()->ChangeFloat32ToFloat64(); |
| 342 } | 355 } |
| 343 if (op == nullptr) { | 356 if (op == nullptr) { |
| 344 return TypeError(node, output_rep, output_type, | 357 return TypeError(node, output_rep, output_type, |
| 345 MachineRepresentation::kFloat64); | 358 MachineRepresentation::kFloat64); |
| 346 } | 359 } |
| 347 return jsgraph()->graph()->NewNode(op, node); | 360 return InsertConversion(node, op, use_node); |
| 348 } | 361 } |
| 349 | 362 |
| 350 | |
| 351 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { | 363 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { |
| 352 return jsgraph()->Int32Constant(DoubleToInt32(value)); | 364 return jsgraph()->Int32Constant(DoubleToInt32(value)); |
| 353 } | 365 } |
| 354 | 366 |
| 355 Node* RepresentationChanger::GetWord32RepresentationFor( | 367 Node* RepresentationChanger::GetWord32RepresentationFor( |
| 356 Node* node, MachineRepresentation output_rep, Type* output_type, | 368 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 357 Truncation truncation) { | 369 Node* use_node, UseInfo use_info) { |
| 358 // Eagerly fold representation changes for constants. | 370 // Eagerly fold representation changes for constants. |
| 359 switch (node->opcode()) { | 371 // TODO(jarin) Properly fold constants in presence of type check. |
| 360 case IrOpcode::kInt32Constant: | 372 if (use_info.type_check() == TypeCheckKind::kNone) { |
| 361 return node; // No change necessary. | 373 switch (node->opcode()) { |
| 362 case IrOpcode::kFloat32Constant: | 374 case IrOpcode::kInt32Constant: |
| 363 return MakeTruncatedInt32Constant(OpParameter<float>(node)); | 375 return node; // No change necessary. |
| 364 case IrOpcode::kNumberConstant: | 376 case IrOpcode::kFloat32Constant: |
| 365 case IrOpcode::kFloat64Constant: | 377 return MakeTruncatedInt32Constant(OpParameter<float>(node)); |
| 366 return MakeTruncatedInt32Constant(OpParameter<double>(node)); | 378 case IrOpcode::kNumberConstant: |
| 367 default: | 379 case IrOpcode::kFloat64Constant: |
| 368 break; | 380 return MakeTruncatedInt32Constant(OpParameter<double>(node)); |
| 381 default: |
| 382 break; |
| 383 } |
| 369 } | 384 } |
| 385 |
| 370 // Select the correct X -> Word32 operator. | 386 // Select the correct X -> Word32 operator. |
| 371 const Operator* op = nullptr; | 387 const Operator* op = nullptr; |
| 372 if (output_rep == MachineRepresentation::kBit) { | 388 if (output_rep == MachineRepresentation::kBit) { |
| 373 return node; // Sloppy comparison -> word32 | 389 return node; // Sloppy comparison -> word32 |
| 374 } else if (output_rep == MachineRepresentation::kFloat64) { | 390 } else if (output_rep == MachineRepresentation::kFloat64) { |
| 375 if (output_type->Is(Type::Unsigned32())) { | 391 if (output_type->Is(Type::Unsigned32())) { |
| 376 op = machine()->ChangeFloat64ToUint32(); | 392 op = machine()->ChangeFloat64ToUint32(); |
| 377 } else if (output_type->Is(Type::Signed32())) { | 393 } else if (output_type->Is(Type::Signed32())) { |
| 378 op = machine()->ChangeFloat64ToInt32(); | 394 op = machine()->ChangeFloat64ToInt32(); |
| 379 } else if (truncation.TruncatesToWord32()) { | 395 } else if (use_info.truncation().TruncatesToWord32()) { |
| 380 op = machine()->TruncateFloat64ToWord32(); | 396 op = machine()->TruncateFloat64ToWord32(); |
| 397 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 398 op = simplified()->CheckedFloat64ToInt32(); |
| 381 } | 399 } |
| 382 } else if (output_rep == MachineRepresentation::kFloat32) { | 400 } else if (output_rep == MachineRepresentation::kFloat32) { |
| 383 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 401 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
| 384 if (output_type->Is(Type::Unsigned32())) { | 402 if (output_type->Is(Type::Unsigned32())) { |
| 385 op = machine()->ChangeFloat64ToUint32(); | 403 op = machine()->ChangeFloat64ToUint32(); |
| 386 } else if (output_type->Is(Type::Signed32())) { | 404 } else if (output_type->Is(Type::Signed32())) { |
| 387 op = machine()->ChangeFloat64ToInt32(); | 405 op = machine()->ChangeFloat64ToInt32(); |
| 388 } else if (truncation.TruncatesToWord32()) { | 406 } else if (use_info.truncation().TruncatesToWord32()) { |
| 389 op = machine()->TruncateFloat64ToWord32(); | 407 op = machine()->TruncateFloat64ToWord32(); |
| 408 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 409 op = simplified()->CheckedFloat64ToInt32(); |
| 390 } | 410 } |
| 391 } else if (output_rep == MachineRepresentation::kTagged) { | 411 } else if (output_rep == MachineRepresentation::kTagged) { |
| 392 if (output_type->Is(Type::TaggedSigned())) { | 412 if (output_type->Is(Type::TaggedSigned())) { |
| 393 op = simplified()->ChangeTaggedSignedToInt32(); | 413 op = simplified()->ChangeTaggedSignedToInt32(); |
| 394 } else if (output_type->Is(Type::Unsigned32())) { | 414 } else if (output_type->Is(Type::Unsigned32())) { |
| 395 op = simplified()->ChangeTaggedToUint32(); | 415 op = simplified()->ChangeTaggedToUint32(); |
| 396 } else if (output_type->Is(Type::Signed32())) { | 416 } else if (output_type->Is(Type::Signed32())) { |
| 397 op = simplified()->ChangeTaggedToInt32(); | 417 op = simplified()->ChangeTaggedToInt32(); |
| 398 } else if (truncation.TruncatesToWord32()) { | 418 } else if (use_info.truncation().TruncatesToWord32()) { |
| 399 op = simplified()->TruncateTaggedToWord32(); | 419 op = simplified()->TruncateTaggedToWord32(); |
| 420 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { |
| 421 op = simplified()->CheckedTaggedToInt32(); |
| 400 } | 422 } |
| 423 } else if (output_rep == MachineRepresentation::kWord32) { |
| 424 // Only the checked case should get here, the non-checked case is |
| 425 // handled in GetRepresentationFor. |
| 426 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); |
| 427 if (output_type->Is(Type::Signed32())) { |
| 428 return node; |
| 429 } else if (output_type->Is(Type::Unsigned32())) { |
| 430 op = simplified()->CheckedUint32ToInt32(); |
| 431 } |
| 432 } else if (output_rep == MachineRepresentation::kWord8 || |
| 433 output_rep == MachineRepresentation::kWord16) { |
| 434 DCHECK(use_info.representation() == MachineRepresentation::kWord32); |
| 435 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); |
| 436 return node; |
| 401 } | 437 } |
| 438 |
| 402 if (op == nullptr) { | 439 if (op == nullptr) { |
| 403 return TypeError(node, output_rep, output_type, | 440 return TypeError(node, output_rep, output_type, |
| 404 MachineRepresentation::kWord32); | 441 MachineRepresentation::kWord32); |
| 405 } | 442 } |
| 443 return InsertConversion(node, op, use_node); |
| 444 } |
| 445 |
| 446 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op, |
| 447 Node* use_node) { |
| 448 if (op->ControlInputCount() > 0) { |
| 449 // If the operator can deoptimize (which means it has control |
| 450 // input), we need to connect it to the effect and control chains |
| 451 // and also provide it with a frame state. |
| 452 Node* effect = NodeProperties::GetEffectInput(use_node); |
| 453 Node* control = NodeProperties::GetControlInput(use_node); |
| 454 Node* frame_state = NodeProperties::GetFrameStateInput(use_node, 0); |
| 455 Node* conversion = |
| 456 jsgraph()->graph()->NewNode(op, node, frame_state, effect, control); |
| 457 NodeProperties::ReplaceControlInput(use_node, control); |
| 458 NodeProperties::ReplaceEffectInput(use_node, effect); |
| 459 return conversion; |
| 460 } |
| 406 return jsgraph()->graph()->NewNode(op, node); | 461 return jsgraph()->graph()->NewNode(op, node); |
| 407 } | 462 } |
| 408 | 463 |
| 409 | 464 |
| 410 Node* RepresentationChanger::GetBitRepresentationFor( | 465 Node* RepresentationChanger::GetBitRepresentationFor( |
| 411 Node* node, MachineRepresentation output_rep, Type* output_type) { | 466 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 412 // Eagerly fold representation changes for constants. | 467 // Eagerly fold representation changes for constants. |
| 413 switch (node->opcode()) { | 468 switch (node->opcode()) { |
| 414 case IrOpcode::kHeapConstant: { | 469 case IrOpcode::kHeapConstant: { |
| 415 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); | 470 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); |
| 416 DCHECK(value.is_identical_to(factory()->true_value()) || | 471 DCHECK(value.is_identical_to(factory()->true_value()) || |
| 417 value.is_identical_to(factory()->false_value())); | 472 value.is_identical_to(factory()->false_value())); |
| 418 return jsgraph()->Int32Constant( | 473 return jsgraph()->Int32Constant( |
| 419 value.is_identical_to(factory()->true_value()) ? 1 : 0); | 474 value.is_identical_to(factory()->true_value()) ? 1 : 0); |
| 420 } | 475 } |
| 421 default: | 476 default: |
| 422 break; | 477 break; |
| 423 } | 478 } |
| 424 // Select the correct X -> Bit operator. | 479 // Select the correct X -> Bit operator. |
| 425 const Operator* op; | 480 const Operator* op; |
| 426 if (output_rep == MachineRepresentation::kTagged) { | 481 if (output_rep == MachineRepresentation::kTagged) { |
| 427 op = simplified()->ChangeTaggedToBit(); | 482 op = simplified()->ChangeTaggedToBit(); |
| 428 } else { | 483 } else { |
| 429 return TypeError(node, output_rep, output_type, | 484 return TypeError(node, output_rep, output_type, |
| 430 MachineRepresentation::kBit); | 485 MachineRepresentation::kBit); |
| 431 } | 486 } |
| 432 return jsgraph()->graph()->NewNode(op, node); | 487 return jsgraph()->graph()->NewNode(op, node); |
| 433 } | 488 } |
| 434 | 489 |
| 435 | |
| 436 Node* RepresentationChanger::GetWord64RepresentationFor( | 490 Node* RepresentationChanger::GetWord64RepresentationFor( |
| 437 Node* node, MachineRepresentation output_rep, Type* output_type) { | 491 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 438 if (output_rep == MachineRepresentation::kBit) { | 492 if (output_rep == MachineRepresentation::kBit) { |
| 439 return node; // Sloppy comparison -> word64 | 493 return node; // Sloppy comparison -> word64 |
| 440 } | 494 } |
| 441 // Can't really convert Word64 to anything else. Purported to be internal. | 495 // Can't really convert Word64 to anything else. Purported to be internal. |
| 442 return TypeError(node, output_rep, output_type, | 496 return TypeError(node, output_rep, output_type, |
| 443 MachineRepresentation::kWord64); | 497 MachineRepresentation::kWord64); |
| 444 } | 498 } |
| 445 | 499 |
| 500 Node* RepresentationChanger::GetCheckedWord32RepresentationFor( |
| 501 Node* node, MachineRepresentation output_rep, Type* output_type, |
| 502 Node* use_node, Truncation truncation, TypeCheckKind check) { |
| 503 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant |
| 504 // does not pass the check). |
| 505 |
| 506 // If the input is already Signed32 in Word32 representation, we do not |
| 507 // have to do anything. (We could fold this into the big if below, but |
| 508 // it feels nicer to have the shortcut return first). |
| 509 if (output_rep == MachineRepresentation::kWord32 || |
| 510 output_type->Is(Type::Signed32())) { |
| 511 return node; |
| 512 } |
| 513 |
| 514 // Select the correct X -> Word32 operator. |
| 515 const Operator* op = nullptr; |
| 516 if (output_rep == MachineRepresentation::kWord32) { |
| 517 if (output_type->Is(Type::Unsigned32())) { |
| 518 op = simplified()->CheckedUint32ToInt32(); |
| 519 } |
| 520 } else if (output_rep == MachineRepresentation::kBit) { |
| 521 return node; // Sloppy comparison -> word32 |
| 522 } else if (output_rep == MachineRepresentation::kFloat64) { |
| 523 if (output_type->Is(Type::Unsigned32())) { |
| 524 op = machine()->ChangeFloat64ToUint32(); |
| 525 } else if (output_type->Is(Type::Signed32())) { |
| 526 op = machine()->ChangeFloat64ToInt32(); |
| 527 } else if (truncation.TruncatesToWord32()) { |
| 528 op = machine()->TruncateFloat64ToWord32(); |
| 529 } else if (check == TypeCheckKind::kSigned32) { |
| 530 op = simplified()->CheckedFloat64ToInt32(); |
| 531 } |
| 532 } else if (output_rep == MachineRepresentation::kFloat32) { |
| 533 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 |
| 534 if (output_type->Is(Type::Unsigned32())) { |
| 535 op = machine()->ChangeFloat64ToUint32(); |
| 536 } else if (output_type->Is(Type::Signed32())) { |
| 537 op = machine()->ChangeFloat64ToInt32(); |
| 538 } else if (truncation.TruncatesToWord32()) { |
| 539 op = machine()->TruncateFloat64ToWord32(); |
| 540 } else if (check == TypeCheckKind::kSigned32) { |
| 541 op = simplified()->CheckedFloat64ToInt32(); |
| 542 } |
| 543 } else if (output_rep == MachineRepresentation::kTagged) { |
| 544 if (output_type->Is(Type::TaggedSigned())) { |
| 545 op = simplified()->ChangeTaggedSignedToInt32(); |
| 546 } else if (output_type->Is(Type::Unsigned32())) { |
| 547 op = simplified()->ChangeTaggedToUint32(); |
| 548 } else if (output_type->Is(Type::Signed32())) { |
| 549 op = simplified()->ChangeTaggedToInt32(); |
| 550 } else if (truncation.TruncatesToWord32()) { |
| 551 op = simplified()->TruncateTaggedToWord32(); |
| 552 } else if (check == TypeCheckKind::kSigned32) { |
| 553 op = simplified()->CheckedTaggedToInt32(); |
| 554 } |
| 555 } |
| 556 if (op == nullptr) { |
| 557 return TypeError(node, output_rep, output_type, |
| 558 MachineRepresentation::kWord32); |
| 559 } |
| 560 if (op->ControlInputCount() > 0) { |
| 561 // If the operator can deoptimize (which means it has control |
| 562 // input), we need to connect it to the effect and control chains |
| 563 // and also provide it with a frame state. |
| 564 UNIMPLEMENTED(); |
| 565 } |
| 566 return jsgraph()->graph()->NewNode(op, node); |
| 567 } |
| 446 | 568 |
| 447 const Operator* RepresentationChanger::Int32OperatorFor( | 569 const Operator* RepresentationChanger::Int32OperatorFor( |
| 448 IrOpcode::Value opcode) { | 570 IrOpcode::Value opcode) { |
| 449 switch (opcode) { | 571 switch (opcode) { |
| 572 case IrOpcode::kSpeculativeNumberAdd: // Fall through. |
| 450 case IrOpcode::kNumberAdd: | 573 case IrOpcode::kNumberAdd: |
| 451 return machine()->Int32Add(); | 574 return machine()->Int32Add(); |
| 575 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. |
| 452 case IrOpcode::kNumberSubtract: | 576 case IrOpcode::kNumberSubtract: |
| 453 return machine()->Int32Sub(); | 577 return machine()->Int32Sub(); |
| 454 case IrOpcode::kNumberMultiply: | 578 case IrOpcode::kNumberMultiply: |
| 455 return machine()->Int32Mul(); | 579 return machine()->Int32Mul(); |
| 456 case IrOpcode::kNumberDivide: | 580 case IrOpcode::kNumberDivide: |
| 457 return machine()->Int32Div(); | 581 return machine()->Int32Div(); |
| 458 case IrOpcode::kNumberModulus: | 582 case IrOpcode::kNumberModulus: |
| 459 return machine()->Int32Mod(); | 583 return machine()->Int32Mod(); |
| 460 case IrOpcode::kNumberBitwiseOr: | 584 case IrOpcode::kNumberBitwiseOr: |
| 461 return machine()->Word32Or(); | 585 return machine()->Word32Or(); |
| 462 case IrOpcode::kNumberBitwiseXor: | 586 case IrOpcode::kNumberBitwiseXor: |
| 463 return machine()->Word32Xor(); | 587 return machine()->Word32Xor(); |
| 464 case IrOpcode::kNumberBitwiseAnd: | 588 case IrOpcode::kNumberBitwiseAnd: |
| 465 return machine()->Word32And(); | 589 return machine()->Word32And(); |
| 466 case IrOpcode::kNumberEqual: | 590 case IrOpcode::kNumberEqual: |
| 467 return machine()->Word32Equal(); | 591 return machine()->Word32Equal(); |
| 468 case IrOpcode::kNumberLessThan: | 592 case IrOpcode::kNumberLessThan: |
| 469 return machine()->Int32LessThan(); | 593 return machine()->Int32LessThan(); |
| 470 case IrOpcode::kNumberLessThanOrEqual: | 594 case IrOpcode::kNumberLessThanOrEqual: |
| 471 return machine()->Int32LessThanOrEqual(); | 595 return machine()->Int32LessThanOrEqual(); |
| 472 default: | 596 default: |
| 473 UNREACHABLE(); | 597 UNREACHABLE(); |
| 474 return nullptr; | 598 return nullptr; |
| 475 } | 599 } |
| 476 } | 600 } |
| 477 | 601 |
| 602 const Operator* RepresentationChanger::Int32OverflowOperatorFor( |
| 603 IrOpcode::Value opcode) { |
| 604 switch (opcode) { |
| 605 case IrOpcode::kSpeculativeNumberAdd: // Fall through. |
| 606 return machine()->Int32AddWithOverflow(); |
| 607 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. |
| 608 return machine()->Int32SubWithOverflow(); |
| 609 default: |
| 610 UNREACHABLE(); |
| 611 return nullptr; |
| 612 } |
| 613 } |
| 478 | 614 |
| 479 const Operator* RepresentationChanger::Uint32OperatorFor( | 615 const Operator* RepresentationChanger::Uint32OperatorFor( |
| 480 IrOpcode::Value opcode) { | 616 IrOpcode::Value opcode) { |
| 481 switch (opcode) { | 617 switch (opcode) { |
| 482 case IrOpcode::kNumberAdd: | 618 case IrOpcode::kNumberAdd: |
| 483 return machine()->Int32Add(); | 619 return machine()->Int32Add(); |
| 484 case IrOpcode::kNumberSubtract: | 620 case IrOpcode::kNumberSubtract: |
| 485 return machine()->Int32Sub(); | 621 return machine()->Int32Sub(); |
| 486 case IrOpcode::kNumberMultiply: | 622 case IrOpcode::kNumberMultiply: |
| 487 return machine()->Int32Mul(); | 623 return machine()->Int32Mul(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 502 default: | 638 default: |
| 503 UNREACHABLE(); | 639 UNREACHABLE(); |
| 504 return nullptr; | 640 return nullptr; |
| 505 } | 641 } |
| 506 } | 642 } |
| 507 | 643 |
| 508 | 644 |
| 509 const Operator* RepresentationChanger::Float64OperatorFor( | 645 const Operator* RepresentationChanger::Float64OperatorFor( |
| 510 IrOpcode::Value opcode) { | 646 IrOpcode::Value opcode) { |
| 511 switch (opcode) { | 647 switch (opcode) { |
| 648 case IrOpcode::kSpeculativeNumberAdd: |
| 512 case IrOpcode::kNumberAdd: | 649 case IrOpcode::kNumberAdd: |
| 513 return machine()->Float64Add(); | 650 return machine()->Float64Add(); |
| 651 case IrOpcode::kSpeculativeNumberSubtract: |
| 514 case IrOpcode::kNumberSubtract: | 652 case IrOpcode::kNumberSubtract: |
| 515 return machine()->Float64Sub(); | 653 return machine()->Float64Sub(); |
| 516 case IrOpcode::kNumberMultiply: | 654 case IrOpcode::kNumberMultiply: |
| 517 return machine()->Float64Mul(); | 655 return machine()->Float64Mul(); |
| 518 case IrOpcode::kNumberDivide: | 656 case IrOpcode::kNumberDivide: |
| 519 return machine()->Float64Div(); | 657 return machine()->Float64Div(); |
| 520 case IrOpcode::kNumberModulus: | 658 case IrOpcode::kNumberModulus: |
| 521 return machine()->Float64Mod(); | 659 return machine()->Float64Mod(); |
| 522 case IrOpcode::kNumberEqual: | 660 case IrOpcode::kNumberEqual: |
| 523 return machine()->Float64Equal(); | 661 return machine()->Float64Equal(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 } | 712 } |
| 575 | 713 |
| 576 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 714 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
| 577 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 715 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
| 578 node); | 716 node); |
| 579 } | 717 } |
| 580 | 718 |
| 581 } // namespace compiler | 719 } // namespace compiler |
| 582 } // namespace internal | 720 } // namespace internal |
| 583 } // namespace v8 | 721 } // namespace v8 |
| OLD | NEW |