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/bytecodes.h"
6
7 #include <iomanip>
8
9 #include "src/base/bits.h"
10 #include "src/interpreter/bytecode-traits.h"
11
12 namespace v8 {
13 namespace internal {
14 namespace interpreter {
15
16 // clang-format off
17 const OperandType* const Bytecodes::kOperandTypes[] = {
18 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes,
19 BYTECODE_LIST(ENTRY)
20 #undef ENTRY
21 };
22
23 const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = {
24 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos,
25 BYTECODE_LIST(ENTRY)
26 #undef ENTRY
27 };
28
29 const int Bytecodes::kOperandCount[] = {
30 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount,
31 BYTECODE_LIST(ENTRY)
32 #undef ENTRY
33 };
34
35 const AccumulatorUse Bytecodes::kAccumulatorUse[] = {
36 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse,
37 BYTECODE_LIST(ENTRY)
38 #undef ENTRY
39 };
40
41 const int Bytecodes::kBytecodeSizes[3][kBytecodeCount] = {
42 {
43 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kSingleScaleSize,
44 BYTECODE_LIST(ENTRY)
45 #undef ENTRY
46 }, {
47 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize,
48 BYTECODE_LIST(ENTRY)
49 #undef ENTRY
50 }, {
51 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize,
52 BYTECODE_LIST(ENTRY)
53 #undef ENTRY
54 }
55 };
56
57 const OperandSize* const Bytecodes::kOperandSizes[3][kBytecodeCount] = {
58 {
59 #define ENTRY(Name, ...) \
60 BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes,
61 BYTECODE_LIST(ENTRY)
62 #undef ENTRY
63 }, {
64 #define ENTRY(Name, ...) \
65 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes,
66 BYTECODE_LIST(ENTRY)
67 #undef ENTRY
68 }, {
69 #define ENTRY(Name, ...) \
70 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes,
71 BYTECODE_LIST(ENTRY)
72 #undef ENTRY
73 }
74 };
75
76 const OperandSize
77 Bytecodes::kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount] = {
78 {
79 #define ENTRY(Name, ...) \
80 OperandScaler<OperandType::k##Name, OperandScale::kSingle>::kOperandSize,
81 OPERAND_TYPE_LIST(ENTRY)
82 #undef ENTRY
83 }, {
84 #define ENTRY(Name, ...) \
85 OperandScaler<OperandType::k##Name, OperandScale::kDouble>::kOperandSize,
86 OPERAND_TYPE_LIST(ENTRY)
87 #undef ENTRY
88 }, {
89 #define ENTRY(Name, ...) \
90 OperandScaler<OperandType::k##Name, OperandScale::kQuadruple>::kOperandSize,
91 OPERAND_TYPE_LIST(ENTRY)
92 #undef ENTRY
93 }
94 };
95 // clang-format on
96
97 // static
ToString(Bytecode bytecode)98 const char* Bytecodes::ToString(Bytecode bytecode) {
99 switch (bytecode) {
100 #define CASE(Name, ...) \
101 case Bytecode::k##Name: \
102 return #Name;
103 BYTECODE_LIST(CASE)
104 #undef CASE
105 }
106 UNREACHABLE();
107 }
108
109 // static
ToString(Bytecode bytecode,OperandScale operand_scale)110 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
111 static const char kSeparator = '.';
112
113 std::string value(ToString(bytecode));
114 if (operand_scale > OperandScale::kSingle) {
115 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
116 std::string suffix = ToString(prefix_bytecode);
117 return value.append(1, kSeparator).append(suffix);
118 } else {
119 return value;
120 }
121 }
122
123 // static
GetDebugBreak(Bytecode bytecode)124 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
125 DCHECK(!IsDebugBreak(bytecode));
126 if (bytecode == Bytecode::kWide) {
127 return Bytecode::kDebugBreakWide;
128 }
129 if (bytecode == Bytecode::kExtraWide) {
130 return Bytecode::kDebugBreakExtraWide;
131 }
132 int bytecode_size = Size(bytecode, OperandScale::kSingle);
133 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \
134 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
135 return Bytecode::k##Name; \
136 }
137 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
138 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
139 UNREACHABLE();
140 }
141
142 // static
GetOperandOffset(Bytecode bytecode,int i,OperandScale operand_scale)143 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
144 OperandScale operand_scale) {
145 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
146 // TODO(oth): restore this to a statically determined constant.
147 int offset = 1;
148 for (int operand_index = 0; operand_index < i; ++operand_index) {
149 OperandSize operand_size =
150 GetOperandSize(bytecode, operand_index, operand_scale);
151 offset += static_cast<int>(operand_size);
152 }
153 return offset;
154 }
155
156 // static
GetJumpWithoutToBoolean(Bytecode bytecode)157 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
158 switch (bytecode) {
159 case Bytecode::kJumpIfToBooleanTrue:
160 return Bytecode::kJumpIfTrue;
161 case Bytecode::kJumpIfToBooleanFalse:
162 return Bytecode::kJumpIfFalse;
163 case Bytecode::kJumpIfToBooleanTrueConstant:
164 return Bytecode::kJumpIfTrueConstant;
165 case Bytecode::kJumpIfToBooleanFalseConstant:
166 return Bytecode::kJumpIfFalseConstant;
167 default:
168 break;
169 }
170 UNREACHABLE();
171 }
172
173 // static
IsDebugBreak(Bytecode bytecode)174 bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
175 switch (bytecode) {
176 #define CASE(Name, ...) case Bytecode::k##Name:
177 DEBUG_BREAK_BYTECODE_LIST(CASE);
178 #undef CASE
179 return true;
180 default:
181 break;
182 }
183 return false;
184 }
185
186 // static
IsRegisterOperandType(OperandType operand_type)187 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
188 switch (operand_type) {
189 #define CASE(Name, _) \
190 case OperandType::k##Name: \
191 return true;
192 REGISTER_OPERAND_TYPE_LIST(CASE)
193 #undef CASE
194 #define CASE(Name, _) \
195 case OperandType::k##Name: \
196 break;
197 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
198 #undef CASE
199 }
200 return false;
201 }
202
203 // static
IsRegisterListOperandType(OperandType operand_type)204 bool Bytecodes::IsRegisterListOperandType(OperandType operand_type) {
205 switch (operand_type) {
206 case OperandType::kRegList:
207 case OperandType::kRegOutList:
208 return true;
209 default:
210 return false;
211 }
212 }
213
MakesCallAlongCriticalPath(Bytecode bytecode)214 bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) {
215 if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true;
216 switch (bytecode) {
217 case Bytecode::kCreateWithContext:
218 case Bytecode::kCreateBlockContext:
219 case Bytecode::kCreateCatchContext:
220 case Bytecode::kCreateRegExpLiteral:
221 return true;
222 default:
223 return false;
224 }
225 }
226
227 // static
IsRegisterInputOperandType(OperandType operand_type)228 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
229 switch (operand_type) {
230 #define CASE(Name, _) \
231 case OperandType::k##Name: \
232 return true;
233 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
234 #undef CASE
235 #define CASE(Name, _) \
236 case OperandType::k##Name: \
237 break;
238 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
239 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
240 #undef CASE
241 }
242 return false;
243 }
244
245 // static
IsRegisterOutputOperandType(OperandType operand_type)246 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
247 switch (operand_type) {
248 #define CASE(Name, _) \
249 case OperandType::k##Name: \
250 return true;
251 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
252 #undef CASE
253 #define CASE(Name, _) \
254 case OperandType::k##Name: \
255 break;
256 NON_REGISTER_OPERAND_TYPE_LIST(CASE)
257 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
258 #undef CASE
259 }
260 return false;
261 }
262
263 // static
IsStarLookahead(Bytecode bytecode,OperandScale operand_scale)264 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
265 if (operand_scale == OperandScale::kSingle) {
266 switch (bytecode) {
267 case Bytecode::kLdaZero:
268 case Bytecode::kLdaSmi:
269 case Bytecode::kLdaNull:
270 case Bytecode::kLdaTheHole:
271 case Bytecode::kLdaConstant:
272 case Bytecode::kLdaUndefined:
273 case Bytecode::kLdaGlobal:
274 case Bytecode::kLdaNamedProperty:
275 case Bytecode::kLdaKeyedProperty:
276 case Bytecode::kLdaContextSlot:
277 case Bytecode::kLdaCurrentContextSlot:
278 case Bytecode::kAdd:
279 case Bytecode::kSub:
280 case Bytecode::kMul:
281 case Bytecode::kAddSmi:
282 case Bytecode::kSubSmi:
283 case Bytecode::kInc:
284 case Bytecode::kDec:
285 case Bytecode::kTypeOf:
286 case Bytecode::kCallAnyReceiver:
287 case Bytecode::kCallProperty:
288 case Bytecode::kCallProperty0:
289 case Bytecode::kCallProperty1:
290 case Bytecode::kCallProperty2:
291 case Bytecode::kCallUndefinedReceiver:
292 case Bytecode::kCallUndefinedReceiver0:
293 case Bytecode::kCallUndefinedReceiver1:
294 case Bytecode::kCallUndefinedReceiver2:
295 case Bytecode::kConstruct:
296 case Bytecode::kConstructWithSpread:
297 return true;
298 default:
299 return false;
300 }
301 }
302 return false;
303 }
304
305 // static
IsBytecodeWithScalableOperands(Bytecode bytecode)306 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
307 for (int i = 0; i < NumberOfOperands(bytecode); i++) {
308 if (OperandIsScalable(bytecode, i)) return true;
309 }
310 return false;
311 }
312
313 // static
IsUnsignedOperandType(OperandType operand_type)314 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
315 switch (operand_type) {
316 #define CASE(Name, _) \
317 case OperandType::k##Name: \
318 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
319 OPERAND_TYPE_LIST(CASE)
320 #undef CASE
321 }
322 UNREACHABLE();
323 }
324
325 // static
BytecodeHasHandler(Bytecode bytecode,OperandScale operand_scale)326 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
327 OperandScale operand_scale) {
328 return operand_scale == OperandScale::kSingle ||
329 Bytecodes::IsBytecodeWithScalableOperands(bytecode);
330 }
331
operator <<(std::ostream & os,const Bytecode & bytecode)332 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
333 return os << Bytecodes::ToString(bytecode);
334 }
335
336 } // namespace interpreter
337 } // namespace internal
338 } // namespace v8
339