OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
| 8 #include "src/interpreter/bytecode-traits.h" |
8 | 9 |
9 namespace v8 { | 10 namespace v8 { |
10 namespace internal { | 11 namespace internal { |
11 namespace interpreter { | 12 namespace interpreter { |
12 | 13 |
13 // Maximum number of operands a bytecode may have. | |
14 static const int kMaxOperands = 3; | |
15 | |
16 // kBytecodeTable relies on kNone being the same as zero to detect length. | |
17 STATIC_ASSERT(static_cast<int>(OperandType::kNone) == 0); | |
18 | |
19 static const OperandType kBytecodeTable[][kMaxOperands] = { | |
20 #define DECLARE_OPERAND(_, ...) \ | |
21 { __VA_ARGS__ } \ | |
22 , | |
23 BYTECODE_LIST(DECLARE_OPERAND) | |
24 #undef DECLARE_OPERAND | |
25 }; | |
26 | |
27 | 14 |
28 // static | 15 // static |
29 const char* Bytecodes::ToString(Bytecode bytecode) { | 16 const char* Bytecodes::ToString(Bytecode bytecode) { |
30 switch (bytecode) { | 17 switch (bytecode) { |
31 #define CASE(Name, ...) \ | 18 #define CASE(Name, ...) \ |
32 case Bytecode::k##Name: \ | 19 case Bytecode::k##Name: \ |
33 return #Name; | 20 return #Name; |
34 BYTECODE_LIST(CASE) | 21 BYTECODE_LIST(CASE) |
35 #undef CASE | 22 #undef CASE |
36 } | 23 } |
37 UNREACHABLE(); | 24 UNREACHABLE(); |
38 return ""; | 25 return ""; |
39 } | 26 } |
40 | 27 |
41 | 28 |
42 // static | 29 // static |
43 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { | 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
44 switch (operand_type) { | 31 switch (operand_type) { |
45 #define CASE(Name) \ | 32 #define CASE(Name, _) \ |
46 case OperandType::k##Name: \ | 33 case OperandType::k##Name: \ |
47 return #Name; | 34 return #Name; |
48 OPERAND_TYPE_LIST(CASE) | 35 OPERAND_TYPE_LIST(CASE) |
49 #undef CASE | 36 #undef CASE |
50 } | 37 } |
51 UNREACHABLE(); | 38 UNREACHABLE(); |
52 return ""; | 39 return ""; |
53 } | 40 } |
54 | 41 |
55 | 42 |
56 // static | 43 // static |
57 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 44 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
58 return static_cast<uint8_t>(bytecode); | 45 return static_cast<uint8_t>(bytecode); |
59 } | 46 } |
60 | 47 |
61 | 48 |
62 // static | 49 // static |
63 Bytecode Bytecodes::FromByte(uint8_t value) { | 50 Bytecode Bytecodes::FromByte(uint8_t value) { |
64 Bytecode bytecode = static_cast<Bytecode>(value); | 51 Bytecode bytecode = static_cast<Bytecode>(value); |
65 DCHECK(bytecode <= Bytecode::kLast); | 52 DCHECK(bytecode <= Bytecode::kLast); |
66 return bytecode; | 53 return bytecode; |
67 } | 54 } |
68 | 55 |
69 | 56 |
70 // static | 57 // static |
| 58 int Bytecodes::Size(Bytecode bytecode) { |
| 59 DCHECK(bytecode <= Bytecode::kLast); |
| 60 switch (bytecode) { |
| 61 #define CASE(Name, ...) \ |
| 62 case Bytecode::k##Name: \ |
| 63 return internal::BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; |
| 64 BYTECODE_LIST(CASE) |
| 65 #undef CASE |
| 66 } |
| 67 UNREACHABLE(); |
| 68 return 0; |
| 69 } |
| 70 |
| 71 |
| 72 // static |
71 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 73 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
72 DCHECK(bytecode <= Bytecode::kLast); | 74 DCHECK(bytecode <= Bytecode::kLast); |
73 int count; | 75 switch (bytecode) { |
74 uint8_t row = ToByte(bytecode); | 76 #define CASE(Name, ...) \ |
75 for (count = 0; count < kMaxOperands; count++) { | 77 case Bytecode::k##Name: \ |
76 if (kBytecodeTable[row][count] == OperandType::kNone) { | 78 return internal::BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; |
77 break; | 79 BYTECODE_LIST(CASE) |
78 } | 80 #undef CASE |
79 } | 81 } |
80 return count; | 82 UNREACHABLE(); |
| 83 return 0; |
81 } | 84 } |
82 | 85 |
83 | 86 |
84 // static | 87 // static |
85 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 88 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
86 DCHECK(bytecode <= Bytecode::kLast && i < NumberOfOperands(bytecode)); | 89 DCHECK(bytecode <= Bytecode::kLast); |
87 return kBytecodeTable[ToByte(bytecode)][i]; | 90 switch (bytecode) { |
| 91 #define CASE(Name, ...) \ |
| 92 case Bytecode::k##Name: \ |
| 93 return internal::BytecodeTraits<__VA_ARGS__, \ |
| 94 OPERAND_TERM>::GetOperandType(i); |
| 95 BYTECODE_LIST(CASE) |
| 96 #undef CASE |
| 97 } |
| 98 UNREACHABLE(); |
| 99 return OperandType::kNone; |
88 } | 100 } |
89 | 101 |
90 | 102 |
91 // static | 103 // static |
92 int Bytecodes::Size(Bytecode bytecode) { | 104 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { |
93 return 1 + NumberOfOperands(bytecode); | 105 DCHECK(bytecode <= Bytecode::kLast); |
| 106 switch (bytecode) { |
| 107 #define CASE(Name, ...) \ |
| 108 case Bytecode::k##Name: \ |
| 109 return internal::BytecodeTraits<__VA_ARGS__, \ |
| 110 OPERAND_TERM>::GetOperandOffset(i); |
| 111 BYTECODE_LIST(CASE) |
| 112 #undef CASE |
| 113 } |
| 114 UNREACHABLE(); |
| 115 return 0; |
94 } | 116 } |
95 | 117 |
96 | 118 |
97 // static | 119 // static |
98 int Bytecodes::MaximumNumberOfOperands() { return kMaxOperands; } | 120 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { |
| 121 switch (operand_type) { |
| 122 #define CASE(Name, Size) \ |
| 123 case OperandType::k##Name: \ |
| 124 return Size; |
| 125 OPERAND_TYPE_LIST(CASE) |
| 126 #undef CASE |
| 127 } |
| 128 UNREACHABLE(); |
| 129 return OperandSize::kNone; |
| 130 } |
99 | 131 |
100 | 132 |
101 // static | 133 // static |
102 int Bytecodes::MaximumSize() { return 1 + kMaxOperands; } | 134 uint16_t Bytecodes::WideOperandFromBytes(const uint8_t* bytes) { |
| 135 return *reinterpret_cast<const uint16_t*>(bytes); |
| 136 } |
103 | 137 |
104 | 138 |
105 // static | 139 // static |
| 140 void Bytecodes::WideOperandToBytes(uint16_t operand, uint8_t* bytes_out) { |
| 141 *reinterpret_cast<uint16_t*>(bytes_out) = operand; |
| 142 } |
| 143 |
| 144 |
| 145 // static |
106 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 146 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
107 int parameter_count) { | 147 int parameter_count) { |
108 Vector<char> buf = Vector<char>::New(50); | 148 Vector<char> buf = Vector<char>::New(50); |
109 | 149 |
110 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); | 150 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
111 int bytecode_size = Bytecodes::Size(bytecode); | 151 int bytecode_size = Bytecodes::Size(bytecode); |
112 | 152 |
113 for (int i = 0; i < bytecode_size; i++) { | 153 for (int i = 0; i < bytecode_size; i++) { |
114 SNPrintF(buf, "%02x ", bytecode_start[i]); | 154 SNPrintF(buf, "%02x ", bytecode_start[i]); |
115 os << buf.start(); | 155 os << buf.start(); |
116 } | 156 } |
117 for (int i = bytecode_size; i < Bytecodes::MaximumSize(); i++) { | 157 const int kBytecodeColumnSize = 6; |
| 158 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { |
118 os << " "; | 159 os << " "; |
119 } | 160 } |
120 | 161 |
121 os << bytecode << " "; | 162 os << bytecode << " "; |
122 | 163 |
123 const uint8_t* operands_start = bytecode_start + 1; | 164 int number_of_operands = NumberOfOperands(bytecode); |
124 int operands_size = bytecode_size - 1; | 165 for (int i = 0; i < number_of_operands; i++) { |
125 for (int i = 0; i < operands_size; i++) { | |
126 OperandType op_type = GetOperandType(bytecode, i); | 166 OperandType op_type = GetOperandType(bytecode, i); |
127 uint8_t operand = operands_start[i]; | 167 const uint8_t* operand_start = |
| 168 &bytecode_start[GetOperandOffset(bytecode, i)]; |
128 switch (op_type) { | 169 switch (op_type) { |
129 case interpreter::OperandType::kCount: | 170 case interpreter::OperandType::kCount: |
130 os << "#" << static_cast<unsigned int>(operand); | 171 os << "#" << static_cast<unsigned int>(*operand_start); |
131 break; | 172 break; |
132 case interpreter::OperandType::kIdx: | 173 case interpreter::OperandType::kIdx: |
133 os << "[" << static_cast<unsigned int>(operand) << "]"; | 174 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; |
134 break; | 175 break; |
| 176 case interpreter::OperandType::kWideIdx: { |
| 177 os << "[" << Bytecodes::WideOperandFromBytes(operand_start) << "]"; |
| 178 break; |
| 179 } |
135 case interpreter::OperandType::kImm8: | 180 case interpreter::OperandType::kImm8: |
136 os << "#" << static_cast<int>(static_cast<int8_t>(operand)); | 181 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); |
137 break; | 182 break; |
138 case interpreter::OperandType::kReg: { | 183 case interpreter::OperandType::kReg: { |
139 Register reg = Register::FromOperand(operand); | 184 Register reg = Register::FromOperand(*operand_start); |
140 if (reg.is_parameter()) { | 185 if (reg.is_parameter()) { |
141 int parameter_index = reg.ToParameterIndex(parameter_count); | 186 int parameter_index = reg.ToParameterIndex(parameter_count); |
142 if (parameter_index == 0) { | 187 if (parameter_index == 0) { |
143 os << "<this>"; | 188 os << "<this>"; |
144 } else { | 189 } else { |
145 os << "a" << parameter_index - 1; | 190 os << "a" << parameter_index - 1; |
146 } | 191 } |
147 } else { | 192 } else { |
148 os << "r" << reg.index(); | 193 os << "r" << reg.index(); |
149 } | 194 } |
150 break; | 195 break; |
151 } | 196 } |
152 case interpreter::OperandType::kNone: | 197 case interpreter::OperandType::kNone: |
153 UNREACHABLE(); | 198 UNREACHABLE(); |
154 break; | 199 break; |
155 } | 200 } |
156 if (i != operands_size - 1) { | 201 if (i != number_of_operands - 1) { |
157 os << ", "; | 202 os << ", "; |
158 } | 203 } |
159 } | 204 } |
160 return os; | 205 return os; |
161 } | 206 } |
162 | 207 |
163 | 208 |
164 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 209 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
165 return os << Bytecodes::ToString(bytecode); | 210 return os << Bytecodes::ToString(bytecode); |
166 } | 211 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } | 249 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } |
205 | 250 |
206 | 251 |
207 Register Register::FromOperand(uint8_t operand) { | 252 Register Register::FromOperand(uint8_t operand) { |
208 return Register(-static_cast<int8_t>(operand)); | 253 return Register(-static_cast<int8_t>(operand)); |
209 } | 254 } |
210 | 255 |
211 } // namespace interpreter | 256 } // namespace interpreter |
212 } // namespace internal | 257 } // namespace internal |
213 } // namespace v8 | 258 } // namespace v8 |
OLD | NEW |