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