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/bytecodes.h" 6 7 #include "src/frames.h" 8 #include "src/interpreter/bytecode-traits.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace interpreter { 13 14 15 // static 16 const char* Bytecodes::ToString(Bytecode bytecode) { 17 switch (bytecode) { 18 #define CASE(Name, ...) \ 19 case Bytecode::k##Name: \ 20 return #Name; 21 BYTECODE_LIST(CASE) 22 #undef CASE 23 } 24 UNREACHABLE(); 25 return ""; 26 } 27 28 29 // static 30 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { 31 switch (operand_type) { 32 #define CASE(Name, _) \ 33 case OperandType::k##Name: \ 34 return #Name; 35 OPERAND_TYPE_LIST(CASE) 36 #undef CASE 37 } 38 UNREACHABLE(); 39 return ""; 40 } 41 42 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 59 uint8_t Bytecodes::ToByte(Bytecode bytecode) { 60 return static_cast<uint8_t>(bytecode); 61 } 62 63 64 // static 65 Bytecode Bytecodes::FromByte(uint8_t value) { 66 Bytecode bytecode = static_cast<Bytecode>(value); 67 DCHECK(bytecode <= Bytecode::kLast); 68 return bytecode; 69 } 70 71 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 88 int Bytecodes::NumberOfOperands(Bytecode bytecode) { 89 DCHECK(bytecode <= Bytecode::kLast); 90 switch (bytecode) { 91 #define CASE(Name, ...) \ 92 case Bytecode::k##Name: \ 93 return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kOperandCount; 94 BYTECODE_LIST(CASE) 95 #undef CASE 96 } 97 UNREACHABLE(); 98 return 0; 99 } 100 101 102 // static 103 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { 104 DCHECK(bytecode <= Bytecode::kLast); 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; 114 } 115 116 117 // static 118 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { 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; 129 } 130 131 132 // static 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 } 145 146 147 // static 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 } 159 160 161 // static 162 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { 163 return bytecode == Bytecode::kJumpIfTrue || 164 bytecode == Bytecode::kJumpIfFalse || 165 bytecode == Bytecode::kJumpIfToBooleanTrue || 166 bytecode == Bytecode::kJumpIfToBooleanFalse || 167 bytecode == Bytecode::kJumpIfNull || 168 bytecode == Bytecode::kJumpIfUndefined; 169 } 170 171 172 // static 173 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { 174 return bytecode == Bytecode::kJumpIfTrueConstant || 175 bytecode == Bytecode::kJumpIfFalseConstant || 176 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || 177 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || 178 bytecode == Bytecode::kJumpIfNullConstant || 179 bytecode == Bytecode::kJumpIfUndefinedConstant; 180 } 181 182 183 // static 184 bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) { 185 return bytecode == Bytecode::kJumpIfTrueConstantWide || 186 bytecode == Bytecode::kJumpIfFalseConstantWide || 187 bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide || 188 bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide || 189 bytecode == Bytecode::kJumpIfNullConstantWide || 190 bytecode == Bytecode::kJumpIfUndefinedConstantWide; 191 } 192 193 194 // static 195 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { 196 return IsConditionalJumpImmediate(bytecode) || 197 IsConditionalJumpConstant(bytecode) || 198 IsConditionalJumpConstantWide(bytecode); 199 } 200 201 202 // static 203 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { 204 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); 205 } 206 207 208 // static 209 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { 210 return bytecode == Bytecode::kJumpConstant || 211 IsConditionalJumpConstant(bytecode); 212 } 213 214 215 // static 216 bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) { 217 return bytecode == Bytecode::kJumpConstantWide || 218 IsConditionalJumpConstantWide(bytecode); 219 } 220 221 222 // static 223 bool Bytecodes::IsJump(Bytecode bytecode) { 224 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) || 225 IsJumpConstantWide(bytecode); 226 } 227 228 229 // static 230 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { 231 return bytecode == Bytecode::kReturn || IsJump(bytecode); 232 } 233 234 235 // static 236 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, 237 int parameter_count) { 238 Vector<char> buf = Vector<char>::New(50); 239 240 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); 241 int bytecode_size = Bytecodes::Size(bytecode); 242 243 for (int i = 0; i < bytecode_size; i++) { 244 SNPrintF(buf, "%02x ", bytecode_start[i]); 245 os << buf.start(); 246 } 247 const int kBytecodeColumnSize = 6; 248 for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { 249 os << " "; 250 } 251 252 os << bytecode << " "; 253 254 int number_of_operands = NumberOfOperands(bytecode); 255 for (int i = 0; i < number_of_operands; i++) { 256 OperandType op_type = GetOperandType(bytecode, i); 257 const uint8_t* operand_start = 258 &bytecode_start[GetOperandOffset(bytecode, i)]; 259 switch (op_type) { 260 case interpreter::OperandType::kCount8: 261 os << "#" << static_cast<unsigned int>(*operand_start); 262 break; 263 case interpreter::OperandType::kCount16: 264 os << '#' << ReadUnalignedUInt16(operand_start); 265 break; 266 case interpreter::OperandType::kIdx8: 267 os << "[" << static_cast<unsigned int>(*operand_start) << "]"; 268 break; 269 case interpreter::OperandType::kIdx16: 270 os << "[" << ReadUnalignedUInt16(operand_start) << "]"; 271 break; 272 case interpreter::OperandType::kImm8: 273 os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); 274 break; 275 case interpreter::OperandType::kReg8: 276 case interpreter::OperandType::kMaybeReg8: { 277 Register reg = Register::FromOperand(*operand_start); 278 if (reg.is_function_context()) { 279 os << "<context>"; 280 } else if (reg.is_function_closure()) { 281 os << "<closure>"; 282 } else if (reg.is_new_target()) { 283 os << "<new.target>"; 284 } else if (reg.is_parameter()) { 285 int parameter_index = reg.ToParameterIndex(parameter_count); 286 if (parameter_index == 0) { 287 os << "<this>"; 288 } else { 289 os << "a" << parameter_index - 1; 290 } 291 } else { 292 os << "r" << reg.index(); 293 } 294 break; 295 } 296 case interpreter::OperandType::kRegPair8: { 297 Register reg = Register::FromOperand(*operand_start); 298 if (reg.is_parameter()) { 299 int parameter_index = reg.ToParameterIndex(parameter_count); 300 DCHECK_NE(parameter_index, 0); 301 os << "a" << parameter_index - 1 << "-" << parameter_index; 302 } else { 303 os << "r" << reg.index() << "-" << reg.index() + 1; 304 } 305 break; 306 } 307 case interpreter::OperandType::kReg16: { 308 Register reg = 309 Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); 310 if (reg.is_parameter()) { 311 int parameter_index = reg.ToParameterIndex(parameter_count); 312 DCHECK_NE(parameter_index, 0); 313 os << "a" << parameter_index - 1; 314 } else { 315 os << "r" << reg.index(); 316 } 317 break; 318 } 319 case interpreter::OperandType::kNone: 320 UNREACHABLE(); 321 break; 322 } 323 if (i != number_of_operands - 1) { 324 os << ", "; 325 } 326 } 327 return os; 328 } 329 330 331 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { 332 return os << Bytecodes::ToString(bytecode); 333 } 334 335 336 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { 337 return os << Bytecodes::OperandTypeToString(operand_type); 338 } 339 340 341 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { 342 return os << Bytecodes::OperandSizeToString(operand_size); 343 } 344 345 346 static const int kLastParamRegisterIndex = 347 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; 348 static const int kFunctionClosureRegisterIndex = 349 -InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize; 350 static const int kFunctionContextRegisterIndex = 351 -InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize; 352 static const int kNewTargetRegisterIndex = 353 -InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize; 354 355 356 // Registers occupy range 0-127 in 8-bit value leaving 128 unused values. 357 // Parameter indices are biased with the negative value kLastParamRegisterIndex 358 // for ease of access in the interpreter. 359 static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex; 360 361 362 Register Register::FromParameterIndex(int index, int parameter_count) { 363 DCHECK_GE(index, 0); 364 DCHECK_LT(index, parameter_count); 365 DCHECK_LE(parameter_count, kMaxParameterIndex + 1); 366 int register_index = kLastParamRegisterIndex - parameter_count + index + 1; 367 DCHECK_LT(register_index, 0); 368 DCHECK_GE(register_index, kMinInt8); 369 return Register(register_index); 370 } 371 372 373 int Register::ToParameterIndex(int parameter_count) const { 374 DCHECK(is_parameter()); 375 return index() - kLastParamRegisterIndex + parameter_count - 1; 376 } 377 378 379 Register Register::function_closure() { 380 return Register(kFunctionClosureRegisterIndex); 381 } 382 383 384 bool Register::is_function_closure() const { 385 return index() == kFunctionClosureRegisterIndex; 386 } 387 388 389 Register Register::function_context() { 390 return Register(kFunctionContextRegisterIndex); 391 } 392 393 394 bool Register::is_function_context() const { 395 return index() == kFunctionContextRegisterIndex; 396 } 397 398 399 Register Register::new_target() { return Register(kNewTargetRegisterIndex); } 400 401 402 bool Register::is_new_target() const { 403 return index() == kNewTargetRegisterIndex; 404 } 405 406 407 int Register::MaxParameterIndex() { return kMaxParameterIndex; } 408 409 410 uint8_t Register::ToOperand() const { 411 DCHECK_GE(index_, kMinInt8); 412 DCHECK_LE(index_, kMaxInt8); 413 return static_cast<uint8_t>(-index_); 414 } 415 416 417 Register Register::FromOperand(uint8_t operand) { 418 return Register(-static_cast<int8_t>(operand)); 419 } 420 421 422 uint16_t Register::ToWideOperand() const { 423 DCHECK_GE(index_, kMinInt16); 424 DCHECK_LE(index_, kMaxInt16); 425 return static_cast<uint16_t>(-index_); 426 } 427 428 429 Register Register::FromWideOperand(uint16_t operand) { 430 return Register(-static_cast<int16_t>(operand)); 431 } 432 433 434 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3, 435 Register reg4, Register reg5) { 436 if (reg1.index() + 1 != reg2.index()) { 437 return false; 438 } 439 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) { 440 return false; 441 } 442 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) { 443 return false; 444 } 445 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) { 446 return false; 447 } 448 return true; 449 } 450 451 } // namespace interpreter 452 } // namespace internal 453 } // namespace v8 454