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