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