1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_COMPILER_BYTECODES_H 17 #define ECMASCRIPT_COMPILER_BYTECODES_H 18 19 #include <cstddef> 20 #include <array> 21 22 #include "libpandabase/macros.h" 23 #include "libpandabase/utils/bit_field.h" 24 #include "libpandafile/bytecode_instruction-inl.h" 25 #include "ecmascript/common.h" 26 #include "ecmascript/js_tagged_value.h" 27 28 namespace panda::ecmascript::kungfu { 29 using VRegIDType = uint32_t; 30 using ICSlotIdType = uint16_t; 31 using ImmValueType = uint64_t; 32 using EcmaOpcode = BytecodeInstruction::Opcode; 33 34 class BytecodeCircuitBuilder; 35 class Bytecodes; 36 class BytecodeInfo; 37 class BytecodeIterator; 38 39 enum BytecodeFlags : uint32_t { 40 READ_ACC = 1 << 0, // 1: flag bit 41 WRITE_ACC = 1 << 1, // 1: flag 1 42 SUPPORT_DEOPT = 1 << 2, // 2: flag 2 43 GENERAL_BC = 1 << 3, 44 READ_THIS_OBJECT = 1 << 4, 45 NO_SIDE_EFFECTS = 1 << 5, 46 NO_THROW = 1 << 6, 47 READ_ENV = 1 << 7, 48 WRITE_ENV = 1 << 8, 49 READ_FUNC = 1 << 9, 50 READ_NEWTARGET = 1 << 10, 51 READ_ARGC = 1 << 11, 52 NO_GC = 1 << 12, 53 }; 54 55 enum BytecodeKind : uint32_t { 56 GENERAL = 0, 57 THROW_BC, 58 RETURN_BC, 59 JUMP_IMM, 60 CONDITIONAL_JUMP, 61 MOV, 62 SET_CONSTANT, 63 SUSPEND, 64 RESUME, 65 GENERATOR_RESOLVE, 66 DISCARDED, 67 CALL_BC, 68 }; 69 70 class BytecodeMetaData { 71 public: 72 static constexpr uint32_t MAX_OPCODE_SIZE = 16; 73 static constexpr uint32_t MAX_SIZE_BITS = 4; 74 static constexpr uint32_t BYTECODE_FLAGS_SIZE = 13; 75 static constexpr uint32_t BYTECODE_KIND_SIZE = 4; 76 77 using OpcodeField = panda::BitField<EcmaOpcode, 0, MAX_OPCODE_SIZE>; 78 using SizeField = OpcodeField::NextField<size_t, MAX_SIZE_BITS>; 79 using KindField = SizeField::NextField<BytecodeKind, BYTECODE_KIND_SIZE>; 80 using FlagsField = KindField::NextField<BytecodeFlags, BYTECODE_FLAGS_SIZE>; 81 HasAccIn()82 bool HasAccIn() const 83 { 84 return HasFlag(BytecodeFlags::READ_ACC); 85 } 86 IsNoSideEffects()87 bool IsNoSideEffects() const 88 { 89 return HasFlag(BytecodeFlags::NO_SIDE_EFFECTS); 90 } 91 IsNoThrow()92 bool IsNoThrow() const 93 { 94 return HasFlag(BytecodeFlags::NO_THROW); 95 } 96 HasThisIn()97 bool HasThisIn() const 98 { 99 return HasFlag(BytecodeFlags::READ_THIS_OBJECT); 100 } 101 HasAccOut()102 bool HasAccOut() const 103 { 104 return HasFlag(BytecodeFlags::WRITE_ACC); 105 } 106 HasEnvIn()107 bool HasEnvIn() const 108 { 109 return HasFlag(BytecodeFlags::READ_ENV); 110 } 111 HasEnvOut()112 bool HasEnvOut() const 113 { 114 return HasFlag(BytecodeFlags::WRITE_ENV); 115 } 116 IsNoGC()117 bool IsNoGC() const 118 { 119 return HasFlag(BytecodeFlags::NO_GC); 120 } 121 IsMov()122 bool IsMov() const 123 { 124 return GetKind() == BytecodeKind::MOV; 125 } 126 IsReturn()127 bool IsReturn() const 128 { 129 return GetKind() == BytecodeKind::RETURN_BC; 130 } 131 IsThrow()132 bool IsThrow() const 133 { 134 return GetKind() == BytecodeKind::THROW_BC; 135 } 136 IsJump()137 bool IsJump() const 138 { 139 return IsJumpImm() || IsCondJump(); 140 } 141 IsCondJump()142 bool IsCondJump() const 143 { 144 return GetKind() == BytecodeKind::CONDITIONAL_JUMP; 145 } 146 IsJumpImm()147 bool IsJumpImm() const 148 { 149 return GetKind() == BytecodeKind::JUMP_IMM; 150 } 151 IsSuspend()152 bool IsSuspend() const 153 { 154 return GetKind() == BytecodeKind::SUSPEND; 155 } 156 IsSetConstant()157 bool IsSetConstant() const 158 { 159 return GetKind() == BytecodeKind::SET_CONSTANT; 160 } 161 SupportDeopt()162 bool SupportDeopt() const 163 { 164 return HasFlag(BytecodeFlags::SUPPORT_DEOPT); 165 } 166 GetSize()167 size_t GetSize() const 168 { 169 return SizeField::Get(value_); 170 } 171 IsGeneral()172 bool IsGeneral() const 173 { 174 return HasFlag(BytecodeFlags::GENERAL_BC); 175 } 176 IsGeneratorResolve()177 bool IsGeneratorResolve() const 178 { 179 return GetKind() == BytecodeKind::GENERATOR_RESOLVE; 180 } 181 IsGeneratorRelative()182 bool IsGeneratorRelative() const 183 { 184 BytecodeKind kind = GetKind(); 185 return (kind == BytecodeKind::RESUME) || (kind == BytecodeKind::SUSPEND) || 186 (kind == BytecodeKind::GENERATOR_RESOLVE); 187 } 188 IsDiscarded()189 bool IsDiscarded() const 190 { 191 return GetKind() == BytecodeKind::DISCARDED; 192 } 193 HasFuncIn()194 bool HasFuncIn() const 195 { 196 return HasFlag(BytecodeFlags::READ_FUNC); 197 } 198 HasNewTargetIn()199 bool HasNewTargetIn() const 200 { 201 return HasFlag(BytecodeFlags::READ_NEWTARGET); 202 } 203 HasArgcIn()204 bool HasArgcIn() const 205 { 206 return HasFlag(BytecodeFlags::READ_ARGC); 207 } 208 GetOpcode()209 inline EcmaOpcode GetOpcode() const 210 { 211 return OpcodeField::Get(value_); 212 } 213 IsInvalid()214 bool IsInvalid() const 215 { 216 return value_ == 0; 217 } 218 IsCall()219 bool IsCall() const 220 { 221 return GetKind() == BytecodeKind::CALL_BC; 222 } 223 224 private: 225 BytecodeMetaData() = default; 226 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData); 227 DEFAULT_COPY_SEMANTIC(BytecodeMetaData); BytecodeMetaData(uint64_t value)228 explicit BytecodeMetaData(uint64_t value) : value_(value) {} 229 230 static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); 231 HasFlag(BytecodeFlags flag)232 inline bool HasFlag(BytecodeFlags flag) const 233 { 234 return (GetFlags() & flag) == flag; 235 } 236 GetFlags()237 inline BytecodeFlags GetFlags() const 238 { 239 return FlagsField::Get(value_); 240 } 241 GetKind()242 inline BytecodeKind GetKind() const 243 { 244 return KindField::Get(value_); 245 } 246 247 uint64_t value_ {0}; 248 friend class Bytecodes; 249 friend class BytecodeInfo; 250 friend class BytecodeCircuitBuilder; 251 }; 252 253 class Bytecodes { 254 public: 255 static constexpr uint32_t NUM_BYTECODES = 0xFF; 256 static constexpr uint32_t OPCODE_MASK = 0xFF00; 257 static constexpr uint32_t BYTE_SIZE = 8; 258 static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251; 259 static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252; 260 static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253; 261 static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254; 262 static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX; 263 264 static constexpr uint32_t LAST_OPCODE = 265 static_cast<uint32_t>(EcmaOpcode::GETASYNCITERATOR_IMM8); 266 static constexpr uint32_t LAST_DEPRECATED_OPCODE = 267 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8); 268 static constexpr uint32_t LAST_WIDE_OPCODE = 269 static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16); 270 static constexpr uint32_t LAST_THROW_OPCODE = 271 static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16); 272 static constexpr uint32_t LAST_CALLRUNTIME_OPCODE = 273 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE); 274 275 static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX == 276 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE)); 277 static_assert(DEPRECATED_PREFIX_OPCODE_INDEX == 278 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE)); 279 static_assert(WIDE_PREFIX_OPCODE_INDEX == 280 static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8)); 281 static_assert(THROW_PREFIX_OPCODE_INDEX == 282 static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE)); 283 284 Bytecodes(); 285 Bytecodes(const Bytecodes&) = delete; 286 void operator=(const Bytecodes&) = delete; 287 GetOpcode(const uint8_t * pc)288 static EcmaOpcode GetOpcode(const uint8_t *pc) 289 { 290 uint8_t primary = ReadByte(pc); 291 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 292 uint8_t secondary = ReadByte1(pc); 293 return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size 294 } 295 return static_cast<EcmaOpcode>(primary); 296 } 297 GetBytecodeMetaData(const uint8_t * pc)298 BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const 299 { 300 uint8_t primary = ReadByte(pc); 301 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 302 uint8_t secondary = ReadByte1(pc); 303 if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) { 304 return callRuntimeBytecodes_[secondary]; 305 } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) { 306 return deprecatedBytecodes_[secondary]; 307 } else if (primary == WIDE_PREFIX_OPCODE_INDEX) { 308 return wideBytecodes_[secondary]; 309 } else { 310 ASSERT(primary == THROW_PREFIX_OPCODE_INDEX); 311 return throwBytecodes_[secondary]; 312 } 313 } 314 return bytecodes_[primary]; 315 } 316 IsCallOp(EcmaOpcode opcode)317 static bool IsCallOp(EcmaOpcode opcode) 318 { 319 switch (opcode) { 320 case EcmaOpcode::CALLARG0_IMM8: 321 case EcmaOpcode::CALLARG1_IMM8_V8: 322 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 323 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 324 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 325 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 326 case EcmaOpcode::CALLTHIS0_IMM8_V8: 327 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 328 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 329 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 330 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 331 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 332 return true; 333 default: 334 return false; 335 } 336 } 337 IsCreateObjectWithBufferOp(EcmaOpcode opcode)338 static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode) 339 { 340 switch (opcode) { 341 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: 342 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: 343 return true; 344 default: 345 return false; 346 } 347 } 348 IsCreateArrayWithBufferOp(EcmaOpcode opcode)349 static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode) 350 { 351 switch (opcode) { 352 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 353 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 354 return true; 355 default: 356 return false; 357 } 358 } 359 360 private: ReadByte(const uint8_t * pc)361 static uint8_t ReadByte(const uint8_t *pc) 362 { 363 return *pc; 364 } ReadByte1(const uint8_t * pc)365 static uint8_t ReadByte1(const uint8_t *pc) 366 { 367 return *(pc + 1); // 1: byte1 368 } 369 BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); 370 371 std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{}; 372 std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{}; 373 std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{}; 374 std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{}; 375 std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{}; 376 }; 377 378 enum class ConstDataIDType : uint8_t { 379 StringIDType, 380 MethodIDType, 381 ArrayLiteralIDType, 382 ObjectLiteralIDType, 383 ClassLiteralIDType, 384 }; 385 386 class VirtualRegister { 387 public: VirtualRegister(VRegIDType id)388 explicit VirtualRegister(VRegIDType id) : id_(id) 389 { 390 } 391 ~VirtualRegister() = default; 392 SetId(VRegIDType id)393 void SetId(VRegIDType id) 394 { 395 id_ = id; 396 } 397 GetId()398 VRegIDType GetId() const 399 { 400 return id_; 401 } 402 403 private: 404 VRegIDType id_; 405 }; 406 407 class Immediate { 408 public: Immediate(ImmValueType value)409 explicit Immediate(ImmValueType value) : value_(value) 410 { 411 } 412 ~Immediate() = default; 413 SetValue(ImmValueType value)414 void SetValue(ImmValueType value) 415 { 416 value_ = value; 417 } 418 ToJSTaggedValueInt()419 ImmValueType ToJSTaggedValueInt() const 420 { 421 return value_ | JSTaggedValue::TAG_INT; 422 } 423 ToJSTaggedValueDouble()424 ImmValueType ToJSTaggedValueDouble() const 425 { 426 return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData(); 427 } 428 GetValue()429 ImmValueType GetValue() const 430 { 431 return value_; 432 } 433 434 private: 435 ImmValueType value_; 436 }; 437 438 439 class ICSlotId { 440 public: ICSlotId(ICSlotIdType id)441 explicit ICSlotId(ICSlotIdType id) : id_(id) 442 { 443 } 444 ~ICSlotId() = default; 445 SetId(ICSlotIdType id)446 void SetId(ICSlotIdType id) 447 { 448 id_ = id; 449 } 450 GetId()451 ICSlotIdType GetId() const 452 { 453 return id_; 454 } 455 456 private: 457 ICSlotIdType id_; 458 }; 459 460 class ConstDataId { 461 public: ConstDataId(ConstDataIDType type,uint16_t id)462 ConstDataId(ConstDataIDType type, uint16_t id) 463 :type_(type), id_(id) 464 { 465 } 466 ConstDataId(uint64_t bitfield)467 explicit ConstDataId(uint64_t bitfield) 468 { 469 type_ = ConstDataIDType(bitfield >> TYPE_SHIFT); 470 id_ = bitfield & ((1 << TYPE_SHIFT) - 1); 471 } 472 473 ~ConstDataId() = default; 474 SetId(uint16_t id)475 void SetId(uint16_t id) 476 { 477 id_ = id; 478 } 479 GetId()480 uint16_t GetId() const 481 { 482 return id_; 483 } 484 SetType(ConstDataIDType type)485 void SetType(ConstDataIDType type) 486 { 487 type_ = type; 488 } 489 GetType()490 ConstDataIDType GetType() const 491 { 492 return type_; 493 } 494 IsStringId()495 bool IsStringId() const 496 { 497 return type_ == ConstDataIDType::StringIDType; 498 } 499 IsMethodId()500 bool IsMethodId() const 501 { 502 return type_ == ConstDataIDType::MethodIDType; 503 } 504 IsClassLiteraId()505 bool IsClassLiteraId() const 506 { 507 return type_ == ConstDataIDType::ClassLiteralIDType; 508 } 509 IsObjectLiteralID()510 bool IsObjectLiteralID() const 511 { 512 return type_ == ConstDataIDType::ObjectLiteralIDType; 513 } 514 IsArrayLiteralID()515 bool IsArrayLiteralID() const 516 { 517 return type_ == ConstDataIDType::ArrayLiteralIDType; 518 } 519 CaculateBitField()520 uint64_t CaculateBitField() const 521 { 522 return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_; 523 } 524 525 private: 526 static constexpr int TYPE_SHIFT = 16; 527 ConstDataIDType type_; 528 uint16_t id_; 529 }; 530 531 class BytecodeInfo { 532 public: 533 // set of id, immediate and read register 534 std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {}; 535 std::vector<VRegIDType> vregOut {}; // write register 536 Deopt()537 bool Deopt() const 538 { 539 return metaData_.SupportDeopt(); 540 } 541 AccOut()542 bool AccOut() const 543 { 544 return metaData_.HasAccOut(); 545 } 546 AccIn()547 bool AccIn() const 548 { 549 return metaData_.HasAccIn(); 550 } 551 EnvIn()552 bool EnvIn() const 553 { 554 return metaData_.HasEnvIn(); 555 } 556 EnvOut()557 bool EnvOut() const 558 { 559 return metaData_.HasEnvOut(); 560 } 561 NoSideEffects()562 bool NoSideEffects() const 563 { 564 return metaData_.IsNoSideEffects(); 565 } 566 NoThrow()567 bool NoThrow() const 568 { 569 return metaData_.IsNoThrow(); 570 } 571 ThisObjectIn()572 bool ThisObjectIn() const 573 { 574 return metaData_.HasThisIn(); 575 } 576 GetSize()577 size_t GetSize() const 578 { 579 return metaData_.GetSize(); 580 } 581 IsDef()582 bool IsDef() const 583 { 584 return (!vregOut.empty()) || AccOut(); 585 } 586 IsOut(VRegIDType reg,uint32_t index)587 bool IsOut(VRegIDType reg, uint32_t index) const 588 { 589 bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index))); 590 return isDefined; 591 } 592 IsMov()593 bool IsMov() const 594 { 595 return metaData_.IsMov(); 596 } 597 IsJump()598 bool IsJump() const 599 { 600 return metaData_.IsJump(); 601 } 602 IsCondJump()603 bool IsCondJump() const 604 { 605 return metaData_.IsCondJump(); 606 } 607 IsReturn()608 bool IsReturn() const 609 { 610 return metaData_.IsReturn(); 611 } 612 IsThrow()613 bool IsThrow() const 614 { 615 return metaData_.IsThrow(); 616 } 617 IsSuspend()618 bool IsSuspend() const 619 { 620 return metaData_.IsSuspend(); 621 } 622 IsGeneratorResolve()623 bool IsGeneratorResolve() const 624 { 625 return metaData_.IsGeneratorResolve(); 626 } 627 IsDiscarded()628 bool IsDiscarded() const 629 { 630 return metaData_.IsDiscarded(); 631 } 632 IsSetConstant()633 bool IsSetConstant() const 634 { 635 return metaData_.IsSetConstant(); 636 } 637 IsGeneral()638 bool IsGeneral() const 639 { 640 return metaData_.IsGeneral(); 641 } 642 needFallThrough()643 bool needFallThrough() const 644 { 645 return !IsJump() && !IsReturn() && !IsThrow(); 646 } 647 IsGeneratorRelative()648 bool IsGeneratorRelative() const 649 { 650 return metaData_.IsGeneratorRelative(); 651 } 652 ComputeValueInputCount()653 size_t ComputeValueInputCount() const 654 { 655 return (AccIn() ? 1 : 0) + inputs.size(); 656 } 657 ComputeOutCount()658 size_t ComputeOutCount() const 659 { 660 return (AccOut() ? 1 : 0) + vregOut.size(); 661 } 662 IsBc(EcmaOpcode ecmaOpcode)663 bool IsBc(EcmaOpcode ecmaOpcode) const 664 { 665 return metaData_.GetOpcode() == ecmaOpcode; 666 } 667 HasFuncIn()668 bool HasFuncIn() const 669 { 670 return metaData_.HasFuncIn(); 671 } 672 HasNewTargetIn()673 bool HasNewTargetIn() const 674 { 675 return metaData_.HasNewTargetIn(); 676 } 677 HasArgcIn()678 bool HasArgcIn() const 679 { 680 return metaData_.HasArgcIn(); 681 } 682 HasFrameArgs()683 bool HasFrameArgs() const 684 { 685 return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn(); 686 } 687 IsCall()688 bool IsCall() const 689 { 690 return metaData_.IsCall(); 691 } 692 GetOpcode()693 inline EcmaOpcode GetOpcode() const 694 { 695 return metaData_.GetOpcode(); 696 } 697 698 static void InitBytecodeInfo(BytecodeCircuitBuilder *builder, 699 BytecodeInfo &info, const uint8_t* pc); 700 701 private: 702 BytecodeMetaData metaData_ { 0 }; 703 friend class BytecodeCircuitBuilder; 704 }; 705 706 class BytecodeIterator { 707 public: 708 BytecodeIterator() = default; BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)709 BytecodeIterator(BytecodeCircuitBuilder *builder, 710 uint32_t start, uint32_t end) 711 : builder_(builder), start_(start), end_(end) {} Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)712 void Reset(BytecodeCircuitBuilder *builder, 713 uint32_t start, uint32_t end) 714 { 715 builder_ = builder; 716 start_ = start; 717 end_ = end; 718 } 719 720 BytecodeIterator& operator++() 721 { 722 if (InRange()) { 723 index_++; 724 } 725 return *this; 726 } 727 BytecodeIterator& operator--() 728 { 729 if (InRange()) { 730 index_--; 731 } 732 return *this; 733 } 734 Goto(uint32_t i)735 void Goto(uint32_t i) 736 { 737 index_ = i; 738 } 739 GotoStart()740 void GotoStart() 741 { 742 index_ = start_; 743 ASSERT(InRange()); 744 } 745 GotoEnd()746 void GotoEnd() 747 { 748 index_ = end_; 749 ASSERT(InRange()); 750 } 751 InRange()752 bool InRange() const 753 { 754 return (index_ <= end_) && (index_ >= start_); 755 } 756 Done()757 bool Done() const 758 { 759 return !InRange(); 760 } 761 Index()762 uint32_t Index() const 763 { 764 return index_; 765 } 766 767 const BytecodeInfo &GetBytecodeInfo() const; 768 const uint8_t *PeekNextPc(size_t i) const; 769 const uint8_t *PeekPrevPc(size_t i) const; 770 771 private: 772 BytecodeCircuitBuilder *builder_ {nullptr}; 773 uint32_t start_ {0}; 774 uint32_t end_ {0}; 775 uint32_t index_{ INVALID_INDEX }; 776 }; 777 778 class BytecodeCallArgc { 779 public: ComputeCallArgc(int gateNumIn,EcmaOpcode op)780 static int ComputeCallArgc(int gateNumIn, EcmaOpcode op) 781 { 782 switch (op) { 783 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 784 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 785 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 786 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 787 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 788 case EcmaOpcode::CALLTHIS0_IMM8_V8: { 789 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this 790 } 791 default: { 792 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget 793 } 794 } 795 } 796 }; 797 } // panda::ecmascript::kungfu 798 #endif // ECMASCRIPT_COMPILER_BYTECODES_H 799