OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
| 8 #include "src/interpreter/bytecode-traits.h" |
8 | 9 |
9 namespace v8 { | 10 namespace v8 { |
10 namespace internal { | 11 namespace internal { |
11 namespace interpreter { | 12 namespace interpreter { |
12 | 13 |
13 // Maximum number of operands a bytecode may have. | |
14 static const int kMaxOperands = 3; | |
15 | |
16 // kBytecodeTable relies on kNone being the same as zero to detect length. | |
17 STATIC_ASSERT(static_cast<int>(OperandType::kNone) == 0); | |
18 | |
19 static const OperandType kBytecodeTable[][kMaxOperands] = { | |
20 #define DECLARE_OPERAND(_, ...) \ | |
21 { __VA_ARGS__ } \ | |
22 , | |
23 BYTECODE_LIST(DECLARE_OPERAND) | |
24 #undef DECLARE_OPERAND | |
25 }; | |
26 | |
27 | 14 |
28 // static | 15 // static |
29 const char* Bytecodes::ToString(Bytecode bytecode) { | 16 const char* Bytecodes::ToString(Bytecode bytecode) { |
30 switch (bytecode) { | 17 switch (bytecode) { |
31 #define CASE(Name, ...) \ | 18 #define CASE(Name, ...) \ |
32 case Bytecode::k##Name: \ | 19 case Bytecode::k##Name: \ |
33 return #Name; | 20 return #Name; |
34 BYTECODE_LIST(CASE) | 21 BYTECODE_LIST(CASE) |
35 #undef CASE | 22 #undef CASE |
36 } | 23 } |
37 UNREACHABLE(); | 24 UNREACHABLE(); |
38 return ""; | 25 return ""; |
39 } | 26 } |
40 | 27 |
41 | 28 |
42 // static | 29 // static |
43 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
44 switch (operand_type) { | 31 switch (operand_type) { |
45 #define CASE(Name) \ | 32 #define CASE(Name, _) \ |
46 case OperandType::k##Name: \ | 33 case OperandType::k##Name: \ |
47 return #Name; | 34 return #Name; |
48 OPERAND_TYPE_LIST(CASE) | 35 OPERAND_TYPE_LIST(CASE) |
49 #undef CASE | 36 #undef CASE |
50 } | 37 } |
51 UNREACHABLE(); | 38 UNREACHABLE(); |
52 return ""; | 39 return ""; |
53 } | 40 } |
54 | 41 |
55 | 42 |
56 // static | 43 // static |
| 44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
| 45 switch (operand_size) { |
| 46 case OperandSize::kNone: |
| 47 return "None"; |
| 48 case OperandSize::kByte: |
| 49 return "Byte"; |
| 50 case OperandSize::kShort: |
| 51 return "Short"; |
| 52 } |
| 53 UNREACHABLE(); |
| 54 return ""; |
| 55 } |
| 56 |
| 57 |
| 58 // static |
57 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 59 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
58 return static_cast<uint8_t>(bytecode); | 60 return static_cast<uint8_t>(bytecode); |
59 } | 61 } |
60 | 62 |
61 | 63 |
62 // static | 64 // static |
63 Bytecode Bytecodes::FromByte(uint8_t value) { | 65 Bytecode Bytecodes::FromByte(uint8_t value) { |
64 Bytecode bytecode = static_cast<Bytecode>(value); | 66 Bytecode bytecode = static_cast<Bytecode>(value); |
65 DCHECK(bytecode <= Bytecode::kLast); | 67 DCHECK(bytecode <= Bytecode::kLast); |
66 return bytecode; | 68 return bytecode; |
67 } | 69 } |
68 | 70 |
69 | 71 |
70 // static | 72 // static |
| 73 int Bytecodes::Size(Bytecode bytecode) { |
| 74 DCHECK(bytecode <= Bytecode::kLast); |
| 75 switch (bytecode) { |
| 76 #define CASE(Name, ...) \ |
| 77 case Bytecode::k##Name: \ |
| 78 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; |
| 79 BYTECODE_LIST(CASE) |
| 80 #undef CASE |
| 81 } |
| 82 UNREACHABLE(); |
| 83 return 0; |
| 84 } |
| 85 |
| 86 |
| 87 // static |
71 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 88 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
72 DCHECK(bytecode <= Bytecode::kLast); | 89 DCHECK(bytecode <= Bytecode::kLast); |
73 int count; | 90 switch (bytecode) { |
74 uint8_t row = ToByte(bytecode); | 91 #define CASE(Name, ...) \ |
75 for (count = 0; count < kMaxOperands; count++) { | 92 case Bytecode::k##Name: \ |
76 if (kBytecodeTable[row][count] == OperandType::kNone) { | 93 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; |
77 break; | 94 BYTECODE_LIST(CASE) |
78 } | 95 #undef CASE |
79 } | 96 } |
80 return count; | 97 UNREACHABLE(); |
| 98 return 0; |
81 } | 99 } |
82 | 100 |
83 | 101 |
84 // static | 102 // static |
85 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 103 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
86 DCHECK(bytecode <= Bytecode::kLast && i < NumberOfOperands(bytecode)); | 104 DCHECK(bytecode <= Bytecode::kLast); |
87 return kBytecodeTable[ToByte(bytecode)][i]; | 105 switch (bytecode) { |
| 106 #define CASE(Name, ...) \ |
| 107 case Bytecode::k##Name: \ |
| 108 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); |
| 109 BYTECODE_LIST(CASE) |
| 110 #undef CASE |
| 111 } |
| 112 UNREACHABLE(); |
| 113 return OperandType::kNone; |
88 } | 114 } |
89 | 115 |
90 | 116 |
91 // static | 117 // static |
92 int Bytecodes::Size(Bytecode bytecode) { | 118 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { |
93 return 1 + NumberOfOperands(bytecode); | 119 DCHECK(bytecode <= Bytecode::kLast); |
| 120 switch (bytecode) { |
| 121 #define CASE(Name, ...) \ |
| 122 case Bytecode::k##Name: \ |
| 123 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); |
| 124 BYTECODE_LIST(CASE) |
| 125 #undef CASE |
| 126 } |
| 127 UNREACHABLE(); |
| 128 return OperandSize::kNone; |
94 } | 129 } |
95 | 130 |
96 | 131 |
97 // static | 132 // static |
98 int Bytecodes::MaximumNumberOfOperands() { return kMaxOperands; } | 133 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { |
| 134 DCHECK(bytecode <= Bytecode::kLast); |
| 135 switch (bytecode) { |
| 136 #define CASE(Name, ...) \ |
| 137 case Bytecode::k##Name: \ |
| 138 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); |
| 139 BYTECODE_LIST(CASE) |
| 140 #undef CASE |
| 141 } |
| 142 UNREACHABLE(); |
| 143 return 0; |
| 144 } |
99 | 145 |
100 | 146 |
101 // static | 147 // static |
102 int Bytecodes::MaximumSize() { return 1 + kMaxOperands; } | 148 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { |
| 149 switch (operand_type) { |
| 150 #define CASE(Name, Size) \ |
| 151 case OperandType::k##Name: \ |
| 152 return Size; |
| 153 OPERAND_TYPE_LIST(CASE) |
| 154 #undef CASE |
| 155 } |
| 156 UNREACHABLE(); |
| 157 return OperandSize::kNone; |
| 158 } |
103 | 159 |
104 | 160 |
105 // static | 161 // static |
106 bool Bytecodes::IsJump(Bytecode bytecode) { | 162 bool Bytecodes::IsJump(Bytecode bytecode) { |
107 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpIfTrue || | 163 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpIfTrue || |
108 bytecode == Bytecode::kJumpIfFalse; | 164 bytecode == Bytecode::kJumpIfFalse; |
109 } | 165 } |
110 | 166 |
111 | 167 |
112 // static | 168 // static |
113 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 169 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
114 return bytecode == Bytecode::kJumpConstant || | 170 return bytecode == Bytecode::kJumpConstant || |
115 bytecode == Bytecode::kJumpIfTrueConstant || | 171 bytecode == Bytecode::kJumpIfTrueConstant || |
116 bytecode == Bytecode::kJumpIfFalseConstant; | 172 bytecode == Bytecode::kJumpIfFalseConstant; |
117 } | 173 } |
118 | 174 |
119 | 175 |
120 // static | 176 // static |
| 177 uint16_t Bytecodes::ShortOperandFromBytes(const uint8_t* bytes) { |
| 178 return *reinterpret_cast<const uint16_t*>(bytes); |
| 179 } |
| 180 |
| 181 |
| 182 // static |
| 183 void Bytecodes::ShortOperandToBytes(uint16_t operand, uint8_t* bytes_out) { |
| 184 *reinterpret_cast<uint16_t*>(bytes_out) = operand; |
| 185 } |
| 186 |
| 187 |
| 188 // static |
121 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 189 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
122 int parameter_count) { | 190 int parameter_count) { |
123 Vector<char> buf = Vector<char>::New(50); | 191 Vector<char> buf = Vector<char>::New(50); |
124 | 192 |
125 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); | 193 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
126 int bytecode_size = Bytecodes::Size(bytecode); | 194 int bytecode_size = Bytecodes::Size(bytecode); |
127 | 195 |
128 for (int i = 0; i < bytecode_size; i++) { | 196 for (int i = 0; i < bytecode_size; i++) { |
129 SNPrintF(buf, "%02x ", bytecode_start[i]); | 197 SNPrintF(buf, "%02x ", bytecode_start[i]); |
130 os << buf.start(); | 198 os << buf.start(); |
131 } | 199 } |
132 for (int i = bytecode_size; i < Bytecodes::MaximumSize(); i++) { | 200 const int kBytecodeColumnSize = 6; |
| 201 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { |
133 os << " "; | 202 os << " "; |
134 } | 203 } |
135 | 204 |
136 os << bytecode << " "; | 205 os << bytecode << " "; |
137 | 206 |
138 const uint8_t* operands_start = bytecode_start + 1; | 207 int number_of_operands = NumberOfOperands(bytecode); |
139 int operands_size = bytecode_size - 1; | 208 for (int i = 0; i < number_of_operands; i++) { |
140 for (int i = 0; i < operands_size; i++) { | |
141 OperandType op_type = GetOperandType(bytecode, i); | 209 OperandType op_type = GetOperandType(bytecode, i); |
142 uint8_t operand = operands_start[i]; | 210 const uint8_t* operand_start = |
| 211 &bytecode_start[GetOperandOffset(bytecode, i)]; |
143 switch (op_type) { | 212 switch (op_type) { |
144 case interpreter::OperandType::kCount: | 213 case interpreter::OperandType::kCount8: |
145 os << "#" << static_cast<unsigned int>(operand); | 214 os << "#" << static_cast<unsigned int>(*operand_start); |
146 break; | 215 break; |
147 case interpreter::OperandType::kIdx: | 216 case interpreter::OperandType::kIdx8: |
148 os << "[" << static_cast<unsigned int>(operand) << "]"; | 217 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; |
149 break; | 218 break; |
| 219 case interpreter::OperandType::kIdx16: { |
| 220 os << "[" << Bytecodes::ShortOperandFromBytes(operand_start) << "]"; |
| 221 break; |
| 222 } |
150 case interpreter::OperandType::kImm8: | 223 case interpreter::OperandType::kImm8: |
151 os << "#" << static_cast<int>(static_cast<int8_t>(operand)); | 224 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); |
152 break; | 225 break; |
153 case interpreter::OperandType::kReg: { | 226 case interpreter::OperandType::kReg8: { |
154 Register reg = Register::FromOperand(operand); | 227 Register reg = Register::FromOperand(*operand_start); |
155 if (reg.is_parameter()) { | 228 if (reg.is_parameter()) { |
156 int parameter_index = reg.ToParameterIndex(parameter_count); | 229 int parameter_index = reg.ToParameterIndex(parameter_count); |
157 if (parameter_index == 0) { | 230 if (parameter_index == 0) { |
158 os << "<this>"; | 231 os << "<this>"; |
159 } else { | 232 } else { |
160 os << "a" << parameter_index - 1; | 233 os << "a" << parameter_index - 1; |
161 } | 234 } |
162 } else { | 235 } else { |
163 os << "r" << reg.index(); | 236 os << "r" << reg.index(); |
164 } | 237 } |
165 break; | 238 break; |
166 } | 239 } |
167 case interpreter::OperandType::kNone: | 240 case interpreter::OperandType::kNone: |
168 UNREACHABLE(); | 241 UNREACHABLE(); |
169 break; | 242 break; |
170 } | 243 } |
171 if (i != operands_size - 1) { | 244 if (i != number_of_operands - 1) { |
172 os << ", "; | 245 os << ", "; |
173 } | 246 } |
174 } | 247 } |
175 return os; | 248 return os; |
176 } | 249 } |
177 | 250 |
178 | 251 |
179 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 252 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
180 return os << Bytecodes::ToString(bytecode); | 253 return os << Bytecodes::ToString(bytecode); |
181 } | 254 } |
182 | 255 |
183 | 256 |
184 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | 257 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
185 return os << Bytecodes::OperandTypeToString(operand_type); | 258 return os << Bytecodes::OperandTypeToString(operand_type); |
186 } | 259 } |
187 | 260 |
188 | 261 |
| 262 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
| 263 return os << Bytecodes::OperandSizeToString(operand_size); |
| 264 } |
| 265 |
| 266 |
189 static const int kLastParamRegisterIndex = | 267 static const int kLastParamRegisterIndex = |
190 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 268 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
191 | 269 |
192 | 270 |
193 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values. | 271 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values. |
194 // Parameter indices are biased with the negative value kLastParamRegisterIndex | 272 // Parameter indices are biased with the negative value kLastParamRegisterIndex |
195 // for ease of access in the interpreter. | 273 // for ease of access in the interpreter. |
196 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex; | 274 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex; |
197 | 275 |
198 | 276 |
(...skipping 20 matching lines...) Expand all Loading... |
219 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } | 297 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } |
220 | 298 |
221 | 299 |
222 Register Register::FromOperand(uint8_t operand) { | 300 Register Register::FromOperand(uint8_t operand) { |
223 return Register(-static_cast<int8_t>(operand)); | 301 return Register(-static_cast<int8_t>(operand)); |
224 } | 302 } |
225 | 303 |
226 } // namespace interpreter | 304 } // namespace interpreter |
227 } // namespace internal | 305 } // namespace internal |
228 } // namespace v8 | 306 } // namespace v8 |
OLD | NEW |