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() = default;
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 
BytecodeRegisterAllocator(int start_index)28   explicit BytecodeRegisterAllocator(int start_index)
29       : next_register_index_(start_index),
30         max_register_count_(start_index),
31         observer_(nullptr) {}
32   ~BytecodeRegisterAllocator() = default;
33   BytecodeRegisterAllocator(const BytecodeRegisterAllocator&) = delete;
34   BytecodeRegisterAllocator& operator=(const BytecodeRegisterAllocator&) =
35       delete;
36 
37   // Returns a new register.
NewRegister()38   Register NewRegister() {
39     Register reg(next_register_index_++);
40     max_register_count_ = std::max(next_register_index_, max_register_count_);
41     if (observer_) {
42       observer_->RegisterAllocateEvent(reg);
43     }
44     return reg;
45   }
46 
47   // Returns a consecutive list of |count| new registers.
NewRegisterList(int count)48   RegisterList NewRegisterList(int count) {
49     RegisterList reg_list(next_register_index_, count);
50     next_register_index_ += count;
51     max_register_count_ = std::max(next_register_index_, max_register_count_);
52     if (observer_) {
53       observer_->RegisterListAllocateEvent(reg_list);
54     }
55     return reg_list;
56   }
57 
58   // Returns a growable register list.
NewGrowableRegisterList()59   RegisterList NewGrowableRegisterList() {
60     RegisterList reg_list(next_register_index_, 0);
61     return reg_list;
62   }
63 
64   // Appends a new register to |reg_list| increasing it's count by one and
65   // returning the register added.
66   //
67   // Note: no other new registers must be currently allocated since the register
68   // list was originally allocated.
GrowRegisterList(RegisterList* reg_list)69   Register GrowRegisterList(RegisterList* reg_list) {
70     Register reg(NewRegister());
71     reg_list->IncrementRegisterCount();
72     // If the following CHECK fails then a register was allocated (and not
73     // freed) between the creation of the RegisterList and this call to add a
74     // Register.
75     CHECK_EQ(reg.index(), reg_list->last_register().index());
76     return reg;
77   }
78 
79   // Release all registers above |register_index|.
ReleaseRegisters(int register_index)80   void ReleaseRegisters(int register_index) {
81     int count = next_register_index_ - register_index;
82     next_register_index_ = register_index;
83     if (observer_) {
84       observer_->RegisterListFreeEvent(RegisterList(register_index, count));
85     }
86   }
87 
88   // Returns true if the register |reg| is a live register.
RegisterIsLive(Register reg) const89   bool RegisterIsLive(Register reg) const {
90     return reg.index() < next_register_index_;
91   }
92 
93   // Returns a register list for all currently live registers.
AllLiveRegisters() const94   RegisterList AllLiveRegisters() const {
95     return RegisterList(0, next_register_index());
96   }
97 
set_observer(Observer* observer)98   void set_observer(Observer* observer) { observer_ = observer; }
99 
next_register_index() const100   int next_register_index() const { return next_register_index_; }
maximum_register_count() const101   int maximum_register_count() const { return max_register_count_; }
102 
103  private:
104   int next_register_index_;
105   int max_register_count_;
106   Observer* observer_;
107 };
108 
109 }  // namespace interpreter
110 }  // namespace internal
111 }  // namespace v8
112 
113 
114 #endif  // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
115