OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/adapters.h" | 9 #include "src/base/adapters.h" |
10 #include "src/compiler/instruction-selector-impl.h" | 10 #include "src/compiler/instruction-selector-impl.h" |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 #endif | 456 #endif |
457 | 457 |
458 Node* input = block->control_input(); | 458 Node* input = block->control_input(); |
459 switch (block->control()) { | 459 switch (block->control()) { |
460 case BasicBlock::kGoto: | 460 case BasicBlock::kGoto: |
461 return VisitGoto(block->SuccessorAt(0)); | 461 return VisitGoto(block->SuccessorAt(0)); |
462 case BasicBlock::kCall: { | 462 case BasicBlock::kCall: { |
463 DCHECK_EQ(IrOpcode::kCall, input->opcode()); | 463 DCHECK_EQ(IrOpcode::kCall, input->opcode()); |
464 BasicBlock* success = block->SuccessorAt(0); | 464 BasicBlock* success = block->SuccessorAt(0); |
465 BasicBlock* exception = block->SuccessorAt(1); | 465 BasicBlock* exception = block->SuccessorAt(1); |
466 return VisitCall(input, exception), VisitGoto(success); | 466 return VisitCall(input, exception, NORMAL_CALL), VisitGoto(success); |
467 } | 467 } |
468 case BasicBlock::kBranch: { | 468 case BasicBlock::kBranch: { |
469 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); | 469 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); |
470 BasicBlock* tbranch = block->SuccessorAt(0); | 470 BasicBlock* tbranch = block->SuccessorAt(0); |
471 BasicBlock* fbranch = block->SuccessorAt(1); | 471 BasicBlock* fbranch = block->SuccessorAt(1); |
472 if (tbranch == fbranch) return VisitGoto(tbranch); | 472 if (tbranch == fbranch) return VisitGoto(tbranch); |
473 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). | 473 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). |
474 Node* const condition = input->InputAt(0); | 474 Node* const condition = input->InputAt(0); |
475 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 475 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); |
476 return VisitBranch(input, tbranch, fbranch); | 476 return VisitBranch(input, tbranch, fbranch); |
(...skipping 22 matching lines...) Expand all Loading... |
499 DCHECK_LE(sw.min_value, sw.max_value); | 499 DCHECK_LE(sw.min_value, sw.max_value); |
500 // Note that {value_range} can be 0 if {min_value} is -2^31 and | 500 // Note that {value_range} can be 0 if {min_value} is -2^31 and |
501 // {max_value} | 501 // {max_value} |
502 // is 2^31-1, so don't assume that it's non-zero below. | 502 // is 2^31-1, so don't assume that it's non-zero below. |
503 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - | 503 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - |
504 bit_cast<uint32_t>(sw.min_value); | 504 bit_cast<uint32_t>(sw.min_value); |
505 return VisitSwitch(input, sw); | 505 return VisitSwitch(input, sw); |
506 } | 506 } |
507 case BasicBlock::kReturn: { | 507 case BasicBlock::kReturn: { |
508 DCHECK_EQ(IrOpcode::kReturn, input->opcode()); | 508 DCHECK_EQ(IrOpcode::kReturn, input->opcode()); |
509 return VisitReturn(input->InputAt(0)); | 509 return VisitReturn(input); |
510 } | 510 } |
511 case BasicBlock::kDeoptimize: { | 511 case BasicBlock::kDeoptimize: { |
512 // If the result itself is a return, return its input. | 512 // If the result itself is a return, return its input. |
513 Node* value = | 513 Node* value = |
514 (input != nullptr && input->opcode() == IrOpcode::kDeoptimize) | 514 (input != nullptr && input->opcode() == IrOpcode::kDeoptimize) |
515 ? input->InputAt(0) | 515 ? input->InputAt(0) |
516 : input; | 516 : input; |
517 return VisitDeoptimize(value); | 517 return VisitDeoptimize(value); |
518 } | 518 } |
519 case BasicBlock::kThrow: | 519 case BasicBlock::kThrow: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 case IrOpcode::kFloat64Constant: | 576 case IrOpcode::kFloat64Constant: |
577 return MarkAsFloat64(node), VisitConstant(node); | 577 return MarkAsFloat64(node), VisitConstant(node); |
578 case IrOpcode::kHeapConstant: | 578 case IrOpcode::kHeapConstant: |
579 return MarkAsReference(node), VisitConstant(node); | 579 return MarkAsReference(node), VisitConstant(node); |
580 case IrOpcode::kNumberConstant: { | 580 case IrOpcode::kNumberConstant: { |
581 double value = OpParameter<double>(node); | 581 double value = OpParameter<double>(node); |
582 if (!IsSmiDouble(value)) MarkAsReference(node); | 582 if (!IsSmiDouble(value)) MarkAsReference(node); |
583 return VisitConstant(node); | 583 return VisitConstant(node); |
584 } | 584 } |
585 case IrOpcode::kCall: | 585 case IrOpcode::kCall: |
586 return VisitCall(node, nullptr); | 586 return VisitCall(node, nullptr, NORMAL_CALL); |
587 case IrOpcode::kFrameState: | 587 case IrOpcode::kFrameState: |
588 case IrOpcode::kStateValues: | 588 case IrOpcode::kStateValues: |
589 return; | 589 return; |
590 case IrOpcode::kLoad: { | 590 case IrOpcode::kLoad: { |
591 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); | 591 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
592 MarkAsRepresentation(rep, node); | 592 MarkAsRepresentation(rep, node); |
593 return VisitLoad(node); | 593 return VisitLoad(node); |
594 } | 594 } |
595 case IrOpcode::kStore: | 595 case IrOpcode::kStore: |
596 return VisitStore(node); | 596 return VisitStore(node); |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 } | 981 } |
982 | 982 |
983 | 983 |
984 void InstructionSelector::VisitGoto(BasicBlock* target) { | 984 void InstructionSelector::VisitGoto(BasicBlock* target) { |
985 // jump to the next block. | 985 // jump to the next block. |
986 OperandGenerator g(this); | 986 OperandGenerator g(this); |
987 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 987 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
988 } | 988 } |
989 | 989 |
990 | 990 |
991 void InstructionSelector::VisitReturn(Node* value) { | 991 namespace { |
| 992 |
| 993 // Returns the call node if the given return node is part of a tail call, |
| 994 // nullptr otherwise. |
| 995 Node* TryMatchTailCall(Node* ret) { |
| 996 // The value which is returned must be the result of a potential tail call, |
| 997 // there must be no try/catch/finally around the call, and there must be no |
| 998 // effects between the call and the return. |
| 999 Node* call = NodeProperties::GetValueInput(ret, 0); |
| 1000 if (call->opcode() != IrOpcode::kCall || |
| 1001 !OpParameter<const CallDescriptor*>(call)->SupportsTailCalls() || |
| 1002 NodeProperties::IsExceptionalCall(call) || |
| 1003 NodeProperties::GetEffectInput(ret, 0) != call) { |
| 1004 return nullptr; |
| 1005 } |
| 1006 // Furthermore, control has to flow via an IfSuccess from the call (for calls |
| 1007 // which can throw), or the return and the call have to use the same control |
| 1008 // input (for calls which can't throw). |
| 1009 Node* control = NodeProperties::GetControlInput(ret, 0); |
| 1010 bool found = (control->opcode() == IrOpcode::kIfSuccess) |
| 1011 ? (NodeProperties::GetControlInput(control, 0) == call) |
| 1012 : (control == NodeProperties::GetControlInput(call, 0)); |
| 1013 return found ? call : nullptr; |
| 1014 } |
| 1015 |
| 1016 } // namespace |
| 1017 |
| 1018 |
| 1019 void InstructionSelector::VisitReturn(Node* node) { |
| 1020 if (FLAG_turbo_tail_calls) { |
| 1021 Node* call = TryMatchTailCall(node); |
| 1022 if (call != nullptr) { |
| 1023 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(call); |
| 1024 if (desc->UsesOnlyRegisters() && |
| 1025 desc->HasSameReturnLocationsAs(linkage()->GetIncomingDescriptor())) { |
| 1026 return VisitCall(call, nullptr, TAIL_CALL); |
| 1027 } |
| 1028 } |
| 1029 } |
| 1030 Node* value = NodeProperties::GetValueInput(node, 0); |
992 DCHECK_NOT_NULL(value); | 1031 DCHECK_NOT_NULL(value); |
993 OperandGenerator g(this); | 1032 OperandGenerator g(this); |
994 Emit(kArchRet, g.NoOutput(), | 1033 Emit(kArchRet, g.NoOutput(), |
995 g.UseLocation(value, linkage()->GetReturnLocation(), | 1034 g.UseLocation(value, linkage()->GetReturnLocation(), |
996 linkage()->GetReturnType())); | 1035 linkage()->GetReturnType())); |
997 } | 1036 } |
998 | 1037 |
999 | 1038 |
1000 void InstructionSelector::VisitDeoptimize(Node* value) { | 1039 void InstructionSelector::VisitDeoptimize(Node* value) { |
1001 OperandGenerator g(this); | 1040 OperandGenerator g(this); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 | 1151 |
1113 | 1152 |
1114 #if !V8_TURBOFAN_BACKEND | 1153 #if !V8_TURBOFAN_BACKEND |
1115 | 1154 |
1116 #define DECLARE_UNIMPLEMENTED_SELECTOR(x) \ | 1155 #define DECLARE_UNIMPLEMENTED_SELECTOR(x) \ |
1117 void InstructionSelector::Visit##x(Node* node) { UNIMPLEMENTED(); } | 1156 void InstructionSelector::Visit##x(Node* node) { UNIMPLEMENTED(); } |
1118 MACHINE_OP_LIST(DECLARE_UNIMPLEMENTED_SELECTOR) | 1157 MACHINE_OP_LIST(DECLARE_UNIMPLEMENTED_SELECTOR) |
1119 #undef DECLARE_UNIMPLEMENTED_SELECTOR | 1158 #undef DECLARE_UNIMPLEMENTED_SELECTOR |
1120 | 1159 |
1121 | 1160 |
1122 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 1161 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler, |
| 1162 CallMode call_mode) { |
1123 UNIMPLEMENTED(); | 1163 UNIMPLEMENTED(); |
1124 } | 1164 } |
1125 | 1165 |
1126 | 1166 |
1127 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1167 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
1128 BasicBlock* fbranch) { | 1168 BasicBlock* fbranch) { |
1129 UNIMPLEMENTED(); | 1169 UNIMPLEMENTED(); |
1130 } | 1170 } |
1131 | 1171 |
1132 | 1172 |
1133 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1173 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
1134 UNIMPLEMENTED(); | 1174 UNIMPLEMENTED(); |
1135 } | 1175 } |
1136 | 1176 |
1137 | 1177 |
1138 // static | 1178 // static |
1139 MachineOperatorBuilder::Flags | 1179 MachineOperatorBuilder::Flags |
1140 InstructionSelector::SupportedMachineOperatorFlags() { | 1180 InstructionSelector::SupportedMachineOperatorFlags() { |
1141 return MachineOperatorBuilder::Flag::kNoFlags; | 1181 return MachineOperatorBuilder::Flag::kNoFlags; |
1142 } | 1182 } |
1143 | 1183 |
1144 #endif // !V8_TURBOFAN_BACKEND | 1184 #endif // !V8_TURBOFAN_BACKEND |
1145 | 1185 |
1146 } // namespace compiler | 1186 } // namespace compiler |
1147 } // namespace internal | 1187 } // namespace internal |
1148 } // namespace v8 | 1188 } // namespace v8 |
OLD | NEW |