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/bytecodes.h" 9 #include "src/zone-containers.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace interpreter { 14 15 class BytecodeArrayBuilder; 16 class Register; 17 class TemporaryRegisterObserver; 18 19 class TemporaryRegisterAllocator final { 20 public: 21 TemporaryRegisterAllocator(Zone* zone, int start_index); 22 23 // Borrow a temporary register. 24 int BorrowTemporaryRegister(); 25 26 // Borrow a temporary register from the register range outside of 27 // |start_index| to |end_index|. 28 int BorrowTemporaryRegisterNotInRange(int start_index, int end_index); 29 30 // Return a temporary register when no longer used. 31 void ReturnTemporaryRegister(int reg_index); 32 33 // Ensure a run of consecutive registers is available. Each register in 34 // the range should be borrowed with BorrowConsecutiveTemporaryRegister(). 35 // Returns the start index of the run. 36 int PrepareForConsecutiveTemporaryRegisters(size_t count); 37 38 // Borrow a register from a range prepared with 39 // PrepareForConsecutiveTemporaryRegisters(). 40 void BorrowConsecutiveTemporaryRegister(int reg_index); 41 42 // Returns true if |reg| is a temporary register and is currently 43 // borrowed. 44 bool RegisterIsLive(Register reg) const; 45 46 // Returns the first register in the range of temporary registers. 47 Register first_temporary_register() const; 48 49 // Returns the last register in the range of temporary registers. 50 Register last_temporary_register() const; 51 52 // Returns the start index of temporary register allocations. 53 int allocation_base() const { return allocation_base_; } 54 55 // Returns the number of temporary register allocations made. 56 int allocation_count() const { return allocation_count_; } 57 58 // Sets an observer for temporary register events. 59 void set_observer(TemporaryRegisterObserver* observer); 60 61 private: 62 // Allocate a temporary register. 63 int AllocateTemporaryRegister(); 64 65 ZoneSet<int> free_temporaries_; 66 int allocation_base_; 67 int allocation_count_; 68 TemporaryRegisterObserver* observer_; 69 70 DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterAllocator); 71 }; 72 73 class TemporaryRegisterObserver { 74 public: 75 virtual ~TemporaryRegisterObserver() {} 76 virtual void TemporaryRegisterFreeEvent(Register reg) = 0; 77 }; 78 79 // A class that allows the instantiator to allocate temporary registers that are 80 // cleaned up when scope is closed. 81 class BytecodeRegisterAllocator final { 82 public: 83 explicit BytecodeRegisterAllocator(Zone* zone, 84 TemporaryRegisterAllocator* allocator); 85 ~BytecodeRegisterAllocator(); 86 Register NewRegister(); 87 88 // Ensure |count| consecutive allocations are available. 89 void PrepareForConsecutiveAllocations(size_t count); 90 91 // Get the next consecutive allocation after calling 92 // PrepareForConsecutiveAllocations. 93 Register NextConsecutiveRegister(); 94 95 // Returns true if |reg| is allocated in this allocator. 96 bool RegisterIsAllocatedInThisScope(Register reg) const; 97 98 // Returns true if unused consecutive allocations remain. 99 bool HasConsecutiveAllocations() const { return next_consecutive_count_ > 0; } 100 101 private: 102 TemporaryRegisterAllocator* base_allocator() const { return base_allocator_; } 103 104 TemporaryRegisterAllocator* base_allocator_; 105 ZoneVector<int> allocated_; 106 int next_consecutive_register_; 107 int next_consecutive_count_; 108 109 DISALLOW_COPY_AND_ASSIGN(BytecodeRegisterAllocator); 110 }; 111 112 } // namespace interpreter 113 } // namespace internal 114 } // namespace v8 115 116 117 #endif // V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_ 118