// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/backend/instruction-scheduler.h"
#include "src/compiler/backend/instruction-selector-impl.h"
#include "src/compiler/backend/instruction.h"

#include "test/cctest/cctest.h"

namespace v8 {
namespace internal {
namespace compiler {

// Create InstructionBlocks with a single block.
InstructionBlocks* CreateSingleBlock(Zone* zone) {
  InstructionBlock* block = new (zone)
      InstructionBlock(zone, RpoNumber::FromInt(0), RpoNumber::Invalid(),
                       RpoNumber::Invalid(), false, false);
  InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
  new (blocks) InstructionBlocks(1, block, zone);
  return blocks;
}

// Wrapper around the InstructionScheduler.
class InstructionSchedulerTester {
 public:
  InstructionSchedulerTester()
      : scope_(),
        blocks_(CreateSingleBlock(scope_.main_zone())),
        sequence_(scope_.main_isolate(), scope_.main_zone(), blocks_),
        scheduler_(scope_.main_zone(), &sequence_) {}

  void StartBlock() { scheduler_.StartBlock(RpoNumber::FromInt(0)); }
  void EndBlock() { scheduler_.EndBlock(RpoNumber::FromInt(0)); }
  void AddInstruction(Instruction* instr) { scheduler_.AddInstruction(instr); }
  void AddTerminator(Instruction* instr) { scheduler_.AddTerminator(instr); }

  void CheckHasSideEffect(Instruction* instr) {
    CHECK(scheduler_.HasSideEffect(instr));
  }
  void CheckIsDeopt(Instruction* instr) { CHECK(instr->IsDeoptimizeCall()); }

  void CheckInSuccessors(Instruction* instr, Instruction* successor) {
    InstructionScheduler::ScheduleGraphNode* node = GetNode(instr);
    InstructionScheduler::ScheduleGraphNode* succ_node = GetNode(successor);

    ZoneDeque<InstructionScheduler::ScheduleGraphNode*>& successors =
        node->successors();
    CHECK_NE(std::find(successors.begin(), successors.end(), succ_node),
             successors.end());
  }

  Zone* zone() { return scope_.main_zone(); }

 private:
  InstructionScheduler::ScheduleGraphNode* GetNode(Instruction* instr) {
    for (auto node : scheduler_.graph_) {
      if (node->instruction() == instr) return node;
    }
    return nullptr;
  }

  HandleAndZoneScope scope_;
  InstructionBlocks* blocks_;
  InstructionSequence sequence_;
  InstructionScheduler scheduler_;
};

TEST(DeoptInMiddleOfBasicBlock) {
  InstructionSchedulerTester tester;
  Zone* zone = tester.zone();

  tester.StartBlock();
  InstructionCode jmp_opcode = kArchJmp;
  // Dummy node for FlagsContinuation::ForDeoptimize (which won't accept
  // nullptr).
  Node* node = Node::New(zone, 0, nullptr, 0, nullptr, false);
  VectorSlotPair feedback;
  FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
      kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, feedback,
      node);
  jmp_opcode = cont.Encode(jmp_opcode);
  Instruction* jmp_inst = Instruction::New(zone, jmp_opcode);
  tester.CheckIsDeopt(jmp_inst);
  tester.AddInstruction(jmp_inst);
  Instruction* side_effect_inst = Instruction::New(zone, kArchPrepareTailCall);
  tester.CheckHasSideEffect(side_effect_inst);
  tester.AddInstruction(side_effect_inst);
  Instruction* other_jmp_inst = Instruction::New(zone, jmp_opcode);
  tester.CheckIsDeopt(other_jmp_inst);
  tester.AddInstruction(other_jmp_inst);
  Instruction* ret_inst = Instruction::New(zone, kArchRet);
  tester.AddTerminator(ret_inst);

  // Check that an instruction with a side effect is a successor of the deopt.
  tester.CheckInSuccessors(jmp_inst, side_effect_inst);
  // Check that the second deopt is a successor of the first deopt.
  tester.CheckInSuccessors(jmp_inst, other_jmp_inst);
  // Check that the second deopt is a successor of the side-effect instruction.
  tester.CheckInSuccessors(side_effect_inst, other_jmp_inst);
  // Check that the block terminator is a successor of all other instructions.
  tester.CheckInSuccessors(jmp_inst, ret_inst);
  tester.CheckInSuccessors(side_effect_inst, ret_inst);
  tester.CheckInSuccessors(other_jmp_inst, ret_inst);

  // Schedule block.
  tester.EndBlock();
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
