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
15namespace v8 {
16namespace internal {
17namespace 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.
21class V8_EXPORT_PRIVATE Register final {
22 public:
23  constexpr explicit Register(int index = kInvalidIndex) : index_(index) {}
24
25  int index() const { return index_; }
26  bool is_parameter() const { return index() < 0; }
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.
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
61  constexpr int32_t ToOperand() const {
62    return kRegisterFileStartOffset - index_;
63  }
64  static Register FromOperand(int32_t operand) {
65    return Register(kRegisterFileStartOffset - operand);
66  }
67
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
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
121class RegisterList {
122 public:
123  RegisterList()
124      : first_reg_index_(Register::invalid_value().index()),
125        register_count_(0) {}
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.
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  }
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
145  const Register first_register() const {
146    return (register_count() == 0) ? Register(0) : (*this)[0];
147  }
148
149  const Register last_register() const {
150    return (register_count() == 0) ? Register(0) : (*this)[register_count_ - 1];
151  }
152
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
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.
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