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