bytecode-decoder.cc 8.09 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/interpreter/bytecode-decoder.h"

#include <iomanip>

9
#include "src/contexts.h"
10
#include "src/interpreter/interpreter-intrinsics.h"
11
#include "src/objects-inl.h"
12 13 14 15 16 17

namespace v8 {
namespace internal {
namespace interpreter {

// static
18
Register BytecodeDecoder::DecodeRegisterOperand(Address operand_start,
19 20 21 22 23 24 25 26
                                                OperandType operand_type,
                                                OperandScale operand_scale) {
  DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
  int32_t operand =
      DecodeSignedOperand(operand_start, operand_type, operand_scale);
  return Register::FromOperand(operand);
}

27 28
// static
RegisterList BytecodeDecoder::DecodeRegisterListOperand(
29
    Address operand_start, uint32_t count, OperandType operand_type,
30 31 32 33 34 35
    OperandScale operand_scale) {
  Register first_reg =
      DecodeRegisterOperand(operand_start, operand_type, operand_scale);
  return RegisterList(first_reg.index(), static_cast<int>(count));
}

36
// static
37
int32_t BytecodeDecoder::DecodeSignedOperand(Address operand_start,
38 39 40 41 42
                                             OperandType operand_type,
                                             OperandScale operand_scale) {
  DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
  switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
    case OperandSize::kByte:
43
      return *reinterpret_cast<const int8_t*>(operand_start);
44 45 46 47 48 49 50 51 52 53 54
    case OperandSize::kShort:
      return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
    case OperandSize::kQuad:
      return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
    case OperandSize::kNone:
      UNREACHABLE();
  }
  return 0;
}

// static
55
uint32_t BytecodeDecoder::DecodeUnsignedOperand(Address operand_start,
56 57 58 59 60
                                                OperandType operand_type,
                                                OperandScale operand_scale) {
  DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
  switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
    case OperandSize::kByte:
61
      return *reinterpret_cast<const uint8_t*>(operand_start);
62 63 64 65 66 67 68 69 70 71
    case OperandSize::kShort:
      return ReadUnalignedUInt16(operand_start);
    case OperandSize::kQuad:
      return ReadUnalignedUInt32(operand_start);
    case OperandSize::kNone:
      UNREACHABLE();
  }
  return 0;
}

72
namespace {
73

74 75 76 77 78 79
const char* NameForRuntimeId(uint32_t idx) {
  switch (idx) {
#define CASE(name, nargs, ressize) \
  case Runtime::k##name:           \
    return #name;                  \
  case Runtime::kInline##name:     \
80
    return "_" #name;
81 82 83 84 85 86
    FOR_EACH_INTRINSIC(CASE)
#undef CASE
    default:
      UNREACHABLE();
  }
}
87 88 89 90 91 92 93 94 95 96 97 98 99

const char* NameForNativeContextIndex(uint32_t idx) {
  switch (idx) {
#define CASE(index_name, type, name) \
  case Context::index_name:          \
    return #name;
    NATIVE_CONTEXT_FIELDS(CASE)
#undef CASE
    default:
      UNREACHABLE();
  }
}

100 101
}  // anonymous namespace

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
// static
std::ostream& BytecodeDecoder::Decode(std::ostream& os,
                                      const uint8_t* bytecode_start,
                                      int parameter_count) {
  Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
  int prefix_offset = 0;
  OperandScale operand_scale = OperandScale::kSingle;
  if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
    prefix_offset = 1;
    operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
    bytecode = Bytecodes::FromByte(bytecode_start[1]);
  }

  // Prepare to print bytecode and operands as hex digits.
  std::ios saved_format(nullptr);
  saved_format.copyfmt(saved_format);
  os.fill('0');
  os.flags(std::ios::hex);

  int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
  for (int i = 0; i < prefix_offset + bytecode_size; i++) {
    os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
  }
  os.copyfmt(saved_format);

  const int kBytecodeColumnSize = 6;
  for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
    os << "   ";
  }

  os << Bytecodes::ToString(bytecode, operand_scale) << " ";

  // Operands for the debug break are from the original instruction.
  if (Bytecodes::IsDebugBreak(bytecode)) return os;

  int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
  for (int i = 0; i < number_of_operands; i++) {
    OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
    int operand_offset =
        Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
142 143
    Address operand_start = reinterpret_cast<Address>(
        &bytecode_start[prefix_offset + operand_offset]);
144 145
    switch (op_type) {
      case interpreter::OperandType::kIdx:
146
      case interpreter::OperandType::kUImm:
147 148 149 150
        os << "["
           << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
           << "]";
        break;
151 152 153 154 155 156
      case interpreter::OperandType::kIntrinsicId: {
        auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
            DecodeUnsignedOperand(operand_start, op_type, operand_scale));
        os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
        break;
      }
157 158 159 160 161
      case interpreter::OperandType::kNativeContextIndex: {
        auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
        os << "[" << NameForNativeContextIndex(id) << "]";
        break;
      }
162 163 164 165 166
      case interpreter::OperandType::kRuntimeId:
        os << "[" << NameForRuntimeId(DecodeUnsignedOperand(
                         operand_start, op_type, operand_scale))
           << "]";
        break;
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
      case interpreter::OperandType::kImm:
        os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
           << "]";
        break;
      case interpreter::OperandType::kFlag8:
        os << "#"
           << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
        break;
      case interpreter::OperandType::kReg:
      case interpreter::OperandType::kRegOut: {
        Register reg =
            DecodeRegisterOperand(operand_start, op_type, operand_scale);
        os << reg.ToString(parameter_count);
        break;
      }
182 183 184 185 186 187 188
      case interpreter::OperandType::kRegOutTriple: {
        RegisterList reg_list =
            DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        break;
      }
189 190
      case interpreter::OperandType::kRegOutPair:
      case interpreter::OperandType::kRegPair: {
191 192 193 194 195 196
        RegisterList reg_list =
            DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        break;
      }
197
      case interpreter::OperandType::kRegOutList:
198 199 200 201 202 203
      case interpreter::OperandType::kRegList: {
        DCHECK_LT(i, number_of_operands - 1);
        DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
                  OperandType::kRegCount);
        int reg_count_offset =
            Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
204 205
        Address reg_count_operand = reinterpret_cast<Address>(
            &bytecode_start[prefix_offset + reg_count_offset]);
206 207 208 209 210 211 212
        uint32_t count = DecodeUnsignedOperand(
            reg_count_operand, OperandType::kRegCount, operand_scale);
        RegisterList reg_list = DecodeRegisterListOperand(
            operand_start, count, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        i++;  // Skip kRegCount.
213 214 215
        break;
      }
      case interpreter::OperandType::kNone:
216
      case interpreter::OperandType::kRegCount:  // Dealt with in kRegList.
217 218 219 220 221 222 223 224 225 226 227 228 229
        UNREACHABLE();
        break;
    }
    if (i != number_of_operands - 1) {
      os << ", ";
    }
  }
  return os;
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8