// Copyright 2015 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_ALLOCATOR_H_
#define V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_

#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecodes.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace interpreter {

// A class that allows the allocation of contiguous temporary registers.
class BytecodeRegisterAllocator final {
 public:
  // Enables observation of register allocation and free events.
  class Observer {
   public:
    virtual ~Observer() = default;
    virtual void RegisterAllocateEvent(Register reg) = 0;
    virtual void RegisterListAllocateEvent(RegisterList reg_list) = 0;
    virtual void RegisterListFreeEvent(RegisterList reg_list) = 0;
  };

  explicit BytecodeRegisterAllocator(int start_index)
      : next_register_index_(start_index),
        max_register_count_(start_index),
        observer_(nullptr) {}
  ~BytecodeRegisterAllocator() = default;

  // Returns a new register.
  Register NewRegister() {
    Register reg(next_register_index_++);
    max_register_count_ = std::max(next_register_index_, max_register_count_);
    if (observer_) {
      observer_->RegisterAllocateEvent(reg);
    }
    return reg;
  }

  // Returns a consecutive list of |count| new registers.
  RegisterList NewRegisterList(int count) {
    RegisterList reg_list(next_register_index_, count);
    next_register_index_ += count;
    max_register_count_ = std::max(next_register_index_, max_register_count_);
    if (observer_) {
      observer_->RegisterListAllocateEvent(reg_list);
    }
    return reg_list;
  }

  // Returns a growable register list.
  RegisterList NewGrowableRegisterList() {
    RegisterList reg_list(next_register_index_, 0);
    return reg_list;
  }

  // Appends a new register to |reg_list| increasing it's count by one and
  // returning the register added.
  //
  // Note: no other new registers must be currently allocated since the register
  // list was originally allocated.
  Register GrowRegisterList(RegisterList* reg_list) {
    Register reg(NewRegister());
    reg_list->IncrementRegisterCount();
    // If the following CHECK fails then a register was allocated (and not
    // freed) between the creation of the RegisterList and this call to add a
    // Register.
    CHECK_EQ(reg.index(), reg_list->last_register().index());
    return reg;
  }

  // Release all registers above |register_index|.
  void ReleaseRegisters(int register_index) {
    int count = next_register_index_ - register_index;
    next_register_index_ = register_index;
    if (observer_) {
      observer_->RegisterListFreeEvent(RegisterList(register_index, count));
    }
  }

  // Returns true if the register |reg| is a live register.
  bool RegisterIsLive(Register reg) const {
    return reg.index() < next_register_index_;
  }

  // Returns a register list for all currently live registers.
  RegisterList AllLiveRegisters() const {
    return RegisterList(0, next_register_index());
  }

  void set_observer(Observer* observer) { observer_ = observer; }

  int next_register_index() const { return next_register_index_; }
  int maximum_register_count() const { return max_register_count_; }

 private:
  int next_register_index_;
  int max_register_count_;
  Observer* observer_;

  DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterAllocator);
};

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


#endif  // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
