v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
bytecode-decoder.cc
Go to the documentation of this file.
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
6
7#include <iomanip>
8
12
13namespace v8 {
14namespace internal {
15namespace interpreter {
16
17// static
19 OperandType operand_type,
20 OperandScale operand_scale) {
22 int32_t operand =
23 DecodeSignedOperand(operand_start, operand_type, operand_scale);
24 return Register::FromOperand(operand);
25}
26
27// static
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
38 OperandType operand_type,
39 OperandScale operand_scale) {
41 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
43 return *reinterpret_cast<const int8_t*>(operand_start);
45 return static_cast<int16_t>(
48 return static_cast<int32_t>(
52 }
53 return 0;
54}
55
56// static
58 OperandType operand_type,
59 OperandScale operand_scale) {
61 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
63 return *reinterpret_cast<const uint8_t*>(operand_start);
65 return base::ReadUnalignedValue<uint16_t>(operand_start);
67 return base::ReadUnalignedValue<uint32_t>(operand_start);
70 }
71 return 0;
72}
73
74namespace {
75
76const char* NameForRuntimeId(Runtime::FunctionId idx) {
77 return Runtime::FunctionForId(idx)->name;
78}
79
80const char* NameForNativeContextIndex(uint32_t idx) {
81 switch (idx) {
82#define CASE(index_name, type, name) \
83 case Context::index_name: \
84 return #name;
86#undef CASE
87 default:
89 }
90}
91
92} // anonymous namespace
93
94// static
95std::ostream& BytecodeDecoder::Decode(std::ostream& os,
96 const uint8_t* bytecode_start,
97 bool with_hex) {
98 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
99 int prefix_offset = 0;
100 OperandScale operand_scale = OperandScale::kSingle;
102 prefix_offset = 1;
103 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
104 bytecode = Bytecodes::FromByte(bytecode_start[1]);
105 }
106
107 // Prepare to print bytecode and operands as hex digits.
108 if (with_hex) {
109 std::ios saved_format(nullptr);
110 saved_format.copyfmt(saved_format);
111 os.fill('0');
112 os.flags(std::ios::hex);
113
114 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
115 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
116 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
117 }
118 os.copyfmt(saved_format);
119
120 const int kBytecodeColumnSize = 6;
121 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
122 os << " ";
123 }
124 }
125
126 os << Bytecodes::ToString(bytecode, operand_scale);
127
128 // Operands for the debug break are from the original instruction.
129 if (Bytecodes::IsDebugBreak(bytecode)) return os;
130
131 int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
132 if (number_of_operands > 0) os << " ";
133 for (int i = 0; i < number_of_operands; i++) {
134 OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
135 int operand_offset =
136 Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
137 Address operand_start = reinterpret_cast<Address>(
138 &bytecode_start[prefix_offset + operand_offset]);
139 switch (op_type) {
140 case interpreter::OperandType::kIdx:
141 case interpreter::OperandType::kUImm:
142 os << "["
143 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
144 << "]";
145 break;
146 case interpreter::OperandType::kIntrinsicId: {
147 auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
148 DecodeUnsignedOperand(operand_start, op_type, operand_scale));
149 os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
150 break;
151 }
152 case interpreter::OperandType::kNativeContextIndex: {
153 auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
154 os << "[" << NameForNativeContextIndex(id) << "]";
155 break;
156 }
157 case interpreter::OperandType::kRuntimeId:
158 os << "["
159 << NameForRuntimeId(static_cast<Runtime::FunctionId>(
160 DecodeUnsignedOperand(operand_start, op_type, operand_scale)))
161 << "]";
162 break;
163 case interpreter::OperandType::kImm:
164 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
165 << "]";
166 break;
167 case interpreter::OperandType::kFlag8:
168 case interpreter::OperandType::kFlag16:
169 os << "#"
170 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
171 break;
172 case interpreter::OperandType::kReg:
173 case interpreter::OperandType::kRegOut:
174 case interpreter::OperandType::kRegInOut: {
175 Register reg =
176 DecodeRegisterOperand(operand_start, op_type, operand_scale);
177 os << reg.ToString();
178 break;
179 }
180 case interpreter::OperandType::kRegOutTriple: {
181 RegisterList reg_list =
182 DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
183 os << reg_list.first_register().ToString() << "-"
184 << reg_list.last_register().ToString();
185 break;
186 }
187 case interpreter::OperandType::kRegOutPair:
188 case interpreter::OperandType::kRegPair: {
189 RegisterList reg_list =
190 DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
191 os << reg_list.first_register().ToString() << "-"
192 << reg_list.last_register().ToString();
193 break;
194 }
195 case interpreter::OperandType::kRegOutList:
196 case interpreter::OperandType::kRegList: {
197 DCHECK_LT(i, number_of_operands - 1);
199 OperandType::kRegCount);
200 int reg_count_offset =
201 Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
202 Address reg_count_operand = reinterpret_cast<Address>(
203 &bytecode_start[prefix_offset + reg_count_offset]);
204 uint32_t count = DecodeUnsignedOperand(
205 reg_count_operand, OperandType::kRegCount, operand_scale);
207 operand_start, count, op_type, operand_scale);
208 os << reg_list.first_register().ToString() << "-"
209 << reg_list.last_register().ToString();
210 i++; // Skip kRegCount.
211 break;
212 }
213 case interpreter::OperandType::kNone:
214 case interpreter::OperandType::kRegCount: // Dealt with in kRegList.
215 UNREACHABLE();
216 }
217 if (i != number_of_operands - 1) {
218 os << ", ";
219 }
220 }
221 return os;
222}
223
224} // namespace interpreter
225} // namespace internal
226} // namespace v8
static V8_EXPORT_PRIVATE const Function * FunctionForId(FunctionId id)
Definition runtime.cc:350
static int32_t DecodeSignedOperand(Address operand_start, OperandType operand_type, OperandScale operand_scale)
static RegisterList DecodeRegisterListOperand(Address operand_start, uint32_t count, OperandType operand_type, OperandScale operand_scale)
static uint32_t DecodeUnsignedOperand(Address operand_start, OperandType operand_type, OperandScale operand_scale)
static Register DecodeRegisterOperand(Address operand_start, OperandType operand_type, OperandScale operand_scale)
static std::ostream & Decode(std::ostream &os, const uint8_t *bytecode_start, bool with_hex=true)
static Bytecode FromByte(uint8_t value)
Definition bytecodes.h:624
static OperandScale PrefixBytecodeToOperandScale(Bytecode bytecode)
Definition bytecodes.h:650
static int GetOperandOffset(Bytecode bytecode, int i, OperandScale operand_scale)
Definition bytecodes.h:951
static bool IsDebugBreak(Bytecode bytecode)
Definition bytecodes.cc:167
static bool IsRegisterOperandType(OperandType operand_type)
Definition bytecodes.cc:180
static OperandSize SizeOfOperand(OperandType operand_type, OperandScale operand_scale)
Definition bytecodes.h:1050
static OperandType GetOperandType(Bytecode bytecode, int i)
Definition bytecodes.h:894
static int Size(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.h:964
static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode)
Definition bytecodes.h:865
static int NumberOfOperands(Bytecode bytecode)
Definition bytecodes.h:886
static bool IsUnsignedOperandType(OperandType operand_type)
Definition bytecodes.cc:321
static const char * ToString(Bytecode bytecode)
Definition bytecodes.cc:123
static Runtime::FunctionId ToRuntimeId(IntrinsicId intrinsic_id)
static constexpr Register FromOperand(int32_t operand)
#define NATIVE_CONTEXT_FIELDS(V)
Definition contexts.h:46
LiftoffRegister reg
static V ReadUnalignedValue(Address p)
Definition memory.h:28
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485