• 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,int parameter_count)95 std::ostream& BytecodeDecoder::Decode(std::ostream& os,
96                                       const uint8_t* bytecode_start,
97                                       int parameter_count) {
98   Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
99   int prefix_offset = 0;
100   OperandScale operand_scale = OperandScale::kSingle;
101   if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
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   std::ios saved_format(nullptr);
109   saved_format.copyfmt(saved_format);
110   os.fill('0');
111   os.flags(std::ios::hex);
112 
113   int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
114   for (int i = 0; i < prefix_offset + bytecode_size; i++) {
115     os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
116   }
117   os.copyfmt(saved_format);
118 
119   const int kBytecodeColumnSize = 6;
120   for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
121     os << "   ";
122   }
123 
124   os << Bytecodes::ToString(bytecode, operand_scale) << " ";
125 
126   // Operands for the debug break are from the original instruction.
127   if (Bytecodes::IsDebugBreak(bytecode)) return os;
128 
129   int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
130   for (int i = 0; i < number_of_operands; i++) {
131     OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
132     int operand_offset =
133         Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
134     Address operand_start = reinterpret_cast<Address>(
135         &bytecode_start[prefix_offset + operand_offset]);
136     switch (op_type) {
137       case interpreter::OperandType::kIdx:
138       case interpreter::OperandType::kUImm:
139         os << "["
140            << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
141            << "]";
142         break;
143       case interpreter::OperandType::kIntrinsicId: {
144         auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
145             DecodeUnsignedOperand(operand_start, op_type, operand_scale));
146         os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
147         break;
148       }
149       case interpreter::OperandType::kNativeContextIndex: {
150         auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
151         os << "[" << NameForNativeContextIndex(id) << "]";
152         break;
153       }
154       case interpreter::OperandType::kRuntimeId:
155         os << "["
156            << NameForRuntimeId(static_cast<Runtime::FunctionId>(
157                   DecodeUnsignedOperand(operand_start, op_type, operand_scale)))
158            << "]";
159         break;
160       case interpreter::OperandType::kImm:
161         os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
162            << "]";
163         break;
164       case interpreter::OperandType::kFlag8:
165         os << "#"
166            << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
167         break;
168       case interpreter::OperandType::kReg:
169       case interpreter::OperandType::kRegOut: {
170         Register reg =
171             DecodeRegisterOperand(operand_start, op_type, operand_scale);
172         os << reg.ToString(parameter_count);
173         break;
174       }
175       case interpreter::OperandType::kRegOutTriple: {
176         RegisterList reg_list =
177             DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
178         os << reg_list.first_register().ToString(parameter_count) << "-"
179            << reg_list.last_register().ToString(parameter_count);
180         break;
181       }
182       case interpreter::OperandType::kRegOutPair:
183       case interpreter::OperandType::kRegPair: {
184         RegisterList reg_list =
185             DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
186         os << reg_list.first_register().ToString(parameter_count) << "-"
187            << reg_list.last_register().ToString(parameter_count);
188         break;
189       }
190       case interpreter::OperandType::kRegOutList:
191       case interpreter::OperandType::kRegList: {
192         DCHECK_LT(i, number_of_operands - 1);
193         DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
194                   OperandType::kRegCount);
195         int reg_count_offset =
196             Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
197         Address reg_count_operand = reinterpret_cast<Address>(
198             &bytecode_start[prefix_offset + reg_count_offset]);
199         uint32_t count = DecodeUnsignedOperand(
200             reg_count_operand, OperandType::kRegCount, operand_scale);
201         RegisterList reg_list = DecodeRegisterListOperand(
202             operand_start, count, op_type, operand_scale);
203         os << reg_list.first_register().ToString(parameter_count) << "-"
204            << reg_list.last_register().ToString(parameter_count);
205         i++;  // Skip kRegCount.
206         break;
207       }
208       case interpreter::OperandType::kNone:
209       case interpreter::OperandType::kRegCount:  // Dealt with in kRegList.
210         UNREACHABLE();
211         break;
212     }
213     if (i != number_of_operands - 1) {
214       os << ", ";
215     }
216   }
217   return os;
218 }
219 
220 }  // namespace interpreter
221 }  // namespace internal
222 }  // namespace v8
223