LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-instruction-scheduler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 38 38 100.0 %
Date: 2019-04-17 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/backend/instruction-scheduler.h"
       6             : #include "src/compiler/backend/instruction-selector-impl.h"
       7             : #include "src/compiler/backend/instruction.h"
       8             : 
       9             : #include "test/cctest/cctest.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : namespace compiler {
      14             : 
      15             : // Create InstructionBlocks with a single block.
      16           5 : InstructionBlocks* CreateSingleBlock(Zone* zone) {
      17             :   InstructionBlock* block = new (zone)
      18          10 :       InstructionBlock(zone, RpoNumber::FromInt(0), RpoNumber::Invalid(),
      19          10 :                        RpoNumber::Invalid(), false, false);
      20             :   InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
      21           5 :   new (blocks) InstructionBlocks(1, block, zone);
      22           5 :   return blocks;
      23             : }
      24             : 
      25             : // Wrapper around the InstructionScheduler.
      26          10 : class InstructionSchedulerTester {
      27             :  public:
      28           5 :   InstructionSchedulerTester()
      29             :       : scope_(),
      30           5 :         blocks_(CreateSingleBlock(scope_.main_zone())),
      31             :         sequence_(scope_.main_isolate(), scope_.main_zone(), blocks_),
      32          20 :         scheduler_(scope_.main_zone(), &sequence_) {}
      33             : 
      34           5 :   void StartBlock() { scheduler_.StartBlock(RpoNumber::FromInt(0)); }
      35           5 :   void EndBlock() { scheduler_.EndBlock(RpoNumber::FromInt(0)); }
      36          15 :   void AddInstruction(Instruction* instr) { scheduler_.AddInstruction(instr); }
      37           5 :   void AddTerminator(Instruction* instr) { scheduler_.AddTerminator(instr); }
      38             : 
      39           5 :   void CheckHasSideEffect(Instruction* instr) {
      40          10 :     CHECK(scheduler_.HasSideEffect(instr));
      41           5 :   }
      42          20 :   void CheckIsDeopt(Instruction* instr) { CHECK(instr->IsDeoptimizeCall()); }
      43             : 
      44          30 :   void CheckInSuccessors(Instruction* instr, Instruction* successor) {
      45             :     InstructionScheduler::ScheduleGraphNode* node = GetNode(instr);
      46          30 :     InstructionScheduler::ScheduleGraphNode* succ_node = GetNode(successor);
      47             : 
      48             :     ZoneDeque<InstructionScheduler::ScheduleGraphNode*>& successors =
      49             :         node->successors();
      50          30 :     CHECK_NE(std::find(successors.begin(), successors.end(), succ_node),
      51             :              successors.end());
      52          30 :   }
      53             : 
      54             :   Zone* zone() { return scope_.main_zone(); }
      55             : 
      56             :  private:
      57             :   InstructionScheduler::ScheduleGraphNode* GetNode(Instruction* instr) {
      58         150 :     for (auto node : scheduler_.graph_) {
      59         150 :       if (node->instruction() == instr) return node;
      60             :     }
      61             :     return nullptr;
      62             :   }
      63             : 
      64             :   HandleAndZoneScope scope_;
      65             :   InstructionBlocks* blocks_;
      66             :   InstructionSequence sequence_;
      67             :   InstructionScheduler scheduler_;
      68             : };
      69             : 
      70       26644 : TEST(DeoptInMiddleOfBasicBlock) {
      71          10 :   InstructionSchedulerTester tester;
      72             :   Zone* zone = tester.zone();
      73             : 
      74             :   tester.StartBlock();
      75             :   InstructionCode jmp_opcode = kArchJmp;
      76             :   // Dummy node for FlagsContinuation::ForDeoptimize (which won't accept
      77             :   // nullptr).
      78           5 :   Node* node = Node::New(zone, 0, nullptr, 0, nullptr, false);
      79           5 :   VectorSlotPair feedback;
      80             :   FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
      81             :       kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, feedback,
      82             :       node);
      83             :   jmp_opcode = cont.Encode(jmp_opcode);
      84             :   Instruction* jmp_inst = Instruction::New(zone, jmp_opcode);
      85           5 :   tester.CheckIsDeopt(jmp_inst);
      86             :   tester.AddInstruction(jmp_inst);
      87             :   Instruction* side_effect_inst = Instruction::New(zone, kArchPrepareTailCall);
      88           5 :   tester.CheckHasSideEffect(side_effect_inst);
      89             :   tester.AddInstruction(side_effect_inst);
      90             :   Instruction* other_jmp_inst = Instruction::New(zone, jmp_opcode);
      91           5 :   tester.CheckIsDeopt(other_jmp_inst);
      92             :   tester.AddInstruction(other_jmp_inst);
      93             :   Instruction* ret_inst = Instruction::New(zone, kArchRet);
      94             :   tester.AddTerminator(ret_inst);
      95             : 
      96             :   // Check that an instruction with a side effect is a successor of the deopt.
      97           5 :   tester.CheckInSuccessors(jmp_inst, side_effect_inst);
      98             :   // Check that the second deopt is a successor of the first deopt.
      99           5 :   tester.CheckInSuccessors(jmp_inst, other_jmp_inst);
     100             :   // Check that the second deopt is a successor of the side-effect instruction.
     101           5 :   tester.CheckInSuccessors(side_effect_inst, other_jmp_inst);
     102             :   // Check that the block terminator is a successor of all other instructions.
     103           5 :   tester.CheckInSuccessors(jmp_inst, ret_inst);
     104           5 :   tester.CheckInSuccessors(side_effect_inst, ret_inst);
     105           5 :   tester.CheckInSuccessors(other_jmp_inst, ret_inst);
     106             : 
     107             :   // Schedule block.
     108             :   tester.EndBlock();
     109           5 : }
     110             : 
     111             : }  // namespace compiler
     112             : }  // namespace internal
     113       79917 : }  // namespace v8

Generated by: LCOV version 1.10