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