| 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 |