| Index: src/compiler/instruction-selector.cc
|
| diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
|
| index 92ac241127f39f26c13dbbe2b50c645cf401cc27..0569ab70844756d4e0a675cade887efabc2cc751 100644
|
| --- a/src/compiler/instruction-selector.cc
|
| +++ b/src/compiler/instruction-selector.cc
|
| @@ -1072,6 +1072,79 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
|
| }
|
|
|
|
|
| +void InstructionSelector::VisitTailCall(Node* node) {
|
| + OperandGenerator g(this);
|
| + CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node);
|
| + DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
|
| + DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite);
|
| + DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall);
|
| +
|
| + // TODO(turbofan): Relax restriction for stack parameters.
|
| +
|
| + if (linkage()->GetIncomingDescriptor()->CanTailCall(node)) {
|
| + CallBuffer buffer(zone(), descriptor, nullptr);
|
| +
|
| + // Compute InstructionOperands for inputs and outputs.
|
| + InitializeCallBuffer(node, &buffer, true, true);
|
| +
|
| + // Select the appropriate opcode based on the call type.
|
| + InstructionCode opcode;
|
| + switch (descriptor->kind()) {
|
| + case CallDescriptor::kCallCodeObject:
|
| + opcode = kArchTailCallCodeObject;
|
| + break;
|
| + case CallDescriptor::kCallJSFunction:
|
| + opcode = kArchTailCallJSFunction;
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + return;
|
| + }
|
| + opcode |= MiscField::encode(descriptor->flags());
|
| +
|
| + // Emit the tailcall instruction.
|
| + Emit(opcode, 0, nullptr, buffer.instruction_args.size(),
|
| + &buffer.instruction_args.front());
|
| + } else {
|
| + FrameStateDescriptor* frame_state_descriptor =
|
| + descriptor->NeedsFrameState()
|
| + ? GetFrameStateDescriptor(
|
| + node->InputAt(static_cast<int>(descriptor->InputCount())))
|
| + : nullptr;
|
| +
|
| + CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
|
| +
|
| + // Compute InstructionOperands for inputs and outputs.
|
| + InitializeCallBuffer(node, &buffer, true, IsTailCallAddressImmediate());
|
| +
|
| + EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
|
| +
|
| + // Select the appropriate opcode based on the call type.
|
| + InstructionCode opcode;
|
| + switch (descriptor->kind()) {
|
| + case CallDescriptor::kCallCodeObject:
|
| + opcode = kArchCallCodeObject;
|
| + break;
|
| + case CallDescriptor::kCallJSFunction:
|
| + opcode = kArchCallJSFunction;
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + return;
|
| + }
|
| + opcode |= MiscField::encode(descriptor->flags());
|
| +
|
| + // Emit the call instruction.
|
| + size_t output_count = buffer.outputs.size();
|
| + auto* outputs = &buffer.outputs.front();
|
| + Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
|
| + &buffer.instruction_args.front())
|
| + ->MarkAsCall();
|
| + Emit(kArchRet, 0, nullptr, output_count, outputs);
|
| + }
|
| +}
|
| +
|
| +
|
| void InstructionSelector::VisitGoto(BasicBlock* target) {
|
| // jump to the next block.
|
| OperandGenerator g(this);
|
|
|