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
|