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
DecodeRegisterOperand(Address operand_start,OperandType operand_type,OperandScale operand_scale)18 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 DecodeSignedOperand(operand_start, operand_type, operand_scale);
24 return Register::FromOperand(operand);
25 }
26
27 // static
DecodeRegisterListOperand(Address operand_start,uint32_t count,OperandType operand_type,OperandScale operand_scale)28 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 return RegisterList(first_reg.index(), static_cast<int>(count));
34 }
35
36 // static
DecodeSignedOperand(Address operand_start,OperandType operand_type,OperandScale operand_scale)37 int32_t BytecodeDecoder::DecodeSignedOperand(Address operand_start,
38 OperandType operand_type,
39 OperandScale operand_scale) {
40 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
41 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
42 case OperandSize::kByte:
43 return *reinterpret_cast<const int8_t*>(operand_start);
44 case OperandSize::kShort:
45 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
46 case OperandSize::kQuad:
47 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
48 case OperandSize::kNone:
49 UNREACHABLE();
50 }
51 return 0;
52 }
53
54 // static
DecodeUnsignedOperand(Address operand_start,OperandType operand_type,OperandScale operand_scale)55 uint32_t BytecodeDecoder::DecodeUnsignedOperand(Address operand_start,
56 OperandType operand_type,
57 OperandScale operand_scale) {
58 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
59 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
60 case OperandSize::kByte:
61 return *reinterpret_cast<const uint8_t*>(operand_start);
62 case OperandSize::kShort:
63 return ReadUnalignedUInt16(operand_start);
64 case OperandSize::kQuad:
65 return ReadUnalignedUInt32(operand_start);
66 case OperandSize::kNone:
67 UNREACHABLE();
68 }
69 return 0;
70 }
71
72 namespace {
73
NameForRuntimeId(uint32_t idx)74 const char* NameForRuntimeId(uint32_t idx) {
75 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 FOR_EACH_INTRINSIC(CASE)
82 #undef CASE
83 default:
84 UNREACHABLE();
85 }
86 }
87
NameForNativeContextIndex(uint32_t idx)88 const char* NameForNativeContextIndex(uint32_t idx) {
89 switch (idx) {
90 #define CASE(index_name, type, name) \
91 case Context::index_name: \
92 return #name;
93 NATIVE_CONTEXT_FIELDS(CASE)
94 #undef CASE
95 default:
96 UNREACHABLE();
97 }
98 }
99
100 } // anonymous namespace
101
102 // static
Decode(std::ostream & os,const uint8_t * bytecode_start,int parameter_count)103 std::ostream& BytecodeDecoder::Decode(std::ostream& os,
104 const uint8_t* bytecode_start,
105 int parameter_count) {
106 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
107 int prefix_offset = 0;
108 OperandScale operand_scale = OperandScale::kSingle;
109 if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
110 prefix_offset = 1;
111 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
112 bytecode = Bytecodes::FromByte(bytecode_start[1]);
113 }
114
115 // Prepare to print bytecode and operands as hex digits.
116 std::ios saved_format(nullptr);
117 saved_format.copyfmt(saved_format);
118 os.fill('0');
119 os.flags(std::ios::hex);
120
121 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
122 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
123 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
124 }
125 os.copyfmt(saved_format);
126
127 const int kBytecodeColumnSize = 6;
128 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
129 os << " ";
130 }
131
132 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
133
134 // Operands for the debug break are from the original instruction.
135 if (Bytecodes::IsDebugBreak(bytecode)) return os;
136
137 int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
138 for (int i = 0; i < number_of_operands; i++) {
139 OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
140 int operand_offset =
141 Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
142 Address operand_start = reinterpret_cast<Address>(
143 &bytecode_start[prefix_offset + operand_offset]);
144 switch (op_type) {
145 case interpreter::OperandType::kIdx:
146 case interpreter::OperandType::kUImm:
147 os << "["
148 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
149 << "]";
150 break;
151 case interpreter::OperandType::kIntrinsicId: {
152 auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
153 DecodeUnsignedOperand(operand_start, op_type, operand_scale));
154 os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
155 break;
156 }
157 case interpreter::OperandType::kNativeContextIndex: {
158 auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
159 os << "[" << NameForNativeContextIndex(id) << "]";
160 break;
161 }
162 case interpreter::OperandType::kRuntimeId:
163 os << "[" << NameForRuntimeId(DecodeUnsignedOperand(
164 operand_start, op_type, operand_scale))
165 << "]";
166 break;
167 case interpreter::OperandType::kImm:
168 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
169 << "]";
170 break;
171 case interpreter::OperandType::kFlag8:
172 os << "#"
173 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
174 break;
175 case interpreter::OperandType::kReg:
176 case interpreter::OperandType::kRegOut: {
177 Register reg =
178 DecodeRegisterOperand(operand_start, op_type, operand_scale);
179 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 os << reg_list.first_register().ToString(parameter_count) << "-"
186 << 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 os << reg_list.first_register().ToString(parameter_count) << "-"
194 << 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 Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
204 Address reg_count_operand = reinterpret_cast<Address>(
205 &bytecode_start[prefix_offset + reg_count_offset]);
206 uint32_t count = DecodeUnsignedOperand(
207 reg_count_operand, OperandType::kRegCount, operand_scale);
208 RegisterList reg_list = DecodeRegisterListOperand(
209 operand_start, count, op_type, operand_scale);
210 os << reg_list.first_register().ToString(parameter_count) << "-"
211 << 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 UNREACHABLE();
218 break;
219 }
220 if (i != number_of_operands - 1) {
221 os << ", ";
222 }
223 }
224 return os;
225 }
226
227 } // namespace interpreter
228 } // namespace internal
229 } // namespace v8
230