Home | History | Annotate | Download | only in interpreter
      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:
    271   Register() : index_(kIllegalIndex) {}
    272 
    273   explicit Register(int index) : index_(index) {}
    274 
    275   int index() const {
    276     DCHECK(index_ != kIllegalIndex);
    277     return index_;
    278   }
    279   bool is_parameter() const { return index() < 0; }
    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