bytecodes.h 50.9 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
#include <vector>
12

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

16 17 18
// 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.
19 20 21 22 23 24

namespace v8 {
namespace internal {
namespace interpreter {

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

374 375 376 377 378 379 380 381 382
// 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)
383

384 385 386
#define DEBUG_BREAK_PREFIX_BYTECODE_LIST(V) \
  V(DebugBreakWide)                         \
  V(DebugBreakExtraWide)
387

388 389 390
#define DEBUG_BREAK_BYTECODE_LIST(V) \
  DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
  DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
391

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
// 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)                                         \
413
  V(JumpIfNotNull)                                      \
414
  V(JumpIfUndefined)                                    \
415
  V(JumpIfNotUndefined)                                 \
416 417
  V(JumpIfUndefinedOrNull)                              \
  V(JumpIfJSReceiver)
418 419 420 421

#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)     \
  JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
  V(JumpIfNullConstant)                                \
422
  V(JumpIfNotNullConstant)                             \
423
  V(JumpIfUndefinedConstant)                           \
424
  V(JumpIfNotUndefinedConstant)                        \
425
  V(JumpIfUndefinedOrNullConstant)                     \
426 427
  V(JumpIfTrueConstant)                                \
  V(JumpIfFalseConstant)                               \
428
  V(JumpIfJSReceiverConstant)
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

#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)

459 460 461 462
#define RETURN_BYTECODE_LIST(V) \
  V(Return)                     \
  V(SuspendGenerator)

463
// Enumeration of interpreter bytecodes.
464
enum class Bytecode : uint8_t {
465
#define DECLARE_BYTECODE(Name, ...) k##Name,
466 467
  BYTECODE_LIST(DECLARE_BYTECODE)
#undef DECLARE_BYTECODE
468
#define COUNT_BYTECODE(x, ...) +1
469 470 471 472 473 474
  // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will
  // evaluate to the same value as the last real bytecode.
  kLast = -1 BYTECODE_LIST(COUNT_BYTECODE)
#undef COUNT_BYTECODE
};

475
class V8_EXPORT_PRIVATE Bytecodes final : public AllStatic {
476
 public:
477
  // The maximum number of operands a bytecode may have.
478
  static const int kMaxOperands = 5;
479

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

483 484 485
  // Returns string representation of |bytecode|.
  static const char* ToString(Bytecode bytecode);

486 487 488 489
  // 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 = ".");
490

491
  // Returns byte value of bytecode.
492 493 494 495
  static uint8_t ToByte(Bytecode bytecode) {
    DCHECK_LE(bytecode, Bytecode::kLast);
    return static_cast<uint8_t>(bytecode);
  }
496 497

  // Returns bytecode for |value|.
498 499
  static Bytecode FromByte(uint8_t value) {
    Bytecode bytecode = static_cast<Bytecode>(value);
500
    DCHECK_LE(bytecode, Bytecode::kLast);
501 502
    return bytecode;
  }
503

504 505
  // Returns the prefix bytecode representing an operand scale to be
  // applied to a a bytecode.
506 507 508 509 510 511 512 513 514 515
  static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale) {
    switch (operand_scale) {
      case OperandScale::kQuadruple:
        return Bytecode::kExtraWide;
      case OperandScale::kDouble:
        return Bytecode::kWide;
      default:
        UNREACHABLE();
    }
  }
516 517

  // Returns true if the operand scale requires a prefix bytecode.
518 519 520
  static bool OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
    return operand_scale != OperandScale::kSingle;
  }
521 522 523

  // Returns the scaling applied to scalable operands if bytecode is
  // is a scaling prefix.
524 525 526 527 528 529 530 531 532 533 534 535
  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();
    }
  }
536

537
  // Returns how accumulator is used by |bytecode|.
538
  static AccumulatorUse GetAccumulatorUse(Bytecode bytecode) {
539
    DCHECK_LE(bytecode, Bytecode::kLast);
540 541
    return kAccumulatorUse[static_cast<size_t>(bytecode)];
  }
542 543

  // Returns true if |bytecode| reads the accumulator.
544
  static bool ReadsAccumulator(Bytecode bytecode) {
545
    return BytecodeOperands::ReadsAccumulator(GetAccumulatorUse(bytecode));
546
  }
547 548

  // Returns true if |bytecode| writes the accumulator.
549
  static bool WritesAccumulator(Bytecode bytecode) {
550
    return BytecodeOperands::WritesAccumulator(GetAccumulatorUse(bytecode));
551
  }
552

553
  // Return true if |bytecode| is an accumulator load without effects,
554
  // e.g. LdaConstant, LdaTrue, Ldar.
555
  static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
556 557 558 559 560
    return bytecode == Bytecode::kLdar || bytecode == Bytecode::kLdaZero ||
           bytecode == Bytecode::kLdaSmi || bytecode == Bytecode::kLdaNull ||
           bytecode == Bytecode::kLdaTrue || bytecode == Bytecode::kLdaFalse ||
           bytecode == Bytecode::kLdaUndefined ||
           bytecode == Bytecode::kLdaTheHole ||
561 562
           bytecode == Bytecode::kLdaConstant ||
           bytecode == Bytecode::kLdaContextSlot ||
563 564 565
           bytecode == Bytecode::kLdaCurrentContextSlot ||
           bytecode == Bytecode::kLdaImmutableContextSlot ||
           bytecode == Bytecode::kLdaImmutableCurrentContextSlot;
566
  }
567

568 569 570 571 572 573 574 575 576
  // Returns true if |bytecode| is a compare operation without external effects
  // (e.g., Type cooersion).
  static constexpr bool IsCompareWithoutEffects(Bytecode bytecode) {
    return bytecode == Bytecode::kTestUndetectable ||
           bytecode == Bytecode::kTestNull ||
           bytecode == Bytecode::kTestUndefined ||
           bytecode == Bytecode::kTestTypeOf;
  }

577
  // Return true if |bytecode| is a register load without effects,
578
  // e.g. Mov, Star.
579
  static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
580
    return bytecode == Bytecode::kMov || bytecode == Bytecode::kPopContext ||
581
           bytecode == Bytecode::kPushContext || bytecode == Bytecode::kStar;
582
  }
583

584
  // Returns true if the bytecode is a conditional jump taking
585
  // an immediate byte operand (OperandType::kImm).
586
  static constexpr bool IsConditionalJumpImmediate(Bytecode bytecode) {
587
    return bytecode >= Bytecode::kJumpIfToBooleanTrue &&
588
           bytecode <= Bytecode::kJumpIfJSReceiver;
589
  }
590

591
  // Returns true if the bytecode is a conditional jump taking
592
  // a constant pool entry (OperandType::kIdx).
593
  static constexpr bool IsConditionalJumpConstant(Bytecode bytecode) {
594 595
    return bytecode >= Bytecode::kJumpIfNullConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
596
  }
597

598
  // Returns true if the bytecode is a conditional jump taking
599
  // any kind of operand.
600
  static constexpr bool IsConditionalJump(Bytecode bytecode) {
601
    return bytecode >= Bytecode::kJumpIfNullConstant &&
602
           bytecode <= Bytecode::kJumpIfJSReceiver;
603
  }
604

605
  // Returns true if the bytecode is an unconditional jump.
606
  static constexpr bool IsUnconditionalJump(Bytecode bytecode) {
607 608
    return bytecode >= Bytecode::kJumpLoop &&
           bytecode <= Bytecode::kJumpConstant;
609 610
  }

611
  // Returns true if the bytecode is a jump or a conditional jump taking
612
  // an immediate byte operand (OperandType::kImm).
613
  static constexpr bool IsJumpImmediate(Bytecode bytecode) {
614 615 616
    return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop ||
           IsConditionalJumpImmediate(bytecode);
  }
617

618
  // Returns true if the bytecode is a jump or conditional jump taking a
619
  // constant pool entry (OperandType::kIdx).
620
  static constexpr bool IsJumpConstant(Bytecode bytecode) {
621 622
    return bytecode >= Bytecode::kJumpConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
623
  }
624

625 626
  // Returns true if the bytecode is a jump that internally coerces the
  // accumulator to a boolean.
627
  static constexpr bool IsJumpIfToBoolean(Bytecode bytecode) {
628 629
    return bytecode >= Bytecode::kJumpIfToBooleanTrueConstant &&
           bytecode <= Bytecode::kJumpIfToBooleanFalse;
630
  }
631

632 633
  // Returns true if the bytecode is a jump or conditional jump taking
  // any kind of operand.
634
  static constexpr bool IsJump(Bytecode bytecode) {
635
    return bytecode >= Bytecode::kJumpLoop &&
636
           bytecode <= Bytecode::kJumpIfJSReceiver;
637
  }
638

639 640
  // Returns true if the bytecode is a forward jump or conditional jump taking
  // any kind of operand.
641
  static constexpr bool IsForwardJump(Bytecode bytecode) {
642 643
    return bytecode >= Bytecode::kJump &&
           bytecode <= Bytecode::kJumpIfJSReceiver;
644 645
  }

646
  // Return true if |bytecode| is a jump without effects,
647 648
  // e.g. any jump excluding those that include type coercion like
  // JumpIfTrueToBoolean, and JumpLoop due to having an implicit StackCheck.
649
  static constexpr bool IsJumpWithoutEffects(Bytecode bytecode) {
650 651
    return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode) &&
           bytecode != Bytecode::kJumpLoop;
652 653
  }

654 655
  // Returns true if the bytecode is a switch.
  static constexpr bool IsSwitch(Bytecode bytecode) {
656 657
    return bytecode == Bytecode::kSwitchOnSmiNoFeedback ||
           bytecode == Bytecode::kSwitchOnGeneratorState;
658 659
  }

660 661
  // Returns true if |bytecode| has no effects. These bytecodes only manipulate
  // interpreter frame state and will never throw.
662
  static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
663 664
    return (IsAccumulatorLoadWithoutEffects(bytecode) ||
            IsRegisterLoadWithoutEffects(bytecode) ||
665
            IsCompareWithoutEffects(bytecode) ||
666
            IsJumpWithoutEffects(bytecode) || IsSwitch(bytecode));
667 668 669
  }

  // Returns true if the bytecode is Ldar or Star.
670
  static constexpr bool IsLdarOrStar(Bytecode bytecode) {
671 672 673
    return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
  }

674
  // Returns true if the bytecode is a call or a constructor call.
675
  static constexpr bool IsCallOrConstruct(Bytecode bytecode) {
676 677
    return bytecode == Bytecode::kCallAnyReceiver ||
           bytecode == Bytecode::kCallProperty ||
678 679 680
           bytecode == Bytecode::kCallProperty0 ||
           bytecode == Bytecode::kCallProperty1 ||
           bytecode == Bytecode::kCallProperty2 ||
681 682 683 684
           bytecode == Bytecode::kCallUndefinedReceiver ||
           bytecode == Bytecode::kCallUndefinedReceiver0 ||
           bytecode == Bytecode::kCallUndefinedReceiver1 ||
           bytecode == Bytecode::kCallUndefinedReceiver2 ||
685
           bytecode == Bytecode::kCallNoFeedback ||
686 687 688 689
           bytecode == Bytecode::kConstruct ||
           bytecode == Bytecode::kCallWithSpread ||
           bytecode == Bytecode::kConstructWithSpread ||
           bytecode == Bytecode::kCallJSRuntime;
690
  }
691

692
  // Returns true if the bytecode is a call to the runtime.
693
  static constexpr bool IsCallRuntime(Bytecode bytecode) {
694 695 696 697
    return bytecode == Bytecode::kCallRuntime ||
           bytecode == Bytecode::kCallRuntimeForPair ||
           bytecode == Bytecode::kInvokeIntrinsic;
  }
698

699 700 701 702 703 704 705 706 707
  // Returns true if the bytecode is an one-shot bytecode.  One-shot bytecodes
  // don`t collect feedback and are intended for code that runs only once and
  // shouldn`t be optimized.
  static constexpr bool IsOneShotBytecode(Bytecode bytecode) {
    return bytecode == Bytecode::kCallNoFeedback ||
           bytecode == Bytecode::kLdaNamedPropertyNoFeedback ||
           bytecode == Bytecode::kStaNamedPropertyNoFeedback;
  }

708
  // Returns true if the bytecode is a scaling prefix bytecode.
709
  static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode) {
710 711 712 713
    return bytecode == Bytecode::kExtraWide || bytecode == Bytecode::kWide ||
           bytecode == Bytecode::kDebugBreakExtraWide ||
           bytecode == Bytecode::kDebugBreakWide;
  }
714

715 716 717 718 719 720 721
  // 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
  }

722 723
  // Returns the number of operands expected by |bytecode|.
  static int NumberOfOperands(Bytecode bytecode) {
724
    DCHECK_LE(bytecode, Bytecode::kLast);
725 726 727 728 729 730 731 732 733 734 735 736 737 738
    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) {
739
    DCHECK_LE(bytecode, Bytecode::kLast);
740 741 742 743 744
    return kOperandTypes[static_cast<size_t>(bytecode)];
  }

  static bool OperandIsScalableSignedByte(Bytecode bytecode,
                                          int operand_index) {
745
    DCHECK_LE(bytecode, Bytecode::kLast);
746 747 748 749 750 751
    return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
           OperandTypeInfo::kScalableSignedByte;
  }

  static bool OperandIsScalableUnsignedByte(Bytecode bytecode,
                                            int operand_index) {
752
    DCHECK_LE(bytecode, Bytecode::kLast);
753 754 755 756 757 758 759 760
    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);
  }
761

762 763
  // Returns true if the bytecode has wider operand forms.
  static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
764

765 766 767 768 769 770 771 772 773 774
  // 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) {
775
    DCHECK_LE(bytecode, Bytecode::kLast);
776 777 778 779 780
    DCHECK_GE(operand_scale, OperandScale::kSingle);
    DCHECK_LE(operand_scale, OperandScale::kLast);
    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
781
    return kOperandSizes[scale_index][static_cast<size_t>(bytecode)];
782
  }
783

784 785 786 787 788 789 790 791
  // 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) {
792
    DCHECK_LE(bytecode, Bytecode::kLast);
793 794 795
    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
796
    return kBytecodeSizes[scale_index][static_cast<size_t>(bytecode)];
797 798 799 800 801 802 803 804
  }

  // 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);

805 806 807 808
  // Returns true if there is a call in the most-frequently executed path
  // through the bytecode's handler.
  static bool MakesCallAlongCriticalPath(Bytecode bytecode);

809 810
  // Returns the receiver mode of the given call bytecode.
  static ConvertReceiverMode GetReceiverMode(Bytecode bytecode) {
811 812
    DCHECK(IsCallOrConstruct(bytecode) ||
           bytecode == Bytecode::kInvokeIntrinsic);
813 814 815 816 817 818 819 820 821 822
    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:
823
      case Bytecode::kCallJSRuntime:
824 825
        return ConvertReceiverMode::kNullOrUndefined;
      case Bytecode::kCallAnyReceiver:
826
      case Bytecode::kCallNoFeedback:
827 828 829 830 831 832 833 834 835 836
      case Bytecode::kConstruct:
      case Bytecode::kCallWithSpread:
      case Bytecode::kConstructWithSpread:
      case Bytecode::kInvokeIntrinsic:
        return ConvertReceiverMode::kAny;
      default:
        UNREACHABLE();
    }
  }

837 838
  // Returns true if the bytecode is a debug break.
  static bool IsDebugBreak(Bytecode bytecode);
839

840 841 842 843 844 845 846 847 848
  // 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);

849 850 851
  // Returns true if |operand_type| represents a register list operand.
  static bool IsRegisterListOperandType(OperandType operand_type);

852 853 854 855
  // 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);

856
  // Returns the number of registers represented by a register operand. For
857 858 859
  // 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.
860 861 862 863 864 865 866 867 868 869
  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;
870
      case OperandType::kRegList:
871
      case OperandType::kRegOutList:
872
        UNREACHABLE();
873 874 875
      default:
        return 0;
    }
876
    UNREACHABLE();
877 878
  }

879 880 881 882 883 884 885 886 887
  // 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);
    STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
                  OperandScale::kLast == OperandScale::kQuadruple);
    int scale_index = static_cast<int>(operand_scale) >> 1;
888
    return kOperandKindSizes[scale_index][static_cast<size_t>(operand_type)];
889
  }
890

891 892 893 894 895 896
  // 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);

897 898 899 900 901 902
  // 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);

903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
  // 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;
    }
  }

936 937 938 939
  static Address bytecode_size_table_address() {
    return reinterpret_cast<Address>(const_cast<int*>(&kBytecodeSizes[0][0]));
  }

940 941 942 943 944 945 946
 private:
  static const OperandType* const kOperandTypes[];
  static const OperandTypeInfo* const kOperandTypeInfos[];
  static const int kOperandCount[];
  static const int kNumberOfRegisterOperands[];
  static const AccumulatorUse kAccumulatorUse[];
  static const bool kIsScalable[];
947 948 949 950
  static const int kBytecodeSizes[3][kBytecodeCount];
  static const OperandSize* const kOperandSizes[3][kBytecodeCount];
  static OperandSize const
      kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount];
951
};
952

953 954
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
                                           const Bytecode& bytecode);
955 956 957 958 959 960

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

#endif  // V8_INTERPRETER_BYTECODES_H_