| 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 |