v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
bytecodes.cc
Go to the documentation of this file.
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
6
7#include <iomanip>
8
10
11namespace v8 {
12namespace internal {
13namespace interpreter {
14
15// clang-format off
17#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes,
19#undef ENTRY
20};
21
23#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos,
25#undef ENTRY
26};
27
28const int Bytecodes::kOperandCount[] = {
29#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount,
31#undef ENTRY
32};
33
35#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kImplicitRegisterUse,
37#undef ENTRY
38};
39
40const uint8_t Bytecodes::kBytecodeSizes[3][kBytecodeCount] = {
41 {
42#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kSingleScaleSize,
44#undef ENTRY
45 }, {
46#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize,
48#undef ENTRY
49 }, {
50#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize,
52#undef ENTRY
53 }
54};
55
56const OperandSize* const Bytecodes::kOperandSizes[3][kBytecodeCount] = {
57 {
58#define ENTRY(Name, ...) \
59 BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes,
61#undef ENTRY
62 }, {
63#define ENTRY(Name, ...) \
64 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes,
66#undef ENTRY
67 }, {
68#define ENTRY(Name, ...) \
69 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes,
71#undef ENTRY
72 }
73};
74
75const int* const Bytecodes::kOperandOffsets[3][kBytecodeCount] = {
76 {
77#define ENTRY(Name, ...) \
78 BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandOffsets.data(),
80#undef ENTRY
81 }, {
82#define ENTRY(Name, ...) \
83 BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandOffsets.data(),
85#undef ENTRY
86 }, {
87#define ENTRY(Name, ...) \
88 BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandOffsets.data(),
90#undef ENTRY
91 }
92};
93
94const OperandSize
96 {
97#define ENTRY(Name, ...) \
98 OperandScaler<OperandType::k##Name, OperandScale::kSingle>::kOperandSize,
100#undef ENTRY
101 }, {
102#define ENTRY(Name, ...) \
103 OperandScaler<OperandType::k##Name, OperandScale::kDouble>::kOperandSize,
105#undef ENTRY
106 }, {
107#define ENTRY(Name, ...) \
108 OperandScaler<OperandType::k##Name, OperandScale::kQuadruple>::kOperandSize,
110#undef ENTRY
111 }
112};
113// clang-format on
114
115// Make sure kFirstShortStar and kLastShortStar are set correctly.
116#define ASSERT_SHORT_STAR_RANGE(Name, ...) \
117 static_assert(Bytecode::k##Name >= Bytecode::kFirstShortStar && \
118 Bytecode::k##Name <= Bytecode::kLastShortStar);
120#undef ASSERT_SHORT_STAR_RANGE
121
122// static
123const char* Bytecodes::ToString(Bytecode bytecode) {
124 switch (bytecode) {
125#define CASE(Name, ...) \
126 case Bytecode::k##Name: \
127 return #Name;
129#undef CASE
130 }
131 UNREACHABLE();
132}
133
134// static
135std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale,
136 const char* separator) {
137 std::string value(ToString(bytecode));
138 if (operand_scale > OperandScale::kSingle) {
139 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
140 std::string suffix = ToString(prefix_bytecode);
141 return value.append(separator).append(suffix);
142 } else {
143 return value;
144 }
145}
146
147// static
149 DCHECK(!IsDebugBreak(bytecode));
150 if (bytecode == Bytecode::kWide) {
151 return Bytecode::kDebugBreakWide;
152 }
153 if (bytecode == Bytecode::kExtraWide) {
154 return Bytecode::kDebugBreakExtraWide;
155 }
156 int bytecode_size = Size(bytecode, OperandScale::kSingle);
157#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \
158 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
159 return Bytecode::k##Name; \
160 }
162#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
163 UNREACHABLE();
164}
165
166// static
168 switch (bytecode) {
169#define CASE(Name, ...) case Bytecode::k##Name:
171#undef CASE
172 return true;
173 default:
174 break;
175 }
176 return false;
177}
178
179// static
181 switch (operand_type) {
182#define CASE(Name, _) \
183 case OperandType::k##Name: \
184 return true;
186#undef CASE
187#define CASE(Name, _) \
188 case OperandType::k##Name: \
189 break;
191#undef CASE
192 }
193 return false;
194}
195
196// static
198 switch (operand_type) {
199 case OperandType::kRegList:
200 case OperandType::kRegOutList:
201 return true;
202 default:
203 return false;
204 }
205}
206
208 if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true;
209 switch (bytecode) {
210 case Bytecode::kCreateWithContext:
211 case Bytecode::kCreateBlockContext:
212 case Bytecode::kCreateCatchContext:
213 case Bytecode::kCreateRegExpLiteral:
214 case Bytecode::kGetIterator:
215 return true;
216 default:
217 return false;
218 }
219}
220
221// static
223 switch (operand_type) {
224#define CASE(Name, _) \
225 case OperandType::k##Name: \
226 return true;
228 CASE(RegInOut, _)
229#undef CASE
230#define CASE(Name, _) \
231 case OperandType::k##Name: \
232 break;
235#undef CASE
236 }
237 return false;
238}
239
240// static
242 switch (operand_type) {
243#define CASE(Name, _) \
244 case OperandType::k##Name: \
245 return true;
247 CASE(RegInOut, _)
248#undef CASE
249#define CASE(Name, _) \
250 case OperandType::k##Name: \
251 break;
254#undef CASE
255 }
256 return false;
257}
258
259// static
260bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
261 if (operand_scale == OperandScale::kSingle) {
262 switch (bytecode) {
263 // Short-star lookahead is required for correctness on kDebugBreak0. The
264 // handler for all short-star codes re-reads the opcode from the bytecode
265 // array and would not work correctly if it instead read kDebugBreak0.
266 case Bytecode::kDebugBreak0:
267
268 case Bytecode::kLdaZero:
269 case Bytecode::kLdaSmi:
270 case Bytecode::kLdaNull:
271 case Bytecode::kLdaTheHole:
272 case Bytecode::kLdaConstant:
273 case Bytecode::kLdaUndefined:
274 case Bytecode::kLdaGlobal:
275 case Bytecode::kGetNamedProperty:
276 case Bytecode::kGetKeyedProperty:
277 case Bytecode::kLdaContextSlot:
278 case Bytecode::kLdaImmutableContextSlot:
279 case Bytecode::kLdaCurrentContextSlot:
280 case Bytecode::kLdaImmutableCurrentContextSlot:
281 case Bytecode::kAdd:
282 case Bytecode::kSub:
283 case Bytecode::kMul:
284 case Bytecode::kAddSmi:
285 case Bytecode::kSubSmi:
286 case Bytecode::kInc:
287 case Bytecode::kDec:
288 case Bytecode::kTypeOf:
289 case Bytecode::kCallAnyReceiver:
290 case Bytecode::kCallProperty:
291 case Bytecode::kCallProperty0:
292 case Bytecode::kCallProperty1:
293 case Bytecode::kCallProperty2:
294 case Bytecode::kCallUndefinedReceiver:
295 case Bytecode::kCallUndefinedReceiver0:
296 case Bytecode::kCallUndefinedReceiver1:
297 case Bytecode::kCallUndefinedReceiver2:
298 case Bytecode::kConstruct:
299 case Bytecode::kConstructWithSpread:
300 case Bytecode::kCreateObjectLiteral:
301 case Bytecode::kCreateArrayLiteral:
302 case Bytecode::kThrowReferenceErrorIfHole:
303 case Bytecode::kGetTemplateObject:
304 return true;
305 default:
306 return false;
307 }
308 }
309 return false;
310}
311
312// static
314 for (int i = 0; i < NumberOfOperands(bytecode); i++) {
315 if (OperandIsScalable(bytecode, i)) return true;
316 }
317 return false;
318}
319
320// static
322 switch (operand_type) {
323#define CASE(Name, _) \
324 case OperandType::k##Name: \
325 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
327#undef CASE
328 }
329 UNREACHABLE();
330}
331
332// static
334 OperandScale operand_scale) {
335 return (operand_scale == OperandScale::kSingle &&
336 (!IsShortStar(bytecode) || bytecode == Bytecode::kStar0)) ||
338}
339
340std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
341 return os << Bytecodes::ToString(bytecode);
342}
343
344} // namespace interpreter
345} // namespace internal
346} // namespace v8
#define REGISTER_INPUT_OPERAND_TYPE_LIST(V)
#define OPERAND_TYPE_LIST(V)
#define NON_REGISTER_OPERAND_TYPE_LIST(V)
#define REGISTER_OPERAND_TYPE_LIST(V)
#define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)
#define ASSERT_SHORT_STAR_RANGE(Name,...)
Definition bytecodes.cc:116
#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name)
#define ENTRY(Name,...)
#define DEBUG_BREAK_PLAIN_BYTECODE_LIST(V)
Definition bytecodes.h:489
#define SHORT_STAR_BYTECODE_LIST(V)
Definition bytecodes.h:24
#define DEBUG_BREAK_BYTECODE_LIST(V)
Definition bytecodes.h:502
#define BYTECODE_LIST(V, V_TSA)
Definition bytecodes.h:479
static OperandSize const kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount]
Definition bytecodes.h:1122
static bool MakesCallAlongCriticalPath(Bytecode bytecode)
Definition bytecodes.cc:207
static constexpr bool IsCallRuntime(Bytecode bytecode)
Definition bytecodes.h:858
static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale)
Definition bytecodes.h:632
static bool IsRegisterOutputOperandType(OperandType operand_type)
Definition bytecodes.cc:241
static const int *const kOperandOffsets[3][kBytecodeCount]
Definition bytecodes.h:1120
static bool OperandIsScalable(Bytecode bytecode, int operand_index)
Definition bytecodes.h:922
static Bytecode GetDebugBreak(Bytecode bytecode)
Definition bytecodes.cc:148
static const OperandTypeInfo *const kOperandTypeInfos[]
Definition bytecodes.h:1113
static bool IsDebugBreak(Bytecode bytecode)
Definition bytecodes.cc:167
static bool IsRegisterOperandType(OperandType operand_type)
Definition bytecodes.cc:180
static constexpr bool IsCallOrConstruct(Bytecode bytecode)
Definition bytecodes.h:840
static const uint8_t kBytecodeSizes[3][kBytecodeCount]
Definition bytecodes.h:1118
static int Size(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.h:964
static const ImplicitRegisterUse kImplicitRegisterUse[]
Definition bytecodes.h:1116
static bool IsRegisterListOperandType(OperandType operand_type)
Definition bytecodes.cc:197
static bool IsRegisterInputOperandType(OperandType operand_type)
Definition bytecodes.cc:222
static int NumberOfOperands(Bytecode bytecode)
Definition bytecodes.h:886
static bool IsUnsignedOperandType(OperandType operand_type)
Definition bytecodes.cc:321
static constexpr bool IsShortStar(Bytecode bytecode)
Definition bytecodes.h:732
static const OperandSize *const kOperandSizes[3][kBytecodeCount]
Definition bytecodes.h:1119
static const char * ToString(Bytecode bytecode)
Definition bytecodes.cc:123
static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.cc:260
static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.cc:333
static bool IsBytecodeWithScalableOperands(Bytecode bytecode)
Definition bytecodes.cc:313
static const OperandType *const kOperandTypes[]
Definition bytecodes.h:1112
#define _
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
return value
Definition map-inl.h:893
#define DCHECK(condition)
Definition logging.h:482