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

Unified 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: Handle callers with args Created 5 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
index 1e2ab974854fd563640ae20861be9871eb9dfceb..4f91bfa7877c45b5eb720006bfb63345ce4cc356 100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -516,7 +516,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
DCHECK_EQ(IrOpcode::kCall, input->opcode());
BasicBlock* success = block->SuccessorAt(0);
BasicBlock* exception = block->SuccessorAt(1);
- return VisitCall(input, exception), VisitGoto(success);
+ return VisitCall(input, exception, NORMAL_CALL), VisitGoto(success);
}
case BasicBlock::kBranch: {
DCHECK_EQ(IrOpcode::kBranch, input->opcode());
@@ -559,7 +559,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
}
case BasicBlock::kReturn: {
DCHECK_EQ(IrOpcode::kReturn, input->opcode());
- return VisitReturn(input->InputAt(0));
+ return VisitReturn(input);
}
case BasicBlock::kDeoptimize: {
// If the result itself is a return, return its input.
@@ -636,7 +636,7 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitConstant(node);
}
case IrOpcode::kCall:
- return VisitCall(node, nullptr);
+ return VisitCall(node, nullptr, NORMAL_CALL);
case IrOpcode::kFrameState:
case IrOpcode::kStateValues:
return;
@@ -1041,7 +1041,40 @@ void InstructionSelector::VisitGoto(BasicBlock* target) {
}
-void InstructionSelector::VisitReturn(Node* value) {
+// Returns the call node if the given return node is part of a tail call,
+// nullptr otherwise.
+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.
+ // The value which is returned must be the result of a potential tail call,
+ // there must be no try/catch/finally around the call, and there must be no
+ // effects between the call and the return.
+ Node* call = NodeProperties::GetValueInput(ret, 0);
+ if (call->opcode() != IrOpcode::kCall ||
+ !OpParameter<const CallDescriptor*>(call)->IsTailCallAllowed() ||
+ NodeProperties::IsExceptionalCall(call) ||
+ NodeProperties::GetEffectInput(ret, 0) != call) {
+ return nullptr;
+ }
+ // Furthermore, control has to flow via an IfSuccess from the call (for calls
+ // which can throw), or the return and the call have to use the same control
+ // input (for calls which can't throw).
+ Node* control = NodeProperties::GetControlInput(ret, 0);
+ return ((control->opcode() == IrOpcode::kIfSuccess)
+ ? (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
+ : (control == NodeProperties::GetControlInput(call, 0)))
+ ? call
+ : nullptr;
+}
+
+
+void InstructionSelector::VisitReturn(Node* node) {
+ if (FLAG_turbo_tail_calls) {
+ Node* call = DetectTailCall(node);
+ if (call != nullptr &&
+ OpParameter<const CallDescriptor*>(call)->UsesOnlyRegisters()) {
+ return VisitCall(call, nullptr, TAIL_CALL);
+ }
+ }
+ Node* value = NodeProperties::GetValueInput(node, 0);
DCHECK_NOT_NULL(value);
OperandGenerator g(this);
Emit(kArchRet, g.NoOutput(),

Powered by Google App Engine
This is Rietveld 408576698