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_H_ 6 #define V8_INTERPRETER_BYTECODE_REGISTER_H_ 7 8 #include "src/interpreter/bytecodes.h" 9 10 #include "src/base/macros.h" 11 #include "src/base/platform/platform.h" 12 #include "src/common/globals.h" 13 #include "src/execution/frame-constants.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace interpreter { 18 19 // An interpreter Register which is located in the function's Register file 20 // in its stack-frame. Register hold parameters, this, and expression values. 21 class V8_EXPORT_PRIVATE Register final { 22 public: index_(index)23 constexpr explicit Register(int index = kInvalidIndex) : index_(index) {} 24 index()25 int index() const { return index_; } is_parameter()26 bool is_parameter() const { return index() < 0; } is_valid()27 bool is_valid() const { return index_ != kInvalidIndex; } 28 29 static Register FromParameterIndex(int index); 30 int ToParameterIndex() const; 31 32 // Returns an invalid register. invalid_value()33 static Register invalid_value() { return Register(); } 34 35 // Returns the register for the function's closure object. 36 static Register function_closure(); 37 bool is_function_closure() const; 38 39 // Returns the register which holds the current context object. 40 static Register current_context(); 41 bool is_current_context() const; 42 43 // Returns the register for the bytecode array. 44 static Register bytecode_array(); 45 bool is_bytecode_array() const; 46 47 // Returns the register for the saved bytecode offset. 48 static Register bytecode_offset(); 49 bool is_bytecode_offset() const; 50 51 // Returns the register for the argument count. 52 static Register argument_count(); 53 54 // Returns a register that can be used to represent the accumulator 55 // within code in the interpreter, but should never be emitted in 56 // bytecode. 57 static Register virtual_accumulator(); 58 59 OperandSize SizeOfOperand() const; 60 ToOperand()61 constexpr int32_t ToOperand() const { 62 return kRegisterFileStartOffset - index_; 63 } FromOperand(int32_t operand)64 static Register FromOperand(int32_t operand) { 65 return Register(kRegisterFileStartOffset - operand); 66 } 67 FromShortStar(Bytecode bytecode)68 static constexpr Register FromShortStar(Bytecode bytecode) { 69 DCHECK(Bytecodes::IsShortStar(bytecode)); 70 return Register(static_cast<int>(Bytecode::kStar0) - 71 static_cast<int>(bytecode)); 72 } 73 TryToShortStar()74 const base::Optional<Bytecode> TryToShortStar() const { 75 if (index() >= 0 && index() < Bytecodes::kShortStarCount) { 76 Bytecode bytecode = 77 static_cast<Bytecode>(static_cast<int>(Bytecode::kStar0) - index()); 78 DCHECK_GE(bytecode, Bytecode::kFirstShortStar); 79 DCHECK_LE(bytecode, Bytecode::kLastShortStar); 80 return bytecode; 81 } 82 return {}; 83 } 84 85 static bool AreContiguous(Register reg1, Register reg2, 86 Register reg3 = invalid_value(), 87 Register reg4 = invalid_value(), 88 Register reg5 = invalid_value()); 89 90 std::string ToString() const; 91 92 bool operator==(const Register& other) const { 93 return index() == other.index(); 94 } 95 bool operator!=(const Register& other) const { 96 return index() != other.index(); 97 } 98 bool operator<(const Register& other) const { 99 return index() < other.index(); 100 } 101 bool operator<=(const Register& other) const { 102 return index() <= other.index(); 103 } 104 bool operator>(const Register& other) const { 105 return index() > other.index(); 106 } 107 bool operator>=(const Register& other) const { 108 return index() >= other.index(); 109 } 110 111 private: 112 DISALLOW_NEW_AND_DELETE() 113 114 static const int kInvalidIndex = kMaxInt; 115 static const int kRegisterFileStartOffset = 116 InterpreterFrameConstants::kRegisterFileFromFp / kSystemPointerSize; 117 118 int index_; 119 }; 120 121 class RegisterList { 122 public: RegisterList()123 RegisterList() 124 : first_reg_index_(Register::invalid_value().index()), 125 register_count_(0) {} RegisterList(Register r)126 explicit RegisterList(Register r) : RegisterList(r.index(), 1) {} 127 128 // Returns a new RegisterList which is a truncated version of this list, with 129 // |count| registers. Truncate(int new_count)130 const RegisterList Truncate(int new_count) { 131 DCHECK_GE(new_count, 0); 132 DCHECK_LT(new_count, register_count_); 133 return RegisterList(first_reg_index_, new_count); 134 } PopLeft()135 const RegisterList PopLeft() { 136 DCHECK_GE(register_count_, 0); 137 return RegisterList(first_reg_index_ + 1, register_count_ - 1); 138 } 139 140 const Register operator[](size_t i) const { 141 DCHECK_LT(static_cast<int>(i), register_count_); 142 return Register(first_reg_index_ + static_cast<int>(i)); 143 } 144 first_register()145 const Register first_register() const { 146 return (register_count() == 0) ? Register(0) : (*this)[0]; 147 } 148 last_register()149 const Register last_register() const { 150 return (register_count() == 0) ? Register(0) : (*this)[register_count_ - 1]; 151 } 152 register_count()153 int register_count() const { return register_count_; } 154 155 private: 156 friend class BytecodeRegisterAllocator; 157 friend class BytecodeDecoder; 158 friend class InterpreterTester; 159 friend class BytecodeUtils; 160 friend class BytecodeArrayIterator; 161 RegisterList(int first_reg_index,int register_count)162 RegisterList(int first_reg_index, int register_count) 163 : first_reg_index_(first_reg_index), register_count_(register_count) {} 164 165 // Increases the size of the register list by one. IncrementRegisterCount()166 void IncrementRegisterCount() { register_count_++; } 167 168 int first_reg_index_; 169 int register_count_; 170 }; 171 172 } // namespace interpreter 173 } // namespace internal 174 } // namespace v8 175 176 #endif // V8_INTERPRETER_BYTECODE_REGISTER_H_ 177