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 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
509 #endif | 509 #endif |
510 | 510 |
511 Node* input = block->control_input(); | 511 Node* input = block->control_input(); |
512 switch (block->control()) { | 512 switch (block->control()) { |
513 case BasicBlock::kGoto: | 513 case BasicBlock::kGoto: |
514 return VisitGoto(block->SuccessorAt(0)); | 514 return VisitGoto(block->SuccessorAt(0)); |
515 case BasicBlock::kCall: { | 515 case BasicBlock::kCall: { |
516 DCHECK_EQ(IrOpcode::kCall, input->opcode()); | 516 DCHECK_EQ(IrOpcode::kCall, input->opcode()); |
517 BasicBlock* success = block->SuccessorAt(0); | 517 BasicBlock* success = block->SuccessorAt(0); |
518 BasicBlock* exception = block->SuccessorAt(1); | 518 BasicBlock* exception = block->SuccessorAt(1); |
519 return VisitCall(input, exception), VisitGoto(success); | 519 return VisitCall(input, exception, NORMAL_CALL), VisitGoto(success); |
520 } | 520 } |
521 case BasicBlock::kBranch: { | 521 case BasicBlock::kBranch: { |
522 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); | 522 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); |
523 BasicBlock* tbranch = block->SuccessorAt(0); | 523 BasicBlock* tbranch = block->SuccessorAt(0); |
524 BasicBlock* fbranch = block->SuccessorAt(1); | 524 BasicBlock* fbranch = block->SuccessorAt(1); |
525 if (tbranch == fbranch) return VisitGoto(tbranch); | 525 if (tbranch == fbranch) return VisitGoto(tbranch); |
526 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). | 526 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). |
527 Node* const condition = input->InputAt(0); | 527 Node* const condition = input->InputAt(0); |
528 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 528 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); |
529 return VisitBranch(input, tbranch, fbranch); | 529 return VisitBranch(input, tbranch, fbranch); |
(...skipping 22 matching lines...) Expand all Loading... | |
552 DCHECK_LE(sw.min_value, sw.max_value); | 552 DCHECK_LE(sw.min_value, sw.max_value); |
553 // Note that {value_range} can be 0 if {min_value} is -2^31 and | 553 // Note that {value_range} can be 0 if {min_value} is -2^31 and |
554 // {max_value} | 554 // {max_value} |
555 // is 2^31-1, so don't assume that it's non-zero below. | 555 // is 2^31-1, so don't assume that it's non-zero below. |
556 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - | 556 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - |
557 bit_cast<uint32_t>(sw.min_value); | 557 bit_cast<uint32_t>(sw.min_value); |
558 return VisitSwitch(input, sw); | 558 return VisitSwitch(input, sw); |
559 } | 559 } |
560 case BasicBlock::kReturn: { | 560 case BasicBlock::kReturn: { |
561 DCHECK_EQ(IrOpcode::kReturn, input->opcode()); | 561 DCHECK_EQ(IrOpcode::kReturn, input->opcode()); |
562 return VisitReturn(input->InputAt(0)); | 562 return VisitReturn(input); |
563 } | 563 } |
564 case BasicBlock::kDeoptimize: { | 564 case BasicBlock::kDeoptimize: { |
565 // If the result itself is a return, return its input. | 565 // If the result itself is a return, return its input. |
566 Node* value = | 566 Node* value = |
567 (input != nullptr && input->opcode() == IrOpcode::kDeoptimize) | 567 (input != nullptr && input->opcode() == IrOpcode::kDeoptimize) |
568 ? input->InputAt(0) | 568 ? input->InputAt(0) |
569 : input; | 569 : input; |
570 return VisitDeoptimize(value); | 570 return VisitDeoptimize(value); |
571 } | 571 } |
572 case BasicBlock::kThrow: | 572 case BasicBlock::kThrow: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 case IrOpcode::kFloat64Constant: | 629 case IrOpcode::kFloat64Constant: |
630 return MarkAsDouble(node), VisitConstant(node); | 630 return MarkAsDouble(node), VisitConstant(node); |
631 case IrOpcode::kHeapConstant: | 631 case IrOpcode::kHeapConstant: |
632 return MarkAsReference(node), VisitConstant(node); | 632 return MarkAsReference(node), VisitConstant(node); |
633 case IrOpcode::kNumberConstant: { | 633 case IrOpcode::kNumberConstant: { |
634 double value = OpParameter<double>(node); | 634 double value = OpParameter<double>(node); |
635 if (!IsSmiDouble(value)) MarkAsReference(node); | 635 if (!IsSmiDouble(value)) MarkAsReference(node); |
636 return VisitConstant(node); | 636 return VisitConstant(node); |
637 } | 637 } |
638 case IrOpcode::kCall: | 638 case IrOpcode::kCall: |
639 return VisitCall(node, nullptr); | 639 return VisitCall(node, nullptr, NORMAL_CALL); |
640 case IrOpcode::kFrameState: | 640 case IrOpcode::kFrameState: |
641 case IrOpcode::kStateValues: | 641 case IrOpcode::kStateValues: |
642 return; | 642 return; |
643 case IrOpcode::kLoad: { | 643 case IrOpcode::kLoad: { |
644 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); | 644 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); |
645 MarkAsRepresentation(rep, node); | 645 MarkAsRepresentation(rep, node); |
646 return VisitLoad(node); | 646 return VisitLoad(node); |
647 } | 647 } |
648 case IrOpcode::kStore: | 648 case IrOpcode::kStore: |
649 return VisitStore(node); | 649 return VisitStore(node); |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 } | 1034 } |
1035 | 1035 |
1036 | 1036 |
1037 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1037 void InstructionSelector::VisitGoto(BasicBlock* target) { |
1038 // jump to the next block. | 1038 // jump to the next block. |
1039 OperandGenerator g(this); | 1039 OperandGenerator g(this); |
1040 Emit(kArchJmp, g.NoOutput(), g.Label(target)); | 1040 Emit(kArchJmp, g.NoOutput(), g.Label(target)); |
1041 } | 1041 } |
1042 | 1042 |
1043 | 1043 |
1044 void InstructionSelector::VisitReturn(Node* value) { | 1044 // Returns the call node if the given return node is part of a tail call, |
1045 // nullptr otherwise. | |
1046 static Node* DetectTailCall(Node* ret) { | |
Benedikt Meurer
2015/04/29 04:06:05
Nit: Use anonymous namespace instead of static, an
Sven Panne
2015/04/29 10:24:18
Done.
| |
1047 // The value which is returned must be the result of a potential tail call, | |
1048 // there must be no try/catch/finally around the call, and there must be no | |
1049 // effects between the call and the return. | |
1050 Node* call = NodeProperties::GetValueInput(ret, 0); | |
1051 if (call->opcode() != IrOpcode::kCall || | |
1052 !OpParameter<const CallDescriptor*>(call)->IsTailCallAllowed() || | |
1053 NodeProperties::IsExceptionalCall(call) || | |
1054 NodeProperties::GetEffectInput(ret, 0) != call) { | |
1055 return nullptr; | |
1056 } | |
1057 // Furthermore, control has to flow via an IfSuccess from the call (for calls | |
1058 // which can throw), or the return and the call have to use the same control | |
1059 // input (for calls which can't throw). | |
1060 Node* control = NodeProperties::GetControlInput(ret, 0); | |
1061 return ((control->opcode() == IrOpcode::kIfSuccess) | |
1062 ? (NodeProperties::GetControlInput(control, 0) == call) | |
Benedikt Meurer
2015/04/29 04:06:05
Urghs, can we please not nest tenary operators?
Sven Panne
2015/04/29 10:24:18
Booh! Functional programming FTW! ;-) Nevertheless
| |
1063 : (control == NodeProperties::GetControlInput(call, 0))) | |
1064 ? call | |
1065 : nullptr; | |
1066 } | |
1067 | |
1068 | |
1069 void InstructionSelector::VisitReturn(Node* node) { | |
1070 if (FLAG_turbo_tail_calls) { | |
1071 Node* call = DetectTailCall(node); | |
1072 if (call != nullptr && | |
1073 OpParameter<const CallDescriptor*>(call)->UsesOnlyRegisters()) { | |
1074 return VisitCall(call, nullptr, TAIL_CALL); | |
1075 } | |
1076 } | |
1077 Node* value = NodeProperties::GetValueInput(node, 0); | |
1045 DCHECK_NOT_NULL(value); | 1078 DCHECK_NOT_NULL(value); |
1046 OperandGenerator g(this); | 1079 OperandGenerator g(this); |
1047 Emit(kArchRet, g.NoOutput(), | 1080 Emit(kArchRet, g.NoOutput(), |
1048 g.UseLocation(value, linkage()->GetReturnLocation(), | 1081 g.UseLocation(value, linkage()->GetReturnLocation(), |
1049 linkage()->GetReturnType())); | 1082 linkage()->GetReturnType())); |
1050 } | 1083 } |
1051 | 1084 |
1052 | 1085 |
1053 void InstructionSelector::VisitDeoptimize(Node* value) { | 1086 void InstructionSelector::VisitDeoptimize(Node* value) { |
1054 OperandGenerator g(this); | 1087 OperandGenerator g(this); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1192 MachineOperatorBuilder::Flags | 1225 MachineOperatorBuilder::Flags |
1193 InstructionSelector::SupportedMachineOperatorFlags() { | 1226 InstructionSelector::SupportedMachineOperatorFlags() { |
1194 return MachineOperatorBuilder::Flag::kNoFlags; | 1227 return MachineOperatorBuilder::Flag::kNoFlags; |
1195 } | 1228 } |
1196 | 1229 |
1197 #endif // !V8_TURBOFAN_BACKEND | 1230 #endif // !V8_TURBOFAN_BACKEND |
1198 | 1231 |
1199 } // namespace compiler | 1232 } // namespace compiler |
1200 } // namespace internal | 1233 } // namespace internal |
1201 } // namespace v8 | 1234 } // namespace v8 |
OLD | NEW |