LCOV - code coverage report
Current view: top level - src/interpreter - bytecode-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 65 78 83.3 %
Date: 2017-10-20 Functions: 6 7 85.7 %

          Line data    Source code
       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/bytecode-decoder.h"
       6             : 
       7             : #include <iomanip>
       8             : 
       9             : #include "src/contexts.h"
      10             : #include "src/interpreter/interpreter-intrinsics.h"
      11             : #include "src/objects-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : namespace interpreter {
      16             : 
      17             : // static
      18    21157886 : Register BytecodeDecoder::DecodeRegisterOperand(const uint8_t* operand_start,
      19             :                                                 OperandType operand_type,
      20             :                                                 OperandScale operand_scale) {
      21             :   DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
      22             :   int32_t operand =
      23    21157920 :       DecodeSignedOperand(operand_start, operand_type, operand_scale);
      24    21157891 :   return Register::FromOperand(operand);
      25             : }
      26             : 
      27             : // static
      28           0 : RegisterList BytecodeDecoder::DecodeRegisterListOperand(
      29             :     const uint8_t* operand_start, uint32_t count, OperandType operand_type,
      30             :     OperandScale operand_scale) {
      31             :   Register first_reg =
      32             :       DecodeRegisterOperand(operand_start, operand_type, operand_scale);
      33           4 :   return RegisterList(first_reg.index(), static_cast<int>(count));
      34             : }
      35             : 
      36             : // static
      37    22158433 : int32_t BytecodeDecoder::DecodeSignedOperand(const uint8_t* operand_start,
      38             :                                              OperandType operand_type,
      39             :                                              OperandScale operand_scale) {
      40             :   DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
      41    22158433 :   switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
      42             :     case OperandSize::kByte:
      43    19514702 :       return static_cast<int8_t>(*operand_start);
      44             :     case OperandSize::kShort:
      45     2605078 :       return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
      46             :     case OperandSize::kQuad:
      47       38681 :       return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
      48             :     case OperandSize::kNone:
      49           0 :       UNREACHABLE();
      50             :   }
      51             :   return 0;
      52             : }
      53             : 
      54             : // static
      55    11831893 : uint32_t BytecodeDecoder::DecodeUnsignedOperand(const uint8_t* operand_start,
      56             :                                                 OperandType operand_type,
      57             :                                                 OperandScale operand_scale) {
      58             :   DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
      59    11831893 :   switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
      60             :     case OperandSize::kByte:
      61    10647837 :       return *operand_start;
      62             :     case OperandSize::kShort:
      63     1173753 :       return ReadUnalignedUInt16(operand_start);
      64             :     case OperandSize::kQuad:
      65       10318 :       return ReadUnalignedUInt32(operand_start);
      66             :     case OperandSize::kNone:
      67           0 :       UNREACHABLE();
      68             :   }
      69             :   return 0;
      70             : }
      71             : 
      72             : namespace {
      73             : 
      74           2 : const char* NameForRuntimeId(uint32_t idx) {
      75           2 :   switch (idx) {
      76             : #define CASE(name, nargs, ressize) \
      77             :   case Runtime::k##name:           \
      78             :     return #name;                  \
      79             :   case Runtime::kInline##name:     \
      80             :     return "_" #name;
      81           0 :     FOR_EACH_INTRINSIC(CASE)
      82             : #undef CASE
      83             :     default:
      84           0 :       UNREACHABLE();
      85             :   }
      86             : }
      87             : 
      88           1 : const char* NameForNativeContextIndex(uint32_t idx) {
      89           1 :   switch (idx) {
      90             : #define CASE(index_name, type, name) \
      91             :   case Context::index_name:          \
      92             :     return #name;
      93           0 :     NATIVE_CONTEXT_FIELDS(CASE)
      94             : #undef CASE
      95             :     default:
      96           0 :       UNREACHABLE();
      97             :   }
      98             : }
      99             : 
     100             : }  // anonymous namespace
     101             : 
     102             : // static
     103          69 : std::ostream& BytecodeDecoder::Decode(std::ostream& os,
     104             :                                       const uint8_t* bytecode_start,
     105             :                                       int parameter_count) {
     106          69 :   Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
     107             :   int prefix_offset = 0;
     108             :   OperandScale operand_scale = OperandScale::kSingle;
     109          69 :   if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
     110             :     prefix_offset = 1;
     111           8 :     operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
     112           8 :     bytecode = Bytecodes::FromByte(bytecode_start[1]);
     113             :   }
     114             : 
     115             :   // Prepare to print bytecode and operands as hex digits.
     116          69 :   std::ios saved_format(nullptr);
     117          69 :   saved_format.copyfmt(saved_format);
     118          69 :   os.fill('0');
     119          69 :   os.flags(std::ios::hex);
     120             : 
     121             :   int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
     122         239 :   for (int i = 0; i < prefix_offset + bytecode_size; i++) {
     123         170 :     os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
     124             :   }
     125          69 :   os.copyfmt(saved_format);
     126             : 
     127             :   const int kBytecodeColumnSize = 6;
     128         320 :   for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
     129         251 :     os << "   ";
     130             :   }
     131             : 
     132         207 :   os << Bytecodes::ToString(bytecode, operand_scale) << " ";
     133             : 
     134             :   // Operands for the debug break are from the original instruction.
     135          69 :   if (Bytecodes::IsDebugBreak(bytecode)) return os;
     136             : 
     137             :   int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
     138         137 :   for (int i = 0; i < number_of_operands; i++) {
     139             :     OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
     140             :     int operand_offset =
     141          68 :         Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
     142             :     const uint8_t* operand_start =
     143          68 :         &bytecode_start[prefix_offset + operand_offset];
     144          68 :     switch (op_type) {
     145             :       case interpreter::OperandType::kIdx:
     146             :       case interpreter::OperandType::kUImm:
     147          20 :         os << "["
     148          20 :            << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
     149          20 :            << "]";
     150          20 :         break;
     151             :       case interpreter::OperandType::kIntrinsicId: {
     152             :         auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
     153           0 :             DecodeUnsignedOperand(operand_start, op_type, operand_scale));
     154           0 :         os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
     155           0 :         break;
     156             :       }
     157             :       case interpreter::OperandType::kNativeContextIndex: {
     158           1 :         auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
     159           1 :         os << "[" << NameForNativeContextIndex(id) << "]";
     160           1 :         break;
     161             :       }
     162             :       case interpreter::OperandType::kRuntimeId:
     163           2 :         os << "[" << NameForRuntimeId(DecodeUnsignedOperand(
     164           4 :                          operand_start, op_type, operand_scale))
     165           2 :            << "]";
     166           2 :         break;
     167             :       case interpreter::OperandType::kImm:
     168          10 :         os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
     169          10 :            << "]";
     170          10 :         break;
     171             :       case interpreter::OperandType::kFlag8:
     172           1 :         os << "#"
     173           1 :            << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
     174             :         break;
     175             :       case interpreter::OperandType::kReg:
     176             :       case interpreter::OperandType::kRegOut: {
     177             :         Register reg =
     178          29 :             DecodeRegisterOperand(operand_start, op_type, operand_scale);
     179          58 :         os << reg.ToString(parameter_count);
     180             :         break;
     181             :       }
     182             :       case interpreter::OperandType::kRegOutTriple: {
     183             :         RegisterList reg_list =
     184             :             DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
     185           3 :         os << reg_list.first_register().ToString(parameter_count) << "-"
     186           2 :            << reg_list.last_register().ToString(parameter_count);
     187             :         break;
     188             :       }
     189             :       case interpreter::OperandType::kRegOutPair:
     190             :       case interpreter::OperandType::kRegPair: {
     191             :         RegisterList reg_list =
     192             :             DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
     193           0 :         os << reg_list.first_register().ToString(parameter_count) << "-"
     194           0 :            << reg_list.last_register().ToString(parameter_count);
     195             :         break;
     196             :       }
     197             :       case interpreter::OperandType::kRegOutList:
     198             :       case interpreter::OperandType::kRegList: {
     199             :         DCHECK_LT(i, number_of_operands - 1);
     200             :         DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
     201             :                   OperandType::kRegCount);
     202             :         int reg_count_offset =
     203           4 :             Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
     204             :         const uint8_t* reg_count_operand =
     205           4 :             &bytecode_start[prefix_offset + reg_count_offset];
     206             :         uint32_t count = DecodeUnsignedOperand(
     207           4 :             reg_count_operand, OperandType::kRegCount, operand_scale);
     208             :         RegisterList reg_list = DecodeRegisterListOperand(
     209             :             operand_start, count, op_type, operand_scale);
     210          12 :         os << reg_list.first_register().ToString(parameter_count) << "-"
     211           8 :            << reg_list.last_register().ToString(parameter_count);
     212             :         i++;  // Skip kRegCount.
     213             :         break;
     214             :       }
     215             :       case interpreter::OperandType::kNone:
     216             :       case interpreter::OperandType::kRegCount:  // Dealt with in kRegList.
     217           0 :         UNREACHABLE();
     218             :         break;
     219             :     }
     220          68 :     if (i != number_of_operands - 1) {
     221          13 :       os << ", ";
     222             :     }
     223             :   }
     224             :   return os;
     225             : }
     226             : 
     227             : }  // namespace interpreter
     228             : }  // namespace internal
     229             : }  // namespace v8

Generated by: LCOV version 1.10