Index: test/unittests/compiler/instruction-selector-unittest.cc |
diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc |
index 645b0f689b7a32961295d288b20ab6a983e242c0..4f0aba1067f9efb526b13df7ed452d76a2de4505 100644 |
--- a/test/unittests/compiler/instruction-selector-unittest.cc |
+++ b/test/unittests/compiler/instruction-selector-unittest.cc |
@@ -4,6 +4,7 @@ |
#include "test/unittests/compiler/instruction-selector-unittest.h" |
+#include "src/code-stubs.h" |
#include "src/compiler/graph.h" |
#include "src/compiler/schedule.h" |
#include "src/flags.h" |
@@ -590,6 +591,53 @@ TARGET_TEST_F(InstructionSelectorTest, |
EXPECT_EQ(index, s.size()); |
} |
+ |
+// ----------------------------------------------------------------------------- |
+// Tail calls. |
+ |
+TARGET_TEST_F(InstructionSelectorTest, TailCall) { |
+ for (int mode = 0; mode < 2; ++mode) { |
+ bool supports_tail_calls = FLAG_turbo_tail_calls && (mode == 0); |
+ |
+ StreamBuilder m(this, kMachAnyTagged); |
+ Node* start = m.graph()->start(); |
+ Node* undefined = m.UndefinedConstant(); |
+ |
+ StringLengthStub stub(isolate()); |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ isolate(), zone(), stub.GetCallInterfaceDescriptor(), 0, |
+ supports_tail_calls ? CallDescriptor::kSupportsTailCalls |
+ : CallDescriptor::kNoFlags, |
+ Operator::kNoProperties); |
+ Node* stub_node = m.NewNode(m.common()->HeapConstant( |
+ Unique<Code>::CreateUninitialized(stub.GetCode()))); |
+ |
+ Node* call = m.NewNode(m.common()->Call(desc), stub_node, undefined, |
+ undefined, undefined, undefined, undefined); |
+ call->AppendInput(zone(), start); // effect |
+ call->AppendInput(zone(), start); // control |
+ |
+ m.Return(call); |
+ Node* ret = *call->uses().begin(); |
+ ret->AppendInput(zone(), call); // effect |
+ ret->AppendInput(zone(), start); // control |
+ |
+ Stream s = m.Build(kAllInstructions); |
+ if (supports_tail_calls) { |
+ ASSERT_EQ(3U, s.size()); |
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode()); |
+ EXPECT_EQ(kArchTailCallCodeObject, s[1]->arch_opcode()); |
+ EXPECT_EQ(kArchNop, s[2]->arch_opcode()); |
+ } else { |
+ ASSERT_EQ(4U, s.size()); |
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode()); |
+ EXPECT_EQ(kArchCallCodeObject, s[1]->arch_opcode()); |
+ EXPECT_EQ(kArchRet, s[2]->arch_opcode()); |
+ EXPECT_EQ(kArchNop, s[3]->arch_opcode()); |
+ } |
+ } |
+} |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |