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 #include "src/interpreter/bytecodes.h"
      6 
      7 #include <iomanip>
      8 
      9 #include "src/base/bits.h"
     10 #include "src/interpreter/bytecode-traits.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace interpreter {
     15 
     16 // clang-format off
     17 const OperandType* const Bytecodes::kOperandTypes[] = {
     18 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes,
     19   BYTECODE_LIST(ENTRY)
     20 #undef ENTRY
     21 };
     22 
     23 const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = {
     24 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos,
     25   BYTECODE_LIST(ENTRY)
     26 #undef ENTRY
     27 };
     28 
     29 const int Bytecodes::kOperandCount[] = {
     30 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount,
     31   BYTECODE_LIST(ENTRY)
     32 #undef ENTRY
     33 };
     34 
     35 const AccumulatorUse Bytecodes::kAccumulatorUse[] = {
     36 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse,
     37   BYTECODE_LIST(ENTRY)
     38 #undef ENTRY
     39 };
     40 
     41 const int Bytecodes::kBytecodeSizes[3][kBytecodeCount] = {
     42   {
     43 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kSingleScaleSize,
     44   BYTECODE_LIST(ENTRY)
     45 #undef ENTRY
     46   }, {
     47 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize,
     48   BYTECODE_LIST(ENTRY)
     49 #undef ENTRY
     50   }, {
     51 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize,
     52   BYTECODE_LIST(ENTRY)
     53 #undef ENTRY
     54   }
     55 };
     56 
     57 const OperandSize* const Bytecodes::kOperandSizes[3][kBytecodeCount] = {
     58   {
     59 #define ENTRY(Name, ...)  \
     60     BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes,
     61   BYTECODE_LIST(ENTRY)
     62 #undef ENTRY
     63   }, {
     64 #define ENTRY(Name, ...)  \
     65     BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes,
     66   BYTECODE_LIST(ENTRY)
     67 #undef ENTRY
     68   }, {
     69 #define ENTRY(Name, ...)  \
     70     BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes,
     71   BYTECODE_LIST(ENTRY)
     72 #undef ENTRY
     73   }
     74 };
     75 
     76 const OperandSize
     77 Bytecodes::kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount] = {
     78   {
     79 #define ENTRY(Name, ...)  \
     80     OperandScaler<OperandType::k##Name, OperandScale::kSingle>::kOperandSize,
     81   OPERAND_TYPE_LIST(ENTRY)
     82 #undef ENTRY
     83   }, {
     84 #define ENTRY(Name, ...)  \
     85     OperandScaler<OperandType::k##Name, OperandScale::kDouble>::kOperandSize,
     86   OPERAND_TYPE_LIST(ENTRY)
     87 #undef ENTRY
     88   }, {
     89 #define ENTRY(Name, ...)  \
     90     OperandScaler<OperandType::k##Name, OperandScale::kQuadruple>::kOperandSize,
     91   OPERAND_TYPE_LIST(ENTRY)
     92 #undef ENTRY
     93   }
     94 };
     95 // clang-format on
     96 
     97 // static
     98 const char* Bytecodes::ToString(Bytecode bytecode) {
     99   switch (bytecode) {
    100 #define CASE(Name, ...)   \
    101   case Bytecode::k##Name: \
    102     return #Name;
    103     BYTECODE_LIST(CASE)
    104 #undef CASE
    105   }
    106   UNREACHABLE();
    107 }
    108 
    109 // static
    110 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) {
    111   static const char kSeparator = '.';
    112 
    113   std::string value(ToString(bytecode));
    114   if (operand_scale > OperandScale::kSingle) {
    115     Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
    116     std::string suffix = ToString(prefix_bytecode);
    117     return value.append(1, kSeparator).append(suffix);
    118   } else {
    119     return value;
    120   }
    121 }
    122 
    123 // static
    124 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
    125   DCHECK(!IsDebugBreak(bytecode));
    126   if (bytecode == Bytecode::kWide) {
    127     return Bytecode::kDebugBreakWide;
    128   }
    129   if (bytecode == Bytecode::kExtraWide) {
    130     return Bytecode::kDebugBreakExtraWide;
    131   }
    132   int bytecode_size = Size(bytecode, OperandScale::kSingle);
    133 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name)                         \
    134   if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
    135     return Bytecode::k##Name;                                            \
    136   }
    137   DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
    138 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
    139   UNREACHABLE();
    140 }
    141 
    142 // static
    143 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
    144                                 OperandScale operand_scale) {
    145   DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
    146   // TODO(oth): restore this to a statically determined constant.
    147   int offset = 1;
    148   for (int operand_index = 0; operand_index < i; ++operand_index) {
    149     OperandSize operand_size =
    150         GetOperandSize(bytecode, operand_index, operand_scale);
    151     offset += static_cast<int>(operand_size);
    152   }
    153   return offset;
    154 }
    155 
    156 // static
    157 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
    158   switch (bytecode) {
    159     case Bytecode::kJumpIfToBooleanTrue:
    160       return Bytecode::kJumpIfTrue;
    161     case Bytecode::kJumpIfToBooleanFalse:
    162       return Bytecode::kJumpIfFalse;
    163     case Bytecode::kJumpIfToBooleanTrueConstant:
    164       return Bytecode::kJumpIfTrueConstant;
    165     case Bytecode::kJumpIfToBooleanFalseConstant:
    166       return Bytecode::kJumpIfFalseConstant;
    167     default:
    168       break;
    169   }
    170   UNREACHABLE();
    171 }
    172 
    173 // static
    174 bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
    175   switch (bytecode) {
    176 #define CASE(Name, ...) case Bytecode::k##Name:
    177     DEBUG_BREAK_BYTECODE_LIST(CASE);
    178 #undef CASE
    179     return true;
    180     default:
    181       break;
    182   }
    183   return false;
    184 }
    185 
    186 // static
    187 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
    188   switch (operand_type) {
    189 #define CASE(Name, _)        \
    190   case OperandType::k##Name: \
    191     return true;
    192     REGISTER_OPERAND_TYPE_LIST(CASE)
    193 #undef CASE
    194 #define CASE(Name, _)        \
    195   case OperandType::k##Name: \
    196     break;
    197     NON_REGISTER_OPERAND_TYPE_LIST(CASE)
    198 #undef CASE
    199   }
    200   return false;
    201 }
    202 
    203 // static
    204 bool Bytecodes::IsRegisterListOperandType(OperandType operand_type) {
    205   switch (operand_type) {
    206     case OperandType::kRegList:
    207     case OperandType::kRegOutList:
    208       return true;
    209     default:
    210       return false;
    211   }
    212 }
    213 
    214 bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) {
    215   if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true;
    216   switch (bytecode) {
    217     case Bytecode::kCreateWithContext:
    218     case Bytecode::kCreateBlockContext:
    219     case Bytecode::kCreateCatchContext:
    220     case Bytecode::kCreateRegExpLiteral:
    221       return true;
    222     default:
    223       return false;
    224   }
    225 }
    226 
    227 // static
    228 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
    229   switch (operand_type) {
    230 #define CASE(Name, _)        \
    231   case OperandType::k##Name: \
    232     return true;
    233     REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
    234 #undef CASE
    235 #define CASE(Name, _)        \
    236   case OperandType::k##Name: \
    237     break;
    238     NON_REGISTER_OPERAND_TYPE_LIST(CASE)
    239     REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
    240 #undef CASE
    241   }
    242   return false;
    243 }
    244 
    245 // static
    246 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
    247   switch (operand_type) {
    248 #define CASE(Name, _)        \
    249   case OperandType::k##Name: \
    250     return true;
    251     REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
    252 #undef CASE
    253 #define CASE(Name, _)        \
    254   case OperandType::k##Name: \
    255     break;
    256     NON_REGISTER_OPERAND_TYPE_LIST(CASE)
    257     REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
    258 #undef CASE
    259   }
    260   return false;
    261 }
    262 
    263 // static
    264 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
    265   if (operand_scale == OperandScale::kSingle) {
    266     switch (bytecode) {
    267       case Bytecode::kLdaZero:
    268       case Bytecode::kLdaSmi:
    269       case Bytecode::kLdaNull:
    270       case Bytecode::kLdaTheHole:
    271       case Bytecode::kLdaConstant:
    272       case Bytecode::kLdaUndefined:
    273       case Bytecode::kLdaGlobal:
    274       case Bytecode::kLdaNamedProperty:
    275       case Bytecode::kLdaKeyedProperty:
    276       case Bytecode::kLdaContextSlot:
    277       case Bytecode::kLdaCurrentContextSlot:
    278       case Bytecode::kAdd:
    279       case Bytecode::kSub:
    280       case Bytecode::kMul:
    281       case Bytecode::kAddSmi:
    282       case Bytecode::kSubSmi:
    283       case Bytecode::kInc:
    284       case Bytecode::kDec:
    285       case Bytecode::kTypeOf:
    286       case Bytecode::kCallAnyReceiver:
    287       case Bytecode::kCallProperty:
    288       case Bytecode::kCallProperty0:
    289       case Bytecode::kCallProperty1:
    290       case Bytecode::kCallProperty2:
    291       case Bytecode::kCallUndefinedReceiver:
    292       case Bytecode::kCallUndefinedReceiver0:
    293       case Bytecode::kCallUndefinedReceiver1:
    294       case Bytecode::kCallUndefinedReceiver2:
    295       case Bytecode::kConstruct:
    296       case Bytecode::kConstructWithSpread:
    297         return true;
    298       default:
    299         return false;
    300     }
    301   }
    302   return false;
    303 }
    304 
    305 // static
    306 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
    307   for (int i = 0; i < NumberOfOperands(bytecode); i++) {
    308     if (OperandIsScalable(bytecode, i)) return true;
    309   }
    310   return false;
    311 }
    312 
    313 // static
    314 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
    315   switch (operand_type) {
    316 #define CASE(Name, _)        \
    317   case OperandType::k##Name: \
    318     return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
    319     OPERAND_TYPE_LIST(CASE)
    320 #undef CASE
    321   }
    322   UNREACHABLE();
    323 }
    324 
    325 // static
    326 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
    327                                    OperandScale operand_scale) {
    328   return operand_scale == OperandScale::kSingle ||
    329          Bytecodes::IsBytecodeWithScalableOperands(bytecode);
    330 }
    331 
    332 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
    333   return os << Bytecodes::ToString(bytecode);
    334 }
    335 
    336 }  // namespace interpreter
    337 }  // namespace internal
    338 }  // namespace v8
    339