Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: src/compiler/instruction-selector.cc

Issue 1108563002: Detect simple tail calls (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixed index type Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698