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 <iosfwd> 9 10 // Clients of this interface shouldn't depend on lots of interpreter internals. 11 // Do not include anything from src/interpreter here! 12 #include "src/utils.h" 13 14 namespace v8 { 15 namespace internal { 16 namespace interpreter { 17 18 // The list of operand types used by bytecodes. 19 #define OPERAND_TYPE_LIST(V) \ 20 \ 21 /* None operand. */ \ 22 V(None, OperandSize::kNone) \ 23 \ 24 /* Byte operands. */ \ 25 V(Count8, OperandSize::kByte) \ 26 V(Imm8, OperandSize::kByte) \ 27 V(Idx8, OperandSize::kByte) \ 28 V(MaybeReg8, OperandSize::kByte) \ 29 V(Reg8, OperandSize::kByte) \ 30 V(RegPair8, OperandSize::kByte) \ 31 \ 32 /* Short operands. */ \ 33 V(Count16, OperandSize::kShort) \ 34 V(Idx16, OperandSize::kShort) \ 35 V(Reg16, OperandSize::kShort) 36 37 // The list of bytecodes which are interpreted by the interpreter. 38 #define BYTECODE_LIST(V) \ 39 \ 40 /* Loading the accumulator */ \ 41 V(LdaZero, OperandType::kNone) \ 42 V(LdaSmi8, OperandType::kImm8) \ 43 V(LdaUndefined, OperandType::kNone) \ 44 V(LdaNull, OperandType::kNone) \ 45 V(LdaTheHole, OperandType::kNone) \ 46 V(LdaTrue, OperandType::kNone) \ 47 V(LdaFalse, OperandType::kNone) \ 48 V(LdaConstant, OperandType::kIdx8) \ 49 V(LdaConstantWide, OperandType::kIdx16) \ 50 \ 51 /* Globals */ \ 52 V(LdaGlobalSloppy, OperandType::kIdx8, OperandType::kIdx8) \ 53 V(LdaGlobalStrict, OperandType::kIdx8, OperandType::kIdx8) \ 54 V(LdaGlobalInsideTypeofSloppy, OperandType::kIdx8, OperandType::kIdx8) \ 55 V(LdaGlobalInsideTypeofStrict, OperandType::kIdx8, OperandType::kIdx8) \ 56 V(LdaGlobalSloppyWide, OperandType::kIdx16, OperandType::kIdx16) \ 57 V(LdaGlobalStrictWide, OperandType::kIdx16, OperandType::kIdx16) \ 58 V(LdaGlobalInsideTypeofSloppyWide, OperandType::kIdx16, OperandType::kIdx16) \ 59 V(LdaGlobalInsideTypeofStrictWide, OperandType::kIdx16, OperandType::kIdx16) \ 60 V(StaGlobalSloppy, OperandType::kIdx8, OperandType::kIdx8) \ 61 V(StaGlobalStrict, OperandType::kIdx8, OperandType::kIdx8) \ 62 V(StaGlobalSloppyWide, OperandType::kIdx16, OperandType::kIdx16) \ 63 V(StaGlobalStrictWide, OperandType::kIdx16, OperandType::kIdx16) \ 64 \ 65 /* Context operations */ \ 66 V(PushContext, OperandType::kReg8) \ 67 V(PopContext, OperandType::kReg8) \ 68 V(LdaContextSlot, OperandType::kReg8, OperandType::kIdx8) \ 69 V(StaContextSlot, OperandType::kReg8, OperandType::kIdx8) \ 70 V(LdaContextSlotWide, OperandType::kReg8, OperandType::kIdx16) \ 71 V(StaContextSlotWide, OperandType::kReg8, OperandType::kIdx16) \ 72 \ 73 /* Load-Store lookup slots */ \ 74 V(LdaLookupSlot, OperandType::kIdx8) \ 75 V(LdaLookupSlotInsideTypeof, OperandType::kIdx8) \ 76 V(LdaLookupSlotWide, OperandType::kIdx16) \ 77 V(LdaLookupSlotInsideTypeofWide, OperandType::kIdx16) \ 78 V(StaLookupSlotSloppy, OperandType::kIdx8) \ 79 V(StaLookupSlotStrict, OperandType::kIdx8) \ 80 V(StaLookupSlotSloppyWide, OperandType::kIdx16) \ 81 V(StaLookupSlotStrictWide, OperandType::kIdx16) \ 82 \ 83 /* Register-accumulator transfers */ \ 84 V(Ldar, OperandType::kReg8) \ 85 V(Star, OperandType::kReg8) \ 86 \ 87 /* Register-register transfers */ \ 88 V(Mov, OperandType::kReg8, OperandType::kReg8) \ 89 V(Exchange, OperandType::kReg8, OperandType::kReg16) \ 90 V(ExchangeWide, OperandType::kReg16, OperandType::kReg16) \ 91 \ 92 /* LoadIC operations */ \ 93 V(LoadICSloppy, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \ 94 V(LoadICStrict, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \ 95 V(KeyedLoadICSloppy, OperandType::kReg8, OperandType::kIdx8) \ 96 V(KeyedLoadICStrict, OperandType::kReg8, OperandType::kIdx8) \ 97 /* TODO(rmcilroy): Wide register operands too? */ \ 98 V(LoadICSloppyWide, OperandType::kReg8, OperandType::kIdx16, \ 99 OperandType::kIdx16) \ 100 V(LoadICStrictWide, OperandType::kReg8, OperandType::kIdx16, \ 101 OperandType::kIdx16) \ 102 V(KeyedLoadICSloppyWide, OperandType::kReg8, OperandType::kIdx16) \ 103 V(KeyedLoadICStrictWide, OperandType::kReg8, OperandType::kIdx16) \ 104 \ 105 /* StoreIC operations */ \ 106 V(StoreICSloppy, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \ 107 V(StoreICStrict, OperandType::kReg8, OperandType::kIdx8, OperandType::kIdx8) \ 108 V(KeyedStoreICSloppy, OperandType::kReg8, OperandType::kReg8, \ 109 OperandType::kIdx8) \ 110 V(KeyedStoreICStrict, OperandType::kReg8, OperandType::kReg8, \ 111 OperandType::kIdx8) \ 112 /* TODO(rmcilroy): Wide register operands too? */ \ 113 V(StoreICSloppyWide, OperandType::kReg8, OperandType::kIdx16, \ 114 OperandType::kIdx16) \ 115 V(StoreICStrictWide, OperandType::kReg8, OperandType::kIdx16, \ 116 OperandType::kIdx16) \ 117 V(KeyedStoreICSloppyWide, OperandType::kReg8, OperandType::kReg8, \ 118 OperandType::kIdx16) \ 119 V(KeyedStoreICStrictWide, OperandType::kReg8, OperandType::kReg8, \ 120 OperandType::kIdx16) \ 121 \ 122 /* Binary Operators */ \ 123 V(Add, OperandType::kReg8) \ 124 V(Sub, OperandType::kReg8) \ 125 V(Mul, OperandType::kReg8) \ 126 V(Div, OperandType::kReg8) \ 127 V(Mod, OperandType::kReg8) \ 128 V(BitwiseOr, OperandType::kReg8) \ 129 V(BitwiseXor, OperandType::kReg8) \ 130 V(BitwiseAnd, OperandType::kReg8) \ 131 V(ShiftLeft, OperandType::kReg8) \ 132 V(ShiftRight, OperandType::kReg8) \ 133 V(ShiftRightLogical, OperandType::kReg8) \ 134 \ 135 /* Unary Operators */ \ 136 V(Inc, OperandType::kNone) \ 137 V(Dec, OperandType::kNone) \ 138 V(LogicalNot, OperandType::kNone) \ 139 V(TypeOf, OperandType::kNone) \ 140 V(DeletePropertyStrict, OperandType::kReg8) \ 141 V(DeletePropertySloppy, OperandType::kReg8) \ 142 V(DeleteLookupSlot, OperandType::kNone) \ 143 \ 144 /* Call operations */ \ 145 V(Call, OperandType::kReg8, OperandType::kReg8, OperandType::kCount8, \ 146 OperandType::kIdx8) \ 147 V(CallWide, OperandType::kReg8, OperandType::kReg8, OperandType::kCount16, \ 148 OperandType::kIdx16) \ 149 V(CallRuntime, OperandType::kIdx16, OperandType::kMaybeReg8, \ 150 OperandType::kCount8) \ 151 V(CallRuntimeForPair, OperandType::kIdx16, OperandType::kMaybeReg8, \ 152 OperandType::kCount8, OperandType::kRegPair8) \ 153 V(CallJSRuntime, OperandType::kIdx16, OperandType::kReg8, \ 154 OperandType::kCount8) \ 155 \ 156 /* New operator */ \ 157 V(New, OperandType::kReg8, OperandType::kMaybeReg8, OperandType::kCount8) \ 158 \ 159 /* Test Operators */ \ 160 V(TestEqual, OperandType::kReg8) \ 161 V(TestNotEqual, OperandType::kReg8) \ 162 V(TestEqualStrict, OperandType::kReg8) \ 163 V(TestNotEqualStrict, OperandType::kReg8) \ 164 V(TestLessThan, OperandType::kReg8) \ 165 V(TestGreaterThan, OperandType::kReg8) \ 166 V(TestLessThanOrEqual, OperandType::kReg8) \ 167 V(TestGreaterThanOrEqual, OperandType::kReg8) \ 168 V(TestInstanceOf, OperandType::kReg8) \ 169 V(TestIn, OperandType::kReg8) \ 170 \ 171 /* Cast operators */ \ 172 V(ToName, OperandType::kNone) \ 173 V(ToNumber, OperandType::kNone) \ 174 V(ToObject, OperandType::kNone) \ 175 \ 176 /* Literals */ \ 177 V(CreateRegExpLiteral, OperandType::kIdx8, OperandType::kIdx8, \ 178 OperandType::kImm8) \ 179 V(CreateArrayLiteral, OperandType::kIdx8, OperandType::kIdx8, \ 180 OperandType::kImm8) \ 181 V(CreateObjectLiteral, OperandType::kIdx8, OperandType::kIdx8, \ 182 OperandType::kImm8) \ 183 V(CreateRegExpLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \ 184 OperandType::kImm8) \ 185 V(CreateArrayLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \ 186 OperandType::kImm8) \ 187 V(CreateObjectLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \ 188 OperandType::kImm8) \ 189 \ 190 /* Closure allocation */ \ 191 V(CreateClosure, OperandType::kIdx8, OperandType::kImm8) \ 192 V(CreateClosureWide, OperandType::kIdx16, OperandType::kImm8) \ 193 \ 194 /* Arguments allocation */ \ 195 V(CreateMappedArguments, OperandType::kNone) \ 196 V(CreateUnmappedArguments, OperandType::kNone) \ 197 \ 198 /* Control Flow */ \ 199 V(Jump, OperandType::kImm8) \ 200 V(JumpConstant, OperandType::kIdx8) \ 201 V(JumpConstantWide, OperandType::kIdx16) \ 202 V(JumpIfTrue, OperandType::kImm8) \ 203 V(JumpIfTrueConstant, OperandType::kIdx8) \ 204 V(JumpIfTrueConstantWide, OperandType::kIdx16) \ 205 V(JumpIfFalse, OperandType::kImm8) \ 206 V(JumpIfFalseConstant, OperandType::kIdx8) \ 207 V(JumpIfFalseConstantWide, OperandType::kIdx16) \ 208 V(JumpIfToBooleanTrue, OperandType::kImm8) \ 209 V(JumpIfToBooleanTrueConstant, OperandType::kIdx8) \ 210 V(JumpIfToBooleanTrueConstantWide, OperandType::kIdx16) \ 211 V(JumpIfToBooleanFalse, OperandType::kImm8) \ 212 V(JumpIfToBooleanFalseConstant, OperandType::kIdx8) \ 213 V(JumpIfToBooleanFalseConstantWide, OperandType::kIdx16) \ 214 V(JumpIfNull, OperandType::kImm8) \ 215 V(JumpIfNullConstant, OperandType::kIdx8) \ 216 V(JumpIfNullConstantWide, OperandType::kIdx16) \ 217 V(JumpIfUndefined, OperandType::kImm8) \ 218 V(JumpIfUndefinedConstant, OperandType::kIdx8) \ 219 V(JumpIfUndefinedConstantWide, OperandType::kIdx16) \ 220 \ 221 /* Complex flow control For..in */ \ 222 V(ForInPrepare, OperandType::kReg8, OperandType::kReg8, OperandType::kReg8) \ 223 V(ForInDone, OperandType::kReg8, OperandType::kReg8) \ 224 V(ForInNext, OperandType::kReg8, OperandType::kReg8, OperandType::kReg8, \ 225 OperandType::kReg8) \ 226 V(ForInStep, OperandType::kReg8) \ 227 \ 228 /* Non-local flow control */ \ 229 V(Throw, OperandType::kNone) \ 230 V(Return, OperandType::kNone) 231 232 233 // Enumeration of the size classes of operand types used by bytecodes. 234 enum class OperandSize : uint8_t { 235 kNone = 0, 236 kByte = 1, 237 kShort = 2, 238 }; 239 240 241 // Enumeration of operand types used by bytecodes. 242 enum class OperandType : uint8_t { 243 #define DECLARE_OPERAND_TYPE(Name, _) k##Name, 244 OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE) 245 #undef DECLARE_OPERAND_TYPE 246 #define COUNT_OPERAND_TYPES(x, _) +1 247 // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will 248 // evaluate to the same value as the last operand. 249 kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES) 250 #undef COUNT_OPERAND_TYPES 251 }; 252 253 254 // Enumeration of interpreter bytecodes. 255 enum class Bytecode : uint8_t { 256 #define DECLARE_BYTECODE(Name, ...) k##Name, 257 BYTECODE_LIST(DECLARE_BYTECODE) 258 #undef DECLARE_BYTECODE 259 #define COUNT_BYTECODE(x, ...) +1 260 // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will 261 // evaluate to the same value as the last real bytecode. 262 kLast = -1 BYTECODE_LIST(COUNT_BYTECODE) 263 #undef COUNT_BYTECODE 264 }; 265 266 267 // An interpreter Register which is located in the function's Register file 268 // in its stack-frame. Register hold parameters, this, and expression values. 269 class Register { 270 public: Register()271 Register() : index_(kIllegalIndex) {} 272 Register(int index)273 explicit Register(int index) : index_(index) {} 274 index()275 int index() const { 276 DCHECK(index_ != kIllegalIndex); 277 return index_; 278 } is_parameter()279 bool is_parameter() const { return index() < 0; } is_valid()280 bool is_valid() const { return index_ != kIllegalIndex; } 281 282 static Register FromParameterIndex(int index, int parameter_count); 283 int ToParameterIndex(int parameter_count) const; 284 static int MaxParameterIndex(); 285 286 // Returns the register for the function's closure object. 287 static Register function_closure(); 288 bool is_function_closure() const; 289 290 // Returns the register for the function's outer context. 291 static Register function_context(); 292 bool is_function_context() const; 293 294 // Returns the register for the incoming new target value. 295 static Register new_target(); 296 bool is_new_target() const; 297 298 static Register FromOperand(uint8_t operand); 299 uint8_t ToOperand() const; 300 301 static Register FromWideOperand(uint16_t operand); 302 uint16_t ToWideOperand() const; 303 304 static bool AreContiguous(Register reg1, Register reg2, 305 Register reg3 = Register(), 306 Register reg4 = Register(), 307 Register reg5 = Register()); 308 309 bool operator==(const Register& other) const { 310 return index() == other.index(); 311 } 312 bool operator!=(const Register& other) const { 313 return index() != other.index(); 314 } 315 bool operator<(const Register& other) const { 316 return index() < other.index(); 317 } 318 bool operator<=(const Register& other) const { 319 return index() <= other.index(); 320 } 321 322 private: 323 static const int kIllegalIndex = kMaxInt; 324 325 void* operator new(size_t size); 326 void operator delete(void* p); 327 328 int index_; 329 }; 330 331 332 class Bytecodes { 333 public: 334 // Returns string representation of |bytecode|. 335 static const char* ToString(Bytecode bytecode); 336 337 // Returns string representation of |operand_type|. 338 static const char* OperandTypeToString(OperandType operand_type); 339 340 // Returns string representation of |operand_size|. 341 static const char* OperandSizeToString(OperandSize operand_size); 342 343 // Returns byte value of bytecode. 344 static uint8_t ToByte(Bytecode bytecode); 345 346 // Returns bytecode for |value|. 347 static Bytecode FromByte(uint8_t value); 348 349 // Returns the number of operands expected by |bytecode|. 350 static int NumberOfOperands(Bytecode bytecode); 351 352 // Return the i-th operand of |bytecode|. 353 static OperandType GetOperandType(Bytecode bytecode, int i); 354 355 // Return the size of the i-th operand of |bytecode|. 356 static OperandSize GetOperandSize(Bytecode bytecode, int i); 357 358 // Returns the offset of the i-th operand of |bytecode| relative to the start 359 // of the bytecode. 360 static int GetOperandOffset(Bytecode bytecode, int i); 361 362 // Returns the size of the bytecode including its operands. 363 static int Size(Bytecode bytecode); 364 365 // Returns the size of |operand|. 366 static OperandSize SizeOfOperand(OperandType operand); 367 368 // Return true if the bytecode is a conditional jump taking 369 // an immediate byte operand (OperandType::kImm8). 370 static bool IsConditionalJumpImmediate(Bytecode bytecode); 371 372 // Return true if the bytecode is a conditional jump taking 373 // a constant pool entry (OperandType::kIdx8). 374 static bool IsConditionalJumpConstant(Bytecode bytecode); 375 376 // Return true if the bytecode is a conditional jump taking 377 // a constant pool entry (OperandType::kIdx16). 378 static bool IsConditionalJumpConstantWide(Bytecode bytecode); 379 380 // Return true if the bytecode is a conditional jump taking 381 // any kind of operand. 382 static bool IsConditionalJump(Bytecode bytecode); 383 384 // Return true if the bytecode is a jump or a conditional jump taking 385 // an immediate byte operand (OperandType::kImm8). 386 static bool IsJumpImmediate(Bytecode bytecode); 387 388 // Return true if the bytecode is a jump or conditional jump taking a 389 // constant pool entry (OperandType::kIdx8). 390 static bool IsJumpConstant(Bytecode bytecode); 391 392 // Return true if the bytecode is a jump or conditional jump taking a 393 // constant pool entry (OperandType::kIdx16). 394 static bool IsJumpConstantWide(Bytecode bytecode); 395 396 // Return true if the bytecode is a jump or conditional jump taking 397 // any kind of operand. 398 static bool IsJump(Bytecode bytecode); 399 400 // Return true if the bytecode is a conditional jump, a jump, or a return. 401 static bool IsJumpOrReturn(Bytecode bytecode); 402 403 // Decode a single bytecode and operands to |os|. 404 static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start, 405 int number_of_parameters); 406 407 private: 408 DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes); 409 }; 410 411 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode); 412 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type); 413 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_type); 414 415 } // namespace interpreter 416 } // namespace internal 417 } // namespace v8 418 419 #endif // V8_INTERPRETER_BYTECODES_H_ 420