// Copyright 2016 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/v8.h"

#include "src/factory.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-optimizer.h"
#include "src/objects-inl.h"
#include "src/objects.h"
#include "test/unittests/test-utils.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeRegisterOptimizerTest : public BytecodePipelineStage,
                                      public TestWithIsolateAndZone {
 public:
  BytecodeRegisterOptimizerTest() {}
  ~BytecodeRegisterOptimizerTest() override { delete register_allocator_; }

  void Initialize(int number_of_parameters, int number_of_locals) {
    register_allocator_ =
        new TemporaryRegisterAllocator(zone(), number_of_locals);
    register_optimizer_ = new (zone()) BytecodeRegisterOptimizer(
        zone(), register_allocator_, number_of_parameters, this);
  }

  void Write(BytecodeNode* node) override { output_.push_back(*node); }
  void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
    output_.push_back(*node);
  }
  void BindLabel(BytecodeLabel* label) override {}
  void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
  Handle<BytecodeArray> ToBytecodeArray(
      int fixed_register_count, int parameter_count,
      Handle<FixedArray> handle_table) override {
    return Handle<BytecodeArray>();
  }

  TemporaryRegisterAllocator* allocator() { return register_allocator_; }
  BytecodeRegisterOptimizer* optimizer() { return register_optimizer_; }

  Register NewTemporary() {
    return Register(allocator()->BorrowTemporaryRegister());
  }

  void KillTemporary(Register reg) {
    allocator()->ReturnTemporaryRegister(reg.index());
  }

  size_t write_count() const { return output_.size(); }
  const BytecodeNode& last_written() const { return output_.back(); }
  const std::vector<BytecodeNode>* output() { return &output_; }

 private:
  TemporaryRegisterAllocator* register_allocator_;
  BytecodeRegisterOptimizer* register_optimizer_;

  std::vector<BytecodeNode> output_;
};

// Sanity tests.

TEST_F(BytecodeRegisterOptimizerTest, WriteNop) {
  Initialize(1, 1);
  BytecodeNode node(Bytecode::kNop);
  optimizer()->Write(&node);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(node, last_written());
}

TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) {
  Initialize(1, 1);
  BytecodeNode node(Bytecode::kNop);
  node.source_info().MakeExpressionPosition(3);
  optimizer()->Write(&node);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(node, last_written());
}

TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) {
  Initialize(1, 1);
  BytecodeNode node(Bytecode::kNop);
  node.source_info().MakeStatementPosition(3);
  optimizer()->Write(&node);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(node, last_written());
}

TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) {
  Initialize(1, 1);
  Register temp = NewTemporary();
  BytecodeNode node(Bytecode::kStar, temp.ToOperand());
  optimizer()->Write(&node);
  CHECK_EQ(write_count(), 0);
  BytecodeLabel label;
  BytecodeNode jump(Bytecode::kJump, 0);
  optimizer()->WriteJump(&jump, &label);
  CHECK_EQ(write_count(), 2);
  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
  CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kJump);
}

TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
  Initialize(1, 1);
  Register temp = NewTemporary();
  BytecodeNode node(Bytecode::kStar, temp.ToOperand());
  optimizer()->Write(&node);
  CHECK_EQ(write_count(), 0);
  BytecodeLabel label;
  optimizer()->BindLabel(&label);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
  CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
}

// Basic Register Optimizations

TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) {
  Initialize(3, 1);
  Register parameter = Register::FromParameterIndex(1, 3);
  BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
  optimizer()->Write(&node0);
  CHECK_EQ(write_count(), 0);
  Register temp = NewTemporary();
  BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand());
  optimizer()->Write(&node1);
  CHECK_EQ(write_count(), 0);
  KillTemporary(temp);
  CHECK_EQ(write_count(), 0);
  BytecodeNode node2(Bytecode::kReturn);
  optimizer()->Write(&node2);
  CHECK_EQ(write_count(), 2);
  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdar);
  CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kReturn);
}

TEST_F(BytecodeRegisterOptimizerTest, StoresToLocalsImmediate) {
  Initialize(3, 1);
  Register parameter = Register::FromParameterIndex(1, 3);
  BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand());
  optimizer()->Write(&node0);
  CHECK_EQ(write_count(), 0);
  Register local = Register(0);
  BytecodeNode node1(Bytecode::kStar, local.ToOperand());
  optimizer()->Write(&node1);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kMov);
  CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
  CHECK_EQ(output()->at(0).operand(1), local.ToOperand());

  BytecodeNode node2(Bytecode::kReturn);
  optimizer()->Write(&node2);
  CHECK_EQ(write_count(), 3);
  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar);
  CHECK_EQ(output()->at(1).operand(0), local.ToOperand());
  CHECK_EQ(output()->at(2).bytecode(), Bytecode::kReturn);
}

TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotMaterializedForInput) {
  Initialize(3, 1);
  Register parameter = Register::FromParameterIndex(1, 3);
  Register temp0 = NewTemporary();
  Register temp1 = NewTemporary();
  BytecodeNode node0(Bytecode::kMov, parameter.ToOperand(), temp0.ToOperand());
  optimizer()->Write(&node0);
  BytecodeNode node1(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
  optimizer()->Write(&node1);
  CHECK_EQ(write_count(), 0);
  BytecodeNode node2(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 1);
  optimizer()->Write(&node2);
  CHECK_EQ(write_count(), 1);
  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kCallJSRuntime);
  CHECK_EQ(output()->at(0).operand(0), 0);
  CHECK_EQ(output()->at(0).operand(1), parameter.ToOperand());
  CHECK_EQ(output()->at(0).operand(2), 1);
}

TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) {
  Initialize(3, 1);
  Register parameter = Register::FromParameterIndex(1, 3);
  Register temp0 = NewTemporary();
  Register temp1 = NewTemporary();
  BytecodeNode node0(Bytecode::kLdaSmi, 3);
  optimizer()->Write(&node0);
  CHECK_EQ(write_count(), 1);
  BytecodeNode node1(Bytecode::kStar, temp0.ToOperand());
  optimizer()->Write(&node1);
  BytecodeNode node2(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
  optimizer()->Write(&node2);
  CHECK_EQ(write_count(), 1);
  BytecodeNode node3(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 2);
  optimizer()->Write(&node3);
  CHECK_EQ(write_count(), 4);

  CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdaSmi);
  CHECK_EQ(output()->at(0).operand(0), 3);

  CHECK_EQ(output()->at(1).bytecode(), Bytecode::kStar);
  CHECK_EQ(output()->at(1).operand(0), temp0.ToOperand());

  CHECK_EQ(output()->at(2).bytecode(), Bytecode::kMov);
  CHECK_EQ(output()->at(2).operand(0), parameter.ToOperand());
  CHECK_EQ(output()->at(2).operand(1), temp1.ToOperand());

  CHECK_EQ(output()->at(3).bytecode(), Bytecode::kCallJSRuntime);
  CHECK_EQ(output()->at(3).operand(0), 0);
  CHECK_EQ(output()->at(3).operand(1), temp0.ToOperand());
  CHECK_EQ(output()->at(3).operand(2), 2);
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8
