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

Unified Diff: test/compiler-unittests/instruction-selector-unittest.cc

Issue 517323002: Make FrameStates recursive (to be used for inlining). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix bug in GetParentCount Created 6 years, 4 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: test/compiler-unittests/instruction-selector-unittest.cc
diff --git a/test/compiler-unittests/instruction-selector-unittest.cc b/test/compiler-unittests/instruction-selector-unittest.cc
index 1cf46f8728717d01f73d615ac72dfc930529a1d6..0f2859d2cc3455d9cf09f9ed5fe232dbdafe2508 100644
--- a/test/compiler-unittests/instruction-selector-unittest.cc
+++ b/test/compiler-unittests/instruction-selector-unittest.cc
@@ -339,8 +339,8 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
Node* locals = m.NewNode(m.common()->StateValues(0));
Node* stack = m.NewNode(m.common()->StateValues(0));
- Node* state_node =
- m.NewNode(m.common()->FrameState(bailout_id), parameters, locals, stack);
+ Node* state_node = m.NewNode(m.common()->FrameState(bailout_id), parameters,
+ locals, stack, m.UndefinedConstant());
m.Deoptimize(state_node);
Stream s = m.Build(kAllExceptNopInstructions);
@@ -376,8 +376,9 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
- Node* frame_state_before = m.NewNode(
- m.common()->FrameState(bailout_id_before), parameters, locals, stack);
+ Node* frame_state_before =
+ m.NewNode(m.common()->FrameState(bailout_id_before), parameters, locals,
+ stack, m.UndefinedConstant());
StreamBuilder::Label deopt, cont;
// Build the call.
@@ -397,8 +398,9 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
Node* stack_after =
m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
- Node* frame_state_after = m.NewNode(m.common()->FrameState(bailout_id_after),
- parameters, locals, stack_after);
+ Node* frame_state_after =
+ m.NewNode(m.common()->FrameState(bailout_id_after), parameters, locals,
+ stack_after, m.UndefinedConstant());
m.Deoptimize(frame_state_after);
Stream s = m.Build(kAllExceptNopInstructions);
@@ -466,6 +468,133 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
EXPECT_EQ(index, s.size());
}
+
+TARGET_TEST_F(InstructionSelectorTest,
+ CallFunctionStubDeoptRecursiveFrameState) {
+ StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
+ kMachAnyTagged);
+
+ BailoutId bailout_id_before(42);
+ BailoutId bailout_id_after(54);
+ BailoutId bailout_id_parent(62);
+
+ // Some arguments for the call node.
+ Node* function_node = m.Parameter(0);
+ Node* receiver = m.Parameter(1);
+ Node* context = m.Int32Constant(1); // Context is ignored.
+
+ // Build frame state for the state before the call.
+ Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(63));
+ Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(64));
+ Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(65));
+ Node* frame_state_parent =
+ m.NewNode(m.common()->FrameState(bailout_id_parent), parameters, locals,
+ stack, m.UndefinedConstant());
+
+ Node* parameters2 =
+ m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
+ Node* locals2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
+ Node* stack2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
+ Node* frame_state_before =
+ m.NewNode(m.common()->FrameState(bailout_id_before), parameters2, locals2,
+ stack2, frame_state_parent);
+
+ StreamBuilder::Label deopt, cont;
+ // Build the call.
+ Node* call =
+ m.CallFunctionStub0(function_node, receiver, context, frame_state_before,
+ &cont, &deopt, CALL_AS_METHOD);
+
+ // Create the continuation branch.
+ m.Bind(&cont);
+ m.NewNode(m.common()->Continuation(), call);
+ m.Return(call);
+
+ // Create the lazy deoptimization block (with a different frame state).
+ m.Bind(&deopt);
+ m.NewNode(m.common()->LazyDeoptimization(), call);
+
+ Node* parameters3 =
+ m.NewNode(m.common()->StateValues(1), m.Int32Constant(53));
+ Node* locals3 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(54));
+ Node* stack_after =
+ m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
+
+ Node* frame_state_after =
+ m.NewNode(m.common()->FrameState(bailout_id_after), parameters3, locals3,
+ stack_after, m.UndefinedConstant());
+ m.Deoptimize(frame_state_after);
+
+ Stream s = m.Build(kAllExceptNopInstructions);
+
+ // Skip until kArchCallJSFunction.
+ size_t index = 0;
+ for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject;
+ index++) {
+ }
+ // Now we should have three instructions: call, return and deoptimize.
+ ASSERT_EQ(index + 3, s.size());
+
+ // Check the call instruction
+ const Instruction* call_instr = s[index++];
+ EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode());
+ size_t num_operands =
+ 1 + // Code object.
+ 1 + // Frame state deopt id
+ 3 + // One input for each value in frame state.
+ 3 + // One input for each value in the parent frame state.
+ 1 + // Function.
+ 1 + // Context.
+ 2; // Continuation and deoptimization block labels.
+ ASSERT_EQ(num_operands, call_instr->InputCount());
+
+ // Code object.
+ EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate());
+
+ // Deoptimization id.
+ int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1));
+ FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before);
+ EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
+ EXPECT_EQ(1, desc_before->parameters_count());
+ EXPECT_EQ(1, desc_before->locals_count());
+ EXPECT_EQ(1, desc_before->stack_count());
+ EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
Jarin 2014/08/29 15:07:07 Hmm, could we put the parent values first here?
sigurds 2014/09/01 08:48:18 Done.
+ EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(3)));
+ EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(4)));
+ // Values from parent environment should follow.
+ EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(5)));
+ EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(6)));
+ EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(7)));
+
+ // Function.
+ EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(8)));
+ // Context.
+ EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(9)));
+ // Continuation.
+ EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(10)));
+ // Deoptimization.
+ EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(11)));
+
+ EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
+
+ // Check the deoptimize instruction.
+ const Instruction* deopt_instr = s[index++];
+ EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode());
+ ASSERT_EQ(5U, deopt_instr->InputCount());
+ int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0));
+ FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after);
+ EXPECT_EQ(bailout_id_after, desc_after->bailout_id());
+ EXPECT_EQ(1, desc_after->parameters_count());
+ EXPECT_EQ(1, desc_after->locals_count());
+ EXPECT_EQ(2, desc_after->stack_count());
+ // Parameter value from the frame state.
+ EXPECT_EQ(53, s.ToInt32(deopt_instr->InputAt(1)));
+ EXPECT_EQ(54, s.ToInt32(deopt_instr->InputAt(2)));
+ EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3)));
+ EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4)));
+ EXPECT_EQ(index, s.size());
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
« src/compiler/instruction-selector.cc ('K') | « test/cctest/compiler/test-codegen-deopt.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698