// 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/interpreter/bytecode-register-optimizer.h"

namespace v8 {
namespace internal {
namespace interpreter {

const uint32_t BytecodeRegisterOptimizer::kInvalidEquivalenceId = kMaxUInt32;

// A class for tracking the state of a register. This class tracks
// which equivalence set a register is a member of and also whether a
// register is materialized in the bytecode stream.
class BytecodeRegisterOptimizer::RegisterInfo final : public ZoneObject {
 public:
  RegisterInfo(Register reg, uint32_t equivalence_id, bool materialized,
               bool allocated)
      : register_(reg),
        equivalence_id_(equivalence_id),
        materialized_(materialized),
        allocated_(allocated),
        needs_flush_(false),
        next_(this),
        prev_(this) {}

  void AddToEquivalenceSetOf(RegisterInfo* info);
  void MoveToNewEquivalenceSet(uint32_t equivalence_id, bool materialized);
  bool IsOnlyMemberOfEquivalenceSet() const;
  bool IsOnlyMaterializedMemberOfEquivalenceSet() const;
  bool IsInSameEquivalenceSet(RegisterInfo* info) const;

  // Get a member of the register's equivalence set that is allocated.
  // Returns itself if allocated, and nullptr if there is no unallocated
  // equivalent register.
  RegisterInfo* GetAllocatedEquivalent();

  // Get a member of this register's equivalence set that is
  // materialized. The materialized equivalent will be this register
  // if it is materialized. Returns nullptr if no materialized
  // equivalent exists.
  RegisterInfo* GetMaterializedEquivalent();

  // Get a member of this register's equivalence set that is
  // materialized and not register |reg|. The materialized equivalent
  // will be this register if it is materialized. Returns nullptr if
  // no materialized equivalent exists.
  RegisterInfo* GetMaterializedEquivalentOtherThan(Register reg);

  // Get a member of this register's equivalence set that is intended
  // to be materialized in place of this register (which is currently
  // materialized). The best candidate is deemed to be the register
  // with the lowest index as this permits temporary registers to be
  // removed from the bytecode stream. Returns nullptr if no candidate
  // exists.
  RegisterInfo* GetEquivalentToMaterialize();

  // Marks all temporary registers of the equivalence set as unmaterialized.
  void MarkTemporariesAsUnmaterialized(Register temporary_base);

  // Get an equivalent register. Returns this if none exists.
  RegisterInfo* GetEquivalent();

  Register register_value() const { return register_; }
  bool materialized() const { return materialized_; }
  void set_materialized(bool materialized) { materialized_ = materialized; }
  bool allocated() const { return allocated_; }
  void set_allocated(bool allocated) { allocated_ = allocated; }
  void set_equivalence_id(uint32_t equivalence_id) {
    equivalence_id_ = equivalence_id;
  }
  uint32_t equivalence_id() const { return equivalence_id_; }
  // Indicates if a register should be processed when calling Flush().
  bool needs_flush() const { return needs_flush_; }
  void set_needs_flush(bool needs_flush) { needs_flush_ = needs_flush; }

 private:
  Register register_;
  uint32_t equivalence_id_;
  bool materialized_;
  bool allocated_;
  bool needs_flush_;

  // Equivalence set pointers.
  RegisterInfo* next_;
  RegisterInfo* prev_;

  DISALLOW_COPY_AND_ASSIGN(RegisterInfo);
};

void BytecodeRegisterOptimizer::RegisterInfo::AddToEquivalenceSetOf(
    RegisterInfo* info) {
  DCHECK_NE(kInvalidEquivalenceId, info->equivalence_id());
  // Fix old list
  next_->prev_ = prev_;
  prev_->next_ = next_;
  // Add to new list.
  next_ = info->next_;
  prev_ = info;
  prev_->next_ = this;
  next_->prev_ = this;
  set_equivalence_id(info->equivalence_id());
  set_materialized(false);
}

void BytecodeRegisterOptimizer::RegisterInfo::MoveToNewEquivalenceSet(
    uint32_t equivalence_id, bool materialized) {
  next_->prev_ = prev_;
  prev_->next_ = next_;
  next_ = prev_ = this;
  equivalence_id_ = equivalence_id;
  materialized_ = materialized;
}

bool BytecodeRegisterOptimizer::RegisterInfo::IsOnlyMemberOfEquivalenceSet()
    const {
  return this->next_ == this;
}

bool BytecodeRegisterOptimizer::RegisterInfo::
    IsOnlyMaterializedMemberOfEquivalenceSet() const {
  DCHECK(materialized());

  const RegisterInfo* visitor = this->next_;
  while (visitor != this) {
    if (visitor->materialized()) {
      return false;
    }
    visitor = visitor->next_;
  }
  return true;
}

bool BytecodeRegisterOptimizer::RegisterInfo::IsInSameEquivalenceSet(
    RegisterInfo* info) const {
  return equivalence_id() == info->equivalence_id();
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::RegisterInfo::GetAllocatedEquivalent() {
  RegisterInfo* visitor = this;
  do {
    if (visitor->allocated()) {
      return visitor;
    }
    visitor = visitor->next_;
  } while (visitor != this);

  return nullptr;
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::RegisterInfo::GetMaterializedEquivalent() {
  RegisterInfo* visitor = this;
  do {
    if (visitor->materialized()) {
      return visitor;
    }
    visitor = visitor->next_;
  } while (visitor != this);

  return nullptr;
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::RegisterInfo::GetMaterializedEquivalentOtherThan(
    Register reg) {
  RegisterInfo* visitor = this;
  do {
    if (visitor->materialized() && visitor->register_value() != reg) {
      return visitor;
    }
    visitor = visitor->next_;
  } while (visitor != this);

  return nullptr;
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::RegisterInfo::GetEquivalentToMaterialize() {
  DCHECK(this->materialized());
  RegisterInfo* visitor = this->next_;
  RegisterInfo* best_info = nullptr;
  while (visitor != this) {
    if (visitor->materialized()) {
      return nullptr;
    }
    if (visitor->allocated() &&
        (best_info == nullptr ||
         visitor->register_value() < best_info->register_value())) {
      best_info = visitor;
    }
    visitor = visitor->next_;
  }
  return best_info;
}

void BytecodeRegisterOptimizer::RegisterInfo::MarkTemporariesAsUnmaterialized(
    Register temporary_base) {
  DCHECK(this->register_value() < temporary_base);
  DCHECK(this->materialized());
  RegisterInfo* visitor = this->next_;
  while (visitor != this) {
    if (visitor->register_value() >= temporary_base) {
      visitor->set_materialized(false);
    }
    visitor = visitor->next_;
  }
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::RegisterInfo::GetEquivalent() {
  return next_;
}

BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
    Zone* zone, BytecodeRegisterAllocator* register_allocator,
    int fixed_registers_count, int parameter_count,
    BytecodeWriter* bytecode_writer)
    : accumulator_(Register::virtual_accumulator()),
      temporary_base_(fixed_registers_count),
      max_register_index_(fixed_registers_count - 1),
      register_info_table_(zone),
      registers_needing_flushed_(zone),
      equivalence_id_(0),
      bytecode_writer_(bytecode_writer),
      flush_required_(false),
      zone_(zone) {
  register_allocator->set_observer(this);

  // Calculate offset so register index values can be mapped into
  // a vector of register metadata.
  // There is at least one parameter, which is the JS receiver.
  DCHECK(parameter_count != 0);
  register_info_table_offset_ =
      -Register::FromParameterIndex(0, parameter_count).index();

  // Initialize register map for parameters, locals, and the
  // accumulator.
  register_info_table_.resize(register_info_table_offset_ +
                              static_cast<size_t>(temporary_base_.index()));
  for (size_t i = 0; i < register_info_table_.size(); ++i) {
    register_info_table_[i] = new (zone) RegisterInfo(
        RegisterFromRegisterInfoTableIndex(i), NextEquivalenceId(), true, true);
    DCHECK_EQ(register_info_table_[i]->register_value().index(),
              RegisterFromRegisterInfoTableIndex(i).index());
  }
  accumulator_info_ = GetRegisterInfo(accumulator_);
  DCHECK(accumulator_info_->register_value() == accumulator_);
}

void BytecodeRegisterOptimizer::PushToRegistersNeedingFlush(RegisterInfo* reg) {
  if (!reg->needs_flush()) {
    reg->set_needs_flush(true);
    registers_needing_flushed_.push_back(reg);
  }
}

bool BytecodeRegisterOptimizer::EnsureAllRegistersAreFlushed() const {
  for (RegisterInfo* reg_info : register_info_table_) {
    if (reg_info->needs_flush()) {
      return false;
    } else if (!reg_info->IsOnlyMemberOfEquivalenceSet()) {
      return false;
    } else if (reg_info->allocated() && !reg_info->materialized()) {
      return false;
    }
  }
  return true;
}

void BytecodeRegisterOptimizer::Flush() {
  if (!flush_required_) {
    return;
  }

  // Materialize all live registers and break equivalences.
  for (RegisterInfo* reg_info : registers_needing_flushed_) {
    if (!reg_info->needs_flush()) continue;
    reg_info->set_needs_flush(false);

    RegisterInfo* materialized = reg_info->materialized()
                                     ? reg_info
                                     : reg_info->GetMaterializedEquivalent();

    if (materialized != nullptr) {
      // Walk equivalents of materialized registers, materializing
      // each equivalent register as necessary and placing in their
      // own equivalence set.
      RegisterInfo* equivalent;
      while ((equivalent = materialized->GetEquivalent()) != materialized) {
        if (equivalent->allocated() && !equivalent->materialized()) {
          OutputRegisterTransfer(materialized, equivalent);
        }
        equivalent->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
        equivalent->set_needs_flush(false);
      }
    } else {
      // Equivalernce class containing only unallocated registers.
      DCHECK(reg_info->GetAllocatedEquivalent() == nullptr);
      reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), false);
    }
  }

  registers_needing_flushed_.clear();
  DCHECK(EnsureAllRegistersAreFlushed());

  flush_required_ = false;
}

void BytecodeRegisterOptimizer::OutputRegisterTransfer(
    RegisterInfo* input_info, RegisterInfo* output_info) {
  Register input = input_info->register_value();
  Register output = output_info->register_value();
  DCHECK_NE(input.index(), output.index());

  if (input == accumulator_) {
    bytecode_writer_->EmitStar(output);
  } else if (output == accumulator_) {
    bytecode_writer_->EmitLdar(input);
  } else {
    bytecode_writer_->EmitMov(input, output);
  }
  if (output != accumulator_) {
    max_register_index_ = std::max(max_register_index_, output.index());
  }
  output_info->set_materialized(true);
}

void BytecodeRegisterOptimizer::CreateMaterializedEquivalent(
    RegisterInfo* info) {
  DCHECK(info->materialized());
  RegisterInfo* unmaterialized = info->GetEquivalentToMaterialize();
  if (unmaterialized) {
    OutputRegisterTransfer(info, unmaterialized);
  }
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::GetMaterializedEquivalent(RegisterInfo* info) {
  return info->materialized() ? info : info->GetMaterializedEquivalent();
}

BytecodeRegisterOptimizer::RegisterInfo*
BytecodeRegisterOptimizer::GetMaterializedEquivalentNotAccumulator(
    RegisterInfo* info) {
  if (info->materialized()) {
    return info;
  }

  RegisterInfo* result = info->GetMaterializedEquivalentOtherThan(accumulator_);
  if (result == nullptr) {
    Materialize(info);
    result = info;
  }
  DCHECK(result->register_value() != accumulator_);
  return result;
}

void BytecodeRegisterOptimizer::Materialize(RegisterInfo* info) {
  if (!info->materialized()) {
    RegisterInfo* materialized = info->GetMaterializedEquivalent();
    DCHECK_NOT_NULL(materialized);
    OutputRegisterTransfer(materialized, info);
  }
}

void BytecodeRegisterOptimizer::AddToEquivalenceSet(
    RegisterInfo* set_member, RegisterInfo* non_set_member) {
  // Equivalence class is now of size >= 2, so we make sure it will be flushed.
  PushToRegistersNeedingFlush(non_set_member);
  non_set_member->AddToEquivalenceSetOf(set_member);
  // Flushing is only required when two or more registers are placed
  // in the same equivalence set.
  flush_required_ = true;
}

void BytecodeRegisterOptimizer::RegisterTransfer(RegisterInfo* input_info,
                                                 RegisterInfo* output_info) {
  bool output_is_observable =
      RegisterIsObservable(output_info->register_value());
  bool in_same_equivalence_set =
      output_info->IsInSameEquivalenceSet(input_info);
  if (in_same_equivalence_set &&
      (!output_is_observable || output_info->materialized())) {
    return;  // Nothing more to do.
  }

  // Materialize an alternate in the equivalence set that
  // |output_info| is leaving.
  if (output_info->materialized()) {
    CreateMaterializedEquivalent(output_info);
  }

  // Add |output_info| to new equivalence set.
  if (!in_same_equivalence_set) {
    AddToEquivalenceSet(input_info, output_info);
  }

  if (output_is_observable) {
    // Force store to be emitted when register is observable.
    output_info->set_materialized(false);
    RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
    OutputRegisterTransfer(materialized_info, output_info);
  }

  bool input_is_observable = RegisterIsObservable(input_info->register_value());
  if (input_is_observable) {
    // If input is observable by the debugger, mark all other temporaries
    // registers as unmaterialized so that this register is used in preference.
    input_info->MarkTemporariesAsUnmaterialized(temporary_base_);
  }
}

void BytecodeRegisterOptimizer::PrepareOutputRegister(Register reg) {
  RegisterInfo* reg_info = GetRegisterInfo(reg);
  if (reg_info->materialized()) {
    CreateMaterializedEquivalent(reg_info);
  }
  reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
  max_register_index_ =
      std::max(max_register_index_, reg_info->register_value().index());
}

void BytecodeRegisterOptimizer::PrepareOutputRegisterList(
    RegisterList reg_list) {
  int start_index = reg_list.first_register().index();
  for (int i = 0; i < reg_list.register_count(); ++i) {
    Register current(start_index + i);
    PrepareOutputRegister(current);
  }
}

Register BytecodeRegisterOptimizer::GetInputRegister(Register reg) {
  RegisterInfo* reg_info = GetRegisterInfo(reg);
  if (reg_info->materialized()) {
    return reg;
  } else {
    RegisterInfo* equivalent_info =
        GetMaterializedEquivalentNotAccumulator(reg_info);
    return equivalent_info->register_value();
  }
}

RegisterList BytecodeRegisterOptimizer::GetInputRegisterList(
    RegisterList reg_list) {
  if (reg_list.register_count() == 1) {
    // If there is only a single register, treat it as a normal input register.
    Register reg(GetInputRegister(reg_list.first_register()));
    return RegisterList(reg.index(), 1);
  } else {
    int start_index = reg_list.first_register().index();
    for (int i = 0; i < reg_list.register_count(); ++i) {
      Register current(start_index + i);
      RegisterInfo* input_info = GetRegisterInfo(current);
      Materialize(input_info);
    }
    return reg_list;
  }
}

void BytecodeRegisterOptimizer::GrowRegisterMap(Register reg) {
  DCHECK(RegisterIsTemporary(reg));
  size_t index = GetRegisterInfoTableIndex(reg);
  if (index >= register_info_table_.size()) {
    size_t new_size = index + 1;
    size_t old_size = register_info_table_.size();
    register_info_table_.resize(new_size);
    for (size_t i = old_size; i < new_size; ++i) {
      register_info_table_[i] =
          new (zone()) RegisterInfo(RegisterFromRegisterInfoTableIndex(i),
                                    NextEquivalenceId(), true, false);
    }
  }
}

void BytecodeRegisterOptimizer::AllocateRegister(RegisterInfo* info) {
  info->set_allocated(true);
  if (!info->materialized()) {
    info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
  }
}

void BytecodeRegisterOptimizer::RegisterAllocateEvent(Register reg) {
  AllocateRegister(GetOrCreateRegisterInfo(reg));
}

void BytecodeRegisterOptimizer::RegisterListAllocateEvent(
    RegisterList reg_list) {
  if (reg_list.register_count() != 0) {
    int first_index = reg_list.first_register().index();
    GrowRegisterMap(Register(first_index + reg_list.register_count() - 1));
    for (int i = 0; i < reg_list.register_count(); i++) {
      AllocateRegister(GetRegisterInfo(Register(first_index + i)));
    }
  }
}

void BytecodeRegisterOptimizer::RegisterListFreeEvent(RegisterList reg_list) {
  int first_index = reg_list.first_register().index();
  for (int i = 0; i < reg_list.register_count(); i++) {
    GetRegisterInfo(Register(first_index + i))->set_allocated(false);
  }
}

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