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