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