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

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

Issue 505133002: Unit test of instruction selection for calls with deoptimization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address review comments. Created 6 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/compiler-unittests/instruction-selector-unittest.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "test/compiler-unittests/instruction-selector-unittest.h" 5 #include "test/compiler-unittests/instruction-selector-unittest.h"
6 6
7 #include "src/flags.h" 7 #include "src/flags.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 switch (instr->arch_opcode()) { 50 switch (instr->arch_opcode()) {
51 #define CASE(Name) \ 51 #define CASE(Name) \
52 case k##Name: \ 52 case k##Name: \
53 break; 53 break;
54 TARGET_ARCH_OPCODE_LIST(CASE) 54 TARGET_ARCH_OPCODE_LIST(CASE)
55 #undef CASE 55 #undef CASE
56 default: 56 default:
57 continue; 57 continue;
58 } 58 }
59 } 59 }
60 if (mode == kAllExceptNopInstructions && instr->arch_opcode() == kArchNop) {
61 continue;
62 }
60 for (size_t i = 0; i < instr->OutputCount(); ++i) { 63 for (size_t i = 0; i < instr->OutputCount(); ++i) {
61 InstructionOperand* output = instr->OutputAt(i); 64 InstructionOperand* output = instr->OutputAt(i);
62 EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind()); 65 EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind());
63 if (output->IsConstant()) { 66 if (output->IsConstant()) {
64 s.constants_.insert(std::make_pair( 67 s.constants_.insert(std::make_pair(
65 output->index(), sequence.GetConstant(output->index()))); 68 output->index(), sequence.GetConstant(output->index())));
66 virtual_registers.insert(output->index()); 69 virtual_registers.insert(output->index());
67 } else if (output->IsUnallocated()) { 70 } else if (output->IsUnallocated()) {
68 virtual_registers.insert( 71 virtual_registers.insert(
69 UnallocatedOperand::cast(output)->virtual_register()); 72 UnallocatedOperand::cast(output)->virtual_register());
(...skipping 17 matching lines...) Expand all
87 int virtual_register = *i; 90 int virtual_register = *i;
88 if (sequence.IsDouble(virtual_register)) { 91 if (sequence.IsDouble(virtual_register)) {
89 EXPECT_FALSE(sequence.IsReference(virtual_register)); 92 EXPECT_FALSE(sequence.IsReference(virtual_register));
90 s.doubles_.insert(virtual_register); 93 s.doubles_.insert(virtual_register);
91 } 94 }
92 if (sequence.IsReference(virtual_register)) { 95 if (sequence.IsReference(virtual_register)) {
93 EXPECT_FALSE(sequence.IsDouble(virtual_register)); 96 EXPECT_FALSE(sequence.IsDouble(virtual_register));
94 s.references_.insert(virtual_register); 97 s.references_.insert(virtual_register);
95 } 98 }
96 } 99 }
100 for (int i = 0; i < sequence.GetDeoptimizationEntryCount(); i++) {
101 s.deoptimization_entries_.push_back(sequence.GetDeoptimizationEntry(i));
102 }
97 return s; 103 return s;
98 } 104 }
99 105
100 106
101 // ----------------------------------------------------------------------------- 107 // -----------------------------------------------------------------------------
102 // Return. 108 // Return.
103 109
104 110
105 TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) { 111 TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
106 StreamBuilder m(this, kMachInt32, kMachInt32); 112 StreamBuilder m(this, kMachInt32, kMachInt32);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 ASSERT_EQ(s1.size(), s2.size()); 306 ASSERT_EQ(s1.size(), s2.size());
301 TRACED_FORRANGE(size_t, i, 0, s1.size() - 1) { 307 TRACED_FORRANGE(size_t, i, 0, s1.size() - 1) {
302 const Instruction* i1 = s1[i]; 308 const Instruction* i1 = s1[i];
303 const Instruction* i2 = s2[i]; 309 const Instruction* i2 = s2[i];
304 EXPECT_EQ(i1->arch_opcode(), i2->arch_opcode()); 310 EXPECT_EQ(i1->arch_opcode(), i2->arch_opcode());
305 EXPECT_EQ(i1->InputCount(), i2->InputCount()); 311 EXPECT_EQ(i1->InputCount(), i2->InputCount());
306 EXPECT_EQ(i1->OutputCount(), i2->OutputCount()); 312 EXPECT_EQ(i1->OutputCount(), i2->OutputCount());
307 } 313 }
308 } 314 }
309 315
316
317 // -----------------------------------------------------------------------------
318 // Calls with deoptimization.
319 TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
320 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged);
321
322 BailoutId bailout_id(42);
323
324 Node* function_node = m.Parameter(0);
325 Node* receiver = m.Parameter(1);
326 StreamBuilder::Label deopt, cont;
327
328 // TODO(jarin) Add frame state.
329 Node* call = m.CallJS0(function_node, receiver, &cont, &deopt);
330
331 m.Bind(&cont);
332 m.NewNode(m.common()->Continuation(), call);
333 m.Return(call);
334
335 m.Bind(&deopt);
336 m.NewNode(m.common()->LazyDeoptimization(), call);
337
338 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1));
339 Node* locals = m.NewNode(m.common()->StateValues(0));
340 Node* stack = m.NewNode(m.common()->StateValues(0));
341
342 Node* state_node =
343 m.NewNode(m.common()->FrameState(bailout_id), parameters, locals, stack);
344 m.Deoptimize(state_node);
345
346 Stream s = m.Build(kAllExceptNopInstructions);
347
348 // Skip until kArchCallJSFunction.
349 size_t index = 0;
350 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction;
351 index++) {
352 }
353 // Now we should have three instructions: call, return and deoptimize.
354 ASSERT_EQ(index + 3, s.size());
355
356 EXPECT_EQ(kArchCallJSFunction, s[index++]->arch_opcode());
357 EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
358 EXPECT_EQ(kArchDeoptimize, s[index++]->arch_opcode());
359 EXPECT_EQ(index, s.size());
360 }
361
362
363 TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
364 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
365 kMachAnyTagged);
366
367 BailoutId bailout_id_before(42);
368 BailoutId bailout_id_after(54);
369
370 // Some arguments for the call node.
371 Node* function_node = m.Parameter(0);
372 Node* receiver = m.Parameter(1);
373 Node* context = m.Int32Constant(1); // Context is ignored.
374
375 // Build frame state for the state before the call.
376 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
377 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
378 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
379 Node* frame_state_before = m.NewNode(
380 m.common()->FrameState(bailout_id_before), parameters, locals, stack);
381
382 StreamBuilder::Label deopt, cont;
383 // Build the call.
384 Node* call =
385 m.CallFunctionStub0(function_node, receiver, context, frame_state_before,
386 &cont, &deopt, CALL_AS_METHOD);
387
388 // Create the continuation branch.
389 m.Bind(&cont);
390 m.NewNode(m.common()->Continuation(), call);
391 m.Return(call);
392
393 // Create the lazy deoptimization block (with a different frame state).
394 m.Bind(&deopt);
395 m.NewNode(m.common()->LazyDeoptimization(), call);
396
397 Node* stack_after =
398 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
399
400 Node* frame_state_after = m.NewNode(m.common()->FrameState(bailout_id_after),
401 parameters, locals, stack_after);
402 m.Deoptimize(frame_state_after);
403
404 Stream s = m.Build(kAllExceptNopInstructions);
405
406 // Skip until kArchCallJSFunction.
407 size_t index = 0;
408 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject;
409 index++) {
410 }
411 // Now we should have three instructions: call, return and deoptimize.
412 ASSERT_EQ(index + 3, s.size());
413
414 // Check the call instruction
415 const Instruction* call_instr = s[index++];
416 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode());
417 size_t num_operands =
418 1 + // Code object.
419 1 +
420 3 + // Frame state deopt id + one input for each value in frame state.
421 1 + // Function.
422 1 + // Context.
423 2; // Continuation and deoptimization block labels.
424 ASSERT_EQ(num_operands, call_instr->InputCount());
425
426 // Code object.
427 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate());
428
429 // Deoptimization id.
430 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1));
431 FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before);
432 EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
433 EXPECT_EQ(1, desc_before->parameters_count());
434 EXPECT_EQ(1, desc_before->locals_count());
435 EXPECT_EQ(1, desc_before->stack_count());
436 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
437 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(3)));
438 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(4)));
439
440 // Function.
441 EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(5)));
442 // Context.
443 EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(6)));
444 // Continuation.
445 EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(7)));
446 // Deoptimization.
447 EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(8)));
448
449 EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
450
451 // Check the deoptimize instruction.
452 const Instruction* deopt_instr = s[index++];
453 EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode());
454 ASSERT_EQ(5U, deopt_instr->InputCount());
455 int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0));
456 FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after);
457 EXPECT_EQ(bailout_id_after, desc_after->bailout_id());
458 EXPECT_EQ(1, desc_after->parameters_count());
459 EXPECT_EQ(1, desc_after->locals_count());
460 EXPECT_EQ(2, desc_after->stack_count());
461 // Parameter value from the frame state.
462 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1)));
463 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(2)));
464 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3)));
465 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4)));
466 EXPECT_EQ(index, s.size());
467 }
468
310 } // namespace compiler 469 } // namespace compiler
311 } // namespace internal 470 } // namespace internal
312 } // namespace v8 471 } // namespace v8
OLDNEW
« no previous file with comments | « test/compiler-unittests/instruction-selector-unittest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698