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_BYTECODES_H_
6#define V8_INTERPRETER_BYTECODES_H_
7
8#include <cstdint>
9#include <iosfwd>
10#include <string>
11
12#include "src/common/globals.h"
13#include "src/interpreter/bytecode-operands.h"
14
15// This interface and it's implementation are independent of the
16// libv8_base library as they are used by the interpreter and the
17// standalone mkpeephole table generator program.
18
19namespace v8 {
20namespace internal {
21namespace interpreter {
22
23// The list of single-byte Star variants, in the format of BYTECODE_LIST.
24#define SHORT_STAR_BYTECODE_LIST(V)                              \
25  V(Star15, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
26  V(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
27  V(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
28  V(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
29  V(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
30  V(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
31  V(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
32  V(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
33  V(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
34  V(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
35  V(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
36  V(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
37  V(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
38  V(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
39  V(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
40  V(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)
41
42// The list of bytecodes which have unique handlers (no other bytecode is
43// executed using identical code).
44// Format is V(<bytecode>, <implicit_register_use>, <operands>).
45#define BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V)                                  \
46  /* Extended width operands */                                                \
47  V(Wide, ImplicitRegisterUse::kNone)                                          \
48  V(ExtraWide, ImplicitRegisterUse::kNone)                                     \
49                                                                               \
50  /* Debug Breakpoints - one for each possible size of unscaled bytecodes */   \
51  /* and one for each operand widening prefix bytecode                    */   \
52  V(DebugBreakWide, ImplicitRegisterUse::kReadWriteAccumulator)                \
53  V(DebugBreakExtraWide, ImplicitRegisterUse::kReadWriteAccumulator)           \
54  V(DebugBreak0, ImplicitRegisterUse::kReadWriteAccumulator)                   \
55  V(DebugBreak1, ImplicitRegisterUse::kReadWriteAccumulator,                   \
56    OperandType::kReg)                                                         \
57  V(DebugBreak2, ImplicitRegisterUse::kReadWriteAccumulator,                   \
58    OperandType::kReg, OperandType::kReg)                                      \
59  V(DebugBreak3, ImplicitRegisterUse::kReadWriteAccumulator,                   \
60    OperandType::kReg, OperandType::kReg, OperandType::kReg)                   \
61  V(DebugBreak4, ImplicitRegisterUse::kReadWriteAccumulator,                   \
62    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
63    OperandType::kReg)                                                         \
64  V(DebugBreak5, ImplicitRegisterUse::kReadWriteAccumulator,                   \
65    OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg)             \
66  V(DebugBreak6, ImplicitRegisterUse::kReadWriteAccumulator,                   \
67    OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg,             \
68    OperandType::kReg)                                                         \
69                                                                               \
70  /* Side-effect-free bytecodes -- carefully ordered for efficient checks */   \
71  /* - [Loading the accumulator] */                                            \
72  V(Ldar, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg)           \
73  V(LdaZero, ImplicitRegisterUse::kWriteAccumulator)                           \
74  V(LdaSmi, ImplicitRegisterUse::kWriteAccumulator, OperandType::kImm)         \
75  V(LdaUndefined, ImplicitRegisterUse::kWriteAccumulator)                      \
76  V(LdaNull, ImplicitRegisterUse::kWriteAccumulator)                           \
77  V(LdaTheHole, ImplicitRegisterUse::kWriteAccumulator)                        \
78  V(LdaTrue, ImplicitRegisterUse::kWriteAccumulator)                           \
79  V(LdaFalse, ImplicitRegisterUse::kWriteAccumulator)                          \
80  V(LdaConstant, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx)    \
81  V(LdaContextSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
82    OperandType::kIdx, OperandType::kUImm)                                     \
83  V(LdaImmutableContextSlot, ImplicitRegisterUse::kWriteAccumulator,           \
84    OperandType::kReg, OperandType::kIdx, OperandType::kUImm)                  \
85  V(LdaCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator,             \
86    OperandType::kIdx)                                                         \
87  V(LdaImmutableCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator,    \
88    OperandType::kIdx)                                                         \
89  /* - [Register Loads ] */                                                    \
90  V(Star, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)         \
91  V(Mov, ImplicitRegisterUse::kNone, OperandType::kReg, OperandType::kRegOut)  \
92  V(PushContext, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)  \
93  V(PopContext, ImplicitRegisterUse::kNone, OperandType::kReg)                 \
94  /* - [Test Operations ] */                                                   \
95  V(TestReferenceEqual, ImplicitRegisterUse::kReadWriteAccumulator,            \
96    OperandType::kReg)                                                         \
97  V(TestUndetectable, ImplicitRegisterUse::kReadWriteAccumulator)              \
98  V(TestNull, ImplicitRegisterUse::kReadWriteAccumulator)                      \
99  V(TestUndefined, ImplicitRegisterUse::kReadWriteAccumulator)                 \
100  V(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator,                    \
101    OperandType::kFlag8)                                                       \
102                                                                               \
103  /* Globals */                                                                \
104  V(LdaGlobal, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx,      \
105    OperandType::kIdx)                                                         \
106  V(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,             \
107    OperandType::kIdx, OperandType::kIdx)                                      \
108  V(StaGlobal, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx,  \
109    OperandType::kIdx)                                                         \
110                                                                               \
111  /* Context operations */                                                     \
112  V(StaContextSlot, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg,  \
113    OperandType::kIdx, OperandType::kUImm)                                     \
114  V(StaCurrentContextSlot, ImplicitRegisterUse::kReadAccumulator,              \
115    OperandType::kIdx)                                                         \
116                                                                               \
117  /* Load-Store lookup slots */                                                \
118  V(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx)  \
119  V(LdaLookupContextSlot, ImplicitRegisterUse::kWriteAccumulator,              \
120    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
121  V(LdaLookupGlobalSlot, ImplicitRegisterUse::kWriteAccumulator,               \
122    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
123  V(LdaLookupSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,         \
124    OperandType::kIdx)                                                         \
125  V(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,  \
126    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
127  V(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,   \
128    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
129  V(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator,                 \
130    OperandType::kIdx, OperandType::kFlag8)                                    \
131                                                                               \
132  /* Property loads (LoadIC) operations */                                     \
133  V(GetNamedProperty, ImplicitRegisterUse::kWriteAccumulator,                  \
134    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
135  V(GetNamedPropertyFromSuper, ImplicitRegisterUse::kReadWriteAccumulator,     \
136    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
137  V(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
138    OperandType::kReg, OperandType::kIdx)                                      \
139                                                                               \
140  /* Operations on module variables */                                         \
141  V(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator,                 \
142    OperandType::kImm, OperandType::kUImm)                                     \
143  V(StaModuleVariable, ImplicitRegisterUse::kReadAccumulator,                  \
144    OperandType::kImm, OperandType::kUImm)                                     \
145                                                                               \
146  /* Propery stores (StoreIC) operations */                                    \
147  V(SetNamedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
148    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
149  V(DefineNamedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator,        \
150    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
151  V(SetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
152    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
153  V(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator,        \
154    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
155  V(StaInArrayLiteral, ImplicitRegisterUse::kReadWriteAccumulator,             \
156    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
157  V(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator,    \
158    OperandType::kReg, OperandType::kReg, OperandType::kFlag8,                 \
159    OperandType::kIdx)                                                         \
160  V(CollectTypeProfile, ImplicitRegisterUse::kReadAccumulator,                 \
161    OperandType::kImm)                                                         \
162                                                                               \
163  /* Binary Operators */                                                       \
164  V(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
165    OperandType::kIdx)                                                         \
166  V(Sub, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
167    OperandType::kIdx)                                                         \
168  V(Mul, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
169    OperandType::kIdx)                                                         \
170  V(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
171    OperandType::kIdx)                                                         \
172  V(Mod, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
173    OperandType::kIdx)                                                         \
174  V(Exp, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
175    OperandType::kIdx)                                                         \
176  V(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
177    OperandType::kIdx)                                                         \
178  V(BitwiseXor, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
179    OperandType::kIdx)                                                         \
180  V(BitwiseAnd, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
181    OperandType::kIdx)                                                         \
182  V(ShiftLeft, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
183    OperandType::kIdx)                                                         \
184  V(ShiftRight, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
185    OperandType::kIdx)                                                         \
186  V(ShiftRightLogical, ImplicitRegisterUse::kReadWriteAccumulator,             \
187    OperandType::kReg, OperandType::kIdx)                                      \
188                                                                               \
189  /* Binary operators with immediate operands */                               \
190  V(AddSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
191    OperandType::kIdx)                                                         \
192  V(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
193    OperandType::kIdx)                                                         \
194  V(MulSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
195    OperandType::kIdx)                                                         \
196  V(DivSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
197    OperandType::kIdx)                                                         \
198  V(ModSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
199    OperandType::kIdx)                                                         \
200  V(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
201    OperandType::kIdx)                                                         \
202  V(BitwiseOrSmi, ImplicitRegisterUse::kReadWriteAccumulator,                  \
203    OperandType::kImm, OperandType::kIdx)                                      \
204  V(BitwiseXorSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
205    OperandType::kImm, OperandType::kIdx)                                      \
206  V(BitwiseAndSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
207    OperandType::kImm, OperandType::kIdx)                                      \
208  V(ShiftLeftSmi, ImplicitRegisterUse::kReadWriteAccumulator,                  \
209    OperandType::kImm, OperandType::kIdx)                                      \
210  V(ShiftRightSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
211    OperandType::kImm, OperandType::kIdx)                                      \
212  V(ShiftRightLogicalSmi, ImplicitRegisterUse::kReadWriteAccumulator,          \
213    OperandType::kImm, OperandType::kIdx)                                      \
214                                                                               \
215  /* Unary Operators */                                                        \
216  V(Inc, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)        \
217  V(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)        \
218  V(Negate, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)     \
219  V(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
220  V(ToBooleanLogicalNot, ImplicitRegisterUse::kReadWriteAccumulator)           \
221  V(LogicalNot, ImplicitRegisterUse::kReadWriteAccumulator)                    \
222  V(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator)                        \
223  V(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator,          \
224    OperandType::kReg)                                                         \
225  V(DeletePropertySloppy, ImplicitRegisterUse::kReadWriteAccumulator,          \
226    OperandType::kReg)                                                         \
227                                                                               \
228  /* GetSuperConstructor operator */                                           \
229  V(GetSuperConstructor, ImplicitRegisterUse::kReadAccumulator,                \
230    OperandType::kRegOut)                                                      \
231                                                                               \
232  /* Call operations */                                                        \
233  V(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator,                   \
234    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
235    OperandType::kIdx)                                                         \
236  V(CallProperty, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,   \
237    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
238  V(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
239    OperandType::kReg, OperandType::kIdx)                                      \
240  V(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
241    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
242  V(CallProperty2, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
243    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
244    OperandType::kIdx)                                                         \
245  V(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator,             \
246    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
247    OperandType::kIdx)                                                         \
248  V(CallUndefinedReceiver0, ImplicitRegisterUse::kWriteAccumulator,            \
249    OperandType::kReg, OperandType::kIdx)                                      \
250  V(CallUndefinedReceiver1, ImplicitRegisterUse::kWriteAccumulator,            \
251    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
252  V(CallUndefinedReceiver2, ImplicitRegisterUse::kWriteAccumulator,            \
253    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
254    OperandType::kIdx)                                                         \
255  V(CallWithSpread, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
256    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
257  V(CallRuntime, ImplicitRegisterUse::kWriteAccumulator,                       \
258    OperandType::kRuntimeId, OperandType::kRegList, OperandType::kRegCount)    \
259  V(CallRuntimeForPair, ImplicitRegisterUse::kNone, OperandType::kRuntimeId,   \
260    OperandType::kRegList, OperandType::kRegCount, OperandType::kRegOutPair)   \
261  V(CallJSRuntime, ImplicitRegisterUse::kWriteAccumulator,                     \
262    OperandType::kNativeContextIndex, OperandType::kRegList,                   \
263    OperandType::kRegCount)                                                    \
264                                                                               \
265  /* Intrinsics */                                                             \
266  V(InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator,                   \
267    OperandType::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount)  \
268                                                                               \
269  /* Construct operators */                                                    \
270  V(Construct, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
271    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
272  V(ConstructWithSpread, ImplicitRegisterUse::kReadWriteAccumulator,           \
273    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
274    OperandType::kIdx)                                                         \
275                                                                               \
276  /* Effectful Test Operators */                                               \
277  V(TestEqual, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
278    OperandType::kIdx)                                                         \
279  V(TestEqualStrict, ImplicitRegisterUse::kReadWriteAccumulator,               \
280    OperandType::kReg, OperandType::kIdx)                                      \
281  V(TestLessThan, ImplicitRegisterUse::kReadWriteAccumulator,                  \
282    OperandType::kReg, OperandType::kIdx)                                      \
283  V(TestGreaterThan, ImplicitRegisterUse::kReadWriteAccumulator,               \
284    OperandType::kReg, OperandType::kIdx)                                      \
285  V(TestLessThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator,           \
286    OperandType::kReg, OperandType::kIdx)                                      \
287  V(TestGreaterThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator,        \
288    OperandType::kReg, OperandType::kIdx)                                      \
289  V(TestInstanceOf, ImplicitRegisterUse::kReadWriteAccumulator,                \
290    OperandType::kReg, OperandType::kIdx)                                      \
291  V(TestIn, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,     \
292    OperandType::kIdx)                                                         \
293                                                                               \
294  /* Cast operators */                                                         \
295  V(ToName, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)       \
296  V(ToNumber, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)   \
297  V(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)  \
298  V(ToObject, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)     \
299  V(ToString, ImplicitRegisterUse::kReadWriteAccumulator)                      \
300                                                                               \
301  /* Literals */                                                               \
302  V(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator,               \
303    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
304  V(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator,                \
305    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
306  V(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator)       \
307  V(CreateEmptyArrayLiteral, ImplicitRegisterUse::kWriteAccumulator,           \
308    OperandType::kIdx)                                                         \
309  V(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator,               \
310    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
311  V(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator)          \
312  V(CloneObject, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,    \
313    OperandType::kFlag8, OperandType::kIdx)                                    \
314                                                                               \
315  /* Tagged templates */                                                       \
316  V(GetTemplateObject, ImplicitRegisterUse::kWriteAccumulator,                 \
317    OperandType::kIdx, OperandType::kIdx)                                      \
318                                                                               \
319  /* Closure allocation */                                                     \
320  V(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx,  \
321    OperandType::kIdx, OperandType::kFlag8)                                    \
322                                                                               \
323  /* Context allocation */                                                     \
324  V(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator,                \
325    OperandType::kIdx)                                                         \
326  V(CreateCatchContext, ImplicitRegisterUse::kWriteAccumulator,                \
327    OperandType::kReg, OperandType::kIdx)                                      \
328  V(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator,             \
329    OperandType::kIdx, OperandType::kUImm)                                     \
330  V(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator,                 \
331    OperandType::kIdx, OperandType::kUImm)                                     \
332  V(CreateWithContext, ImplicitRegisterUse::kWriteAccumulator,                 \
333    OperandType::kReg, OperandType::kIdx)                                      \
334                                                                               \
335  /* Arguments allocation */                                                   \
336  V(CreateMappedArguments, ImplicitRegisterUse::kWriteAccumulator)             \
337  V(CreateUnmappedArguments, ImplicitRegisterUse::kWriteAccumulator)           \
338  V(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator)               \
339                                                                               \
340  /* Control Flow -- carefully ordered for efficient checks */                 \
341  /* - [Unconditional jumps] */                                                \
342  V(JumpLoop, ImplicitRegisterUse::kNone, OperandType::kUImm,                  \
343    OperandType::kImm)                                                         \
344  /* - [Forward jumps] */                                                      \
345  V(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm)                      \
346  /* - [Start constant jumps] */                                               \
347  V(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx)               \
348  /* - [Conditional jumps] */                                                  \
349  /* - [Conditional constant jumps] */                                         \
350  V(JumpIfNullConstant, ImplicitRegisterUse::kReadAccumulator,                 \
351    OperandType::kIdx)                                                         \
352  V(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator,              \
353    OperandType::kIdx)                                                         \
354  V(JumpIfUndefinedConstant, ImplicitRegisterUse::kReadAccumulator,            \
355    OperandType::kIdx)                                                         \
356  V(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator,         \
357    OperandType::kIdx)                                                         \
358  V(JumpIfUndefinedOrNullConstant, ImplicitRegisterUse::kReadAccumulator,      \
359    OperandType::kIdx)                                                         \
360  V(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator,                 \
361    OperandType::kIdx)                                                         \
362  V(JumpIfFalseConstant, ImplicitRegisterUse::kReadAccumulator,                \
363    OperandType::kIdx)                                                         \
364  V(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator,           \
365    OperandType::kIdx)                                                         \
366  /* - [Start ToBoolean jumps] */                                              \
367  V(JumpIfToBooleanTrueConstant, ImplicitRegisterUse::kReadAccumulator,        \
368    OperandType::kIdx)                                                         \
369  V(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator,       \
370    OperandType::kIdx)                                                         \
371  /* - [End constant jumps] */                                                 \
372  /* - [Conditional immediate jumps] */                                        \
373  V(JumpIfToBooleanTrue, ImplicitRegisterUse::kReadAccumulator,                \
374    OperandType::kUImm)                                                        \
375  V(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator,               \
376    OperandType::kUImm)                                                        \
377  /* - [End ToBoolean jumps] */                                                \
378  V(JumpIfTrue, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)     \
379  V(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)    \
380  V(JumpIfNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)     \
381  V(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)  \
382  V(JumpIfUndefined, ImplicitRegisterUse::kReadAccumulator,                    \
383    OperandType::kUImm)                                                        \
384  V(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator,                 \
385    OperandType::kUImm)                                                        \
386  V(JumpIfUndefinedOrNull, ImplicitRegisterUse::kReadAccumulator,              \
387    OperandType::kUImm)                                                        \
388  V(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator,                   \
389    OperandType::kUImm)                                                        \
390                                                                               \
391  /* Smi-table lookup for switch statements */                                 \
392  V(SwitchOnSmiNoFeedback, ImplicitRegisterUse::kReadAccumulator,              \
393    OperandType::kIdx, OperandType::kUImm, OperandType::kImm)                  \
394                                                                               \
395  /* Complex flow control For..in */                                           \
396  V(ForInEnumerate, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg) \
397  V(ForInPrepare, ImplicitRegisterUse::kReadWriteAccumulator,                  \
398    OperandType::kRegOutTriple, OperandType::kIdx)                             \
399  V(ForInContinue, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
400    OperandType::kReg)                                                         \
401  V(ForInNext, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,      \
402    OperandType::kReg, OperandType::kRegPair, OperandType::kIdx)               \
403  V(ForInStep, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg)      \
404                                                                               \
405  /* Update the pending message */                                             \
406  V(SetPendingMessage, ImplicitRegisterUse::kReadWriteAccumulator)             \
407                                                                               \
408  /* Non-local flow control */                                                 \
409  V(Throw, ImplicitRegisterUse::kReadAccumulator)                              \
410  V(ReThrow, ImplicitRegisterUse::kReadAccumulator)                            \
411  V(Return, ImplicitRegisterUse::kReadAccumulator)                             \
412  V(ThrowReferenceErrorIfHole, ImplicitRegisterUse::kReadAccumulator,          \
413    OperandType::kIdx)                                                         \
414  V(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator)          \
415  V(ThrowSuperAlreadyCalledIfNotHole, ImplicitRegisterUse::kReadAccumulator)   \
416  V(ThrowIfNotSuperConstructor, ImplicitRegisterUse::kNone, OperandType::kReg) \
417                                                                               \
418  /* Generators */                                                             \
419  V(SwitchOnGeneratorState, ImplicitRegisterUse::kNone, OperandType::kReg,     \
420    OperandType::kIdx, OperandType::kUImm)                                     \
421  V(SuspendGenerator, ImplicitRegisterUse::kReadAccumulator,                   \
422    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
423    OperandType::kUImm)                                                        \
424  V(ResumeGenerator, ImplicitRegisterUse::kWriteAccumulator,                   \
425    OperandType::kReg, OperandType::kRegOutList, OperandType::kRegCount)       \
426                                                                               \
427  /* Iterator protocol operations */                                           \
428  V(GetIterator, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,    \
429    OperandType::kIdx, OperandType::kIdx)                                      \
430                                                                               \
431  /* Debugger */                                                               \
432  V(Debugger, ImplicitRegisterUse::kNone)                                      \
433                                                                               \
434  /* Block Coverage */                                                         \
435  V(IncBlockCounter, ImplicitRegisterUse::kNone, OperandType::kIdx)            \
436                                                                               \
437  /* Execution Abort (internal error) */                                       \
438  V(Abort, ImplicitRegisterUse::kNone, OperandType::kIdx)
439
440// The list of bytecodes which are interpreted by the interpreter.
441// Format is V(<bytecode>, <implicit_register_use>, <operands>).
442#define BYTECODE_LIST(V)                                             \
443  BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V)                              \
444                                                                     \
445  /* Special-case Star for common register numbers, to save space */ \
446  SHORT_STAR_BYTECODE_LIST(V)                                        \
447                                                                     \
448  /* Illegal bytecode  */                                            \
449  V(Illegal, ImplicitRegisterUse::kNone)
450
451// List of debug break bytecodes.
452#define DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
453  V(DebugBreak0)                           \
454  V(DebugBreak1)                           \
455  V(DebugBreak2)                           \
456  V(DebugBreak3)                           \
457  V(DebugBreak4)                           \
458  V(DebugBreak5)                           \
459  V(DebugBreak6)
460
461#define DEBUG_BREAK_PREFIX_BYTECODE_LIST(V) \
462  V(DebugBreakWide)                         \
463  V(DebugBreakExtraWide)
464
465#define DEBUG_BREAK_BYTECODE_LIST(V) \
466  DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
467  DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
468
469// Lists of jump bytecodes.
470
471#define JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
472  V(JumpLoop)                                         \
473  V(Jump)
474
475#define JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) V(JumpConstant)
476
477#define JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
478  V(JumpIfToBooleanTrue)                                      \
479  V(JumpIfToBooleanFalse)
480
481#define JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
482  V(JumpIfToBooleanTrueConstant)                             \
483  V(JumpIfToBooleanFalseConstant)
484
485#define JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V)     \
486  JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
487  V(JumpIfTrue)                                         \
488  V(JumpIfFalse)                                        \
489  V(JumpIfNull)                                         \
490  V(JumpIfNotNull)                                      \
491  V(JumpIfUndefined)                                    \
492  V(JumpIfNotUndefined)                                 \
493  V(JumpIfUndefinedOrNull)                              \
494  V(JumpIfJSReceiver)
495
496#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)     \
497  JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
498  V(JumpIfNullConstant)                                \
499  V(JumpIfNotNullConstant)                             \
500  V(JumpIfUndefinedConstant)                           \
501  V(JumpIfNotUndefinedConstant)                        \
502  V(JumpIfUndefinedOrNullConstant)                     \
503  V(JumpIfTrueConstant)                                \
504  V(JumpIfFalseConstant)                               \
505  V(JumpIfJSReceiverConstant)
506
507#define JUMP_CONSTANT_BYTECODE_LIST(V)         \
508  JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
509  JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
510
511#define JUMP_IMMEDIATE_BYTECODE_LIST(V)         \
512  JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
513  JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V)
514
515#define JUMP_TO_BOOLEAN_BYTECODE_LIST(V)                \
516  JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
517  JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
518
519#define JUMP_UNCONDITIONAL_BYTECODE_LIST(V)     \
520  JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
521  JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V)
522
523#define JUMP_CONDITIONAL_BYTECODE_LIST(V)     \
524  JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
525  JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
526
527#define JUMP_FORWARD_BYTECODE_LIST(V) \
528  V(Jump)                             \
529  V(JumpConstant)                     \
530  JUMP_CONDITIONAL_BYTECODE_LIST(V)
531
532#define JUMP_BYTECODE_LIST(V)   \
533  JUMP_FORWARD_BYTECODE_LIST(V) \
534  V(JumpLoop)
535
536#define RETURN_BYTECODE_LIST(V) \
537  V(Return)                     \
538  V(SuspendGenerator)
539
540#define UNCONDITIONAL_THROW_BYTECODE_LIST(V) \
541  V(Throw)                                   \
542  V(ReThrow)
543
544// Enumeration of interpreter bytecodes.
545enum class Bytecode : uint8_t {
546#define DECLARE_BYTECODE(Name, ...) k##Name,
547  BYTECODE_LIST(DECLARE_BYTECODE)
548#undef DECLARE_BYTECODE
549#define COUNT_BYTECODE(x, ...) +1
550  // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will
551  // evaluate to the same value as the last real bytecode.
552  kLast = -1 BYTECODE_LIST(COUNT_BYTECODE),
553  kFirstShortStar = kStar15,
554  kLastShortStar = kStar0
555#undef COUNT_BYTECODE
556};
557
558class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
559 public:
560  // The maximum number of operands a bytecode may have.
561  static const int kMaxOperands = 5;
562
563  // The total number of bytecodes used.
564  static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
565
566  static const int kShortStarCount =
567      static_cast<int>(Bytecode::kLastShortStar) -
568      static_cast<int>(Bytecode::kFirstShortStar) + 1;
569
570  // Returns string representation of |bytecode|.
571  static const char* ToString(Bytecode bytecode);
572
573  // Returns string representation of |bytecode| combined with |operand_scale|
574  // using the optionally provided |separator|.
575  static std::string ToString(Bytecode bytecode, OperandScale operand_scale,
576                              const char* separator = ".");
577
578  // Returns byte value of bytecode.
579  static uint8_t ToByte(Bytecode bytecode) {
580    DCHECK_LE(bytecode, Bytecode::kLast);
581    return static_cast<uint8_t>(bytecode);
582  }
583
584  // Returns bytecode for |value|.
585  static Bytecode FromByte(uint8_t value) {
586    Bytecode bytecode = static_cast<Bytecode>(value);
587    DCHECK_LE(bytecode, Bytecode::kLast);
588    return bytecode;
589  }
590
591  // Returns the prefix bytecode representing an operand scale to be
592  // applied to a a bytecode.
593  static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale) {
594    switch (operand_scale) {
595      case OperandScale::kQuadruple:
596        return Bytecode::kExtraWide;
597      case OperandScale::kDouble:
598        return Bytecode::kWide;
599      default:
600        UNREACHABLE();
601    }
602  }
603
604  // Returns true if the operand scale requires a prefix bytecode.
605  static bool OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
606    return operand_scale != OperandScale::kSingle;
607  }
608
609  // Returns the scaling applied to scalable operands if bytecode is
610  // is a scaling prefix.
611  static OperandScale PrefixBytecodeToOperandScale(Bytecode bytecode) {
612    switch (bytecode) {
613      case Bytecode::kExtraWide:
614      case Bytecode::kDebugBreakExtraWide:
615        return OperandScale::kQuadruple;
616      case Bytecode::kWide:
617      case Bytecode::kDebugBreakWide:
618        return OperandScale::kDouble;
619      default:
620        UNREACHABLE();
621    }
622  }
623
624  // Returns how accumulator is used by |bytecode|.
625  static ImplicitRegisterUse GetImplicitRegisterUse(Bytecode bytecode) {
626    DCHECK_LE(bytecode, Bytecode::kLast);
627    return kImplicitRegisterUse[static_cast<size_t>(bytecode)];
628  }
629
630  // Returns true if |bytecode| reads the accumulator.
631  static bool ReadsAccumulator(Bytecode bytecode) {
632    return BytecodeOperands::ReadsAccumulator(GetImplicitRegisterUse(bytecode));
633  }
634
635  // Returns true if |bytecode| writes the accumulator.
636  static bool WritesAccumulator(Bytecode bytecode) {
637    return BytecodeOperands::WritesAccumulator(
638        GetImplicitRegisterUse(bytecode));
639  }
640
641  // Returns true if |bytecode| writes to a register not specified by an
642  // operand.
643  static bool WritesImplicitRegister(Bytecode bytecode) {
644    return BytecodeOperands::WritesImplicitRegister(
645        GetImplicitRegisterUse(bytecode));
646  }
647
648  // Return true if |bytecode| is an accumulator load without effects,
649  // e.g. LdaConstant, LdaTrue, Ldar.
650  static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
651    STATIC_ASSERT(Bytecode::kLdar < Bytecode::kLdaImmutableCurrentContextSlot);
652    return bytecode >= Bytecode::kLdar &&
653           bytecode <= Bytecode::kLdaImmutableCurrentContextSlot;
654  }
655
656  // Returns true if |bytecode| is a compare operation without external effects
657  // (e.g., Type cooersion).
658  static constexpr bool IsCompareWithoutEffects(Bytecode bytecode) {
659    STATIC_ASSERT(Bytecode::kTestReferenceEqual < Bytecode::kTestTypeOf);
660    return bytecode >= Bytecode::kTestReferenceEqual &&
661           bytecode <= Bytecode::kTestTypeOf;
662  }
663
664  static constexpr bool IsShortStar(Bytecode bytecode) {
665    return bytecode >= Bytecode::kFirstShortStar &&
666           bytecode <= Bytecode::kLastShortStar;
667  }
668
669  static constexpr bool IsAnyStar(Bytecode bytecode) {
670    return bytecode == Bytecode::kStar || IsShortStar(bytecode);
671  }
672
673  // Return true if |bytecode| is a register load without effects,
674  // e.g. Mov, Star.
675  static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
676    return IsShortStar(bytecode) ||
677           (bytecode >= Bytecode::kStar && bytecode <= Bytecode::kPopContext);
678  }
679
680  // Returns true if the bytecode is a conditional jump taking
681  // an immediate byte operand (OperandType::kImm).
682  static constexpr bool IsConditionalJumpImmediate(Bytecode bytecode) {
683    return bytecode >= Bytecode::kJumpIfToBooleanTrue &&
684           bytecode <= Bytecode::kJumpIfJSReceiver;
685  }
686
687  // Returns true if the bytecode is a conditional jump taking
688  // a constant pool entry (OperandType::kIdx).
689  static constexpr bool IsConditionalJumpConstant(Bytecode bytecode) {
690    return bytecode >= Bytecode::kJumpIfNullConstant &&
691           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
692  }
693
694  // Returns true if the bytecode is a conditional jump taking
695  // any kind of operand.
696  static constexpr bool IsConditionalJump(Bytecode bytecode) {
697    return bytecode >= Bytecode::kJumpIfNullConstant &&
698           bytecode <= Bytecode::kJumpIfJSReceiver;
699  }
700
701  // Returns true if the bytecode is an unconditional jump.
702  static constexpr bool IsUnconditionalJump(Bytecode bytecode) {
703    return bytecode >= Bytecode::kJumpLoop &&
704           bytecode <= Bytecode::kJumpConstant;
705  }
706
707  // Returns true if the bytecode is a jump or a conditional jump taking
708  // an immediate byte operand (OperandType::kImm).
709  static constexpr bool IsJumpImmediate(Bytecode bytecode) {
710    return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop ||
711           IsConditionalJumpImmediate(bytecode);
712  }
713
714  // Returns true if the bytecode is a jump or conditional jump taking a
715  // constant pool entry (OperandType::kIdx).
716  static constexpr bool IsJumpConstant(Bytecode bytecode) {
717    return bytecode >= Bytecode::kJumpConstant &&
718           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
719  }
720
721  // Returns true if the bytecode is a jump that internally coerces the
722  // accumulator to a boolean.
723  static constexpr bool IsJumpIfToBoolean(Bytecode bytecode) {
724    return bytecode >= Bytecode::kJumpIfToBooleanTrueConstant &&
725           bytecode <= Bytecode::kJumpIfToBooleanFalse;
726  }
727
728  // Returns true if the bytecode is a jump or conditional jump taking
729  // any kind of operand.
730  static constexpr bool IsJump(Bytecode bytecode) {
731    return bytecode >= Bytecode::kJumpLoop &&
732           bytecode <= Bytecode::kJumpIfJSReceiver;
733  }
734
735  // Returns true if the bytecode is a forward jump or conditional jump taking
736  // any kind of operand.
737  static constexpr bool IsForwardJump(Bytecode bytecode) {
738    return bytecode >= Bytecode::kJump &&
739           bytecode <= Bytecode::kJumpIfJSReceiver;
740  }
741
742  // Return true if |bytecode| is a jump without effects,
743  // e.g. any jump excluding those that include type coercion like
744  // JumpIfTrueToBoolean, and JumpLoop due to having an implicit StackCheck.
745  static constexpr bool IsJumpWithoutEffects(Bytecode bytecode) {
746    return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode) &&
747           bytecode != Bytecode::kJumpLoop;
748  }
749
750  // Returns true if the bytecode is a switch.
751  static constexpr bool IsSwitch(Bytecode bytecode) {
752    return bytecode == Bytecode::kSwitchOnSmiNoFeedback ||
753           bytecode == Bytecode::kSwitchOnGeneratorState;
754  }
755
756  // Returns true if |bytecode| has no effects. These bytecodes only manipulate
757  // interpreter frame state and will never throw.
758  static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
759    return (IsAccumulatorLoadWithoutEffects(bytecode) ||
760            IsRegisterLoadWithoutEffects(bytecode) ||
761            IsCompareWithoutEffects(bytecode) ||
762            IsJumpWithoutEffects(bytecode) || IsSwitch(bytecode));
763  }
764
765  // Returns true if the bytecode is Ldar or Star.
766  static constexpr bool IsLdarOrStar(Bytecode bytecode) {
767    return bytecode == Bytecode::kLdar || IsAnyStar(bytecode);
768  }
769
770  // Returns true if the bytecode is a call or a constructor call.
771  static constexpr bool IsCallOrConstruct(Bytecode bytecode) {
772    return bytecode == Bytecode::kCallAnyReceiver ||
773           bytecode == Bytecode::kCallProperty ||
774           bytecode == Bytecode::kCallProperty0 ||
775           bytecode == Bytecode::kCallProperty1 ||
776           bytecode == Bytecode::kCallProperty2 ||
777           bytecode == Bytecode::kCallUndefinedReceiver ||
778           bytecode == Bytecode::kCallUndefinedReceiver0 ||
779           bytecode == Bytecode::kCallUndefinedReceiver1 ||
780           bytecode == Bytecode::kCallUndefinedReceiver2 ||
781           bytecode == Bytecode::kConstruct ||
782           bytecode == Bytecode::kCallWithSpread ||
783           bytecode == Bytecode::kConstructWithSpread ||
784           bytecode == Bytecode::kCallJSRuntime;
785  }
786
787  // Returns true if the bytecode is a call to the runtime.
788  static constexpr bool IsCallRuntime(Bytecode bytecode) {
789    return bytecode == Bytecode::kCallRuntime ||
790           bytecode == Bytecode::kCallRuntimeForPair ||
791           bytecode == Bytecode::kInvokeIntrinsic;
792  }
793
794  // Returns true if the bytecode is a scaling prefix bytecode.
795  static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode) {
796    return bytecode == Bytecode::kExtraWide || bytecode == Bytecode::kWide ||
797           bytecode == Bytecode::kDebugBreakExtraWide ||
798           bytecode == Bytecode::kDebugBreakWide;
799  }
800
801  // Returns true if the bytecode returns.
802  static constexpr bool Returns(Bytecode bytecode) {
803#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
804    return false RETURN_BYTECODE_LIST(OR_BYTECODE);
805#undef OR_BYTECODE
806  }
807
808  // Returns true if the bytecode unconditionally throws.
809  static constexpr bool UnconditionallyThrows(Bytecode bytecode) {
810#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
811    return false UNCONDITIONAL_THROW_BYTECODE_LIST(OR_BYTECODE);
812#undef OR_BYTECODE
813  }
814
815  // Returns the number of operands expected by |bytecode|.
816  static int NumberOfOperands(Bytecode bytecode) {
817    DCHECK_LE(bytecode, Bytecode::kLast);
818    return kOperandCount[static_cast<size_t>(bytecode)];
819  }
820
821  // Returns the i-th operand of |bytecode|.
822  static OperandType GetOperandType(Bytecode bytecode, int i) {
823    DCHECK_LE(bytecode, Bytecode::kLast);
824    DCHECK_LT(i, NumberOfOperands(bytecode));
825    DCHECK_GE(i, 0);
826    return GetOperandTypes(bytecode)[i];
827  }
828
829  // Returns a pointer to an array of operand types terminated in
830  // OperandType::kNone.
831  static const OperandType* GetOperandTypes(Bytecode bytecode) {
832    DCHECK_LE(bytecode, Bytecode::kLast);
833    return kOperandTypes[static_cast<size_t>(bytecode)];
834  }
835
836  static bool OperandIsScalableSignedByte(Bytecode bytecode,
837                                          int operand_index) {
838    DCHECK_LE(bytecode, Bytecode::kLast);
839    return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
840           OperandTypeInfo::kScalableSignedByte;
841  }
842
843  static bool OperandIsScalableUnsignedByte(Bytecode bytecode,
844                                            int operand_index) {
845    DCHECK_LE(bytecode, Bytecode::kLast);
846    return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
847           OperandTypeInfo::kScalableUnsignedByte;
848  }
849
850  static bool OperandIsScalable(Bytecode bytecode, int operand_index) {
851    return OperandIsScalableSignedByte(bytecode, operand_index) ||
852           OperandIsScalableUnsignedByte(bytecode, operand_index);
853  }
854
855  // Returns true if the bytecode has wider operand forms.
856  static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
857
858  // Returns the size of the i-th operand of |bytecode|.
859  static OperandSize GetOperandSize(Bytecode bytecode, int i,
860                                    OperandScale operand_scale) {
861    CHECK_LT(i, NumberOfOperands(bytecode));
862    return GetOperandSizes(bytecode, operand_scale)[i];
863  }
864
865  // Returns the operand sizes of |bytecode| with scale |operand_scale|.
866  static const OperandSize* GetOperandSizes(Bytecode bytecode,
867                                            OperandScale operand_scale) {
868    DCHECK_LE(bytecode, Bytecode::kLast);
869    DCHECK_GE(operand_scale, OperandScale::kSingle);
870    DCHECK_LE(operand_scale, OperandScale::kLast);
871    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
872                  OperandScale::kLast == OperandScale::kQuadruple);
873    int scale_index = static_cast<int>(operand_scale) >> 1;
874    return kOperandSizes[scale_index][static_cast<size_t>(bytecode)];
875  }
876
877  // Returns the offset of the i-th operand of |bytecode| relative to the start
878  // of the bytecode.
879  static int GetOperandOffset(Bytecode bytecode, int i,
880                              OperandScale operand_scale);
881
882  // Returns the size of the bytecode including its operands for the
883  // given |operand_scale|.
884  static int Size(Bytecode bytecode, OperandScale operand_scale) {
885    DCHECK_LE(bytecode, Bytecode::kLast);
886    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
887                  OperandScale::kLast == OperandScale::kQuadruple);
888    int scale_index = static_cast<int>(operand_scale) >> 1;
889    return kBytecodeSizes[scale_index][static_cast<size_t>(bytecode)];
890  }
891
892  // Returns a debug break bytecode to replace |bytecode|.
893  static Bytecode GetDebugBreak(Bytecode bytecode);
894
895  // Returns the equivalent jump bytecode without the accumulator coercion.
896  static Bytecode GetJumpWithoutToBoolean(Bytecode bytecode);
897
898  // Returns true if there is a call in the most-frequently executed path
899  // through the bytecode's handler.
900  static bool MakesCallAlongCriticalPath(Bytecode bytecode);
901
902  // Returns the receiver mode of the given call bytecode.
903  static ConvertReceiverMode GetReceiverMode(Bytecode bytecode) {
904    DCHECK(IsCallOrConstruct(bytecode) ||
905           bytecode == Bytecode::kInvokeIntrinsic);
906    switch (bytecode) {
907      case Bytecode::kCallProperty:
908      case Bytecode::kCallProperty0:
909      case Bytecode::kCallProperty1:
910      case Bytecode::kCallProperty2:
911        return ConvertReceiverMode::kNotNullOrUndefined;
912      case Bytecode::kCallUndefinedReceiver:
913      case Bytecode::kCallUndefinedReceiver0:
914      case Bytecode::kCallUndefinedReceiver1:
915      case Bytecode::kCallUndefinedReceiver2:
916      case Bytecode::kCallJSRuntime:
917        return ConvertReceiverMode::kNullOrUndefined;
918      case Bytecode::kCallAnyReceiver:
919      case Bytecode::kConstruct:
920      case Bytecode::kCallWithSpread:
921      case Bytecode::kConstructWithSpread:
922      case Bytecode::kInvokeIntrinsic:
923        return ConvertReceiverMode::kAny;
924      default:
925        UNREACHABLE();
926    }
927  }
928
929  // Returns true if the bytecode is a debug break.
930  static bool IsDebugBreak(Bytecode bytecode);
931
932  // Returns true if |operand_type| is any type of register operand.
933  static bool IsRegisterOperandType(OperandType operand_type);
934
935  // Returns true if |operand_type| represents a register used as an input.
936  static bool IsRegisterInputOperandType(OperandType operand_type);
937
938  // Returns true if |operand_type| represents a register used as an output.
939  static bool IsRegisterOutputOperandType(OperandType operand_type);
940
941  // Returns true if |operand_type| represents a register list operand.
942  static bool IsRegisterListOperandType(OperandType operand_type);
943
944  // Returns true if the handler for |bytecode| should look ahead and inline a
945  // dispatch to a Star bytecode.
946  static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale);
947
948  // Returns the number of registers represented by a register operand. For
949  // instance, a RegPair represents two registers. Should not be called for
950  // kRegList which has a variable number of registers based on the following
951  // kRegCount operand.
952  static int GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
953    switch (operand_type) {
954      case OperandType::kReg:
955      case OperandType::kRegOut:
956        return 1;
957      case OperandType::kRegPair:
958      case OperandType::kRegOutPair:
959        return 2;
960      case OperandType::kRegOutTriple:
961        return 3;
962      case OperandType::kRegList:
963      case OperandType::kRegOutList:
964        UNREACHABLE();
965      default:
966        return 0;
967    }
968    UNREACHABLE();
969  }
970
971  // Returns the size of |operand_type| for |operand_scale|.
972  static OperandSize SizeOfOperand(OperandType operand_type,
973                                   OperandScale operand_scale) {
974    DCHECK_LE(operand_type, OperandType::kLast);
975    DCHECK_GE(operand_scale, OperandScale::kSingle);
976    DCHECK_LE(operand_scale, OperandScale::kLast);
977    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
978                  OperandScale::kLast == OperandScale::kQuadruple);
979    int scale_index = static_cast<int>(operand_scale) >> 1;
980    return kOperandKindSizes[scale_index][static_cast<size_t>(operand_type)];
981  }
982
983  // Returns true if |operand_type| is a runtime-id operand (kRuntimeId).
984  static bool IsRuntimeIdOperandType(OperandType operand_type);
985
986  // Returns true if |operand_type| is unsigned, false if signed.
987  static bool IsUnsignedOperandType(OperandType operand_type);
988
989  // Returns true if a handler is generated for a bytecode at a given
990  // operand scale. All bytecodes have handlers at OperandScale::kSingle,
991  // but only bytecodes with scalable operands have handlers with larger
992  // OperandScale values.
993  static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale);
994
995  // Return the operand scale required to hold a signed operand with |value|.
996  static OperandScale ScaleForSignedOperand(int32_t value) {
997    if (value >= kMinInt8 && value <= kMaxInt8) {
998      return OperandScale::kSingle;
999    } else if (value >= kMinInt16 && value <= kMaxInt16) {
1000      return OperandScale::kDouble;
1001    } else {
1002      return OperandScale::kQuadruple;
1003    }
1004  }
1005
1006  // Return the operand scale required to hold an unsigned operand with |value|.
1007  static OperandScale ScaleForUnsignedOperand(uint32_t value) {
1008    if (value <= kMaxUInt8) {
1009      return OperandScale::kSingle;
1010    } else if (value <= kMaxUInt16) {
1011      return OperandScale::kDouble;
1012    } else {
1013      return OperandScale::kQuadruple;
1014    }
1015  }
1016
1017  // Return the operand size required to hold an unsigned operand with |value|.
1018  static OperandSize SizeForUnsignedOperand(uint32_t value) {
1019    if (value <= kMaxUInt8) {
1020      return OperandSize::kByte;
1021    } else if (value <= kMaxUInt16) {
1022      return OperandSize::kShort;
1023    } else {
1024      return OperandSize::kQuad;
1025    }
1026  }
1027
1028  static Address bytecode_size_table_address() {
1029    return reinterpret_cast<Address>(
1030        const_cast<uint8_t*>(&kBytecodeSizes[0][0]));
1031  }
1032
1033 private:
1034  static const OperandType* const kOperandTypes[];
1035  static const OperandTypeInfo* const kOperandTypeInfos[];
1036  static const int kOperandCount[];
1037  static const int kNumberOfRegisterOperands[];
1038  static const ImplicitRegisterUse kImplicitRegisterUse[];
1039  static const bool kIsScalable[];
1040  static const uint8_t kBytecodeSizes[3][kBytecodeCount];
1041  static const OperandSize* const kOperandSizes[3][kBytecodeCount];
1042  static OperandSize const
1043      kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount];
1044};
1045
1046V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
1047                                           const Bytecode& bytecode);
1048
1049}  // namespace interpreter
1050}  // namespace internal
1051}  // namespace v8
1052
1053#endif  // V8_INTERPRETER_BYTECODES_H_
1054