Chromium Code Reviews| 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 |