| Index: src/compiler/tail-call-optimization.cc
|
| diff --git a/src/compiler/tail-call-optimization.cc b/src/compiler/tail-call-optimization.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a88ebe3e63d6f5d220a6958860953ec9b82b869b
|
| --- /dev/null
|
| +++ b/src/compiler/tail-call-optimization.cc
|
| @@ -0,0 +1,83 @@
|
| +// Copyright 2015 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/compiler/tail-call-optimization.h"
|
| +
|
| +#include "src/compiler/common-operator.h"
|
| +#include "src/compiler/graph.h"
|
| +#include "src/compiler/linkage.h"
|
| +#include "src/compiler/node-properties.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace compiler {
|
| +
|
| +Reduction TailCallOptimization::Reduce(Node* node) {
|
| + if (node->opcode() != IrOpcode::kReturn) return NoChange();
|
| + // 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
|
| + // other effect between the Call and the Return nodes.
|
| + Node* const call = NodeProperties::GetValueInput(node, 0);
|
| + if (call->opcode() == IrOpcode::kCall &&
|
| + OpParameter<CallDescriptor const*>(call)->SupportsTailCalls() &&
|
| + NodeProperties::GetEffectInput(node) == call &&
|
| + !NodeProperties::IsExceptionalCall(call)) {
|
| + Node* const control = NodeProperties::GetControlInput(node);
|
| + if (control->opcode() == IrOpcode::kIfSuccess &&
|
| + call->OwnedBy(node, control) && control->OwnedBy(node)) {
|
| + // Furthermore, control has to flow via an IfSuccess from the Call, so
|
| + // the Return node value and effect depends directly on the Call node,
|
| + // and indirectly control depends on the Call via an IfSuccess.
|
| +
|
| + // Value1 ... ValueN Effect Control
|
| + // ^ ^ ^ ^
|
| + // | | | |
|
| + // | +--+ +-+ |
|
| + // +----------+ | | +------+
|
| + // \ | | /
|
| + // Call[Descriptor]
|
| + // ^ ^ ^
|
| + // | | |
|
| + // +-+ | |
|
| + // | | |
|
| + // | +-+ |
|
| + // | | IfSuccess
|
| + // | | ^
|
| + // | | |
|
| + // Return
|
| + // ^
|
| + // |
|
| +
|
| + // The resulting graph looks like this:
|
| +
|
| + // Value1 ... ValueN Effect Control
|
| + // ^ ^ ^ ^
|
| + // | | | |
|
| + // | +--+ +-+ |
|
| + // +----------+ | | +------+
|
| + // \ | | /
|
| + // TailCall[Descriptor]
|
| + // ^
|
| + // |
|
| +
|
| + DCHECK_EQ(call, NodeProperties::GetControlInput(control, 0));
|
| + DCHECK_EQ(3, node->InputCount());
|
| + node->set_op(
|
| + common()->TailCall(OpParameter<CallDescriptor const*>(call)));
|
| + node->ReplaceInput(0, NodeProperties::GetEffectInput(call));
|
| + node->ReplaceInput(1, NodeProperties::GetControlInput(call));
|
| + node->RemoveInput(2);
|
| + for (int index = 0; index < call->op()->ValueInputCount(); ++index) {
|
| + node->InsertInput(graph()->zone(), index,
|
| + NodeProperties::GetValueInput(call, index));
|
| + }
|
| + return Changed(node);
|
| + }
|
| + }
|
| + return NoChange();
|
| +}
|
| +
|
| +} // namespace compiler
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|