Chromium Code Reviews| 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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 } else if (output_rep == MachineRepresentation::kFloat64) { | 287 } else if (output_rep == MachineRepresentation::kFloat64) { | 
| 280 op = machine()->TruncateFloat64ToFloat32(); | 288 op = machine()->TruncateFloat64ToFloat32(); | 
| 281 } | 289 } | 
| 282 if (op == nullptr) { | 290 if (op == nullptr) { | 
| 283 return TypeError(node, output_rep, output_type, | 291 return TypeError(node, output_rep, output_type, | 
| 284 MachineRepresentation::kFloat32); | 292 MachineRepresentation::kFloat32); | 
| 285 } | 293 } | 
| 286 return jsgraph()->graph()->NewNode(op, node); | 294 return jsgraph()->graph()->NewNode(op, node); | 
| 287 } | 295 } | 
| 288 | 296 | 
| 289 | |
| 290 Node* RepresentationChanger::GetFloat64RepresentationFor( | 297 Node* RepresentationChanger::GetFloat64RepresentationFor( | 
| 291 Node* node, MachineRepresentation output_rep, Type* output_type, | 298 Node* node, MachineRepresentation output_rep, Type* output_type, | 
| 292 Truncation truncation) { | 299 Node* use_node, UseInfo use_info) { | 
| 293 // Eagerly fold representation changes for constants. | 300 // Eagerly fold representation changes for constants. | 
| 294 switch (node->opcode()) { | 301 if ((use_info.type_check() == TypeCheckKind::kNone)) { | 
| 295 case IrOpcode::kNumberConstant: | 302 // TODO(jarin) Handle checked constant conversions. | 
| 296 return jsgraph()->Float64Constant(OpParameter<double>(node)); | 303 switch (node->opcode()) { | 
| 297 case IrOpcode::kInt32Constant: | 304 case IrOpcode::kNumberConstant: | 
| 298 if (output_type->Is(Type::Signed32())) { | 305 return jsgraph()->Float64Constant(OpParameter<double>(node)); | 
| 299 int32_t value = OpParameter<int32_t>(node); | 306 case IrOpcode::kInt32Constant: | 
| 300 return jsgraph()->Float64Constant(value); | 307 if (output_type->Is(Type::Signed32())) { | 
| 301 } else { | 308 int32_t value = OpParameter<int32_t>(node); | 
| 302 DCHECK(output_type->Is(Type::Unsigned32())); | 309 return jsgraph()->Float64Constant(value); | 
| 303 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 310 } else { | 
| 304 return jsgraph()->Float64Constant(static_cast<double>(value)); | 311 DCHECK(output_type->Is(Type::Unsigned32())); | 
| 305 } | 312 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 
| 306 case IrOpcode::kFloat64Constant: | 313 return jsgraph()->Float64Constant(static_cast<double>(value)); | 
| 307 return node; // No change necessary. | 314 } | 
| 308 case IrOpcode::kFloat32Constant: | 315 case IrOpcode::kFloat64Constant: | 
| 309 return jsgraph()->Float64Constant(OpParameter<float>(node)); | 316 return node; // No change necessary. | 
| 310 default: | 317 case IrOpcode::kFloat32Constant: | 
| 311 break; | 318 return jsgraph()->Float64Constant(OpParameter<float>(node)); | 
| 319 default: | |
| 320 break; | |
| 321 } | |
| 312 } | 322 } | 
| 313 // Select the correct X -> Float64 operator. | 323 // Select the correct X -> Float64 operator. | 
| 314 const Operator* op = nullptr; | 324 const Operator* op = nullptr; | 
| 315 if (IsWord(output_rep)) { | 325 if (IsWord(output_rep)) { | 
| 316 if (output_type->Is(Type::Signed32())) { | 326 if (output_type->Is(Type::Signed32())) { | 
| 317 op = machine()->ChangeInt32ToFloat64(); | 327 op = machine()->ChangeInt32ToFloat64(); | 
| 318 } else if (output_type->Is(Type::Unsigned32()) || | 328 } else if (output_type->Is(Type::Unsigned32()) || | 
| 319 truncation.TruncatesToWord32()) { | 329 use_info.truncation().TruncatesToWord32()) { | 
| 320 // Either the output is uint32 or the uses only care about the | 330 // Either the output is uint32 or the uses only care about the | 
| 321 // low 32 bits (so we can pick uint32 safely). | 331 // low 32 bits (so we can pick uint32 safely). | 
| 322 op = machine()->ChangeUint32ToFloat64(); | 332 op = machine()->ChangeUint32ToFloat64(); | 
| 323 } | 333 } | 
| 324 } else if (output_rep == MachineRepresentation::kTagged) { | 334 } else if (output_rep == MachineRepresentation::kTagged) { | 
| 325 if (output_type->Is(Type::Undefined())) { | 335 if (output_type->Is(Type::Undefined())) { | 
| 326 return jsgraph()->Float64Constant( | 336 return jsgraph()->Float64Constant( | 
| 327 std::numeric_limits<double>::quiet_NaN()); | 337 std::numeric_limits<double>::quiet_NaN()); | 
| 328 } else if (output_type->Is(Type::TaggedSigned())) { | 338 } else if (output_type->Is(Type::TaggedSigned())) { | 
| 329 node = InsertChangeTaggedSignedToInt32(node); | 339 node = InsertChangeTaggedSignedToInt32(node); | 
| 330 op = machine()->ChangeInt32ToFloat64(); | 340 op = machine()->ChangeInt32ToFloat64(); | 
| 331 } else if (output_type->Is(Type::NumberOrUndefined())) { | 341 } else if (output_type->Is(Type::NumberOrUndefined())) { | 
| 342 // TODO(jarin) Here we should check that truncation is Number. | |
| 332 op = simplified()->ChangeTaggedToFloat64(); | 343 op = simplified()->ChangeTaggedToFloat64(); | 
| 
 
Benedikt Meurer
2016/05/30 18:39:50
This should probably be TruncateTaggedToFloat64
 
Jarin
2016/05/31 20:28:53
Done in https://codereview.chromium.org/2027593002
 
 | |
| 344 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) { | |
| 345 op = simplified()->CheckedTaggedToFloat64(); | |
| 333 } | 346 } | 
| 334 } else if (output_rep == MachineRepresentation::kFloat32) { | 347 } else if (output_rep == MachineRepresentation::kFloat32) { | 
| 335 op = machine()->ChangeFloat32ToFloat64(); | 348 op = machine()->ChangeFloat32ToFloat64(); | 
| 336 } | 349 } | 
| 337 if (op == nullptr) { | 350 if (op == nullptr) { | 
| 338 return TypeError(node, output_rep, output_type, | 351 return TypeError(node, output_rep, output_type, | 
| 339 MachineRepresentation::kFloat64); | 352 MachineRepresentation::kFloat64); | 
| 340 } | 353 } | 
| 341 return jsgraph()->graph()->NewNode(op, node); | 354 return InsertConversion(node, op, use_node); | 
| 342 } | 355 } | 
| 343 | 356 | 
| 344 | |
| 345 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { | 357 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { | 
| 346 return jsgraph()->Int32Constant(DoubleToInt32(value)); | 358 return jsgraph()->Int32Constant(DoubleToInt32(value)); | 
| 347 } | 359 } | 
| 348 | 360 | 
| 349 Node* RepresentationChanger::GetWord32RepresentationFor( | 361 Node* RepresentationChanger::GetWord32RepresentationFor( | 
| 350 Node* node, MachineRepresentation output_rep, Type* output_type, | 362 Node* node, MachineRepresentation output_rep, Type* output_type, | 
| 351 Truncation truncation) { | 363 Node* use_node, UseInfo use_info) { | 
| 352 // Eagerly fold representation changes for constants. | 364 // Eagerly fold representation changes for constants. | 
| 353 switch (node->opcode()) { | 365 // TODO(jarin) Properly fold constants in presence of type check. | 
| 354 case IrOpcode::kInt32Constant: | 366 if (use_info.type_check() == TypeCheckKind::kNone) { | 
| 355 return node; // No change necessary. | 367 switch (node->opcode()) { | 
| 356 case IrOpcode::kFloat32Constant: | 368 case IrOpcode::kInt32Constant: | 
| 357 return MakeTruncatedInt32Constant(OpParameter<float>(node)); | 369 return node; // No change necessary. | 
| 358 case IrOpcode::kNumberConstant: | 370 case IrOpcode::kFloat32Constant: | 
| 359 case IrOpcode::kFloat64Constant: | 371 return MakeTruncatedInt32Constant(OpParameter<float>(node)); | 
| 360 return MakeTruncatedInt32Constant(OpParameter<double>(node)); | 372 case IrOpcode::kNumberConstant: | 
| 361 default: | 373 case IrOpcode::kFloat64Constant: | 
| 362 break; | 374 return MakeTruncatedInt32Constant(OpParameter<double>(node)); | 
| 375 default: | |
| 376 break; | |
| 377 } | |
| 363 } | 378 } | 
| 379 | |
| 364 // Select the correct X -> Word32 operator. | 380 // Select the correct X -> Word32 operator. | 
| 365 const Operator* op = nullptr; | 381 const Operator* op = nullptr; | 
| 366 if (output_rep == MachineRepresentation::kBit) { | 382 if (output_rep == MachineRepresentation::kBit) { | 
| 367 return node; // Sloppy comparison -> word32 | 383 return node; // Sloppy comparison -> word32 | 
| 368 } else if (output_rep == MachineRepresentation::kFloat64) { | 384 } else if (output_rep == MachineRepresentation::kFloat64) { | 
| 369 if (output_type->Is(Type::Unsigned32())) { | 385 if (output_type->Is(Type::Unsigned32())) { | 
| 370 op = machine()->ChangeFloat64ToUint32(); | 386 op = machine()->ChangeFloat64ToUint32(); | 
| 371 } else if (output_type->Is(Type::Signed32())) { | 387 } else if (output_type->Is(Type::Signed32())) { | 
| 372 op = machine()->ChangeFloat64ToInt32(); | 388 op = machine()->ChangeFloat64ToInt32(); | 
| 373 } else if (truncation.TruncatesToWord32()) { | 389 } else if (use_info.truncation().TruncatesToWord32()) { | 
| 374 op = machine()->TruncateFloat64ToWord32(); | 390 op = machine()->TruncateFloat64ToWord32(); | 
| 391 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { | |
| 392 op = simplified()->CheckedFloat64ToInt32(); | |
| 375 } | 393 } | 
| 376 } else if (output_rep == MachineRepresentation::kFloat32) { | 394 } else if (output_rep == MachineRepresentation::kFloat32) { | 
| 377 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 395 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | 
| 378 if (output_type->Is(Type::Unsigned32())) { | 396 if (output_type->Is(Type::Unsigned32())) { | 
| 379 op = machine()->ChangeFloat64ToUint32(); | 397 op = machine()->ChangeFloat64ToUint32(); | 
| 380 } else if (output_type->Is(Type::Signed32())) { | 398 } else if (output_type->Is(Type::Signed32())) { | 
| 381 op = machine()->ChangeFloat64ToInt32(); | 399 op = machine()->ChangeFloat64ToInt32(); | 
| 382 } else if (truncation.TruncatesToWord32()) { | 400 } else if (use_info.truncation().TruncatesToWord32()) { | 
| 383 op = machine()->TruncateFloat64ToWord32(); | 401 op = machine()->TruncateFloat64ToWord32(); | 
| 402 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { | |
| 403 op = simplified()->CheckedFloat64ToInt32(); | |
| 384 } | 404 } | 
| 385 } else if (output_rep == MachineRepresentation::kTagged) { | 405 } else if (output_rep == MachineRepresentation::kTagged) { | 
| 386 if (output_type->Is(Type::TaggedSigned())) { | 406 if (output_type->Is(Type::TaggedSigned())) { | 
| 387 op = simplified()->ChangeTaggedSignedToInt32(); | 407 op = simplified()->ChangeTaggedSignedToInt32(); | 
| 388 } else if (output_type->Is(Type::Unsigned32())) { | 408 } else if (output_type->Is(Type::Unsigned32())) { | 
| 389 op = simplified()->ChangeTaggedToUint32(); | 409 op = simplified()->ChangeTaggedToUint32(); | 
| 390 } else if (output_type->Is(Type::Signed32())) { | 410 } else if (output_type->Is(Type::Signed32())) { | 
| 391 op = simplified()->ChangeTaggedToInt32(); | 411 op = simplified()->ChangeTaggedToInt32(); | 
| 392 } else if (truncation.TruncatesToWord32()) { | 412 } else if (use_info.truncation().TruncatesToWord32()) { | 
| 393 op = simplified()->TruncateTaggedToWord32(); | 413 op = simplified()->TruncateTaggedToWord32(); | 
| 414 } else if (use_info.type_check() == TypeCheckKind::kSigned32) { | |
| 415 op = simplified()->CheckedTaggedToInt32(); | |
| 394 } | 416 } | 
| 417 } else if (output_rep == MachineRepresentation::kWord32) { | |
| 418 // Only the checked case should get here, the non-checked case is | |
| 419 // handled in GetRepresentationFor. | |
| 420 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); | |
| 421 if (output_type->Is(Type::Signed32())) { | |
| 422 return node; | |
| 423 } else if (output_type->Is(Type::Unsigned32())) { | |
| 424 op = simplified()->CheckedUint32ToInt32(); | |
| 425 } | |
| 426 } else if (output_rep == MachineRepresentation::kWord8 || | |
| 427 output_rep == MachineRepresentation::kWord16) { | |
| 428 DCHECK(use_info.representation() == MachineRepresentation::kWord32); | |
| 429 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32); | |
| 430 return node; | |
| 395 } | 431 } | 
| 432 | |
| 396 if (op == nullptr) { | 433 if (op == nullptr) { | 
| 397 return TypeError(node, output_rep, output_type, | 434 return TypeError(node, output_rep, output_type, | 
| 398 MachineRepresentation::kWord32); | 435 MachineRepresentation::kWord32); | 
| 399 } | 436 } | 
| 437 return InsertConversion(node, op, use_node); | |
| 438 } | |
| 439 | |
| 440 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op, | |
| 441 Node* use_node) { | |
| 442 if (op->ControlInputCount() > 0) { | |
| 443 // If the operator can deoptimize (which means it has control | |
| 444 // input), we need to connect it to the effect and control chains | |
| 445 // and also provide it with a frame state. | |
| 446 Node* effect = NodeProperties::GetEffectInput(use_node); | |
| 447 Node* control = NodeProperties::GetControlInput(use_node); | |
| 448 Node* frame_state = NodeProperties::GetFrameStateInput(use_node, 0); | |
| 449 Node* conversion = | |
| 450 jsgraph()->graph()->NewNode(op, node, frame_state, effect, control); | |
| 451 NodeProperties::ReplaceControlInput(use_node, control); | |
| 452 NodeProperties::ReplaceEffectInput(use_node, effect); | |
| 453 return conversion; | |
| 454 } | |
| 400 return jsgraph()->graph()->NewNode(op, node); | 455 return jsgraph()->graph()->NewNode(op, node); | 
| 401 } | 456 } | 
| 402 | 457 | 
| 403 | 458 | 
| 404 Node* RepresentationChanger::GetBitRepresentationFor( | 459 Node* RepresentationChanger::GetBitRepresentationFor( | 
| 405 Node* node, MachineRepresentation output_rep, Type* output_type) { | 460 Node* node, MachineRepresentation output_rep, Type* output_type) { | 
| 406 // Eagerly fold representation changes for constants. | 461 // Eagerly fold representation changes for constants. | 
| 407 switch (node->opcode()) { | 462 switch (node->opcode()) { | 
| 408 case IrOpcode::kHeapConstant: { | 463 case IrOpcode::kHeapConstant: { | 
| 409 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); | 464 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); | 
| 410 DCHECK(value.is_identical_to(factory()->true_value()) || | 465 DCHECK(value.is_identical_to(factory()->true_value()) || | 
| 411 value.is_identical_to(factory()->false_value())); | 466 value.is_identical_to(factory()->false_value())); | 
| 412 return jsgraph()->Int32Constant( | 467 return jsgraph()->Int32Constant( | 
| 413 value.is_identical_to(factory()->true_value()) ? 1 : 0); | 468 value.is_identical_to(factory()->true_value()) ? 1 : 0); | 
| 414 } | 469 } | 
| 415 default: | 470 default: | 
| 416 break; | 471 break; | 
| 417 } | 472 } | 
| 418 // Select the correct X -> Bit operator. | 473 // Select the correct X -> Bit operator. | 
| 419 const Operator* op; | 474 const Operator* op; | 
| 420 if (output_rep == MachineRepresentation::kTagged) { | 475 if (output_rep == MachineRepresentation::kTagged) { | 
| 421 op = simplified()->ChangeTaggedToBit(); | 476 op = simplified()->ChangeTaggedToBit(); | 
| 422 } else { | 477 } else { | 
| 423 return TypeError(node, output_rep, output_type, | 478 return TypeError(node, output_rep, output_type, | 
| 424 MachineRepresentation::kBit); | 479 MachineRepresentation::kBit); | 
| 425 } | 480 } | 
| 426 return jsgraph()->graph()->NewNode(op, node); | 481 return jsgraph()->graph()->NewNode(op, node); | 
| 427 } | 482 } | 
| 428 | 483 | 
| 429 | |
| 430 Node* RepresentationChanger::GetWord64RepresentationFor( | 484 Node* RepresentationChanger::GetWord64RepresentationFor( | 
| 431 Node* node, MachineRepresentation output_rep, Type* output_type) { | 485 Node* node, MachineRepresentation output_rep, Type* output_type) { | 
| 432 if (output_rep == MachineRepresentation::kBit) { | 486 if (output_rep == MachineRepresentation::kBit) { | 
| 433 return node; // Sloppy comparison -> word64 | 487 return node; // Sloppy comparison -> word64 | 
| 434 } | 488 } | 
| 435 // Can't really convert Word64 to anything else. Purported to be internal. | 489 // Can't really convert Word64 to anything else. Purported to be internal. | 
| 436 return TypeError(node, output_rep, output_type, | 490 return TypeError(node, output_rep, output_type, | 
| 437 MachineRepresentation::kWord64); | 491 MachineRepresentation::kWord64); | 
| 438 } | 492 } | 
| 439 | 493 | 
| 494 Node* RepresentationChanger::GetCheckedWord32RepresentationFor( | |
| 495 Node* node, MachineRepresentation output_rep, Type* output_type, | |
| 496 Node* use_node, Truncation truncation, TypeCheckKind check) { | |
| 497 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant | |
| 498 // does not pass the check). | |
| 499 | |
| 500 // If the input is already Signed32 in Word32 representation, we do not | |
| 501 // have to do anything. (We could fold this into the big if below, but | |
| 502 // it feels nicer to have the shortcut return first). | |
| 503 if (output_rep == MachineRepresentation::kWord32 || | |
| 504 output_type->Is(Type::Signed32())) { | |
| 505 return node; | |
| 506 } | |
| 507 | |
| 508 // Select the correct X -> Word32 operator. | |
| 509 const Operator* op = nullptr; | |
| 510 if (output_rep == MachineRepresentation::kWord32) { | |
| 511 if (output_type->Is(Type::Unsigned32())) { | |
| 512 op = simplified()->CheckedUint32ToInt32(); | |
| 513 } | |
| 514 } else if (output_rep == MachineRepresentation::kBit) { | |
| 515 return node; // Sloppy comparison -> word32 | |
| 516 } else if (output_rep == MachineRepresentation::kFloat64) { | |
| 517 if (output_type->Is(Type::Unsigned32())) { | |
| 518 op = machine()->ChangeFloat64ToUint32(); | |
| 519 } else if (output_type->Is(Type::Signed32())) { | |
| 520 op = machine()->ChangeFloat64ToInt32(); | |
| 521 } else if (truncation.TruncatesToWord32()) { | |
| 522 op = machine()->TruncateFloat64ToWord32(); | |
| 523 } else if (check == TypeCheckKind::kSigned32) { | |
| 524 op = simplified()->CheckedFloat64ToInt32(); | |
| 525 } | |
| 526 } else if (output_rep == MachineRepresentation::kFloat32) { | |
| 527 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 | |
| 528 if (output_type->Is(Type::Unsigned32())) { | |
| 529 op = machine()->ChangeFloat64ToUint32(); | |
| 530 } else if (output_type->Is(Type::Signed32())) { | |
| 531 op = machine()->ChangeFloat64ToInt32(); | |
| 532 } else if (truncation.TruncatesToWord32()) { | |
| 533 op = machine()->TruncateFloat64ToWord32(); | |
| 534 } else if (check == TypeCheckKind::kSigned32) { | |
| 535 op = simplified()->CheckedFloat64ToInt32(); | |
| 536 } | |
| 537 } else if (output_rep == MachineRepresentation::kTagged) { | |
| 538 if (output_type->Is(Type::TaggedSigned())) { | |
| 539 op = simplified()->ChangeTaggedSignedToInt32(); | |
| 540 } else if (output_type->Is(Type::Unsigned32())) { | |
| 541 op = simplified()->ChangeTaggedToUint32(); | |
| 542 } else if (output_type->Is(Type::Signed32())) { | |
| 543 op = simplified()->ChangeTaggedToInt32(); | |
| 544 } else if (truncation.TruncatesToWord32()) { | |
| 545 op = simplified()->TruncateTaggedToWord32(); | |
| 546 } else if (check == TypeCheckKind::kSigned32) { | |
| 547 op = simplified()->CheckedTaggedToInt32(); | |
| 548 } | |
| 549 } | |
| 550 if (op == nullptr) { | |
| 551 return TypeError(node, output_rep, output_type, | |
| 552 MachineRepresentation::kWord32); | |
| 553 } | |
| 554 if (op->ControlInputCount() > 0) { | |
| 555 // If the operator can deoptimize (which means it has control | |
| 556 // input), we need to connect it to the effect and control chains | |
| 557 // and also provide it with a frame state. | |
| 558 UNIMPLEMENTED(); | |
| 559 } | |
| 560 return jsgraph()->graph()->NewNode(op, node); | |
| 561 } | |
| 440 | 562 | 
| 441 const Operator* RepresentationChanger::Int32OperatorFor( | 563 const Operator* RepresentationChanger::Int32OperatorFor( | 
| 442 IrOpcode::Value opcode) { | 564 IrOpcode::Value opcode) { | 
| 443 switch (opcode) { | 565 switch (opcode) { | 
| 566 case IrOpcode::kSpeculativeNumberAdd: // Fall through. | |
| 444 case IrOpcode::kNumberAdd: | 567 case IrOpcode::kNumberAdd: | 
| 445 return machine()->Int32Add(); | 568 return machine()->Int32Add(); | 
| 569 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. | |
| 446 case IrOpcode::kNumberSubtract: | 570 case IrOpcode::kNumberSubtract: | 
| 447 return machine()->Int32Sub(); | 571 return machine()->Int32Sub(); | 
| 448 case IrOpcode::kNumberMultiply: | 572 case IrOpcode::kNumberMultiply: | 
| 449 return machine()->Int32Mul(); | 573 return machine()->Int32Mul(); | 
| 450 case IrOpcode::kNumberDivide: | 574 case IrOpcode::kNumberDivide: | 
| 451 return machine()->Int32Div(); | 575 return machine()->Int32Div(); | 
| 452 case IrOpcode::kNumberModulus: | 576 case IrOpcode::kNumberModulus: | 
| 453 return machine()->Int32Mod(); | 577 return machine()->Int32Mod(); | 
| 454 case IrOpcode::kNumberBitwiseOr: | 578 case IrOpcode::kNumberBitwiseOr: | 
| 455 return machine()->Word32Or(); | 579 return machine()->Word32Or(); | 
| 456 case IrOpcode::kNumberBitwiseXor: | 580 case IrOpcode::kNumberBitwiseXor: | 
| 457 return machine()->Word32Xor(); | 581 return machine()->Word32Xor(); | 
| 458 case IrOpcode::kNumberBitwiseAnd: | 582 case IrOpcode::kNumberBitwiseAnd: | 
| 459 return machine()->Word32And(); | 583 return machine()->Word32And(); | 
| 460 case IrOpcode::kNumberEqual: | 584 case IrOpcode::kNumberEqual: | 
| 461 return machine()->Word32Equal(); | 585 return machine()->Word32Equal(); | 
| 462 case IrOpcode::kNumberLessThan: | 586 case IrOpcode::kNumberLessThan: | 
| 463 return machine()->Int32LessThan(); | 587 return machine()->Int32LessThan(); | 
| 464 case IrOpcode::kNumberLessThanOrEqual: | 588 case IrOpcode::kNumberLessThanOrEqual: | 
| 465 return machine()->Int32LessThanOrEqual(); | 589 return machine()->Int32LessThanOrEqual(); | 
| 466 default: | 590 default: | 
| 467 UNREACHABLE(); | 591 UNREACHABLE(); | 
| 468 return nullptr; | 592 return nullptr; | 
| 469 } | 593 } | 
| 470 } | 594 } | 
| 471 | 595 | 
| 596 const Operator* RepresentationChanger::Int32OverflowOperatorFor( | |
| 597 IrOpcode::Value opcode) { | |
| 598 switch (opcode) { | |
| 599 case IrOpcode::kSpeculativeNumberAdd: // Fall through. | |
| 600 return machine()->Int32AddWithOverflow(); | |
| 601 case IrOpcode::kSpeculativeNumberSubtract: // Fall through. | |
| 602 return machine()->Int32SubWithOverflow(); | |
| 603 default: | |
| 604 UNREACHABLE(); | |
| 605 return nullptr; | |
| 606 } | |
| 607 } | |
| 472 | 608 | 
| 473 const Operator* RepresentationChanger::Uint32OperatorFor( | 609 const Operator* RepresentationChanger::Uint32OperatorFor( | 
| 474 IrOpcode::Value opcode) { | 610 IrOpcode::Value opcode) { | 
| 475 switch (opcode) { | 611 switch (opcode) { | 
| 476 case IrOpcode::kNumberAdd: | 612 case IrOpcode::kNumberAdd: | 
| 477 return machine()->Int32Add(); | 613 return machine()->Int32Add(); | 
| 478 case IrOpcode::kNumberSubtract: | 614 case IrOpcode::kNumberSubtract: | 
| 479 return machine()->Int32Sub(); | 615 return machine()->Int32Sub(); | 
| 480 case IrOpcode::kNumberMultiply: | 616 case IrOpcode::kNumberMultiply: | 
| 481 return machine()->Int32Mul(); | 617 return machine()->Int32Mul(); | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 496 default: | 632 default: | 
| 497 UNREACHABLE(); | 633 UNREACHABLE(); | 
| 498 return nullptr; | 634 return nullptr; | 
| 499 } | 635 } | 
| 500 } | 636 } | 
| 501 | 637 | 
| 502 | 638 | 
| 503 const Operator* RepresentationChanger::Float64OperatorFor( | 639 const Operator* RepresentationChanger::Float64OperatorFor( | 
| 504 IrOpcode::Value opcode) { | 640 IrOpcode::Value opcode) { | 
| 505 switch (opcode) { | 641 switch (opcode) { | 
| 642 case IrOpcode::kSpeculativeNumberAdd: | |
| 506 case IrOpcode::kNumberAdd: | 643 case IrOpcode::kNumberAdd: | 
| 507 return machine()->Float64Add(); | 644 return machine()->Float64Add(); | 
| 645 case IrOpcode::kSpeculativeNumberSubtract: | |
| 508 case IrOpcode::kNumberSubtract: | 646 case IrOpcode::kNumberSubtract: | 
| 509 return machine()->Float64Sub(); | 647 return machine()->Float64Sub(); | 
| 510 case IrOpcode::kNumberMultiply: | 648 case IrOpcode::kNumberMultiply: | 
| 511 return machine()->Float64Mul(); | 649 return machine()->Float64Mul(); | 
| 512 case IrOpcode::kNumberDivide: | 650 case IrOpcode::kNumberDivide: | 
| 513 return machine()->Float64Div(); | 651 return machine()->Float64Div(); | 
| 514 case IrOpcode::kNumberModulus: | 652 case IrOpcode::kNumberModulus: | 
| 515 return machine()->Float64Mod(); | 653 return machine()->Float64Mod(); | 
| 516 case IrOpcode::kNumberEqual: | 654 case IrOpcode::kNumberEqual: | 
| 517 return machine()->Float64Equal(); | 655 return machine()->Float64Equal(); | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 } | 706 } | 
| 569 | 707 | 
| 570 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 708 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 
| 571 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 709 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 
| 572 node); | 710 node); | 
| 573 } | 711 } | 
| 574 | 712 | 
| 575 } // namespace compiler | 713 } // namespace compiler | 
| 576 } // namespace internal | 714 } // namespace internal | 
| 577 } // namespace v8 | 715 } // namespace v8 | 
| OLD | NEW |