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