11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
61cb0ef41Sopenharmony_ci#define V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register.h"
91cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h"
101cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_cinamespace interpreter {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// A class that allows the allocation of contiguous temporary registers.
171cb0ef41Sopenharmony_ciclass BytecodeRegisterAllocator final {
181cb0ef41Sopenharmony_ci public:
191cb0ef41Sopenharmony_ci  // Enables observation of register allocation and free events.
201cb0ef41Sopenharmony_ci  class Observer {
211cb0ef41Sopenharmony_ci   public:
221cb0ef41Sopenharmony_ci    virtual ~Observer() = default;
231cb0ef41Sopenharmony_ci    virtual void RegisterAllocateEvent(Register reg) = 0;
241cb0ef41Sopenharmony_ci    virtual void RegisterListAllocateEvent(RegisterList reg_list) = 0;
251cb0ef41Sopenharmony_ci    virtual void RegisterListFreeEvent(RegisterList reg_list) = 0;
261cb0ef41Sopenharmony_ci  };
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  explicit BytecodeRegisterAllocator(int start_index)
291cb0ef41Sopenharmony_ci      : next_register_index_(start_index),
301cb0ef41Sopenharmony_ci        max_register_count_(start_index),
311cb0ef41Sopenharmony_ci        observer_(nullptr) {}
321cb0ef41Sopenharmony_ci  ~BytecodeRegisterAllocator() = default;
331cb0ef41Sopenharmony_ci  BytecodeRegisterAllocator(const BytecodeRegisterAllocator&) = delete;
341cb0ef41Sopenharmony_ci  BytecodeRegisterAllocator& operator=(const BytecodeRegisterAllocator&) =
351cb0ef41Sopenharmony_ci      delete;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  // Returns a new register.
381cb0ef41Sopenharmony_ci  Register NewRegister() {
391cb0ef41Sopenharmony_ci    Register reg(next_register_index_++);
401cb0ef41Sopenharmony_ci    max_register_count_ = std::max(next_register_index_, max_register_count_);
411cb0ef41Sopenharmony_ci    if (observer_) {
421cb0ef41Sopenharmony_ci      observer_->RegisterAllocateEvent(reg);
431cb0ef41Sopenharmony_ci    }
441cb0ef41Sopenharmony_ci    return reg;
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  // Returns a consecutive list of |count| new registers.
481cb0ef41Sopenharmony_ci  RegisterList NewRegisterList(int count) {
491cb0ef41Sopenharmony_ci    RegisterList reg_list(next_register_index_, count);
501cb0ef41Sopenharmony_ci    next_register_index_ += count;
511cb0ef41Sopenharmony_ci    max_register_count_ = std::max(next_register_index_, max_register_count_);
521cb0ef41Sopenharmony_ci    if (observer_) {
531cb0ef41Sopenharmony_ci      observer_->RegisterListAllocateEvent(reg_list);
541cb0ef41Sopenharmony_ci    }
551cb0ef41Sopenharmony_ci    return reg_list;
561cb0ef41Sopenharmony_ci  }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  // Returns a growable register list.
591cb0ef41Sopenharmony_ci  RegisterList NewGrowableRegisterList() {
601cb0ef41Sopenharmony_ci    RegisterList reg_list(next_register_index_, 0);
611cb0ef41Sopenharmony_ci    return reg_list;
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // Appends a new register to |reg_list| increasing it's count by one and
651cb0ef41Sopenharmony_ci  // returning the register added.
661cb0ef41Sopenharmony_ci  //
671cb0ef41Sopenharmony_ci  // Note: no other new registers must be currently allocated since the register
681cb0ef41Sopenharmony_ci  // list was originally allocated.
691cb0ef41Sopenharmony_ci  Register GrowRegisterList(RegisterList* reg_list) {
701cb0ef41Sopenharmony_ci    Register reg(NewRegister());
711cb0ef41Sopenharmony_ci    reg_list->IncrementRegisterCount();
721cb0ef41Sopenharmony_ci    // If the following CHECK fails then a register was allocated (and not
731cb0ef41Sopenharmony_ci    // freed) between the creation of the RegisterList and this call to add a
741cb0ef41Sopenharmony_ci    // Register.
751cb0ef41Sopenharmony_ci    CHECK_EQ(reg.index(), reg_list->last_register().index());
761cb0ef41Sopenharmony_ci    return reg;
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Release all registers above |register_index|.
801cb0ef41Sopenharmony_ci  void ReleaseRegisters(int register_index) {
811cb0ef41Sopenharmony_ci    int count = next_register_index_ - register_index;
821cb0ef41Sopenharmony_ci    next_register_index_ = register_index;
831cb0ef41Sopenharmony_ci    if (observer_) {
841cb0ef41Sopenharmony_ci      observer_->RegisterListFreeEvent(RegisterList(register_index, count));
851cb0ef41Sopenharmony_ci    }
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  // Returns true if the register |reg| is a live register.
891cb0ef41Sopenharmony_ci  bool RegisterIsLive(Register reg) const {
901cb0ef41Sopenharmony_ci    return reg.index() < next_register_index_;
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  // Returns a register list for all currently live registers.
941cb0ef41Sopenharmony_ci  RegisterList AllLiveRegisters() const {
951cb0ef41Sopenharmony_ci    return RegisterList(0, next_register_index());
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  void set_observer(Observer* observer) { observer_ = observer; }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  int next_register_index() const { return next_register_index_; }
1011cb0ef41Sopenharmony_ci  int maximum_register_count() const { return max_register_count_; }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci private:
1041cb0ef41Sopenharmony_ci  int next_register_index_;
1051cb0ef41Sopenharmony_ci  int max_register_count_;
1061cb0ef41Sopenharmony_ci  Observer* observer_;
1071cb0ef41Sopenharmony_ci};
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci}  // namespace interpreter
1101cb0ef41Sopenharmony_ci}  // namespace internal
1111cb0ef41Sopenharmony_ci}  // namespace v8
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci#endif  // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
115