| 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 |
| 44 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
| 45 switch (operand_size) { |
| 46 case OperandSize::kNone: |
| 47 return "None"; |
| 48 case OperandSize::kByte: |
| 49 return "Byte"; |
| 50 case OperandSize::kShort: |
| 51 return "Short"; |
| 52 } |
| 53 UNREACHABLE(); |
| 54 return ""; |
| 55 } |
| 56 |
| 57 |
| 58 // static |
| 57 uint8_t Bytecodes::ToByte(Bytecode bytecode) { | 59 uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
| 58 return static_cast<uint8_t>(bytecode); | 60 return static_cast<uint8_t>(bytecode); |
| 59 } | 61 } |
| 60 | 62 |
| 61 | 63 |
| 62 // static | 64 // static |
| 63 Bytecode Bytecodes::FromByte(uint8_t value) { | 65 Bytecode Bytecodes::FromByte(uint8_t value) { |
| 64 Bytecode bytecode = static_cast<Bytecode>(value); | 66 Bytecode bytecode = static_cast<Bytecode>(value); |
| 65 DCHECK(bytecode <= Bytecode::kLast); | 67 DCHECK(bytecode <= Bytecode::kLast); |
| 66 return bytecode; | 68 return bytecode; |
| 67 } | 69 } |
| 68 | 70 |
| 69 | 71 |
| 70 // static | 72 // static |
| 73 int Bytecodes::Size(Bytecode bytecode) { |
| 74 DCHECK(bytecode <= Bytecode::kLast); |
| 75 switch (bytecode) { |
| 76 #define CASE(Name, ...) \ |
| 77 case Bytecode::k##Name: \ |
| 78 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; |
| 79 BYTECODE_LIST(CASE) |
| 80 #undef CASE |
| 81 } |
| 82 UNREACHABLE(); |
| 83 return 0; |
| 84 } |
| 85 |
| 86 |
| 87 // static |
| 71 int Bytecodes::NumberOfOperands(Bytecode bytecode) { | 88 int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
| 72 DCHECK(bytecode <= Bytecode::kLast); | 89 DCHECK(bytecode <= Bytecode::kLast); |
| 73 int count; | 90 switch (bytecode) { |
| 74 uint8_t row = ToByte(bytecode); | 91 #define CASE(Name, ...) \ |
| 75 for (count = 0; count < kMaxOperands; count++) { | 92 case Bytecode::k##Name: \ |
| 76 if (kBytecodeTable[row][count] == OperandType::kNone) { | 93 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; |
| 77 break; | 94 BYTECODE_LIST(CASE) |
| 78 } | 95 #undef CASE |
| 79 } | 96 } |
| 80 return count; | 97 UNREACHABLE(); |
| 98 return 0; |
| 81 } | 99 } |
| 82 | 100 |
| 83 | 101 |
| 84 // static | 102 // static |
| 85 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 103 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
| 86 DCHECK(bytecode <= Bytecode::kLast && i < NumberOfOperands(bytecode)); | 104 DCHECK(bytecode <= Bytecode::kLast); |
| 87 return kBytecodeTable[ToByte(bytecode)][i]; | 105 switch (bytecode) { |
| 106 #define CASE(Name, ...) \ |
| 107 case Bytecode::k##Name: \ |
| 108 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandType(i); |
| 109 BYTECODE_LIST(CASE) |
| 110 #undef CASE |
| 111 } |
| 112 UNREACHABLE(); |
| 113 return OperandType::kNone; |
| 88 } | 114 } |
| 89 | 115 |
| 90 | 116 |
| 91 // static | 117 // static |
| 92 int Bytecodes::Size(Bytecode bytecode) { | 118 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { |
| 93 return 1 + NumberOfOperands(bytecode); | 119 DCHECK(bytecode <= Bytecode::kLast); |
| 120 switch (bytecode) { |
| 121 #define CASE(Name, ...) \ |
| 122 case Bytecode::k##Name: \ |
| 123 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); |
| 124 BYTECODE_LIST(CASE) |
| 125 #undef CASE |
| 126 } |
| 127 UNREACHABLE(); |
| 128 return OperandSize::kNone; |
| 94 } | 129 } |
| 95 | 130 |
| 96 | 131 |
| 97 // static | 132 // static |
| 98 int Bytecodes::MaximumNumberOfOperands() { return kMaxOperands; } | 133 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { |
| 134 DCHECK(bytecode <= Bytecode::kLast); |
| 135 switch (bytecode) { |
| 136 #define CASE(Name, ...) \ |
| 137 case Bytecode::k##Name: \ |
| 138 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); |
| 139 BYTECODE_LIST(CASE) |
| 140 #undef CASE |
| 141 } |
| 142 UNREACHABLE(); |
| 143 return 0; |
| 144 } |
| 99 | 145 |
| 100 | 146 |
| 101 // static | 147 // static |
| 102 int Bytecodes::MaximumSize() { return 1 + kMaxOperands; } | 148 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { |
| 149 switch (operand_type) { |
| 150 #define CASE(Name, Size) \ |
| 151 case OperandType::k##Name: \ |
| 152 return Size; |
| 153 OPERAND_TYPE_LIST(CASE) |
| 154 #undef CASE |
| 155 } |
| 156 UNREACHABLE(); |
| 157 return OperandSize::kNone; |
| 158 } |
| 103 | 159 |
| 104 | 160 |
| 105 // static | 161 // static |
| 106 bool Bytecodes::IsJump(Bytecode bytecode) { | 162 bool Bytecodes::IsJump(Bytecode bytecode) { |
| 107 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpIfTrue || | 163 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpIfTrue || |
| 108 bytecode == Bytecode::kJumpIfFalse; | 164 bytecode == Bytecode::kJumpIfFalse; |
| 109 } | 165 } |
| 110 | 166 |
| 111 | 167 |
| 112 // static | 168 // static |
| 113 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 169 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
| 114 return bytecode == Bytecode::kJumpConstant || | 170 return bytecode == Bytecode::kJumpConstant || |
| 115 bytecode == Bytecode::kJumpIfTrueConstant || | 171 bytecode == Bytecode::kJumpIfTrueConstant || |
| 116 bytecode == Bytecode::kJumpIfFalseConstant; | 172 bytecode == Bytecode::kJumpIfFalseConstant; |
| 117 } | 173 } |
| 118 | 174 |
| 119 | 175 |
| 120 // static | 176 // static |
| 177 uint16_t Bytecodes::ShortOperandFromBytes(const uint8_t* bytes) { |
| 178 return *reinterpret_cast<const uint16_t*>(bytes); |
| 179 } |
| 180 |
| 181 |
| 182 // static |
| 183 void Bytecodes::ShortOperandToBytes(uint16_t operand, uint8_t* bytes_out) { |
| 184 *reinterpret_cast<uint16_t*>(bytes_out) = operand; |
| 185 } |
| 186 |
| 187 |
| 188 // static |
| 121 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, | 189 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
| 122 int parameter_count) { | 190 int parameter_count) { |
| 123 Vector<char> buf = Vector<char>::New(50); | 191 Vector<char> buf = Vector<char>::New(50); |
| 124 | 192 |
| 125 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); | 193 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
| 126 int bytecode_size = Bytecodes::Size(bytecode); | 194 int bytecode_size = Bytecodes::Size(bytecode); |
| 127 | 195 |
| 128 for (int i = 0; i < bytecode_size; i++) { | 196 for (int i = 0; i < bytecode_size; i++) { |
| 129 SNPrintF(buf, "%02x ", bytecode_start[i]); | 197 SNPrintF(buf, "%02x ", bytecode_start[i]); |
| 130 os << buf.start(); | 198 os << buf.start(); |
| 131 } | 199 } |
| 132 for (int i = bytecode_size; i < Bytecodes::MaximumSize(); i++) { | 200 const int kBytecodeColumnSize = 6; |
| 201 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { |
| 133 os << " "; | 202 os << " "; |
| 134 } | 203 } |
| 135 | 204 |
| 136 os << bytecode << " "; | 205 os << bytecode << " "; |
| 137 | 206 |
| 138 const uint8_t* operands_start = bytecode_start + 1; | 207 int number_of_operands = NumberOfOperands(bytecode); |
| 139 int operands_size = bytecode_size - 1; | 208 for (int i = 0; i < number_of_operands; i++) { |
| 140 for (int i = 0; i < operands_size; i++) { | |
| 141 OperandType op_type = GetOperandType(bytecode, i); | 209 OperandType op_type = GetOperandType(bytecode, i); |
| 142 uint8_t operand = operands_start[i]; | 210 const uint8_t* operand_start = |
| 211 &bytecode_start[GetOperandOffset(bytecode, i)]; |
| 143 switch (op_type) { | 212 switch (op_type) { |
| 144 case interpreter::OperandType::kCount: | 213 case interpreter::OperandType::kCount8: |
| 145 os << "#" << static_cast<unsigned int>(operand); | 214 os << "#" << static_cast<unsigned int>(*operand_start); |
| 146 break; | 215 break; |
| 147 case interpreter::OperandType::kIdx: | 216 case interpreter::OperandType::kIdx8: |
| 148 os << "[" << static_cast<unsigned int>(operand) << "]"; | 217 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; |
| 149 break; | 218 break; |
| 219 case interpreter::OperandType::kIdx16: { |
| 220 os << "[" << Bytecodes::ShortOperandFromBytes(operand_start) << "]"; |
| 221 break; |
| 222 } |
| 150 case interpreter::OperandType::kImm8: | 223 case interpreter::OperandType::kImm8: |
| 151 os << "#" << static_cast<int>(static_cast<int8_t>(operand)); | 224 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); |
| 152 break; | 225 break; |
| 153 case interpreter::OperandType::kReg: { | 226 case interpreter::OperandType::kReg8: { |
| 154 Register reg = Register::FromOperand(operand); | 227 Register reg = Register::FromOperand(*operand_start); |
| 155 if (reg.is_parameter()) { | 228 if (reg.is_parameter()) { |
| 156 int parameter_index = reg.ToParameterIndex(parameter_count); | 229 int parameter_index = reg.ToParameterIndex(parameter_count); |
| 157 if (parameter_index == 0) { | 230 if (parameter_index == 0) { |
| 158 os << "<this>"; | 231 os << "<this>"; |
| 159 } else { | 232 } else { |
| 160 os << "a" << parameter_index - 1; | 233 os << "a" << parameter_index - 1; |
| 161 } | 234 } |
| 162 } else { | 235 } else { |
| 163 os << "r" << reg.index(); | 236 os << "r" << reg.index(); |
| 164 } | 237 } |
| 165 break; | 238 break; |
| 166 } | 239 } |
| 167 case interpreter::OperandType::kNone: | 240 case interpreter::OperandType::kNone: |
| 168 UNREACHABLE(); | 241 UNREACHABLE(); |
| 169 break; | 242 break; |
| 170 } | 243 } |
| 171 if (i != operands_size - 1) { | 244 if (i != number_of_operands - 1) { |
| 172 os << ", "; | 245 os << ", "; |
| 173 } | 246 } |
| 174 } | 247 } |
| 175 return os; | 248 return os; |
| 176 } | 249 } |
| 177 | 250 |
| 178 | 251 |
| 179 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { | 252 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
| 180 return os << Bytecodes::ToString(bytecode); | 253 return os << Bytecodes::ToString(bytecode); |
| 181 } | 254 } |
| 182 | 255 |
| 183 | 256 |
| 184 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { | 257 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
| 185 return os << Bytecodes::OperandTypeToString(operand_type); | 258 return os << Bytecodes::OperandTypeToString(operand_type); |
| 186 } | 259 } |
| 187 | 260 |
| 188 | 261 |
| 262 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
| 263 return os << Bytecodes::OperandSizeToString(operand_size); |
| 264 } |
| 265 |
| 266 |
| 189 static const int kLastParamRegisterIndex = | 267 static const int kLastParamRegisterIndex = |
| 190 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 268 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
| 191 | 269 |
| 192 | 270 |
| 193 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values. | 271 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values. |
| 194 // Parameter indices are biased with the negative value kLastParamRegisterIndex | 272 // Parameter indices are biased with the negative value kLastParamRegisterIndex |
| 195 // for ease of access in the interpreter. | 273 // for ease of access in the interpreter. |
| 196 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex; | 274 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex; |
| 197 | 275 |
| 198 | 276 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 219 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } | 297 uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); } |
| 220 | 298 |
| 221 | 299 |
| 222 Register Register::FromOperand(uint8_t operand) { | 300 Register Register::FromOperand(uint8_t operand) { |
| 223 return Register(-static_cast<int8_t>(operand)); | 301 return Register(-static_cast<int8_t>(operand)); |
| 224 } | 302 } |
| 225 | 303 |
| 226 } // namespace interpreter | 304 } // namespace interpreter |
| 227 } // namespace internal | 305 } // namespace internal |
| 228 } // namespace v8 | 306 } // namespace v8 |
| OLD | NEW |