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 // static
    170 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
    171   switch (operand_type) {
    172 #define CASE(Name, _)        \
    173   case OperandType::k##Name: \
    174     return true;
    175     REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
    176 #undef CASE
    177 #define CASE(Name, _)        \
    178   case OperandType::k##Name: \
    179     break;
    180     NON_REGISTER_OPERAND_TYPE_LIST(CASE)
    181     REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
    182 #undef CASE
    183   }
    184   return false;
    185 }
    186 
    187 // static
    188 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
    189   switch (operand_type) {
    190 #define CASE(Name, _)        \
    191   case OperandType::k##Name: \
    192     return true;
    193     REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
    194 #undef CASE
    195 #define CASE(Name, _)        \
    196   case OperandType::k##Name: \
    197     break;
    198     NON_REGISTER_OPERAND_TYPE_LIST(CASE)
    199     REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
    200 #undef CASE
    201   }
    202   return false;
    203 }
    204 
    205 // static
    206 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
    207   if (operand_scale == OperandScale::kSingle) {
    208     switch (bytecode) {
    209       case Bytecode::kLdaZero:
    210       case Bytecode::kLdaSmi:
    211       case Bytecode::kLdaNull:
    212       case Bytecode::kLdaTheHole:
    213       case Bytecode::kLdaConstant:
    214       case Bytecode::kLdaUndefined:
    215       case Bytecode::kLdaGlobal:
    216       case Bytecode::kLdaNamedProperty:
    217       case Bytecode::kLdaKeyedProperty:
    218       case Bytecode::kLdaContextSlot:
    219       case Bytecode::kLdaCurrentContextSlot:
    220       case Bytecode::kAdd:
    221       case Bytecode::kSub:
    222       case Bytecode::kMul:
    223       case Bytecode::kAddSmi:
    224       case Bytecode::kSubSmi:
    225       case Bytecode::kInc:
    226       case Bytecode::kDec:
    227       case Bytecode::kTypeOf:
    228       case Bytecode::kCall:
    229       case Bytecode::kCallProperty:
    230       case Bytecode::kNew:
    231         return true;
    232       default:
    233         return false;
    234     }
    235   }
    236   return false;
    237 }
    238 
    239 // static
    240 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
    241   for (int i = 0; i < NumberOfOperands(bytecode); i++) {
    242     if (OperandIsScalable(bytecode, i)) return true;
    243   }
    244   return false;
    245 }
    246 
    247 // static
    248 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
    249   switch (operand_type) {
    250 #define CASE(Name, _)        \
    251   case OperandType::k##Name: \
    252     return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
    253     OPERAND_TYPE_LIST(CASE)
    254 #undef CASE
    255   }
    256   UNREACHABLE();
    257   return false;
    258 }
    259 
    260 // static
    261 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type,
    262                                      OperandScale operand_scale) {
    263   DCHECK_LE(operand_type, OperandType::kLast);
    264   DCHECK_GE(operand_scale, OperandScale::kSingle);
    265   DCHECK_LE(operand_scale, OperandScale::kLast);
    266   STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
    267                 OperandScale::kLast == OperandScale::kQuadruple);
    268   int scale_index = static_cast<int>(operand_scale) >> 1;
    269   // clang-format off
    270   static const OperandSize kOperandSizes[][3] = {
    271 #define ENTRY(Name, ...)                                \
    272   { OperandScaler<OperandType::k##Name,                 \
    273                  OperandScale::kSingle>::kOperandSize,  \
    274     OperandScaler<OperandType::k##Name,                 \
    275                  OperandScale::kDouble>::kOperandSize,  \
    276     OperandScaler<OperandType::k##Name,                 \
    277                  OperandScale::kQuadruple>::kOperandSize },
    278     OPERAND_TYPE_LIST(ENTRY)
    279 #undef ENTRY
    280   };
    281   // clang-format on
    282   return kOperandSizes[static_cast<size_t>(operand_type)][scale_index];
    283 }
    284 
    285 // static
    286 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
    287                                    OperandScale operand_scale) {
    288   return operand_scale == OperandScale::kSingle ||
    289          Bytecodes::IsBytecodeWithScalableOperands(bytecode);
    290 }
    291 
    292 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
    293   return os << Bytecodes::ToString(bytecode);
    294 }
    295 
    296 }  // namespace interpreter
    297 }  // namespace internal
    298 }  // namespace v8
    299