// 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.

#ifndef V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
#define V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_

#include "src/base/compiler-specific.h"
#include "src/globals.h"
#include "src/interpreter/bytecode-register-allocator.h"

namespace v8 {
namespace internal {
namespace interpreter {

// An optimization stage for eliminating unnecessary transfers between
// registers. The bytecode generator uses temporary registers
// liberally for correctness and convenience and this stage removes
// transfers that are not required and preserves correctness.
class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
    : public NON_EXPORTED_BASE(BytecodeRegisterAllocator::Observer),
      public NON_EXPORTED_BASE(ZoneObject) {
 public:
  class BytecodeWriter {
   public:
    BytecodeWriter() {}
    virtual ~BytecodeWriter() {}

    // Called to emit a register transfer bytecode.
    virtual void EmitLdar(Register input) = 0;
    virtual void EmitStar(Register output) = 0;
    virtual void EmitMov(Register input, Register output) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(BytecodeWriter);
  };

  BytecodeRegisterOptimizer(Zone* zone,
                            BytecodeRegisterAllocator* register_allocator,
                            int fixed_registers_count, int parameter_count,
                            BytecodeWriter* bytecode_writer);
  virtual ~BytecodeRegisterOptimizer() {}

  // Perform explicit register transfer operations.
  void DoLdar(Register input) {
    // TODO(rmcilroy): Avoid treating accumulator loads as clobbering the
    // accumulator until the value is actually materialized in the accumulator.
    RegisterInfo* input_info = GetRegisterInfo(input);
    RegisterTransfer(input_info, accumulator_info_);
  }
  void DoStar(Register output) {
    RegisterInfo* output_info = GetRegisterInfo(output);
    RegisterTransfer(accumulator_info_, output_info);
  }
  void DoMov(Register input, Register output) {
    RegisterInfo* input_info = GetRegisterInfo(input);
    RegisterInfo* output_info = GetRegisterInfo(output);
    RegisterTransfer(input_info, output_info);
  }

  // Materialize all live registers and flush equivalence sets.
  void Flush();

  // Prepares for |bytecode|.
  template <Bytecode bytecode, AccumulatorUse accumulator_use>
  INLINE(void PrepareForBytecode()) {
    if (Bytecodes::IsJump(bytecode) || Bytecodes::IsSwitch(bytecode) ||
        bytecode == Bytecode::kDebugger ||
        bytecode == Bytecode::kSuspendGenerator ||
        bytecode == Bytecode::kRestoreGeneratorRegisters) {
      // All state must be flushed before emitting
      // - a jump bytecode (as the register equivalents at the jump target
      //   aren't known)
      // - a switch bytecode (as the register equivalents at the switch targets
      //   aren't known)
      // - a call to the debugger (as it can manipulate locals and parameters),
      // - a generator suspend (as this involves saving all registers).
      // - a generator register restore.
      Flush();
    }

    // Materialize the accumulator if it is read by the bytecode. The
    // accumulator is special and no other register can be materialized
    // in it's place.
    if (BytecodeOperands::ReadsAccumulator(accumulator_use)) {
      Materialize(accumulator_info_);
    }

    // Materialize an equivalent to the accumulator if it will be
    // clobbered when the bytecode is dispatched.
    if (BytecodeOperands::WritesAccumulator(accumulator_use)) {
      PrepareOutputRegister(accumulator_);
    }
  }

  // Prepares |reg| for being used as an output operand.
  void PrepareOutputRegister(Register reg);

  // Prepares registers in |reg_list| for being used as an output operand.
  void PrepareOutputRegisterList(RegisterList reg_list);

  // Returns an equivalent register to |reg| to be used as an input operand.
  Register GetInputRegister(Register reg);

  // Returns an equivalent register list to |reg_list| to be used as an input
  // operand.
  RegisterList GetInputRegisterList(RegisterList reg_list);

  int maxiumum_register_index() const { return max_register_index_; }

 private:
  static const uint32_t kInvalidEquivalenceId;

  class RegisterInfo;

  // BytecodeRegisterAllocator::Observer interface.
  void RegisterAllocateEvent(Register reg) override;
  void RegisterListAllocateEvent(RegisterList reg_list) override;
  void RegisterListFreeEvent(RegisterList reg) override;

  // Update internal state for register transfer from |input| to |output|
  void RegisterTransfer(RegisterInfo* input, RegisterInfo* output);

  // Emit a register transfer bytecode from |input| to |output|.
  void OutputRegisterTransfer(RegisterInfo* input, RegisterInfo* output);

  void CreateMaterializedEquivalent(RegisterInfo* info);
  RegisterInfo* GetMaterializedEquivalent(RegisterInfo* info);
  RegisterInfo* GetMaterializedEquivalentNotAccumulator(RegisterInfo* info);
  void Materialize(RegisterInfo* info);
  void AddToEquivalenceSet(RegisterInfo* set_member,
                           RegisterInfo* non_set_member);

  void PushToRegistersNeedingFlush(RegisterInfo* reg);
  bool EnsureAllRegistersAreFlushed() const;

  // Methods for finding and creating metadata for each register.
  RegisterInfo* GetRegisterInfo(Register reg) {
    size_t index = GetRegisterInfoTableIndex(reg);
    DCHECK_LT(index, register_info_table_.size());
    return register_info_table_[index];
  }
  RegisterInfo* GetOrCreateRegisterInfo(Register reg) {
    size_t index = GetRegisterInfoTableIndex(reg);
    return index < register_info_table_.size() ? register_info_table_[index]
                                               : NewRegisterInfo(reg);
  }
  RegisterInfo* NewRegisterInfo(Register reg) {
    size_t index = GetRegisterInfoTableIndex(reg);
    DCHECK_GE(index, register_info_table_.size());
    GrowRegisterMap(reg);
    return register_info_table_[index];
  }

  void GrowRegisterMap(Register reg);

  bool RegisterIsTemporary(Register reg) const {
    return reg >= temporary_base_;
  }

  bool RegisterIsObservable(Register reg) const {
    return reg != accumulator_ && !RegisterIsTemporary(reg);
  }

  static Register OperandToRegister(uint32_t operand) {
    return Register::FromOperand(static_cast<int32_t>(operand));
  }

  size_t GetRegisterInfoTableIndex(Register reg) const {
    return static_cast<size_t>(reg.index() + register_info_table_offset_);
  }

  Register RegisterFromRegisterInfoTableIndex(size_t index) const {
    return Register(static_cast<int>(index) - register_info_table_offset_);
  }

  uint32_t NextEquivalenceId() {
    equivalence_id_++;
    // TODO(rmcilroy): use the same type for these and remove static_cast.
    CHECK_NE(static_cast<size_t>(equivalence_id_), kInvalidEquivalenceId);
    return equivalence_id_;
  }

  void AllocateRegister(RegisterInfo* info);

  Zone* zone() { return zone_; }

  const Register accumulator_;
  RegisterInfo* accumulator_info_;
  const Register temporary_base_;
  int max_register_index_;

  // Direct mapping to register info.
  ZoneVector<RegisterInfo*> register_info_table_;
  int register_info_table_offset_;

  ZoneDeque<RegisterInfo*> registers_needing_flushed_;

  // Counter for equivalence sets identifiers.
  int equivalence_id_;

  BytecodeWriter* bytecode_writer_;
  bool flush_required_;
  Zone* zone_;

  DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterOptimizer);
};

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

#endif  // V8_INTERPRETER_BYTECODE_REGISTER_OPTIMIZER_H_
