// 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/bytecodes.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeArrayBuilder;
class Register;
class TemporaryRegisterObserver;

class TemporaryRegisterAllocator final {
 public:
  TemporaryRegisterAllocator(Zone* zone, int start_index);

  // Borrow a temporary register.
  int BorrowTemporaryRegister();

  // Borrow a temporary register from the register range outside of
  // |start_index| to |end_index|.
  int BorrowTemporaryRegisterNotInRange(int start_index, int end_index);

  // Return a temporary register when no longer used.
  void ReturnTemporaryRegister(int reg_index);

  // Ensure a run of consecutive registers is available. Each register in
  // the range should be borrowed with BorrowConsecutiveTemporaryRegister().
  // Returns the start index of the run.
  int PrepareForConsecutiveTemporaryRegisters(size_t count);

  // Borrow a register from a range prepared with
  // PrepareForConsecutiveTemporaryRegisters().
  void BorrowConsecutiveTemporaryRegister(int reg_index);

  // Returns true if |reg| is a temporary register and is currently
  // borrowed.
  bool RegisterIsLive(Register reg) const;

  // Returns the first register in the range of temporary registers.
  Register first_temporary_register() const;

  // Returns the last register in the range of temporary registers.
  Register last_temporary_register() const;

  // Returns the start index of temporary register allocations.
  int allocation_base() const { return allocation_base_; }

  // Returns the number of temporary register allocations made.
  int allocation_count() const { return allocation_count_; }

  // Sets an observer for temporary register events.
  void set_observer(TemporaryRegisterObserver* observer);

 private:
  // Allocate a temporary register.
  int AllocateTemporaryRegister();

  ZoneSet<int> free_temporaries_;
  int allocation_base_;
  int allocation_count_;
  TemporaryRegisterObserver* observer_;

  DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterAllocator);
};

class TemporaryRegisterObserver {
 public:
  virtual ~TemporaryRegisterObserver() {}
  virtual void TemporaryRegisterFreeEvent(Register reg) = 0;
};

// A class that allows the instantiator to allocate temporary registers that are
// cleaned up when scope is closed.
class BytecodeRegisterAllocator final {
 public:
  explicit BytecodeRegisterAllocator(Zone* zone,
                                     TemporaryRegisterAllocator* allocator);
  ~BytecodeRegisterAllocator();
  Register NewRegister();

  // Ensure |count| consecutive allocations are available.
  void PrepareForConsecutiveAllocations(size_t count);

  // Get the next consecutive allocation after calling
  // PrepareForConsecutiveAllocations.
  Register NextConsecutiveRegister();

  // Returns true if |reg| is allocated in this allocator.
  bool RegisterIsAllocatedInThisScope(Register reg) const;

  // Returns true if unused consecutive allocations remain.
  bool HasConsecutiveAllocations() const { return next_consecutive_count_ > 0; }

 private:
  TemporaryRegisterAllocator* base_allocator() const { return base_allocator_; }

  TemporaryRegisterAllocator* base_allocator_;
  ZoneVector<int> allocated_;
  int next_consecutive_register_;
  int next_consecutive_count_;

  DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterAllocator);
};

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


#endif  // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
