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 <iomanip> 8 9 #include "src/base/bits.h" 10 #include "src/frames.h" 11 #include "src/interpreter/bytecode-traits.h" 12 #include "src/interpreter/interpreter.h" 13 14 namespace v8 { 15 namespace internal { 16 namespace interpreter { 17 18 19 // static 20 const char* Bytecodes::ToString(Bytecode bytecode) { 21 switch (bytecode) { 22 #define CASE(Name, ...) \ 23 case Bytecode::k##Name: \ 24 return #Name; 25 BYTECODE_LIST(CASE) 26 #undef CASE 27 } 28 UNREACHABLE(); 29 return ""; 30 } 31 32 // static 33 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { 34 static const char kSeparator = '.'; 35 36 std::string value(ToString(bytecode)); 37 if (operand_scale > OperandScale::kSingle) { 38 Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale); 39 std::string suffix = ToString(prefix_bytecode); 40 return value.append(1, kSeparator).append(suffix); 41 } else { 42 return value; 43 } 44 } 45 46 // static 47 const char* Bytecodes::AccumulatorUseToString(AccumulatorUse accumulator_use) { 48 switch (accumulator_use) { 49 case AccumulatorUse::kNone: 50 return "None"; 51 case AccumulatorUse::kRead: 52 return "Read"; 53 case AccumulatorUse::kWrite: 54 return "Write"; 55 case AccumulatorUse::kReadWrite: 56 return "ReadWrite"; 57 } 58 UNREACHABLE(); 59 return ""; 60 } 61 62 // static 63 const char* Bytecodes::OperandTypeToString(OperandType operand_type) { 64 switch (operand_type) { 65 #define CASE(Name, _) \ 66 case OperandType::k##Name: \ 67 return #Name; 68 OPERAND_TYPE_LIST(CASE) 69 #undef CASE 70 } 71 UNREACHABLE(); 72 return ""; 73 } 74 75 // static 76 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { 77 switch (operand_scale) { 78 #define CASE(Name, _) \ 79 case OperandScale::k##Name: \ 80 return #Name; 81 OPERAND_SCALE_LIST(CASE) 82 #undef CASE 83 } 84 UNREACHABLE(); 85 return ""; 86 } 87 88 // static 89 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { 90 switch (operand_size) { 91 case OperandSize::kNone: 92 return "None"; 93 case OperandSize::kByte: 94 return "Byte"; 95 case OperandSize::kShort: 96 return "Short"; 97 case OperandSize::kQuad: 98 return "Quad"; 99 } 100 UNREACHABLE(); 101 return ""; 102 } 103 104 // static 105 Bytecode Bytecodes::FromByte(uint8_t value) { 106 Bytecode bytecode = static_cast<Bytecode>(value); 107 DCHECK(bytecode <= Bytecode::kLast); 108 return bytecode; 109 } 110 111 // static 112 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { 113 DCHECK(!IsDebugBreak(bytecode)); 114 if (bytecode == Bytecode::kWide) { 115 return Bytecode::kDebugBreakWide; 116 } 117 if (bytecode == Bytecode::kExtraWide) { 118 return Bytecode::kDebugBreakExtraWide; 119 } 120 int bytecode_size = Size(bytecode, OperandScale::kSingle); 121 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ 122 if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ 123 return Bytecode::k##Name; \ 124 } 125 DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) 126 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES 127 UNREACHABLE(); 128 return Bytecode::kIllegal; 129 } 130 131 // static 132 int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) { 133 int size = 1; 134 for (int i = 0; i < NumberOfOperands(bytecode); i++) { 135 OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); 136 int delta = static_cast<int>(operand_size); 137 DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); 138 size += delta; 139 } 140 return size; 141 } 142 143 // static 144 size_t Bytecodes::ReturnCount(Bytecode bytecode) { 145 return bytecode == Bytecode::kReturn ? 1 : 0; 146 } 147 148 // static 149 int Bytecodes::NumberOfOperands(Bytecode bytecode) { 150 DCHECK(bytecode <= Bytecode::kLast); 151 switch (bytecode) { 152 #define CASE(Name, ...) \ 153 case Bytecode::k##Name: \ 154 return BytecodeTraits<__VA_ARGS__>::kOperandCount; 155 BYTECODE_LIST(CASE) 156 #undef CASE 157 } 158 UNREACHABLE(); 159 return 0; 160 } 161 162 // static 163 int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) { 164 DCHECK(bytecode <= Bytecode::kLast); 165 switch (bytecode) { 166 #define CASE(Name, ...) \ 167 case Bytecode::k##Name: \ 168 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ 169 return Name##Trait::kRegisterOperandCount; 170 BYTECODE_LIST(CASE) 171 #undef CASE 172 } 173 UNREACHABLE(); 174 return false; 175 } 176 177 // static 178 Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) { 179 switch (operand_scale) { 180 case OperandScale::kQuadruple: 181 return Bytecode::kExtraWide; 182 case OperandScale::kDouble: 183 return Bytecode::kWide; 184 default: 185 UNREACHABLE(); 186 return Bytecode::kIllegal; 187 } 188 } 189 190 // static 191 bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) { 192 return operand_scale != OperandScale::kSingle; 193 } 194 195 // static 196 OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) { 197 switch (bytecode) { 198 case Bytecode::kExtraWide: 199 case Bytecode::kDebugBreakExtraWide: 200 return OperandScale::kQuadruple; 201 case Bytecode::kWide: 202 case Bytecode::kDebugBreakWide: 203 return OperandScale::kDouble; 204 default: 205 UNREACHABLE(); 206 return OperandScale::kSingle; 207 } 208 } 209 210 // static 211 AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) { 212 DCHECK(bytecode <= Bytecode::kLast); 213 switch (bytecode) { 214 #define CASE(Name, ...) \ 215 case Bytecode::k##Name: \ 216 return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse; 217 BYTECODE_LIST(CASE) 218 #undef CASE 219 } 220 UNREACHABLE(); 221 return AccumulatorUse::kNone; 222 } 223 224 // static 225 bool Bytecodes::ReadsAccumulator(Bytecode bytecode) { 226 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) == 227 AccumulatorUse::kRead; 228 } 229 230 // static 231 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { 232 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == 233 AccumulatorUse::kWrite; 234 } 235 236 // static 237 bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) { 238 switch (bytecode) { 239 case Bytecode::kLdaTrue: 240 case Bytecode::kLdaFalse: 241 case Bytecode::kToBooleanLogicalNot: 242 case Bytecode::kLogicalNot: 243 case Bytecode::kTestEqual: 244 case Bytecode::kTestNotEqual: 245 case Bytecode::kTestEqualStrict: 246 case Bytecode::kTestLessThan: 247 case Bytecode::kTestLessThanOrEqual: 248 case Bytecode::kTestGreaterThan: 249 case Bytecode::kTestGreaterThanOrEqual: 250 case Bytecode::kTestInstanceOf: 251 case Bytecode::kTestIn: 252 case Bytecode::kForInDone: 253 return true; 254 default: 255 return false; 256 } 257 } 258 259 // static 260 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { 261 switch (bytecode) { 262 case Bytecode::kLdaZero: 263 case Bytecode::kLdaSmi: 264 case Bytecode::kLdaUndefined: 265 case Bytecode::kLdaNull: 266 case Bytecode::kLdaTheHole: 267 case Bytecode::kLdaTrue: 268 case Bytecode::kLdaFalse: 269 case Bytecode::kLdaConstant: 270 case Bytecode::kLdar: 271 return true; 272 default: 273 return false; 274 } 275 } 276 277 // static 278 bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) { 279 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode); 280 } 281 282 // static 283 bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) { 284 switch (bytecode) { 285 case Bytecode::kMov: 286 case Bytecode::kPopContext: 287 case Bytecode::kPushContext: 288 case Bytecode::kStar: 289 case Bytecode::kLdrUndefined: 290 return true; 291 default: 292 return false; 293 } 294 } 295 296 // static 297 bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) { 298 // These bytecodes only manipulate interpreter frame state and will 299 // never throw. 300 return (IsAccumulatorLoadWithoutEffects(bytecode) || 301 IsRegisterLoadWithoutEffects(bytecode) || 302 bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode)); 303 } 304 305 // static 306 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { 307 DCHECK_LE(bytecode, Bytecode::kLast); 308 DCHECK_LT(i, NumberOfOperands(bytecode)); 309 DCHECK_GE(i, 0); 310 return GetOperandTypes(bytecode)[i]; 311 } 312 313 // static 314 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { 315 DCHECK(bytecode <= Bytecode::kLast); 316 switch (bytecode) { 317 #define CASE(Name, ...) \ 318 case Bytecode::k##Name: \ 319 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); 320 BYTECODE_LIST(CASE) 321 #undef CASE 322 } 323 UNREACHABLE(); 324 return nullptr; 325 } 326 327 // static 328 const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) { 329 DCHECK(bytecode <= Bytecode::kLast); 330 switch (bytecode) { 331 #define CASE(Name, ...) \ 332 case Bytecode::k##Name: \ 333 return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos(); 334 BYTECODE_LIST(CASE) 335 #undef CASE 336 } 337 UNREACHABLE(); 338 return nullptr; 339 } 340 341 // static 342 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, 343 OperandScale operand_scale) { 344 DCHECK_LT(i, NumberOfOperands(bytecode)); 345 return GetOperandSizes(bytecode, operand_scale)[i]; 346 } 347 348 // static 349 const OperandSize* Bytecodes::GetOperandSizes(Bytecode bytecode, 350 OperandScale operand_scale) { 351 DCHECK(bytecode <= Bytecode::kLast); 352 switch (bytecode) { 353 #define CASE(Name, ...) \ 354 case Bytecode::k##Name: \ 355 return BytecodeTraits<__VA_ARGS__>::GetOperandSizes(operand_scale); 356 BYTECODE_LIST(CASE) 357 #undef CASE 358 } 359 UNREACHABLE(); 360 return nullptr; 361 } 362 363 // static 364 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { 365 DCHECK(bytecode <= Bytecode::kLast); 366 switch (bytecode) { 367 #define CASE(Name, ...) \ 368 case Bytecode::k##Name: \ 369 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ 370 return Name##Trait::kRegisterOperandBitmap; 371 BYTECODE_LIST(CASE) 372 #undef CASE 373 } 374 UNREACHABLE(); 375 return false; 376 } 377 378 // static 379 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, 380 OperandScale operand_scale) { 381 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); 382 // TODO(oth): restore this to a statically determined constant. 383 int offset = 1; 384 for (int operand_index = 0; operand_index < i; ++operand_index) { 385 OperandSize operand_size = 386 GetOperandSize(bytecode, operand_index, operand_scale); 387 offset += static_cast<int>(operand_size); 388 } 389 return offset; 390 } 391 392 // static 393 OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, 394 OperandScale operand_scale) { 395 return static_cast<OperandSize>( 396 ScaledOperandSize(operand_type, operand_scale)); 397 } 398 399 // static 400 bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { 401 return bytecode == Bytecode::kJumpIfTrue || 402 bytecode == Bytecode::kJumpIfFalse || 403 bytecode == Bytecode::kJumpIfToBooleanTrue || 404 bytecode == Bytecode::kJumpIfToBooleanFalse || 405 bytecode == Bytecode::kJumpIfNotHole || 406 bytecode == Bytecode::kJumpIfNull || 407 bytecode == Bytecode::kJumpIfUndefined; 408 } 409 410 411 // static 412 bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { 413 return bytecode == Bytecode::kJumpIfTrueConstant || 414 bytecode == Bytecode::kJumpIfFalseConstant || 415 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || 416 bytecode == Bytecode::kJumpIfToBooleanFalseConstant || 417 bytecode == Bytecode::kJumpIfNotHoleConstant || 418 bytecode == Bytecode::kJumpIfNullConstant || 419 bytecode == Bytecode::kJumpIfUndefinedConstant; 420 } 421 422 // static 423 bool Bytecodes::IsConditionalJump(Bytecode bytecode) { 424 return IsConditionalJumpImmediate(bytecode) || 425 IsConditionalJumpConstant(bytecode); 426 } 427 428 429 // static 430 bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { 431 return bytecode == Bytecode::kJump || IsConditionalJumpImmediate(bytecode); 432 } 433 434 435 // static 436 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { 437 return bytecode == Bytecode::kJumpConstant || 438 IsConditionalJumpConstant(bytecode); 439 } 440 441 // static 442 bool Bytecodes::IsJump(Bytecode bytecode) { 443 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); 444 } 445 446 // static 447 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { 448 return bytecode == Bytecode::kJumpIfToBooleanTrue || 449 bytecode == Bytecode::kJumpIfToBooleanFalse || 450 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || 451 bytecode == Bytecode::kJumpIfToBooleanFalseConstant; 452 } 453 454 // static 455 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { 456 switch (bytecode) { 457 case Bytecode::kJumpIfToBooleanTrue: 458 return Bytecode::kJumpIfTrue; 459 case Bytecode::kJumpIfToBooleanFalse: 460 return Bytecode::kJumpIfFalse; 461 case Bytecode::kJumpIfToBooleanTrueConstant: 462 return Bytecode::kJumpIfTrueConstant; 463 case Bytecode::kJumpIfToBooleanFalseConstant: 464 return Bytecode::kJumpIfFalseConstant; 465 default: 466 break; 467 } 468 UNREACHABLE(); 469 return Bytecode::kIllegal; 470 } 471 472 // static 473 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { 474 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || 475 bytecode == Bytecode::kNew; 476 } 477 478 // static 479 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { 480 return bytecode == Bytecode::kCallRuntime || 481 bytecode == Bytecode::kCallRuntimeForPair || 482 bytecode == Bytecode::kInvokeIntrinsic; 483 } 484 485 // static 486 bool Bytecodes::IsDebugBreak(Bytecode bytecode) { 487 switch (bytecode) { 488 #define CASE(Name, ...) case Bytecode::k##Name: 489 DEBUG_BREAK_BYTECODE_LIST(CASE); 490 #undef CASE 491 return true; 492 default: 493 break; 494 } 495 return false; 496 } 497 498 // static 499 bool Bytecodes::IsLdarOrStar(Bytecode bytecode) { 500 return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar; 501 } 502 503 // static 504 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { 505 switch (bytecode) { 506 #define CASE(Name, ...) \ 507 case Bytecode::k##Name: \ 508 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ 509 return Name##Trait::IsScalable(); 510 BYTECODE_LIST(CASE) 511 #undef CASE 512 } 513 UNREACHABLE(); 514 return false; 515 } 516 517 // static 518 bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) { 519 switch (bytecode) { 520 case Bytecode::kExtraWide: 521 case Bytecode::kDebugBreakExtraWide: 522 case Bytecode::kWide: 523 case Bytecode::kDebugBreakWide: 524 return true; 525 default: 526 return false; 527 } 528 } 529 530 // static 531 bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { 532 return bytecode == Bytecode::kReturn || IsJump(bytecode); 533 } 534 535 // static 536 bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { 537 return operand_type == OperandType::kMaybeReg; 538 } 539 540 // static 541 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { 542 switch (operand_type) { 543 #define CASE(Name, _) \ 544 case OperandType::k##Name: \ 545 return true; 546 REGISTER_OPERAND_TYPE_LIST(CASE) 547 #undef CASE 548 #define CASE(Name, _) \ 549 case OperandType::k##Name: \ 550 break; 551 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 552 #undef CASE 553 } 554 return false; 555 } 556 557 // static 558 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { 559 switch (operand_type) { 560 #define CASE(Name, _) \ 561 case OperandType::k##Name: \ 562 return true; 563 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 564 #undef CASE 565 #define CASE(Name, _) \ 566 case OperandType::k##Name: \ 567 break; 568 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 569 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 570 #undef CASE 571 } 572 return false; 573 } 574 575 // static 576 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { 577 switch (operand_type) { 578 #define CASE(Name, _) \ 579 case OperandType::k##Name: \ 580 return true; 581 REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) 582 #undef CASE 583 #define CASE(Name, _) \ 584 case OperandType::k##Name: \ 585 break; 586 NON_REGISTER_OPERAND_TYPE_LIST(CASE) 587 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) 588 #undef CASE 589 } 590 return false; 591 } 592 593 // static 594 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { 595 switch (operand_type) { 596 case OperandType::kMaybeReg: 597 case OperandType::kReg: 598 case OperandType::kRegOut: 599 return 1; 600 case OperandType::kRegPair: 601 case OperandType::kRegOutPair: 602 return 2; 603 case OperandType::kRegOutTriple: 604 return 3; 605 default: 606 UNREACHABLE(); 607 } 608 return 0; 609 } 610 611 // static 612 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { 613 switch (operand_type) { 614 #define CASE(Name, _) \ 615 case OperandType::k##Name: \ 616 return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned; 617 OPERAND_TYPE_LIST(CASE) 618 #undef CASE 619 } 620 UNREACHABLE(); 621 return false; 622 } 623 624 // static 625 OperandSize Bytecodes::SizeForSignedOperand(int value) { 626 if (value >= kMinInt8 && value <= kMaxInt8) { 627 return OperandSize::kByte; 628 } else if (value >= kMinInt16 && value <= kMaxInt16) { 629 return OperandSize::kShort; 630 } else { 631 return OperandSize::kQuad; 632 } 633 } 634 635 // static 636 OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) { 637 if (value <= kMaxUInt8) { 638 return OperandSize::kByte; 639 } else if (value <= kMaxUInt16) { 640 return OperandSize::kShort; 641 } else { 642 return OperandSize::kQuad; 643 } 644 } 645 646 // static 647 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, 648 OperandType operand_type, 649 OperandScale operand_scale) { 650 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); 651 int32_t operand = 652 DecodeSignedOperand(operand_start, operand_type, operand_scale); 653 return Register::FromOperand(operand); 654 } 655 656 // static 657 int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start, 658 OperandType operand_type, 659 OperandScale operand_scale) { 660 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type)); 661 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { 662 case OperandSize::kByte: 663 return static_cast<int8_t>(*operand_start); 664 case OperandSize::kShort: 665 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start)); 666 case OperandSize::kQuad: 667 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start)); 668 case OperandSize::kNone: 669 UNREACHABLE(); 670 } 671 return 0; 672 } 673 674 // static 675 uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start, 676 OperandType operand_type, 677 OperandScale operand_scale) { 678 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type)); 679 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { 680 case OperandSize::kByte: 681 return *operand_start; 682 case OperandSize::kShort: 683 return ReadUnalignedUInt16(operand_start); 684 case OperandSize::kQuad: 685 return ReadUnalignedUInt32(operand_start); 686 case OperandSize::kNone: 687 UNREACHABLE(); 688 } 689 return 0; 690 } 691 692 // static 693 std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, 694 int parameter_count) { 695 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); 696 int prefix_offset = 0; 697 OperandScale operand_scale = OperandScale::kSingle; 698 if (IsPrefixScalingBytecode(bytecode)) { 699 prefix_offset = 1; 700 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode); 701 bytecode = Bytecodes::FromByte(bytecode_start[1]); 702 } 703 704 // Prepare to print bytecode and operands as hex digits. 705 std::ios saved_format(nullptr); 706 saved_format.copyfmt(saved_format); 707 os.fill('0'); 708 os.flags(std::ios::hex); 709 710 int bytecode_size = Bytecodes::Size(bytecode, operand_scale); 711 for (int i = 0; i < prefix_offset + bytecode_size; i++) { 712 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' '; 713 } 714 os.copyfmt(saved_format); 715 716 const int kBytecodeColumnSize = 6; 717 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) { 718 os << " "; 719 } 720 721 os << Bytecodes::ToString(bytecode, operand_scale) << " "; 722 723 // Operands for the debug break are from the original instruction. 724 if (IsDebugBreak(bytecode)) return os; 725 726 int number_of_operands = NumberOfOperands(bytecode); 727 int range = 0; 728 for (int i = 0; i < number_of_operands; i++) { 729 OperandType op_type = GetOperandType(bytecode, i); 730 const uint8_t* operand_start = 731 &bytecode_start[prefix_offset + 732 GetOperandOffset(bytecode, i, operand_scale)]; 733 switch (op_type) { 734 case interpreter::OperandType::kRegCount: 735 os << "#" 736 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); 737 break; 738 case interpreter::OperandType::kIdx: 739 case interpreter::OperandType::kRuntimeId: 740 case interpreter::OperandType::kIntrinsicId: 741 os << "[" 742 << DecodeUnsignedOperand(operand_start, op_type, operand_scale) 743 << "]"; 744 break; 745 case interpreter::OperandType::kImm: 746 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale) 747 << "]"; 748 break; 749 case interpreter::OperandType::kFlag8: 750 os << "#" 751 << DecodeUnsignedOperand(operand_start, op_type, operand_scale); 752 break; 753 case interpreter::OperandType::kMaybeReg: 754 case interpreter::OperandType::kReg: 755 case interpreter::OperandType::kRegOut: { 756 Register reg = 757 DecodeRegisterOperand(operand_start, op_type, operand_scale); 758 os << reg.ToString(parameter_count); 759 break; 760 } 761 case interpreter::OperandType::kRegOutTriple: 762 range += 1; 763 case interpreter::OperandType::kRegOutPair: 764 case interpreter::OperandType::kRegPair: { 765 range += 1; 766 Register first_reg = 767 DecodeRegisterOperand(operand_start, op_type, operand_scale); 768 Register last_reg = Register(first_reg.index() + range); 769 os << first_reg.ToString(parameter_count) << "-" 770 << last_reg.ToString(parameter_count); 771 break; 772 } 773 case interpreter::OperandType::kNone: 774 UNREACHABLE(); 775 break; 776 } 777 if (i != number_of_operands - 1) { 778 os << ", "; 779 } 780 } 781 return os; 782 } 783 784 // static 785 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode, 786 OperandScale operand_scale) { 787 return operand_scale == OperandScale::kSingle || 788 Bytecodes::IsBytecodeWithScalableOperands(bytecode); 789 } 790 791 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { 792 return os << Bytecodes::ToString(bytecode); 793 } 794 795 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { 796 return os << Bytecodes::AccumulatorUseToString(use); 797 } 798 799 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { 800 return os << Bytecodes::OperandSizeToString(operand_size); 801 } 802 803 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { 804 return os << Bytecodes::OperandScaleToString(operand_scale); 805 } 806 807 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { 808 return os << Bytecodes::OperandTypeToString(operand_type); 809 } 810 811 static const int kLastParamRegisterIndex = 812 (InterpreterFrameConstants::kRegisterFileFromFp - 813 InterpreterFrameConstants::kLastParamFromFp) / 814 kPointerSize; 815 static const int kFunctionClosureRegisterIndex = 816 (InterpreterFrameConstants::kRegisterFileFromFp - 817 StandardFrameConstants::kFunctionOffset) / 818 kPointerSize; 819 static const int kCurrentContextRegisterIndex = 820 (InterpreterFrameConstants::kRegisterFileFromFp - 821 StandardFrameConstants::kContextOffset) / 822 kPointerSize; 823 static const int kNewTargetRegisterIndex = 824 (InterpreterFrameConstants::kRegisterFileFromFp - 825 InterpreterFrameConstants::kNewTargetFromFp) / 826 kPointerSize; 827 static const int kBytecodeArrayRegisterIndex = 828 (InterpreterFrameConstants::kRegisterFileFromFp - 829 InterpreterFrameConstants::kBytecodeArrayFromFp) / 830 kPointerSize; 831 static const int kBytecodeOffsetRegisterIndex = 832 (InterpreterFrameConstants::kRegisterFileFromFp - 833 InterpreterFrameConstants::kBytecodeOffsetFromFp) / 834 kPointerSize; 835 static const int kCallerPCOffsetRegisterIndex = 836 (InterpreterFrameConstants::kRegisterFileFromFp - 837 InterpreterFrameConstants::kCallerPCOffsetFromFp) / 838 kPointerSize; 839 840 Register Register::FromParameterIndex(int index, int parameter_count) { 841 DCHECK_GE(index, 0); 842 DCHECK_LT(index, parameter_count); 843 int register_index = kLastParamRegisterIndex - parameter_count + index + 1; 844 DCHECK_LT(register_index, 0); 845 return Register(register_index); 846 } 847 848 int Register::ToParameterIndex(int parameter_count) const { 849 DCHECK(is_parameter()); 850 return index() - kLastParamRegisterIndex + parameter_count - 1; 851 } 852 853 Register Register::function_closure() { 854 return Register(kFunctionClosureRegisterIndex); 855 } 856 857 bool Register::is_function_closure() const { 858 return index() == kFunctionClosureRegisterIndex; 859 } 860 861 Register Register::current_context() { 862 return Register(kCurrentContextRegisterIndex); 863 } 864 865 bool Register::is_current_context() const { 866 return index() == kCurrentContextRegisterIndex; 867 } 868 869 Register Register::new_target() { return Register(kNewTargetRegisterIndex); } 870 871 bool Register::is_new_target() const { 872 return index() == kNewTargetRegisterIndex; 873 } 874 875 Register Register::bytecode_array() { 876 return Register(kBytecodeArrayRegisterIndex); 877 } 878 879 bool Register::is_bytecode_array() const { 880 return index() == kBytecodeArrayRegisterIndex; 881 } 882 883 Register Register::bytecode_offset() { 884 return Register(kBytecodeOffsetRegisterIndex); 885 } 886 887 bool Register::is_bytecode_offset() const { 888 return index() == kBytecodeOffsetRegisterIndex; 889 } 890 891 // static 892 Register Register::virtual_accumulator() { 893 return Register(kCallerPCOffsetRegisterIndex); 894 } 895 896 OperandSize Register::SizeOfOperand() const { 897 int32_t operand = ToOperand(); 898 if (operand >= kMinInt8 && operand <= kMaxInt8) { 899 return OperandSize::kByte; 900 } else if (operand >= kMinInt16 && operand <= kMaxInt16) { 901 return OperandSize::kShort; 902 } else { 903 return OperandSize::kQuad; 904 } 905 } 906 907 bool Register::AreContiguous(Register reg1, Register reg2, Register reg3, 908 Register reg4, Register reg5) { 909 if (reg1.index() + 1 != reg2.index()) { 910 return false; 911 } 912 if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) { 913 return false; 914 } 915 if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) { 916 return false; 917 } 918 if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) { 919 return false; 920 } 921 return true; 922 } 923 924 std::string Register::ToString(int parameter_count) { 925 if (is_current_context()) { 926 return std::string("<context>"); 927 } else if (is_function_closure()) { 928 return std::string("<closure>"); 929 } else if (is_new_target()) { 930 return std::string("<new.target>"); 931 } else if (is_parameter()) { 932 int parameter_index = ToParameterIndex(parameter_count); 933 if (parameter_index == 0) { 934 return std::string("<this>"); 935 } else { 936 std::ostringstream s; 937 s << "a" << parameter_index - 1; 938 return s.str(); 939 } 940 } else { 941 std::ostringstream s; 942 s << "r" << index(); 943 return s.str(); 944 } 945 } 946 947 } // namespace interpreter 948 } // namespace internal 949 } // namespace v8 950