// 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::kResumeGenerator) {
      // 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_
