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/frame-constants.h"
13 #include "src/globals.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   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, int parameter_count);
30   int ToParameterIndex(int parameter_count) 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 a register that can be used to represent the accumulator
52   // within code in the interpreter, but should never be emitted in
53   // bytecode.
54   static Register virtual_accumulator();
55 
56   OperandSize SizeOfOperand() const;
57 
ToOperand()58   int32_t ToOperand() const { return kRegisterFileStartOffset - index_; }
FromOperand(int32_t operand)59   static Register FromOperand(int32_t operand) {
60     return Register(kRegisterFileStartOffset - operand);
61   }
62 
63   static bool AreContiguous(Register reg1, Register reg2,
64                             Register reg3 = invalid_value(),
65                             Register reg4 = invalid_value(),
66                             Register reg5 = invalid_value());
67 
68   std::string ToString(int parameter_count) const;
69 
70   bool operator==(const Register& other) const {
71     return index() == other.index();
72   }
73   bool operator!=(const Register& other) const {
74     return index() != other.index();
75   }
76   bool operator<(const Register& other) const {
77     return index() < other.index();
78   }
79   bool operator<=(const Register& other) const {
80     return index() <= other.index();
81   }
82   bool operator>(const Register& other) const {
83     return index() > other.index();
84   }
85   bool operator>=(const Register& other) const {
86     return index() >= other.index();
87   }
88 
89  private:
90   DISALLOW_NEW_AND_DELETE();
91 
92   static const int kInvalidIndex = kMaxInt;
93   static const int kRegisterFileStartOffset =
94       InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize;
95 
96   int index_;
97 };
98 
99 class RegisterList {
100  public:
RegisterList()101   RegisterList()
102       : first_reg_index_(Register::invalid_value().index()),
103         register_count_(0) {}
RegisterList(Register r)104   explicit RegisterList(Register r) : RegisterList(r.index(), 1) {}
105 
106   // Returns a new RegisterList which is a truncated version of this list, with
107   // |count| registers.
Truncate(int new_count)108   const RegisterList Truncate(int new_count) {
109     DCHECK_GE(new_count, 0);
110     DCHECK_LT(new_count, register_count_);
111     return RegisterList(first_reg_index_, new_count);
112   }
113 
114   const Register operator[](size_t i) const {
115     DCHECK_LT(static_cast<int>(i), register_count_);
116     return Register(first_reg_index_ + static_cast<int>(i));
117   }
118 
first_register()119   const Register first_register() const {
120     return (register_count() == 0) ? Register(0) : (*this)[0];
121   }
122 
last_register()123   const Register last_register() const {
124     return (register_count() == 0) ? Register(0) : (*this)[register_count_ - 1];
125   }
126 
register_count()127   int register_count() const { return register_count_; }
128 
129  private:
130   friend class BytecodeRegisterAllocator;
131   friend class BytecodeDecoder;
132   friend class InterpreterTester;
133   friend class BytecodeUtils;
134 
RegisterList(int first_reg_index,int register_count)135   RegisterList(int first_reg_index, int register_count)
136       : first_reg_index_(first_reg_index), register_count_(register_count) {}
137 
138   // Increases the size of the register list by one.
IncrementRegisterCount()139   void IncrementRegisterCount() { register_count_++; }
140 
141   int first_reg_index_;
142   int register_count_;
143 };
144 
145 }  // namespace interpreter
146 }  // namespace internal
147 }  // namespace v8
148 
149 #endif  // V8_INTERPRETER_BYTECODE_REGISTER_H_
150