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 #include "src/interpreter/bytecode-register.h"
6
7 namespace v8 {
8 namespace internal {
9 namespace interpreter {
10
11 static const int kLastParamRegisterIndex =
12 (InterpreterFrameConstants::kRegisterFileFromFp -
13 InterpreterFrameConstants::kLastParamFromFp) /
14 kPointerSize;
15 static const int kFunctionClosureRegisterIndex =
16 (InterpreterFrameConstants::kRegisterFileFromFp -
17 StandardFrameConstants::kFunctionOffset) /
18 kPointerSize;
19 static const int kCurrentContextRegisterIndex =
20 (InterpreterFrameConstants::kRegisterFileFromFp -
21 StandardFrameConstants::kContextOffset) /
22 kPointerSize;
23 static const int kNewTargetRegisterIndex =
24 (InterpreterFrameConstants::kRegisterFileFromFp -
25 InterpreterFrameConstants::kNewTargetFromFp) /
26 kPointerSize;
27 static const int kBytecodeArrayRegisterIndex =
28 (InterpreterFrameConstants::kRegisterFileFromFp -
29 InterpreterFrameConstants::kBytecodeArrayFromFp) /
30 kPointerSize;
31 static const int kBytecodeOffsetRegisterIndex =
32 (InterpreterFrameConstants::kRegisterFileFromFp -
33 InterpreterFrameConstants::kBytecodeOffsetFromFp) /
34 kPointerSize;
35 static const int kCallerPCOffsetRegisterIndex =
36 (InterpreterFrameConstants::kRegisterFileFromFp -
37 InterpreterFrameConstants::kCallerPCOffsetFromFp) /
38 kPointerSize;
39
FromParameterIndex(int index,int parameter_count)40 Register Register::FromParameterIndex(int index, int parameter_count) {
41 DCHECK_GE(index, 0);
42 DCHECK_LT(index, parameter_count);
43 int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
44 DCHECK_LT(register_index, 0);
45 return Register(register_index);
46 }
47
ToParameterIndex(int parameter_count) const48 int Register::ToParameterIndex(int parameter_count) const {
49 DCHECK(is_parameter());
50 return index() - kLastParamRegisterIndex + parameter_count - 1;
51 }
52
function_closure()53 Register Register::function_closure() {
54 return Register(kFunctionClosureRegisterIndex);
55 }
56
is_function_closure() const57 bool Register::is_function_closure() const {
58 return index() == kFunctionClosureRegisterIndex;
59 }
60
current_context()61 Register Register::current_context() {
62 return Register(kCurrentContextRegisterIndex);
63 }
64
is_current_context() const65 bool Register::is_current_context() const {
66 return index() == kCurrentContextRegisterIndex;
67 }
68
new_target()69 Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
70
is_new_target() const71 bool Register::is_new_target() const {
72 return index() == kNewTargetRegisterIndex;
73 }
74
bytecode_array()75 Register Register::bytecode_array() {
76 return Register(kBytecodeArrayRegisterIndex);
77 }
78
is_bytecode_array() const79 bool Register::is_bytecode_array() const {
80 return index() == kBytecodeArrayRegisterIndex;
81 }
82
bytecode_offset()83 Register Register::bytecode_offset() {
84 return Register(kBytecodeOffsetRegisterIndex);
85 }
86
is_bytecode_offset() const87 bool Register::is_bytecode_offset() const {
88 return index() == kBytecodeOffsetRegisterIndex;
89 }
90
91 // static
virtual_accumulator()92 Register Register::virtual_accumulator() {
93 return Register(kCallerPCOffsetRegisterIndex);
94 }
95
SizeOfOperand() const96 OperandSize Register::SizeOfOperand() const {
97 int32_t operand = ToOperand();
98 if (operand >= kMinInt8 && operand <= kMaxInt8) {
99 return OperandSize::kByte;
100 } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
101 return OperandSize::kShort;
102 } else {
103 return OperandSize::kQuad;
104 }
105 }
106
AreContiguous(Register reg1,Register reg2,Register reg3,Register reg4,Register reg5)107 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
108 Register reg4, Register reg5) {
109 if (reg1.index() + 1 != reg2.index()) {
110 return false;
111 }
112 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
113 return false;
114 }
115 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
116 return false;
117 }
118 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
119 return false;
120 }
121 return true;
122 }
123
ToString(int parameter_count) const124 std::string Register::ToString(int parameter_count) const {
125 if (is_current_context()) {
126 return std::string("<context>");
127 } else if (is_function_closure()) {
128 return std::string("<closure>");
129 } else if (is_new_target()) {
130 return std::string("<new.target>");
131 } else if (is_parameter()) {
132 int parameter_index = ToParameterIndex(parameter_count);
133 if (parameter_index == 0) {
134 return std::string("<this>");
135 } else {
136 std::ostringstream s;
137 s << "a" << parameter_index - 1;
138 return s.str();
139 }
140 } else {
141 std::ostringstream s;
142 s << "r" << index();
143 return s.str();
144 }
145 }
146
147 } // namespace interpreter
148 } // namespace internal
149 } // namespace v8
150