// 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/api.h"
#include "src/factory.h"
#include "src/interpreter/bytecode-array-writer.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-node.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecode-source-info.h"
#include "src/interpreter/constant-array-builder.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/source-position-table.h"
#include "src/utils.h"
#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"

namespace v8 {
namespace internal {
namespace interpreter {
namespace bytecode_array_writer_unittest {

#define B(Name) static_cast<uint8_t>(Bytecode::k##Name)
#define R(i) static_cast<uint32_t>(Register(i).ToOperand())

class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
 public:
  BytecodeArrayWriterUnittest()
      : constant_array_builder_(zone()),
        bytecode_array_writer_(
            zone(), &constant_array_builder_,
            SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS) {}
  ~BytecodeArrayWriterUnittest() override {}

  void Write(Bytecode bytecode, BytecodeSourceInfo info = BytecodeSourceInfo());
  void Write(Bytecode bytecode, uint32_t operand0,
             BytecodeSourceInfo info = BytecodeSourceInfo());
  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
             BytecodeSourceInfo info = BytecodeSourceInfo());
  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
             uint32_t operand2, BytecodeSourceInfo info = BytecodeSourceInfo());
  void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
             uint32_t operand2, uint32_t operand3,
             BytecodeSourceInfo info = BytecodeSourceInfo());

  void WriteJump(Bytecode bytecode, BytecodeLabel* label,
                 BytecodeSourceInfo info = BytecodeSourceInfo());
  void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth,
                     BytecodeSourceInfo info = BytecodeSourceInfo());

  BytecodeArrayWriter* writer() { return &bytecode_array_writer_; }
  ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); }
  SourcePositionTableBuilder* source_position_table_builder() {
    return writer()->source_position_table_builder();
  }

 private:
  ConstantArrayBuilder constant_array_builder_;
  BytecodeArrayWriter bytecode_array_writer_;
};

void BytecodeArrayWriterUnittest::Write(Bytecode bytecode,
                                        BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, info);
  writer()->Write(&node);
}

void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
                                        BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, operand0, info);
  writer()->Write(&node);
}

void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
                                        uint32_t operand1,
                                        BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, operand0, operand1, info);
  writer()->Write(&node);
}

void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
                                        uint32_t operand1, uint32_t operand2,
                                        BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, operand0, operand1, operand2, info);
  writer()->Write(&node);
}

void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
                                        uint32_t operand1, uint32_t operand2,
                                        uint32_t operand3,
                                        BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, info);
  writer()->Write(&node);
}

void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode,
                                            BytecodeLabel* label,
                                            BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, 0, info);
  writer()->WriteJump(&node, label);
}

void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode,
                                                BytecodeLabel* label, int depth,
                                                BytecodeSourceInfo info) {
  BytecodeNode node(bytecode, 0, depth, info);
  writer()->WriteJump(&node, label);
}

TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
  CHECK_EQ(bytecodes()->size(), 0u);

  Write(Bytecode::kStackCheck, {10, false});
  CHECK_EQ(bytecodes()->size(), 1u);

  Write(Bytecode::kLdaSmi, 127, {55, true});
  CHECK_EQ(bytecodes()->size(), 3u);

  Write(Bytecode::kStar, Register(20).ToOperand());
  CHECK_EQ(bytecodes()->size(), 5u);

  Write(Bytecode::kLdar, Register(200).ToOperand());
  CHECK_EQ(bytecodes()->size(), 9u);

  Write(Bytecode::kReturn, {70, true});
  CHECK_EQ(bytecodes()->size(), 10u);

  static const uint8_t expected_bytes[] = {
      // clang-format off
      /*  0 10 E> */ B(StackCheck),
      /*  1 55 S> */ B(LdaSmi), U8(127),
      /*  3       */ B(Star), R8(20),
      /*  5       */ B(Wide), B(Ldar), R16(200),
      /*  9 70 S> */ B(Return),
      // clang-format on
  };
  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
  for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
    CHECK_EQ(bytecodes()->at(i), expected_bytes[i]);
  }

  Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray(
      isolate(), 0, 0, factory()->empty_fixed_array());
  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));

  PositionTableEntry expected_positions[] = {
      {0, 10, false}, {1, 55, true}, {9, 70, true}};
  SourcePositionTableIterator source_iterator(
      bytecode_array->SourcePositionTable());
  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
    const PositionTableEntry& expected = expected_positions[i];
    CHECK_EQ(source_iterator.code_offset(), expected.code_offset);
    CHECK_EQ(source_iterator.source_position().ScriptOffset(),
             expected.source_position);
    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
    source_iterator.Advance();
  }
  CHECK(source_iterator.done());
}

TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
  static const uint8_t expected_bytes[] = {
      // clang-format off
      /*  0 30 E> */ B(StackCheck),
      /*  1 42 S> */ B(LdaConstant), U8(0),
      /*  3 42 E> */ B(Add), R8(1), U8(1),
      /*  5 68 S> */ B(JumpIfUndefined), U8(39),
      /*  7       */ B(JumpIfNull), U8(37),
      /*  9       */ B(ToObject), R8(3),
      /* 11       */ B(ForInPrepare), R8(3), U8(4),
      /* 14       */ B(LdaZero),
      /* 15       */ B(Star), R8(7),
      /* 17 63 S> */ B(ForInContinue), R8(7), R8(6),
      /* 20       */ B(JumpIfFalse), U8(24),
      /* 22       */ B(ForInNext), R8(3), R8(7), R8(4), U8(1),
      /* 27       */ B(JumpIfUndefined), U8(10),
      /* 29       */ B(Star), R8(0),
      /* 31 54 E> */ B(StackCheck),
      /* 32       */ B(Ldar), R8(0),
      /* 34       */ B(Star), R8(2),
      /* 36 85 S> */ B(Return),
      /* 37       */ B(ForInStep), R8(7),
      /* 39       */ B(Star), R8(7),
      /* 41       */ B(JumpLoop), U8(24), U8(0),
      /* 44       */ B(LdaUndefined),
      /* 45 85 S> */ B(Return),
      // clang-format on
  };

  static const PositionTableEntry expected_positions[] = {
      {0, 30, false}, {1, 42, true},   {3, 42, false}, {6, 68, true},
      {18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}};

  BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3;

  Write(Bytecode::kStackCheck, {30, false});
  Write(Bytecode::kLdaConstant, U8(0), {42, true});
  Write(Bytecode::kAdd, R(1), U8(1), {42, false});
  WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true});
  WriteJump(Bytecode::kJumpIfNull, &jump_end_2);
  Write(Bytecode::kToObject, R(3));
  Write(Bytecode::kForInPrepare, R(3), U8(4));
  Write(Bytecode::kLdaZero);
  Write(Bytecode::kStar, R(7));
  writer()->BindLabel(&back_jump);
  Write(Bytecode::kForInContinue, R(7), R(6), {63, true});
  WriteJump(Bytecode::kJumpIfFalse, &jump_end_3);
  Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1));
  WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in);
  Write(Bytecode::kStar, R(0));
  Write(Bytecode::kStackCheck, {54, false});
  Write(Bytecode::kLdar, R(0));
  Write(Bytecode::kStar, R(2));
  Write(Bytecode::kReturn, {85, true});
  writer()->BindLabel(&jump_for_in);
  Write(Bytecode::kForInStep, R(7));
  Write(Bytecode::kStar, R(7));
  WriteJumpLoop(Bytecode::kJumpLoop, &back_jump, 0);
  writer()->BindLabel(&jump_end_1);
  writer()->BindLabel(&jump_end_2);
  writer()->BindLabel(&jump_end_3);
  Write(Bytecode::kLdaUndefined);
  Write(Bytecode::kReturn, {85, true});

  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
  for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
    CHECK_EQ(static_cast<int>(bytecodes()->at(i)),
             static_cast<int>(expected_bytes[i]));
  }

  Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray(
      isolate(), 0, 0, factory()->empty_fixed_array());
  SourcePositionTableIterator source_iterator(
      bytecode_array->SourcePositionTable());
  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
    const PositionTableEntry& expected = expected_positions[i];
    CHECK_EQ(source_iterator.code_offset(), expected.code_offset);
    CHECK_EQ(source_iterator.source_position().ScriptOffset(),
             expected.source_position);
    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
    source_iterator.Advance();
  }
  CHECK(source_iterator.done());
}

TEST_F(BytecodeArrayWriterUnittest, ElideNoneffectfulBytecodes) {
  if (!i::FLAG_ignition_elide_noneffectful_bytecodes) return;

  static const uint8_t expected_bytes[] = {
      // clang-format off
      /*  0  10 E> */ B(StackCheck),
      /*  1  55 S> */ B(Ldar), R8(20),
      /*  3        */ B(Star), R8(20),
      /*  5        */ B(CreateMappedArguments),
      /*  6  60 S> */ B(LdaSmi), U8(127),
      /*  8  70 S> */ B(Ldar), R8(20),
      /*  10 75 S> */ B(Return),
      // clang-format on
  };

  static const PositionTableEntry expected_positions[] = {{0, 10, false},
                                                          {1, 55, true},
                                                          {6, 60, false},
                                                          {8, 70, true},
                                                          {10, 75, true}};

  Write(Bytecode::kStackCheck, {10, false});
  Write(Bytecode::kLdaSmi, 127, {55, true});  // Should be elided.
  Write(Bytecode::kLdar, Register(20).ToOperand());
  Write(Bytecode::kStar, Register(20).ToOperand());
  Write(Bytecode::kLdar, Register(20).ToOperand());  // Should be elided.
  Write(Bytecode::kCreateMappedArguments);
  Write(Bytecode::kLdaSmi, 127, {60, false});  // Not elided due to source info.
  Write(Bytecode::kLdar, Register(20).ToOperand(), {70, true});
  Write(Bytecode::kReturn, {75, true});

  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
  for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
    CHECK_EQ(static_cast<int>(bytecodes()->at(i)),
             static_cast<int>(expected_bytes[i]));
  }

  Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray(
      isolate(), 0, 0, factory()->empty_fixed_array());
  SourcePositionTableIterator source_iterator(
      bytecode_array->SourcePositionTable());
  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
    const PositionTableEntry& expected = expected_positions[i];
    CHECK_EQ(source_iterator.code_offset(), expected.code_offset);
    CHECK_EQ(source_iterator.source_position().ScriptOffset(),
             expected.source_position);
    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
    source_iterator.Advance();
  }
  CHECK(source_iterator.done());
}

TEST_F(BytecodeArrayWriterUnittest, DeadcodeElimination) {
  static const uint8_t expected_bytes[] = {
      // clang-format off
      /*  0  10 E> */ B(StackCheck),
      /*  1  55 S> */ B(LdaSmi), U8(127),
      /*  3        */ B(Jump), U8(2),
      /*  5  65 S> */ B(LdaSmi), U8(127),
      /*  7        */ B(JumpIfFalse), U8(3),
      /*  9  75 S> */ B(Return),
      /*  10       */ B(JumpIfFalse), U8(3),
      /*  12       */ B(Throw),
      /*  13       */ B(JumpIfFalse), U8(3),
      /*  15       */ B(ReThrow),
      /*  16       */ B(Return),
      // clang-format on
  };

  static const PositionTableEntry expected_positions[] = {
      {0, 10, false}, {1, 55, true}, {5, 65, true}, {9, 75, true}};

  BytecodeLabel after_jump, after_conditional_jump, after_return, after_throw,
      after_rethrow;

  Write(Bytecode::kStackCheck, {10, false});
  Write(Bytecode::kLdaSmi, 127, {55, true});
  WriteJump(Bytecode::kJump, &after_jump);
  Write(Bytecode::kLdaSmi, 127);                               // Dead code.
  WriteJump(Bytecode::kJumpIfFalse, &after_conditional_jump);  // Dead code.
  writer()->BindLabel(&after_jump);
  writer()->BindLabel(&after_conditional_jump);
  Write(Bytecode::kLdaSmi, 127, {65, true});
  WriteJump(Bytecode::kJumpIfFalse, &after_return);
  Write(Bytecode::kReturn, {75, true});
  Write(Bytecode::kLdaSmi, 127, {100, true});  // Dead code.
  writer()->BindLabel(&after_return);
  WriteJump(Bytecode::kJumpIfFalse, &after_throw);
  Write(Bytecode::kThrow);
  Write(Bytecode::kLdaSmi, 127);  // Dead code.
  writer()->BindLabel(&after_throw);
  WriteJump(Bytecode::kJumpIfFalse, &after_rethrow);
  Write(Bytecode::kReThrow);
  Write(Bytecode::kLdaSmi, 127);  // Dead code.
  writer()->BindLabel(&after_rethrow);
  Write(Bytecode::kReturn);

  CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
  for (size_t i = 0; i < arraysize(expected_bytes); ++i) {
    CHECK_EQ(static_cast<int>(bytecodes()->at(i)),
             static_cast<int>(expected_bytes[i]));
  }

  Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray(
      isolate(), 0, 0, factory()->empty_fixed_array());
  SourcePositionTableIterator source_iterator(
      bytecode_array->SourcePositionTable());
  for (size_t i = 0; i < arraysize(expected_positions); ++i) {
    const PositionTableEntry& expected = expected_positions[i];
    CHECK_EQ(source_iterator.code_offset(), expected.code_offset);
    CHECK_EQ(source_iterator.source_position().ScriptOffset(),
             expected.source_position);
    CHECK_EQ(source_iterator.is_statement(), expected.is_statement);
    source_iterator.Advance();
  }
  CHECK(source_iterator.done());
}

#undef B
#undef R

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