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

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: Make the test platform independent. 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 == kAllWithoutNopInstructions &&
61 instr->arch_opcode() == kArchNop) {
62 continue;
63 }
60 for (size_t i = 0; i < instr->OutputCount(); ++i) { 64 for (size_t i = 0; i < instr->OutputCount(); ++i) {
61 InstructionOperand* output = instr->OutputAt(i); 65 InstructionOperand* output = instr->OutputAt(i);
62 EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind()); 66 EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind());
63 if (output->IsConstant()) { 67 if (output->IsConstant()) {
64 s.constants_.insert(std::make_pair( 68 s.constants_.insert(std::make_pair(
65 output->index(), sequence.GetConstant(output->index()))); 69 output->index(), sequence.GetConstant(output->index())));
66 virtual_registers.insert(output->index()); 70 virtual_registers.insert(output->index());
67 } else if (output->IsUnallocated()) { 71 } else if (output->IsUnallocated()) {
68 virtual_registers.insert( 72 virtual_registers.insert(
69 UnallocatedOperand::cast(output)->virtual_register()); 73 UnallocatedOperand::cast(output)->virtual_register());
(...skipping 17 matching lines...) Expand all
87 int virtual_register = *i; 91 int virtual_register = *i;
88 if (sequence.IsDouble(virtual_register)) { 92 if (sequence.IsDouble(virtual_register)) {
89 EXPECT_FALSE(sequence.IsReference(virtual_register)); 93 EXPECT_FALSE(sequence.IsReference(virtual_register));
90 s.doubles_.insert(virtual_register); 94 s.doubles_.insert(virtual_register);
91 } 95 }
92 if (sequence.IsReference(virtual_register)) { 96 if (sequence.IsReference(virtual_register)) {
93 EXPECT_FALSE(sequence.IsDouble(virtual_register)); 97 EXPECT_FALSE(sequence.IsDouble(virtual_register));
94 s.references_.insert(virtual_register); 98 s.references_.insert(virtual_register);
95 } 99 }
96 } 100 }
101 for (int i = 0; i < sequence.GetDeoptimizationEntryCount(); i++) {
102 s.deoptimization_entries_.push_back(sequence.GetDeoptimizationEntry(i));
103 }
97 return s; 104 return s;
98 } 105 }
99 106
100 107
101 // ----------------------------------------------------------------------------- 108 // -----------------------------------------------------------------------------
102 // Return. 109 // Return.
103 110
104 111
105 TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) { 112 TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
106 StreamBuilder m(this, kMachInt32, kMachInt32); 113 StreamBuilder m(this, kMachInt32, kMachInt32);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 ASSERT_EQ(s1.size(), s2.size()); 307 ASSERT_EQ(s1.size(), s2.size());
301 TRACED_FORRANGE(size_t, i, 0, s1.size() - 1) { 308 TRACED_FORRANGE(size_t, i, 0, s1.size() - 1) {
302 const Instruction* i1 = s1[i]; 309 const Instruction* i1 = s1[i];
303 const Instruction* i2 = s2[i]; 310 const Instruction* i2 = s2[i];
304 EXPECT_EQ(i1->arch_opcode(), i2->arch_opcode()); 311 EXPECT_EQ(i1->arch_opcode(), i2->arch_opcode());
305 EXPECT_EQ(i1->InputCount(), i2->InputCount()); 312 EXPECT_EQ(i1->InputCount(), i2->InputCount());
306 EXPECT_EQ(i1->OutputCount(), i2->OutputCount()); 313 EXPECT_EQ(i1->OutputCount(), i2->OutputCount());
307 } 314 }
308 } 315 }
309 316
317
318 // -----------------------------------------------------------------------------
319 // Calls with deoptimization.
320 TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
321 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged);
322
323 BailoutId bailout_id(42);
324
325 Node* function_node = m.Parameter(0);
326 Node* receiver = m.Parameter(1);
327 StreamBuilder::Label deopt, cont;
328
329 // TODO(jarin) Add frame state.
330 Node* call = m.CallJS0(function_node, receiver, &cont, &deopt);
331
332 m.Bind(&cont);
333 m.NewNode(m.common()->Continuation(), call);
334 m.Return(call);
335
336 m.Bind(&deopt);
337 m.NewNode(m.common()->LazyDeoptimization(), call);
338
339 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1));
340 Node* locals = m.NewNode(m.common()->StateValues(0));
341 Node* stack = m.NewNode(m.common()->StateValues(0));
342
343 Node* state_node =
344 m.NewNode(m.common()->FrameState(bailout_id), parameters, locals, stack);
345 m.Deoptimize(state_node);
346
347 Stream s = m.Build(kAllWithoutNopInstructions);
348
349 // Skip until kArchCallJSFunction.
350 size_t index = 0;
351 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction;
352 index++) {
353 }
354 // Now we should have three instructions: call, return and deoptimize.
355 ASSERT_EQ(index + 3, s.size());
356
357 EXPECT_EQ(kArchCallJSFunction, s[index++]->arch_opcode());
358 EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
359 EXPECT_EQ(kArchDeoptimize, s[index++]->arch_opcode());
360 EXPECT_EQ(index, s.size());
361 }
362
363
364 TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) {
365 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
366 kMachAnyTagged);
367
368 BailoutId bailout_id_before(42);
369 BailoutId bailout_id_after(54);
370
371 // Some arguments for the call node.
372 Node* function_node = m.Parameter(0);
373 Node* receiver = m.Parameter(1);
374 Node* context = m.Int32Constant(1); // Context is ignored.
375
376 // Build frame state for the state before the call.
377 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
378 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
379 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
380 Node* frame_state_before = m.NewNode(
381 m.common()->FrameState(bailout_id_before), parameters, locals, stack);
382
383 StreamBuilder::Label deopt, cont;
384 // Build the call.
385 Node* call =
386 m.CallFunctionStub0(function_node, receiver, context, frame_state_before,
387 &cont, &deopt, CALL_AS_METHOD);
388
389 // Create the continuation branch.
390 m.Bind(&cont);
391 m.NewNode(m.common()->Continuation(), call);
392 m.Return(call);
393
394 // Create the lazy deoptimization block (with a different frame state).
395 m.Bind(&deopt);
396 m.NewNode(m.common()->LazyDeoptimization(), call);
397
398 Node* stack_after =
399 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
400
401 Node* frame_state_after = m.NewNode(m.common()->FrameState(bailout_id_after),
402 parameters, locals, stack_after);
403 m.Deoptimize(frame_state_after);
404
405 Stream s = m.Build(kAllWithoutNopInstructions);
Benedikt Meurer 2014/08/27 09:02:36 Nit: Please rename to kAllExceptNopInstructions
406
407 // Skip until kArchCallJSFunction.
408 size_t index = 0;
409 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject;
410 index++) {
411 }
412 // Now we should have three instructions: call, return and deoptimize.
413 ASSERT_EQ(index + 3, s.size());
414
415 // Check the call instruction
416 const Instruction* call_instr = s[index++];
417 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode());
418 size_t num_operands =
419 1 + // Code object.
420 1 +
421 3 + // Frame state deopt id + one input for each value in frame state.
422 1 + // Function.
423 1 + // Context.
424 2; // Continuation and deoptimization block labels.
425 ASSERT_EQ(num_operands, call_instr->InputCount());
426
427 // Code object.
428 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate());
429
430 // Deoptimization id.
431 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1));
432 FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before);
433 EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
434 EXPECT_EQ(1, desc_before->parameters_count());
435 EXPECT_EQ(1, desc_before->locals_count());
436 EXPECT_EQ(1, desc_before->stack_count());
437 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
438 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(3)));
439 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(4)));
440
441 // Function.
442 EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(5)));
443 // Context.
444 EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(6)));
445 // Continuation.
446 EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(7)));
447 // Deoptimization.
448 EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(8)));
449
450 EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
451
452 // Check the deoptimize instruction.
453 const Instruction* deopt_instr = s[index++];
454 EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode());
455 ASSERT_EQ(5U, deopt_instr->InputCount());
456 int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0));
457 FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after);
458 EXPECT_EQ(bailout_id_after, desc_after->bailout_id());
459 EXPECT_EQ(1, desc_after->parameters_count());
460 EXPECT_EQ(1, desc_after->locals_count());
461 EXPECT_EQ(2, desc_after->stack_count());
462 // Parameter value from the frame state.
463 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1)));
464 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(2)));
465 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3)));
466 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4)));
467 EXPECT_EQ(index, s.size());
468 }
Benedikt Meurer 2014/08/27 09:02:36 Nit: missing blank line for cpplint happiness.
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