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