bytecodes.h 56.7 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTERPRETER_BYTECODES_H_
#define V8_INTERPRETER_BYTECODES_H_

8
#include <cstdint>
9
#include <iosfwd>
10
#include <string>
11

12
#include "src/common/globals.h"
13 14
#include "src/interpreter/bytecode-operands.h"

15 16 17
// This interface and it's implementation are independent of the
// libv8_base library as they are used by the interpreter and the
// standalone mkpeephole table generator program.
18 19 20 21 22

namespace v8 {
namespace internal {
namespace interpreter {

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
// The list of single-byte Star variants, in the format of BYTECODE_LIST.
#define SHORT_STAR_BYTECODE_LIST(V)                              \
  V(Star15, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
  V(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)  \
  V(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)

// The list of bytecodes which have unique handlers (no other bytecode is
// executed using identical code).
44
// Format is V(<bytecode>, <implicit_register_use>, <operands>).
45
#define BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V)                                  \
46
  /* Extended width operands */                                                \
47 48
  V(Wide, ImplicitRegisterUse::kNone)                                          \
  V(ExtraWide, ImplicitRegisterUse::kNone)                                     \
49
                                                                               \
50 51
  /* Debug Breakpoints - one for each possible size of unscaled bytecodes */   \
  /* and one for each operand widening prefix bytecode                    */   \
52 53 54 55
  V(DebugBreakWide, ImplicitRegisterUse::kReadWriteAccumulator)                \
  V(DebugBreakExtraWide, ImplicitRegisterUse::kReadWriteAccumulator)           \
  V(DebugBreak0, ImplicitRegisterUse::kReadWriteAccumulator)                   \
  V(DebugBreak1, ImplicitRegisterUse::kReadWriteAccumulator,                   \
56
    OperandType::kReg)                                                         \
57
  V(DebugBreak2, ImplicitRegisterUse::kReadWriteAccumulator,                   \
58
    OperandType::kReg, OperandType::kReg)                                      \
59
  V(DebugBreak3, ImplicitRegisterUse::kReadWriteAccumulator,                   \
60
    OperandType::kReg, OperandType::kReg, OperandType::kReg)                   \
61 62 63 64 65 66 67 68
  V(DebugBreak4, ImplicitRegisterUse::kReadWriteAccumulator,                   \
    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
    OperandType::kReg)                                                         \
  V(DebugBreak5, ImplicitRegisterUse::kReadWriteAccumulator,                   \
    OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg)             \
  V(DebugBreak6, ImplicitRegisterUse::kReadWriteAccumulator,                   \
    OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg,             \
    OperandType::kReg)                                                         \
69
                                                                               \
70 71 72
  /* Side-effect-free bytecodes -- carefully ordered for efficient checks */   \
  /* - [Loading the accumulator] */                                            \
  V(Ldar, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg)           \
73 74 75 76 77 78 79 80
  V(LdaZero, ImplicitRegisterUse::kWriteAccumulator)                           \
  V(LdaSmi, ImplicitRegisterUse::kWriteAccumulator, OperandType::kImm)         \
  V(LdaUndefined, ImplicitRegisterUse::kWriteAccumulator)                      \
  V(LdaNull, ImplicitRegisterUse::kWriteAccumulator)                           \
  V(LdaTheHole, ImplicitRegisterUse::kWriteAccumulator)                        \
  V(LdaTrue, ImplicitRegisterUse::kWriteAccumulator)                           \
  V(LdaFalse, ImplicitRegisterUse::kWriteAccumulator)                          \
  V(LdaConstant, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx)    \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  V(LdaContextSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
    OperandType::kIdx, OperandType::kUImm)                                     \
  V(LdaImmutableContextSlot, ImplicitRegisterUse::kWriteAccumulator,           \
    OperandType::kReg, OperandType::kIdx, OperandType::kUImm)                  \
  V(LdaCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator,             \
    OperandType::kIdx)                                                         \
  V(LdaImmutableCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator,    \
    OperandType::kIdx)                                                         \
  /* - [Register Loads ] */                                                    \
  V(Star, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)         \
  V(Mov, ImplicitRegisterUse::kNone, OperandType::kReg, OperandType::kRegOut)  \
  V(PushContext, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)  \
  V(PopContext, ImplicitRegisterUse::kNone, OperandType::kReg)                 \
  /* - [Test Operations ] */                                                   \
  V(TestReferenceEqual, ImplicitRegisterUse::kReadWriteAccumulator,            \
    OperandType::kReg)                                                         \
  V(TestUndetectable, ImplicitRegisterUse::kReadWriteAccumulator)              \
  V(TestNull, ImplicitRegisterUse::kReadWriteAccumulator)                      \
  V(TestUndefined, ImplicitRegisterUse::kReadWriteAccumulator)                 \
  V(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator,                    \
    OperandType::kFlag8)                                                       \
102 103
                                                                               \
  /* Globals */                                                                \
104 105 106 107
  V(LdaGlobal, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx,      \
    OperandType::kIdx)                                                         \
  V(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,             \
    OperandType::kIdx, OperandType::kIdx)                                      \
108
  V(StaGlobal, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx,  \
109 110 111
    OperandType::kIdx)                                                         \
                                                                               \
  /* Context operations */                                                     \
112
  V(StaContextSlot, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg,  \
113
    OperandType::kIdx, OperandType::kUImm)                                     \
114 115
  V(StaCurrentContextSlot, ImplicitRegisterUse::kReadAccumulator,              \
    OperandType::kIdx)                                                         \
116 117
                                                                               \
  /* Load-Store lookup slots */                                                \
118 119
  V(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx)  \
  V(LdaLookupContextSlot, ImplicitRegisterUse::kWriteAccumulator,              \
120
    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
121
  V(LdaLookupGlobalSlot, ImplicitRegisterUse::kWriteAccumulator,               \
122
    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
123 124 125 126 127 128 129 130
  V(LdaLookupSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,         \
    OperandType::kIdx)                                                         \
  V(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,  \
    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
  V(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator,   \
    OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
  V(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator,                 \
    OperandType::kIdx, OperandType::kFlag8)                                    \
131 132
                                                                               \
  /* Property loads (LoadIC) operations */                                     \
133
  V(GetNamedProperty, ImplicitRegisterUse::kWriteAccumulator,                  \
134
    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
135
  V(GetNamedPropertyFromSuper, ImplicitRegisterUse::kReadWriteAccumulator,     \
136
    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
137
  V(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
138
    OperandType::kReg, OperandType::kIdx)                                      \
139 140
                                                                               \
  /* Operations on module variables */                                         \
141 142 143 144
  V(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator,                 \
    OperandType::kImm, OperandType::kUImm)                                     \
  V(StaModuleVariable, ImplicitRegisterUse::kReadAccumulator,                  \
    OperandType::kImm, OperandType::kUImm)                                     \
145 146
                                                                               \
  /* Propery stores (StoreIC) operations */                                    \
147
  V(SetNamedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
148
    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
149
  V(DefineNamedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator,        \
150
    OperandType::kReg, OperandType::kIdx, OperandType::kIdx)                   \
151
  V(SetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator,              \
152
    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
153
  V(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadWriteAccumulator,        \
154
    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
155 156
  V(StaInArrayLiteral, ImplicitRegisterUse::kReadWriteAccumulator,             \
    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
157
  V(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator,    \
158 159 160 161
    OperandType::kReg, OperandType::kReg, OperandType::kFlag8,                 \
    OperandType::kIdx)                                                         \
  V(CollectTypeProfile, ImplicitRegisterUse::kReadAccumulator,                 \
    OperandType::kImm)                                                         \
162 163
                                                                               \
  /* Binary Operators */                                                       \
164 165 166 167 168 169 170 171 172
  V(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
    OperandType::kIdx)                                                         \
  V(Sub, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
    OperandType::kIdx)                                                         \
  V(Mul, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
    OperandType::kIdx)                                                         \
  V(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
    OperandType::kIdx)                                                         \
  V(Mod, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
173
    OperandType::kIdx)                                                         \
174
  V(Exp, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,        \
175
    OperandType::kIdx)                                                         \
176
  V(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
177
    OperandType::kIdx)                                                         \
178
  V(BitwiseXor, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
179
    OperandType::kIdx)                                                         \
180
  V(BitwiseAnd, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
181
    OperandType::kIdx)                                                         \
182
  V(ShiftLeft, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
183
    OperandType::kIdx)                                                         \
184 185 186 187
  V(ShiftRight, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
    OperandType::kIdx)                                                         \
  V(ShiftRightLogical, ImplicitRegisterUse::kReadWriteAccumulator,             \
    OperandType::kReg, OperandType::kIdx)                                      \
188 189
                                                                               \
  /* Binary operators with immediate operands */                               \
190
  V(AddSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
191
    OperandType::kIdx)                                                         \
192
  V(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
193
    OperandType::kIdx)                                                         \
194
  V(MulSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
195
    OperandType::kIdx)                                                         \
196
  V(DivSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
197
    OperandType::kIdx)                                                         \
198
  V(ModSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
199
    OperandType::kIdx)                                                         \
200
  V(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm,     \
201
    OperandType::kIdx)                                                         \
202 203 204 205 206 207 208 209 210 211 212 213
  V(BitwiseOrSmi, ImplicitRegisterUse::kReadWriteAccumulator,                  \
    OperandType::kImm, OperandType::kIdx)                                      \
  V(BitwiseXorSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
    OperandType::kImm, OperandType::kIdx)                                      \
  V(BitwiseAndSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
    OperandType::kImm, OperandType::kIdx)                                      \
  V(ShiftLeftSmi, ImplicitRegisterUse::kReadWriteAccumulator,                  \
    OperandType::kImm, OperandType::kIdx)                                      \
  V(ShiftRightSmi, ImplicitRegisterUse::kReadWriteAccumulator,                 \
    OperandType::kImm, OperandType::kIdx)                                      \
  V(ShiftRightLogicalSmi, ImplicitRegisterUse::kReadWriteAccumulator,          \
    OperandType::kImm, OperandType::kIdx)                                      \
214 215
                                                                               \
  /* Unary Operators */                                                        \
216 217 218 219 220 221 222 223 224 225 226
  V(Inc, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)        \
  V(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)        \
  V(Negate, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)     \
  V(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
  V(ToBooleanLogicalNot, ImplicitRegisterUse::kReadWriteAccumulator)           \
  V(LogicalNot, ImplicitRegisterUse::kReadWriteAccumulator)                    \
  V(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator)                        \
  V(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator,          \
    OperandType::kReg)                                                         \
  V(DeletePropertySloppy, ImplicitRegisterUse::kReadWriteAccumulator,          \
    OperandType::kReg)                                                         \
227 228
                                                                               \
  /* GetSuperConstructor operator */                                           \
229 230
  V(GetSuperConstructor, ImplicitRegisterUse::kReadAccumulator,                \
    OperandType::kRegOut)                                                      \
231 232
                                                                               \
  /* Call operations */                                                        \
233 234 235 236
  V(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator,                   \
    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
    OperandType::kIdx)                                                         \
  V(CallProperty, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,   \
237
    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
238
  V(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
239
    OperandType::kReg, OperandType::kIdx)                                      \
240
  V(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
241
    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
242
  V(CallProperty2, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
243 244
    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
    OperandType::kIdx)                                                         \
245 246
  V(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator,             \
    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
247
    OperandType::kIdx)                                                         \
248
  V(CallUndefinedReceiver0, ImplicitRegisterUse::kWriteAccumulator,            \
249
    OperandType::kReg, OperandType::kIdx)                                      \
250
  V(CallUndefinedReceiver1, ImplicitRegisterUse::kWriteAccumulator,            \
251
    OperandType::kReg, OperandType::kReg, OperandType::kIdx)                   \
252 253 254 255
  V(CallUndefinedReceiver2, ImplicitRegisterUse::kWriteAccumulator,            \
    OperandType::kReg, OperandType::kReg, OperandType::kReg,                   \
    OperandType::kIdx)                                                         \
  V(CallWithSpread, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
256
    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
257 258 259
  V(CallRuntime, ImplicitRegisterUse::kWriteAccumulator,                       \
    OperandType::kRuntimeId, OperandType::kRegList, OperandType::kRegCount)    \
  V(CallRuntimeForPair, ImplicitRegisterUse::kNone, OperandType::kRuntimeId,   \
260
    OperandType::kRegList, OperandType::kRegCount, OperandType::kRegOutPair)   \
261 262 263
  V(CallJSRuntime, ImplicitRegisterUse::kWriteAccumulator,                     \
    OperandType::kNativeContextIndex, OperandType::kRegList,                   \
    OperandType::kRegCount)                                                    \
264 265
                                                                               \
  /* Intrinsics */                                                             \
266 267
  V(InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator,                   \
    OperandType::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount)  \
268 269
                                                                               \
  /* Construct operators */                                                    \
270
  V(Construct, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
271
    OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
272 273 274
  V(ConstructWithSpread, ImplicitRegisterUse::kReadWriteAccumulator,           \
    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
    OperandType::kIdx)                                                         \
275
                                                                               \
276
  /* Effectful Test Operators */                                               \
277
  V(TestEqual, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,  \
278
    OperandType::kIdx)                                                         \
279 280 281 282 283 284 285 286 287 288 289 290 291
  V(TestEqualStrict, ImplicitRegisterUse::kReadWriteAccumulator,               \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestLessThan, ImplicitRegisterUse::kReadWriteAccumulator,                  \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestGreaterThan, ImplicitRegisterUse::kReadWriteAccumulator,               \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestLessThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator,           \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestGreaterThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator,        \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestInstanceOf, ImplicitRegisterUse::kReadWriteAccumulator,                \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(TestIn, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg,     \
292
    OperandType::kIdx)                                                         \
293 294
                                                                               \
  /* Cast operators */                                                         \
295 296 297 298 299
  V(ToName, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)       \
  V(ToNumber, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)   \
  V(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx)  \
  V(ToObject, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut)     \
  V(ToString, ImplicitRegisterUse::kReadWriteAccumulator)                      \
300 301
                                                                               \
  /* Literals */                                                               \
302 303 304 305 306 307 308 309 310 311 312
  V(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator,               \
    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
  V(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator,                \
    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
  V(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator)       \
  V(CreateEmptyArrayLiteral, ImplicitRegisterUse::kWriteAccumulator,           \
    OperandType::kIdx)                                                         \
  V(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator,               \
    OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8)                 \
  V(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator)          \
  V(CloneObject, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,    \
313
    OperandType::kFlag8, OperandType::kIdx)                                    \
314
                                                                               \
315
  /* Tagged templates */                                                       \
316 317
  V(GetTemplateObject, ImplicitRegisterUse::kWriteAccumulator,                 \
    OperandType::kIdx, OperandType::kIdx)                                      \
318
                                                                               \
319
  /* Closure allocation */                                                     \
320
  V(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx,  \
321 322 323
    OperandType::kIdx, OperandType::kFlag8)                                    \
                                                                               \
  /* Context allocation */                                                     \
324
  V(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator,                \
325
    OperandType::kIdx)                                                         \
326 327 328 329 330 331 332 333
  V(CreateCatchContext, ImplicitRegisterUse::kWriteAccumulator,                \
    OperandType::kReg, OperandType::kIdx)                                      \
  V(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator,             \
    OperandType::kIdx, OperandType::kUImm)                                     \
  V(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator,                 \
    OperandType::kIdx, OperandType::kUImm)                                     \
  V(CreateWithContext, ImplicitRegisterUse::kWriteAccumulator,                 \
    OperandType::kReg, OperandType::kIdx)                                      \
334 335
                                                                               \
  /* Arguments allocation */                                                   \
336 337 338
  V(CreateMappedArguments, ImplicitRegisterUse::kWriteAccumulator)             \
  V(CreateUnmappedArguments, ImplicitRegisterUse::kWriteAccumulator)           \
  V(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator)               \
339 340 341
                                                                               \
  /* Control Flow -- carefully ordered for efficient checks */                 \
  /* - [Unconditional jumps] */                                                \
342
  V(JumpLoop, ImplicitRegisterUse::kNone, OperandType::kUImm,                  \
343
    OperandType::kImm, OperandType::kIdx)                                      \
344
  /* - [Forward jumps] */                                                      \
345
  V(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm)                      \
346
  /* - [Start constant jumps] */                                               \
347
  V(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx)               \
348 349
  /* - [Conditional jumps] */                                                  \
  /* - [Conditional constant jumps] */                                         \
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
  V(JumpIfNullConstant, ImplicitRegisterUse::kReadAccumulator,                 \
    OperandType::kIdx)                                                         \
  V(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator,              \
    OperandType::kIdx)                                                         \
  V(JumpIfUndefinedConstant, ImplicitRegisterUse::kReadAccumulator,            \
    OperandType::kIdx)                                                         \
  V(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator,         \
    OperandType::kIdx)                                                         \
  V(JumpIfUndefinedOrNullConstant, ImplicitRegisterUse::kReadAccumulator,      \
    OperandType::kIdx)                                                         \
  V(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator,                 \
    OperandType::kIdx)                                                         \
  V(JumpIfFalseConstant, ImplicitRegisterUse::kReadAccumulator,                \
    OperandType::kIdx)                                                         \
  V(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator,           \
    OperandType::kIdx)                                                         \
366
  /* - [Start ToBoolean jumps] */                                              \
367 368 369 370
  V(JumpIfToBooleanTrueConstant, ImplicitRegisterUse::kReadAccumulator,        \
    OperandType::kIdx)                                                         \
  V(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator,       \
    OperandType::kIdx)                                                         \
371 372
  /* - [End constant jumps] */                                                 \
  /* - [Conditional immediate jumps] */                                        \
373 374 375 376
  V(JumpIfToBooleanTrue, ImplicitRegisterUse::kReadAccumulator,                \
    OperandType::kUImm)                                                        \
  V(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator,               \
    OperandType::kUImm)                                                        \
377
  /* - [End ToBoolean jumps] */                                                \
378 379 380 381 382 383 384 385 386 387 388 389
  V(JumpIfTrue, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)     \
  V(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)    \
  V(JumpIfNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)     \
  V(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm)  \
  V(JumpIfUndefined, ImplicitRegisterUse::kReadAccumulator,                    \
    OperandType::kUImm)                                                        \
  V(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator,                 \
    OperandType::kUImm)                                                        \
  V(JumpIfUndefinedOrNull, ImplicitRegisterUse::kReadAccumulator,              \
    OperandType::kUImm)                                                        \
  V(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator,                   \
    OperandType::kUImm)                                                        \
390
                                                                               \
391
  /* Smi-table lookup for switch statements */                                 \
392 393
  V(SwitchOnSmiNoFeedback, ImplicitRegisterUse::kReadAccumulator,              \
    OperandType::kIdx, OperandType::kUImm, OperandType::kImm)                  \
394
                                                                               \
395
  /* Complex flow control For..in */                                           \
396
  V(ForInEnumerate, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg) \
397
  V(ForInPrepare, ImplicitRegisterUse::kReadWriteAccumulator,                  \
398 399
    OperandType::kRegOutTriple, OperandType::kIdx)                             \
  V(ForInContinue, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,  \
400
    OperandType::kReg)                                                         \
401 402 403
  V(ForInNext, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,      \
    OperandType::kReg, OperandType::kRegPair, OperandType::kIdx)               \
  V(ForInStep, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg)      \
404 405
                                                                               \
  /* Update the pending message */                                             \
406
  V(SetPendingMessage, ImplicitRegisterUse::kReadWriteAccumulator)             \
407 408
                                                                               \
  /* Non-local flow control */                                                 \
409 410 411 412 413 414 415 416
  V(Throw, ImplicitRegisterUse::kReadAccumulator)                              \
  V(ReThrow, ImplicitRegisterUse::kReadAccumulator)                            \
  V(Return, ImplicitRegisterUse::kReadAccumulator)                             \
  V(ThrowReferenceErrorIfHole, ImplicitRegisterUse::kReadAccumulator,          \
    OperandType::kIdx)                                                         \
  V(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator)          \
  V(ThrowSuperAlreadyCalledIfNotHole, ImplicitRegisterUse::kReadAccumulator)   \
  V(ThrowIfNotSuperConstructor, ImplicitRegisterUse::kNone, OperandType::kReg) \
417 418
                                                                               \
  /* Generators */                                                             \
419
  V(SwitchOnGeneratorState, ImplicitRegisterUse::kNone, OperandType::kReg,     \
420
    OperandType::kIdx, OperandType::kUImm)                                     \
421 422 423 424 425
  V(SuspendGenerator, ImplicitRegisterUse::kReadAccumulator,                   \
    OperandType::kReg, OperandType::kRegList, OperandType::kRegCount,          \
    OperandType::kUImm)                                                        \
  V(ResumeGenerator, ImplicitRegisterUse::kWriteAccumulator,                   \
    OperandType::kReg, OperandType::kRegOutList, OperandType::kRegCount)       \
426
                                                                               \
427
  /* Iterator protocol operations */                                           \
428 429
  V(GetIterator, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg,    \
    OperandType::kIdx, OperandType::kIdx)                                      \
430
                                                                               \
431
  /* Debugger */                                                               \
432
  V(Debugger, ImplicitRegisterUse::kNone)                                      \
433
                                                                               \
434
  /* Block Coverage */                                                         \
435
  V(IncBlockCounter, ImplicitRegisterUse::kNone, OperandType::kIdx)            \
436
                                                                               \
437
  /* Execution Abort (internal error) */                                       \
438 439 440 441 442 443 444 445 446 447 448
  V(Abort, ImplicitRegisterUse::kNone, OperandType::kIdx)

// The list of bytecodes which are interpreted by the interpreter.
// Format is V(<bytecode>, <implicit_register_use>, <operands>).
#define BYTECODE_LIST(V)                                             \
  BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V)                              \
                                                                     \
  /* Special-case Star for common register numbers, to save space */ \
  SHORT_STAR_BYTECODE_LIST(V)                                        \
                                                                     \
  /* Illegal bytecode  */                                            \
449
  V(Illegal, ImplicitRegisterUse::kNone)
450

451 452 453 454 455 456 457 458 459
// List of debug break bytecodes.
#define DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
  V(DebugBreak0)                           \
  V(DebugBreak1)                           \
  V(DebugBreak2)                           \
  V(DebugBreak3)                           \
  V(DebugBreak4)                           \
  V(DebugBreak5)                           \
  V(DebugBreak6)
460

461 462 463
#define DEBUG_BREAK_PREFIX_BYTECODE_LIST(V) \
  V(DebugBreakWide)                         \
  V(DebugBreakExtraWide)
464

465 466 467
#define DEBUG_BREAK_BYTECODE_LIST(V) \
  DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
  DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
468

469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
// Lists of jump bytecodes.

#define JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  V(JumpLoop)                                         \
  V(Jump)

#define JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) V(JumpConstant)

#define JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  V(JumpIfToBooleanTrue)                                      \
  V(JumpIfToBooleanFalse)

#define JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
  V(JumpIfToBooleanTrueConstant)                             \
  V(JumpIfToBooleanFalseConstant)

#define JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V)     \
  JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  V(JumpIfTrue)                                         \
  V(JumpIfFalse)                                        \
  V(JumpIfNull)                                         \
490
  V(JumpIfNotNull)                                      \
491
  V(JumpIfUndefined)                                    \
492
  V(JumpIfNotUndefined)                                 \
493 494
  V(JumpIfUndefinedOrNull)                              \
  V(JumpIfJSReceiver)
495 496 497 498

#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)     \
  JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
  V(JumpIfNullConstant)                                \
499
  V(JumpIfNotNullConstant)                             \
500
  V(JumpIfUndefinedConstant)                           \
501
  V(JumpIfNotUndefinedConstant)                        \
502
  V(JumpIfUndefinedOrNullConstant)                     \
503 504
  V(JumpIfTrueConstant)                                \
  V(JumpIfFalseConstant)                               \
505
  V(JumpIfJSReceiverConstant)
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535

#define JUMP_CONSTANT_BYTECODE_LIST(V)         \
  JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
  JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)

#define JUMP_IMMEDIATE_BYTECODE_LIST(V)         \
  JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V)

#define JUMP_TO_BOOLEAN_BYTECODE_LIST(V)                \
  JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)

#define JUMP_UNCONDITIONAL_BYTECODE_LIST(V)     \
  JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V)

#define JUMP_CONDITIONAL_BYTECODE_LIST(V)     \
  JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
  JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)

#define JUMP_FORWARD_BYTECODE_LIST(V) \
  V(Jump)                             \
  V(JumpConstant)                     \
  JUMP_CONDITIONAL_BYTECODE_LIST(V)

#define JUMP_BYTECODE_LIST(V)   \
  JUMP_FORWARD_BYTECODE_LIST(V) \
  V(JumpLoop)

536 537 538 539
#define RETURN_BYTECODE_LIST(V) \
  V(Return)                     \
  V(SuspendGenerator)

540 541 542 543
#define UNCONDITIONAL_THROW_BYTECODE_LIST(V) \
  V(Throw)                                   \
  V(ReThrow)

544
// Enumeration of interpreter bytecodes.
545
enum class Bytecode : uint8_t {
546
#define DECLARE_BYTECODE(Name, ...) k##Name,
547 548
  BYTECODE_LIST(DECLARE_BYTECODE)
#undef DECLARE_BYTECODE
549
#define COUNT_BYTECODE(x, ...) +1
550 551
  // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will
  // evaluate to the same value as the last real bytecode.
552 553 554
  kLast = -1 BYTECODE_LIST(COUNT_BYTECODE),
  kFirstShortStar = kStar15,
  kLastShortStar = kStar0
555 556 557
#undef COUNT_BYTECODE
};

558
class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
559
 public:
560
  // The maximum number of operands a bytecode may have.
561
  static const int kMaxOperands = 5;
562

563 564 565
  // The total number of bytecodes used.
  static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;

566 567 568 569
  static const int kShortStarCount =
      static_cast<int>(Bytecode::kLastShortStar) -
      static_cast<int>(Bytecode::kFirstShortStar) + 1;

570 571 572
  // Returns string representation of |bytecode|.
  static const char* ToString(Bytecode bytecode);

573 574 575 576
  // Returns string representation of |bytecode| combined with |operand_scale|
  // using the optionally provided |separator|.
  static std::string ToString(Bytecode bytecode, OperandScale operand_scale,
                              const char* separator = ".");
577

578
  // Returns byte value of bytecode.
579 580 581 582
  static uint8_t ToByte(Bytecode bytecode) {
    DCHECK_LE(bytecode, Bytecode::kLast);
    return static_cast<uint8_t>(bytecode);
  }
583 584

  // Returns bytecode for |value|.
585 586
  static Bytecode FromByte(uint8_t value) {
    Bytecode bytecode = static_cast<Bytecode>(value);
587
    DCHECK_LE(bytecode, Bytecode::kLast);
588 589
    return bytecode;
  }
590

591 592
  // Returns the prefix bytecode representing an operand scale to be
  // applied to a a bytecode.
593 594 595 596 597 598 599 600 601 602
  static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale) {
    switch (operand_scale) {
      case OperandScale::kQuadruple:
        return Bytecode::kExtraWide;
      case OperandScale::kDouble:
        return Bytecode::kWide;
      default:
        UNREACHABLE();
    }
  }
603 604

  // Returns true if the operand scale requires a prefix bytecode.
605 606 607
  static bool OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
    return operand_scale != OperandScale::kSingle;
  }
608 609 610

  // Returns the scaling applied to scalable operands if bytecode is
  // is a scaling prefix.
611 612 613 614 615 616 617 618 619 620 621 622
  static OperandScale PrefixBytecodeToOperandScale(Bytecode bytecode) {
    switch (bytecode) {
      case Bytecode::kExtraWide:
      case Bytecode::kDebugBreakExtraWide:
        return OperandScale::kQuadruple;
      case Bytecode::kWide:
      case Bytecode::kDebugBreakWide:
        return OperandScale::kDouble;
      default:
        UNREACHABLE();
    }
  }
623

624
  // Returns how accumulator is used by |bytecode|.
625
  static ImplicitRegisterUse GetImplicitRegisterUse(Bytecode bytecode) {
626
    DCHECK_LE(bytecode, Bytecode::kLast);
627
    return kImplicitRegisterUse[static_cast<size_t>(bytecode)];
628
  }
629 630

  // Returns true if |bytecode| reads the accumulator.
631
  static bool ReadsAccumulator(Bytecode bytecode) {
632
    return BytecodeOperands::ReadsAccumulator(GetImplicitRegisterUse(bytecode));
633
  }
634 635

  // Returns true if |bytecode| writes the accumulator.
636
  static bool WritesAccumulator(Bytecode bytecode) {
637 638
    return BytecodeOperands::WritesAccumulator(
        GetImplicitRegisterUse(bytecode));
639
  }
640

641 642 643 644 645 646 647
  // Returns true if |bytecode| writes to a register not specified by an
  // operand.
  static bool WritesImplicitRegister(Bytecode bytecode) {
    return BytecodeOperands::WritesImplicitRegister(
        GetImplicitRegisterUse(bytecode));
  }

648
  // Return true if |bytecode| is an accumulator load without effects,
649
  // e.g. LdaConstant, LdaTrue, Ldar.
650
  static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
651
    static_assert(Bytecode::kLdar < Bytecode::kLdaImmutableCurrentContextSlot);
652 653
    return bytecode >= Bytecode::kLdar &&
           bytecode <= Bytecode::kLdaImmutableCurrentContextSlot;
654
  }
655

656 657 658
  // Returns true if |bytecode| is a compare operation without external effects
  // (e.g., Type cooersion).
  static constexpr bool IsCompareWithoutEffects(Bytecode bytecode) {
659
    static_assert(Bytecode::kTestReferenceEqual < Bytecode::kTestTypeOf);
660 661
    return bytecode >= Bytecode::kTestReferenceEqual &&
           bytecode <= Bytecode::kTestTypeOf;
662 663
  }

664 665 666 667 668 669 670 671 672
  static constexpr bool IsShortStar(Bytecode bytecode) {
    return bytecode >= Bytecode::kFirstShortStar &&
           bytecode <= Bytecode::kLastShortStar;
  }

  static constexpr bool IsAnyStar(Bytecode bytecode) {
    return bytecode == Bytecode::kStar || IsShortStar(bytecode);
  }

673
  // Return true if |bytecode| is a register load without effects,
674
  // e.g. Mov, Star.
675
  static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
676 677
    return IsShortStar(bytecode) ||
           (bytecode >= Bytecode::kStar && bytecode <= Bytecode::kPopContext);
678
  }
679

680
  // Returns true if the bytecode is a conditional jump taking
681
  // an immediate byte operand (OperandType::kImm).
682
  static constexpr bool IsConditionalJumpImmediate(Bytecode bytecode) {
683
    return bytecode >= Bytecode::kJumpIfToBooleanTrue &&
684
           bytecode <= Bytecode::kJumpIfJSReceiver;
685
  }
686

687
  // Returns true if the bytecode is a conditional jump taking
688
  // a constant pool entry (OperandType::kIdx).
689
  static constexpr bool IsConditionalJumpConstant(Bytecode bytecode) {
690 691
    return bytecode >= Bytecode::kJumpIfNullConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
692
  }
693

694
  // Returns true if the bytecode is a conditional jump taking
695
  // any kind of operand.
696
  static constexpr bool IsConditionalJump(Bytecode bytecode) {
697
    return bytecode >= Bytecode::kJumpIfNullConstant &&
698
           bytecode <= Bytecode::kJumpIfJSReceiver;
699
  }
700

701
  // Returns true if the bytecode is an unconditional jump.
702
  static constexpr bool IsUnconditionalJump(Bytecode bytecode) {
703 704
    return bytecode >= Bytecode::kJumpLoop &&
           bytecode <= Bytecode::kJumpConstant;
705 706
  }

707
  // Returns true if the bytecode is a jump or a conditional jump taking
708
  // an immediate byte operand (OperandType::kImm).
709
  static constexpr bool IsJumpImmediate(Bytecode bytecode) {
710 711 712
    return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop ||
           IsConditionalJumpImmediate(bytecode);
  }
713

714
  // Returns true if the bytecode is a jump or conditional jump taking a
715
  // constant pool entry (OperandType::kIdx).
716
  static constexpr bool IsJumpConstant(Bytecode bytecode) {
717 718
    return bytecode >= Bytecode::kJumpConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
719
  }
720

721 722
  // Returns true if the bytecode is a jump that internally coerces the
  // accumulator to a boolean.
723
  static constexpr bool IsJumpIfToBoolean(Bytecode bytecode) {
724 725
    return bytecode >= Bytecode::kJumpIfToBooleanTrueConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalse;
726
  }
727

728 729
  // Returns true if the bytecode is a jump or conditional jump taking
  // any kind of operand.
730
  static constexpr bool IsJump(Bytecode bytecode) {
731
    return bytecode >= Bytecode::kJumpLoop &&
732
           bytecode <= Bytecode::kJumpIfJSReceiver;
733
  }
734

735 736
  // Returns true if the bytecode is a forward jump or conditional jump taking
  // any kind of operand.
737
  static constexpr bool IsForwardJump(Bytecode bytecode) {
738 739
    return bytecode >= Bytecode::kJump &&
           bytecode <= Bytecode::kJumpIfJSReceiver;
740 741
  }

742
  // Return true if |bytecode| is a jump without effects,
743 744
  // e.g. any jump excluding those that include type coercion like
  // JumpIfTrueToBoolean, and JumpLoop due to having an implicit StackCheck.
745
  static constexpr bool IsJumpWithoutEffects(Bytecode bytecode) {
746 747
    return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode) &&
           bytecode != Bytecode::kJumpLoop;
748 749
  }

750 751
  // Returns true if the bytecode is a switch.
  static constexpr bool IsSwitch(Bytecode bytecode) {
752 753
    return bytecode == Bytecode::kSwitchOnSmiNoFeedback ||
           bytecode == Bytecode::kSwitchOnGeneratorState;
754 755
  }

756 757
  // Returns true if |bytecode| has no effects. These bytecodes only manipulate
  // interpreter frame state and will never throw.
758
  static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
759 760
    return (IsAccumulatorLoadWithoutEffects(bytecode) ||
            IsRegisterLoadWithoutEffects(bytecode) ||
761
            IsCompareWithoutEffects(bytecode) ||
762
            IsJumpWithoutEffects(bytecode) || IsSwitch(bytecode));
763 764 765
  }

  // Returns true if the bytecode is Ldar or Star.
766
  static constexpr bool IsLdarOrStar(Bytecode bytecode) {
767
    return bytecode == Bytecode::kLdar || IsAnyStar(bytecode);
768 769
  }

770
  // Returns true if the bytecode is a call or a constructor call.
771
  static constexpr bool IsCallOrConstruct(Bytecode bytecode) {
772 773
    return bytecode == Bytecode::kCallAnyReceiver ||
           bytecode == Bytecode::kCallProperty ||
774 775 776
           bytecode == Bytecode::kCallProperty0 ||
           bytecode == Bytecode::kCallProperty1 ||
           bytecode == Bytecode::kCallProperty2 ||
777 778 779 780
           bytecode == Bytecode::kCallUndefinedReceiver ||
           bytecode == Bytecode::kCallUndefinedReceiver0 ||
           bytecode == Bytecode::kCallUndefinedReceiver1 ||
           bytecode == Bytecode::kCallUndefinedReceiver2 ||
781 782 783 784
           bytecode == Bytecode::kConstruct ||
           bytecode == Bytecode::kCallWithSpread ||
           bytecode == Bytecode::kConstructWithSpread ||
           bytecode == Bytecode::kCallJSRuntime;
785
  }
786

787
  // Returns true if the bytecode is a call to the runtime.
788
  static constexpr bool IsCallRuntime(Bytecode bytecode) {
789 790 791 792
    return bytecode == Bytecode::kCallRuntime ||
           bytecode == Bytecode::kCallRuntimeForPair ||
           bytecode == Bytecode::kInvokeIntrinsic;
  }
793

794
  // Returns true if the bytecode is a scaling prefix bytecode.
795
  static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode) {
796 797 798 799
    return bytecode == Bytecode::kExtraWide || bytecode == Bytecode::kWide ||
           bytecode == Bytecode::kDebugBreakExtraWide ||
           bytecode == Bytecode::kDebugBreakWide;
  }
800

801 802 803 804 805 806 807
  // Returns true if the bytecode returns.
  static constexpr bool Returns(Bytecode bytecode) {
#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
    return false RETURN_BYTECODE_LIST(OR_BYTECODE);
#undef OR_BYTECODE
  }

808 809 810 811 812 813 814
  // Returns true if the bytecode unconditionally throws.
  static constexpr bool UnconditionallyThrows(Bytecode bytecode) {
#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
    return false UNCONDITIONAL_THROW_BYTECODE_LIST(OR_BYTECODE);
#undef OR_BYTECODE
  }

815 816
  // Returns the number of operands expected by |bytecode|.
  static int NumberOfOperands(Bytecode bytecode) {
817
    DCHECK_LE(bytecode, Bytecode::kLast);
818 819 820 821 822 823 824 825 826 827 828 829 830 831
    return kOperandCount[static_cast<size_t>(bytecode)];
  }

  // Returns the i-th operand of |bytecode|.
  static OperandType GetOperandType(Bytecode bytecode, int i) {
    DCHECK_LE(bytecode, Bytecode::kLast);
    DCHECK_LT(i, NumberOfOperands(bytecode));
    DCHECK_GE(i, 0);
    return GetOperandTypes(bytecode)[i];
  }

  // Returns a pointer to an array of operand types terminated in
  // OperandType::kNone.
  static const OperandType* GetOperandTypes(Bytecode bytecode) {
832
    DCHECK_LE(bytecode, Bytecode::kLast);
833 834 835 836 837
    return kOperandTypes[static_cast<size_t>(bytecode)];
  }

  static bool OperandIsScalableSignedByte(Bytecode bytecode,
                                          int operand_index) {
838
    DCHECK_LE(bytecode, Bytecode::kLast);
839 840 841 842 843 844
    return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
           OperandTypeInfo::kScalableSignedByte;
  }

  static bool OperandIsScalableUnsignedByte(Bytecode bytecode,
                                            int operand_index) {
845
    DCHECK_LE(bytecode, Bytecode::kLast);
846 847 848 849 850 851 852 853
    return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
           OperandTypeInfo::kScalableUnsignedByte;
  }

  static bool OperandIsScalable(Bytecode bytecode, int operand_index) {
    return OperandIsScalableSignedByte(bytecode, operand_index) ||
           OperandIsScalableUnsignedByte(bytecode, operand_index);
  }
854

855 856
  // Returns true if the bytecode has wider operand forms.
  static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
857

858 859 860 861 862 863 864 865 866 867
  // Returns the size of the i-th operand of |bytecode|.
  static OperandSize GetOperandSize(Bytecode bytecode, int i,
                                    OperandScale operand_scale) {
    CHECK_LT(i, NumberOfOperands(bytecode));
    return GetOperandSizes(bytecode, operand_scale)[i];
  }

  // Returns the operand sizes of |bytecode| with scale |operand_scale|.
  static const OperandSize* GetOperandSizes(Bytecode bytecode,
                                            OperandScale operand_scale) {
868
    DCHECK_LE(bytecode, Bytecode::kLast);
869 870
    DCHECK_GE(operand_scale, OperandScale::kSingle);
    DCHECK_LE(operand_scale, OperandScale::kLast);
871
    static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
872 873
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
874
    return kOperandSizes[scale_index][static_cast<size_t>(bytecode)];
875
  }
876

877 878 879 880 881 882 883 884
  // Returns the offset of the i-th operand of |bytecode| relative to the start
  // of the bytecode.
  static int GetOperandOffset(Bytecode bytecode, int i,
                              OperandScale operand_scale);

  // Returns the size of the bytecode including its operands for the
  // given |operand_scale|.
  static int Size(Bytecode bytecode, OperandScale operand_scale) {
885
    DCHECK_LE(bytecode, Bytecode::kLast);
886
    static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
887 888
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
889
    return kBytecodeSizes[scale_index][static_cast<size_t>(bytecode)];
890 891 892 893 894 895 896 897
  }

  // Returns a debug break bytecode to replace |bytecode|.
  static Bytecode GetDebugBreak(Bytecode bytecode);

  // Returns the equivalent jump bytecode without the accumulator coercion.
  static Bytecode GetJumpWithoutToBoolean(Bytecode bytecode);

898 899 900 901
  // Returns true if there is a call in the most-frequently executed path
  // through the bytecode's handler.
  static bool MakesCallAlongCriticalPath(Bytecode bytecode);

902 903
  // Returns the receiver mode of the given call bytecode.
  static ConvertReceiverMode GetReceiverMode(Bytecode bytecode) {
904 905
    DCHECK(IsCallOrConstruct(bytecode) ||
           bytecode == Bytecode::kInvokeIntrinsic);
906 907 908 909 910 911 912 913 914 915
    switch (bytecode) {
      case Bytecode::kCallProperty:
      case Bytecode::kCallProperty0:
      case Bytecode::kCallProperty1:
      case Bytecode::kCallProperty2:
        return ConvertReceiverMode::kNotNullOrUndefined;
      case Bytecode::kCallUndefinedReceiver:
      case Bytecode::kCallUndefinedReceiver0:
      case Bytecode::kCallUndefinedReceiver1:
      case Bytecode::kCallUndefinedReceiver2:
916
      case Bytecode::kCallJSRuntime:
917 918 919 920 921 922 923 924 925 926 927 928
        return ConvertReceiverMode::kNullOrUndefined;
      case Bytecode::kCallAnyReceiver:
      case Bytecode::kConstruct:
      case Bytecode::kCallWithSpread:
      case Bytecode::kConstructWithSpread:
      case Bytecode::kInvokeIntrinsic:
        return ConvertReceiverMode::kAny;
      default:
        UNREACHABLE();
    }
  }

929 930
  // Returns true if the bytecode is a debug break.
  static bool IsDebugBreak(Bytecode bytecode);
931

932 933 934 935 936 937 938 939 940
  // Returns true if |operand_type| is any type of register operand.
  static bool IsRegisterOperandType(OperandType operand_type);

  // Returns true if |operand_type| represents a register used as an input.
  static bool IsRegisterInputOperandType(OperandType operand_type);

  // Returns true if |operand_type| represents a register used as an output.
  static bool IsRegisterOutputOperandType(OperandType operand_type);

941 942 943
  // Returns true if |operand_type| represents a register list operand.
  static bool IsRegisterListOperandType(OperandType operand_type);

944 945 946 947
  // Returns true if the handler for |bytecode| should look ahead and inline a
  // dispatch to a Star bytecode.
  static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale);

948
  // Returns the number of registers represented by a register operand. For
949 950 951
  // instance, a RegPair represents two registers. Should not be called for
  // kRegList which has a variable number of registers based on the following
  // kRegCount operand.
952 953 954 955 956 957 958 959 960 961
  static int GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
    switch (operand_type) {
      case OperandType::kReg:
      case OperandType::kRegOut:
        return 1;
      case OperandType::kRegPair:
      case OperandType::kRegOutPair:
        return 2;
      case OperandType::kRegOutTriple:
        return 3;
962
      case OperandType::kRegList:
963
      case OperandType::kRegOutList:
964
        UNREACHABLE();
965 966 967
      default:
        return 0;
    }
968
    UNREACHABLE();
969 970
  }

971 972 973 974 975 976
  // Returns the size of |operand_type| for |operand_scale|.
  static OperandSize SizeOfOperand(OperandType operand_type,
                                   OperandScale operand_scale) {
    DCHECK_LE(operand_type, OperandType::kLast);
    DCHECK_GE(operand_scale, OperandScale::kSingle);
    DCHECK_LE(operand_scale, OperandScale::kLast);
977
    static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
978 979
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
980
    return kOperandKindSizes[scale_index][static_cast<size_t>(operand_type)];
981
  }
982

983 984 985 986 987 988
  // Returns true if |operand_type| is a runtime-id operand (kRuntimeId).
  static bool IsRuntimeIdOperandType(OperandType operand_type);

  // Returns true if |operand_type| is unsigned, false if signed.
  static bool IsUnsignedOperandType(OperandType operand_type);

989 990 991 992 993 994
  // Returns true if a handler is generated for a bytecode at a given
  // operand scale. All bytecodes have handlers at OperandScale::kSingle,
  // but only bytecodes with scalable operands have handlers with larger
  // OperandScale values.
  static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale);

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
  // Return the operand scale required to hold a signed operand with |value|.
  static OperandScale ScaleForSignedOperand(int32_t value) {
    if (value >= kMinInt8 && value <= kMaxInt8) {
      return OperandScale::kSingle;
    } else if (value >= kMinInt16 && value <= kMaxInt16) {
      return OperandScale::kDouble;
    } else {
      return OperandScale::kQuadruple;
    }
  }

  // Return the operand scale required to hold an unsigned operand with |value|.
  static OperandScale ScaleForUnsignedOperand(uint32_t value) {
    if (value <= kMaxUInt8) {
      return OperandScale::kSingle;
    } else if (value <= kMaxUInt16) {
      return OperandScale::kDouble;
    } else {
      return OperandScale::kQuadruple;
    }
  }

  // Return the operand size required to hold an unsigned operand with |value|.
  static OperandSize SizeForUnsignedOperand(uint32_t value) {
    if (value <= kMaxUInt8) {
      return OperandSize::kByte;
    } else if (value <= kMaxUInt16) {
      return OperandSize::kShort;
    } else {
      return OperandSize::kQuad;
    }
  }

1028
  static Address bytecode_size_table_address() {
1029 1030
    return reinterpret_cast<Address>(
        const_cast<uint8_t*>(&kBytecodeSizes[0][0]));
1031 1032
  }

1033 1034 1035 1036 1037
 private:
  static const OperandType* const kOperandTypes[];
  static const OperandTypeInfo* const kOperandTypeInfos[];
  static const int kOperandCount[];
  static const int kNumberOfRegisterOperands[];
1038
  static const ImplicitRegisterUse kImplicitRegisterUse[];
1039
  static const bool kIsScalable[];
1040
  static const uint8_t kBytecodeSizes[3][kBytecodeCount];
1041 1042 1043
  static const OperandSize* const kOperandSizes[3][kBytecodeCount];
  static OperandSize const
      kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount];
1044
};
1045

1046 1047
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
                                           const Bytecode& bytecode);
1048 1049 1050 1051 1052 1053

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODES_H_