1 // Copyright 2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_REGISTER_ALLOCATOR_H_ 29 #define V8_REGISTER_ALLOCATOR_H_ 30 31 #include "macro-assembler.h" 32 33 #if V8_TARGET_ARCH_IA32 34 #include "ia32/register-allocator-ia32.h" 35 #elif V8_TARGET_ARCH_X64 36 #include "x64/register-allocator-x64.h" 37 #elif V8_TARGET_ARCH_ARM 38 #include "arm/register-allocator-arm.h" 39 #else 40 #error Unsupported target architecture. 41 #endif 42 43 namespace v8 { 44 namespace internal { 45 46 47 // ------------------------------------------------------------------------- 48 // Results 49 // 50 // Results encapsulate the compile-time values manipulated by the code 51 // generator. They can represent registers or constants. 52 53 class Result BASE_EMBEDDED { 54 public: 55 enum Type { 56 INVALID, 57 REGISTER, 58 CONSTANT 59 }; 60 61 // Construct an invalid result. Result()62 Result() { invalidate(); } 63 64 // Construct a register Result. 65 explicit Result(Register reg); 66 67 // Construct a Result whose value is a compile-time constant. Result(Handle<Object> value)68 explicit Result(Handle<Object> value) { 69 value_ = TypeField::encode(CONSTANT) 70 | DataField::encode(ConstantList()->length()); 71 ConstantList()->Add(value); 72 } 73 74 // The copy constructor and assignment operators could each create a new 75 // register reference. Result(const Result & other)76 Result(const Result& other) { 77 other.CopyTo(this); 78 } 79 80 Result& operator=(const Result& other) { 81 if (this != &other) { 82 Unuse(); 83 other.CopyTo(this); 84 } 85 return *this; 86 } 87 88 inline ~Result(); 89 90 // Static indirection table for handles to constants. If a Result 91 // represents a constant, the data contains an index into this table 92 // of handles to the actual constants. 93 typedef ZoneList<Handle<Object> > ZoneObjectList; 94 95 static ZoneObjectList* ConstantList(); 96 97 // Clear the constants indirection table. ClearConstantList()98 static void ClearConstantList() { 99 ConstantList()->Clear(); 100 } 101 102 inline void Unuse(); 103 type()104 Type type() const { return TypeField::decode(value_); } 105 invalidate()106 void invalidate() { value_ = TypeField::encode(INVALID); } 107 is_valid()108 bool is_valid() const { return type() != INVALID; } is_register()109 bool is_register() const { return type() == REGISTER; } is_constant()110 bool is_constant() const { return type() == CONSTANT; } 111 reg()112 Register reg() const { 113 ASSERT(is_register()); 114 uint32_t reg = DataField::decode(value_); 115 Register result; 116 result.code_ = reg; 117 return result; 118 } 119 handle()120 Handle<Object> handle() const { 121 ASSERT(type() == CONSTANT); 122 return ConstantList()->at(DataField::decode(value_)); 123 } 124 125 // Move this result to an arbitrary register. The register is not 126 // necessarily spilled from the frame or even singly-referenced outside 127 // it. 128 void ToRegister(); 129 130 // Move this result to a specified register. The register is spilled from 131 // the frame, and the register is singly-referenced (by this result) 132 // outside the frame. 133 void ToRegister(Register reg); 134 135 private: 136 uint32_t value_; 137 138 class TypeField: public BitField<Type, 0, 2> {}; 139 class DataField: public BitField<uint32_t, 2, 32 - 3> {}; 140 141 inline void CopyTo(Result* destination) const; 142 143 friend class CodeGeneratorScope; 144 }; 145 146 147 // ------------------------------------------------------------------------- 148 // Register file 149 // 150 // The register file tracks reference counts for the processor registers. 151 // It is used by both the register allocator and the virtual frame. 152 153 class RegisterFile BASE_EMBEDDED { 154 public: RegisterFile()155 RegisterFile() { Reset(); } 156 Reset()157 void Reset() { 158 for (int i = 0; i < kNumRegisters; i++) { 159 ref_counts_[i] = 0; 160 } 161 } 162 163 // Predicates and accessors for the reference counts. is_used(int num)164 bool is_used(int num) { 165 ASSERT(0 <= num && num < kNumRegisters); 166 return ref_counts_[num] > 0; 167 } 168 count(int num)169 int count(int num) { 170 ASSERT(0 <= num && num < kNumRegisters); 171 return ref_counts_[num]; 172 } 173 174 // Record a use of a register by incrementing its reference count. Use(int num)175 void Use(int num) { 176 ASSERT(0 <= num && num < kNumRegisters); 177 ref_counts_[num]++; 178 } 179 180 // Record that a register will no longer be used by decrementing its 181 // reference count. Unuse(int num)182 void Unuse(int num) { 183 ASSERT(is_used(num)); 184 ref_counts_[num]--; 185 } 186 187 // Copy the reference counts from this register file to the other. CopyTo(RegisterFile * other)188 void CopyTo(RegisterFile* other) { 189 for (int i = 0; i < kNumRegisters; i++) { 190 other->ref_counts_[i] = ref_counts_[i]; 191 } 192 } 193 194 private: 195 static const int kNumRegisters = RegisterAllocatorConstants::kNumRegisters; 196 197 int ref_counts_[kNumRegisters]; 198 199 // Very fast inlined loop to find a free register. Used in 200 // RegisterAllocator::AllocateWithoutSpilling. Returns 201 // kInvalidRegister if no free register found. ScanForFreeRegister()202 int ScanForFreeRegister() { 203 for (int i = 0; i < RegisterAllocatorConstants::kNumRegisters; i++) { 204 if (!is_used(i)) return i; 205 } 206 return RegisterAllocatorConstants::kInvalidRegister; 207 } 208 209 friend class RegisterAllocator; 210 }; 211 212 213 // ------------------------------------------------------------------------- 214 // Register allocator 215 // 216 217 class RegisterAllocator BASE_EMBEDDED { 218 public: 219 static const int kNumRegisters = 220 RegisterAllocatorConstants::kNumRegisters; 221 static const int kInvalidRegister = 222 RegisterAllocatorConstants::kInvalidRegister; 223 RegisterAllocator(CodeGenerator * cgen)224 explicit RegisterAllocator(CodeGenerator* cgen) : cgen_(cgen) {} 225 226 // True if the register is reserved by the code generator, false if it 227 // can be freely used by the allocator Defined in the 228 // platform-specific XXX-inl.h files.. 229 static inline bool IsReserved(Register reg); 230 231 // Convert between (unreserved) assembler registers and allocator 232 // numbers. Defined in the platform-specific XXX-inl.h files. 233 static inline int ToNumber(Register reg); 234 static inline Register ToRegister(int num); 235 236 // Predicates and accessors for the registers' reference counts. is_used(int num)237 bool is_used(int num) { return registers_.is_used(num); } is_used(Register reg)238 bool is_used(Register reg) { return registers_.is_used(ToNumber(reg)); } 239 count(int num)240 int count(int num) { return registers_.count(num); } count(Register reg)241 int count(Register reg) { return registers_.count(ToNumber(reg)); } 242 243 // Explicitly record a reference to a register. Use(int num)244 void Use(int num) { registers_.Use(num); } Use(Register reg)245 void Use(Register reg) { registers_.Use(ToNumber(reg)); } 246 247 // Explicitly record that a register will no longer be used. Unuse(int num)248 void Unuse(int num) { registers_.Unuse(num); } Unuse(Register reg)249 void Unuse(Register reg) { registers_.Unuse(ToNumber(reg)); } 250 251 // Reset the register reference counts to free all non-reserved registers. Reset()252 void Reset() { registers_.Reset(); } 253 254 // Initialize the register allocator for entry to a JS function. On 255 // entry, the (non-reserved) registers used by the JS calling 256 // convention are referenced and the other (non-reserved) registers 257 // are free. 258 inline void Initialize(); 259 260 // Allocate a free register and return a register result if possible or 261 // fail and return an invalid result. 262 Result Allocate(); 263 264 // Allocate a specific register if possible, spilling it from the 265 // current frame if necessary, or else fail and return an invalid 266 // result. 267 Result Allocate(Register target); 268 269 // Allocate a free register without spilling any from the current 270 // frame or fail and return an invalid result. 271 Result AllocateWithoutSpilling(); 272 273 // Allocate a free byte register without spilling any from the current 274 // frame or fail and return an invalid result. 275 Result AllocateByteRegisterWithoutSpilling(); 276 277 // Copy the internal state to a register file, to be restored later by 278 // RestoreFrom. SaveTo(RegisterFile * register_file)279 void SaveTo(RegisterFile* register_file) { 280 registers_.CopyTo(register_file); 281 } 282 283 // Restore the internal state. RestoreFrom(RegisterFile * register_file)284 void RestoreFrom(RegisterFile* register_file) { 285 register_file->CopyTo(®isters_); 286 } 287 288 private: 289 CodeGenerator* cgen_; 290 RegisterFile registers_; 291 }; 292 293 } } // namespace v8::internal 294 295 #endif // V8_REGISTER_ALLOCATOR_H_ 296