Home | History | Annotate | Download | only in interpreter
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
      6 #define V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
      7 
      8 #include "src/interpreter/bytecode-register.h"
      9 #include "src/interpreter/bytecodes.h"
     10 #include "src/zone/zone-containers.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace interpreter {
     15 
     16 // A class that allows the allocation of contiguous temporary registers.
     17 class BytecodeRegisterAllocator final {
     18  public:
     19   // Enables observation of register allocation and free events.
     20   class Observer {
     21    public:
     22     virtual ~Observer() {}
     23     virtual void RegisterAllocateEvent(Register reg) = 0;
     24     virtual void RegisterListAllocateEvent(RegisterList reg_list) = 0;
     25     virtual void RegisterListFreeEvent(RegisterList reg_list) = 0;
     26   };
     27 
     28   explicit BytecodeRegisterAllocator(int start_index)
     29       : next_register_index_(start_index),
     30         max_register_count_(start_index),
     31         observer_(nullptr) {}
     32   ~BytecodeRegisterAllocator() {}
     33 
     34   // Returns a new register.
     35   Register NewRegister() {
     36     Register reg(next_register_index_++);
     37     max_register_count_ = std::max(next_register_index_, max_register_count_);
     38     if (observer_) {
     39       observer_->RegisterAllocateEvent(reg);
     40     }
     41     return reg;
     42   }
     43 
     44   // Returns a consecutive list of |count| new registers.
     45   RegisterList NewRegisterList(int count) {
     46     RegisterList reg_list(next_register_index_, count);
     47     next_register_index_ += count;
     48     max_register_count_ = std::max(next_register_index_, max_register_count_);
     49     if (observer_) {
     50       observer_->RegisterListAllocateEvent(reg_list);
     51     }
     52     return reg_list;
     53   }
     54 
     55   // Returns a growable register list.
     56   RegisterList NewGrowableRegisterList() {
     57     RegisterList reg_list(next_register_index_, 0);
     58     return reg_list;
     59   }
     60 
     61   // Appends a new register to |reg_list| increasing it's count by one and
     62   // returning the register added.
     63   //
     64   // Note: no other new registers must be currently allocated since the register
     65   // list was originally allocated.
     66   Register GrowRegisterList(RegisterList* reg_list) {
     67     Register reg(NewRegister());
     68     reg_list->IncrementRegisterCount();
     69     // If the following CHECK fails then a register was allocated (and not
     70     // freed) between the creation of the RegisterList and this call to add a
     71     // Register.
     72     CHECK_EQ(reg.index(), reg_list->last_register().index());
     73     return reg;
     74   }
     75 
     76   // Release all registers above |register_index|.
     77   void ReleaseRegisters(int register_index) {
     78     if (observer_) {
     79       observer_->RegisterListFreeEvent(
     80           RegisterList(register_index, next_register_index_ - register_index));
     81     }
     82     next_register_index_ = register_index;
     83   }
     84 
     85   // Returns true if the register |reg| is a live register.
     86   bool RegisterIsLive(Register reg) const {
     87     return reg.index() < next_register_index_;
     88   }
     89 
     90   void set_observer(Observer* observer) { observer_ = observer; }
     91 
     92   int next_register_index() const { return next_register_index_; }
     93   int maximum_register_count() const { return max_register_count_; }
     94 
     95  private:
     96   int next_register_index_;
     97   int max_register_count_;
     98   Observer* observer_;
     99 
    100   DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterAllocator);
    101 };
    102 
    103 }  // namespace interpreter
    104 }  // namespace internal
    105 }  // namespace v8
    106 
    107 
    108 #endif  // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
    109