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 DEBUGGER_STMT = 1 << 13, 54 }; 55 56 enum BytecodeKind : uint32_t { 57 GENERAL = 0, 58 THROW_BC, 59 RETURN_BC, 60 JUMP_IMM, 61 CONDITIONAL_JUMP, 62 MOV, 63 SET_CONSTANT, 64 SUSPEND, 65 RESUME, 66 GENERATOR_RESOLVE, 67 DISCARDED, 68 CALL_BC, 69 ACCESSOR_BC, 70 }; 71 72 class BytecodeMetaData { 73 public: 74 static constexpr uint32_t MAX_OPCODE_SIZE = 16; 75 static constexpr uint32_t MAX_SIZE_BITS = 4; 76 static constexpr uint32_t BYTECODE_FLAGS_SIZE = 14; 77 static constexpr uint32_t BYTECODE_KIND_SIZE = 4; 78 79 using OpcodeField = panda::BitField<EcmaOpcode, 0, MAX_OPCODE_SIZE>; 80 using SizeField = OpcodeField::NextField<size_t, MAX_SIZE_BITS>; 81 using KindField = SizeField::NextField<BytecodeKind, BYTECODE_KIND_SIZE>; 82 using FlagsField = KindField::NextField<BytecodeFlags, BYTECODE_FLAGS_SIZE>; 83 HasAccIn()84 bool HasAccIn() const 85 { 86 return HasFlag(BytecodeFlags::READ_ACC); 87 } 88 IsNoSideEffects()89 bool IsNoSideEffects() const 90 { 91 return HasFlag(BytecodeFlags::NO_SIDE_EFFECTS); 92 } 93 IsNoThrow()94 bool IsNoThrow() const 95 { 96 return HasFlag(BytecodeFlags::NO_THROW); 97 } 98 HasThisIn()99 bool HasThisIn() const 100 { 101 return HasFlag(BytecodeFlags::READ_THIS_OBJECT); 102 } 103 HasAccOut()104 bool HasAccOut() const 105 { 106 return HasFlag(BytecodeFlags::WRITE_ACC); 107 } 108 HasEnvIn()109 bool HasEnvIn() const 110 { 111 return HasFlag(BytecodeFlags::READ_ENV); 112 } 113 HasEnvOut()114 bool HasEnvOut() const 115 { 116 return HasFlag(BytecodeFlags::WRITE_ENV); 117 } 118 IsNoGC()119 bool IsNoGC() const 120 { 121 return HasFlag(BytecodeFlags::NO_GC); 122 } 123 IsMov()124 bool IsMov() const 125 { 126 return GetKind() == BytecodeKind::MOV; 127 } 128 IsReturn()129 bool IsReturn() const 130 { 131 return GetKind() == BytecodeKind::RETURN_BC; 132 } 133 IsThrow()134 bool IsThrow() const 135 { 136 return GetKind() == BytecodeKind::THROW_BC; 137 } 138 IsJump()139 bool IsJump() const 140 { 141 return IsJumpImm() || IsCondJump(); 142 } 143 IsCondJump()144 bool IsCondJump() const 145 { 146 return GetKind() == BytecodeKind::CONDITIONAL_JUMP; 147 } 148 IsJumpImm()149 bool IsJumpImm() const 150 { 151 return GetKind() == BytecodeKind::JUMP_IMM; 152 } 153 IsSuspend()154 bool IsSuspend() const 155 { 156 return GetKind() == BytecodeKind::SUSPEND; 157 } 158 IsSetConstant()159 bool IsSetConstant() const 160 { 161 return GetKind() == BytecodeKind::SET_CONSTANT; 162 } 163 SupportDeopt()164 bool SupportDeopt() const 165 { 166 return HasFlag(BytecodeFlags::SUPPORT_DEOPT); 167 } 168 GetSize()169 size_t GetSize() const 170 { 171 return SizeField::Get(value_); 172 } 173 IsGeneral()174 bool IsGeneral() const 175 { 176 return HasFlag(BytecodeFlags::GENERAL_BC); 177 } 178 IsGeneratorResolve()179 bool IsGeneratorResolve() const 180 { 181 return GetKind() == BytecodeKind::GENERATOR_RESOLVE; 182 } 183 IsGeneratorRelative()184 bool IsGeneratorRelative() const 185 { 186 BytecodeKind kind = GetKind(); 187 return (kind == BytecodeKind::RESUME) || (kind == BytecodeKind::SUSPEND) || 188 (kind == BytecodeKind::GENERATOR_RESOLVE); 189 } 190 IsDiscarded()191 bool IsDiscarded() const 192 { 193 return GetKind() == BytecodeKind::DISCARDED; 194 } 195 HasFuncIn()196 bool HasFuncIn() const 197 { 198 return HasFlag(BytecodeFlags::READ_FUNC); 199 } 200 HasNewTargetIn()201 bool HasNewTargetIn() const 202 { 203 return HasFlag(BytecodeFlags::READ_NEWTARGET); 204 } 205 HasArgcIn()206 bool HasArgcIn() const 207 { 208 return HasFlag(BytecodeFlags::READ_ARGC); 209 } 210 GetOpcode()211 inline EcmaOpcode GetOpcode() const 212 { 213 return OpcodeField::Get(value_); 214 } 215 IsInvalid()216 bool IsInvalid() const 217 { 218 return value_ == 0; 219 } 220 IsCall()221 bool IsCall() const 222 { 223 return GetKind() == BytecodeKind::CALL_BC; 224 } 225 IsAccessorBC()226 bool IsAccessorBC() const 227 { 228 return GetKind() == BytecodeKind::ACCESSOR_BC; 229 } 230 HasDebuggerStmt()231 bool HasDebuggerStmt() const 232 { 233 return HasFlag(BytecodeFlags::DEBUGGER_STMT); 234 } 235 236 private: 237 BytecodeMetaData() = default; 238 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData); 239 DEFAULT_COPY_SEMANTIC(BytecodeMetaData); BytecodeMetaData(uint64_t value)240 explicit BytecodeMetaData(uint64_t value) : value_(value) {} 241 242 static BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); 243 HasFlag(BytecodeFlags flag)244 inline bool HasFlag(BytecodeFlags flag) const 245 { 246 return (GetFlags() & flag) == flag; 247 } 248 GetFlags()249 inline BytecodeFlags GetFlags() const 250 { 251 return FlagsField::Get(value_); 252 } 253 GetKind()254 inline BytecodeKind GetKind() const 255 { 256 return KindField::Get(value_); 257 } 258 259 uint64_t value_ {0}; 260 friend class Bytecodes; 261 friend class BytecodeInfo; 262 friend class BytecodeCircuitBuilder; 263 }; 264 265 class Bytecodes { 266 public: 267 static constexpr uint32_t NUM_BYTECODES = 0xFF; 268 static constexpr uint32_t OPCODE_MASK = 0xFF00; 269 static constexpr uint32_t BYTE_SIZE = 8; 270 static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251; 271 static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252; 272 static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253; 273 static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254; 274 static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX; 275 276 static constexpr uint32_t LAST_OPCODE = 277 static_cast<uint32_t>(EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8); 278 static constexpr uint32_t LAST_DEPRECATED_OPCODE = 279 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8); 280 static constexpr uint32_t LAST_WIDE_OPCODE = 281 static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16); 282 static constexpr uint32_t LAST_THROW_OPCODE = 283 static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16); 284 static constexpr uint32_t LAST_CALLRUNTIME_OPCODE = 285 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16); 286 287 static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX == 288 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE)); 289 static_assert(DEPRECATED_PREFIX_OPCODE_INDEX == 290 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE)); 291 static_assert(WIDE_PREFIX_OPCODE_INDEX == 292 static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8)); 293 static_assert(THROW_PREFIX_OPCODE_INDEX == 294 static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE)); 295 296 Bytecodes(); 297 Bytecodes(const Bytecodes&) = delete; 298 void operator=(const Bytecodes&) = delete; 299 GetOpcode(const uint8_t * pc)300 static EcmaOpcode GetOpcode(const uint8_t *pc) 301 { 302 uint8_t primary = ReadByte(pc); 303 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 304 uint8_t secondary = ReadByte1(pc); 305 return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size 306 } 307 return static_cast<EcmaOpcode>(primary); 308 } 309 GetBytecodeMetaData(const uint8_t * pc)310 BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const 311 { 312 uint8_t primary = ReadByte(pc); 313 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 314 uint8_t secondary = ReadByte1(pc); 315 if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) { 316 return callRuntimeBytecodes_[secondary]; 317 } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) { 318 return deprecatedBytecodes_[secondary]; 319 } else if (primary == WIDE_PREFIX_OPCODE_INDEX) { 320 return wideBytecodes_[secondary]; 321 } else { 322 ASSERT(primary == THROW_PREFIX_OPCODE_INDEX); 323 return throwBytecodes_[secondary]; 324 } 325 } 326 return bytecodes_[primary]; 327 } 328 IsCallOp(EcmaOpcode opcode)329 static bool IsCallOp(EcmaOpcode opcode) 330 { 331 switch (opcode) { 332 case EcmaOpcode::CALLARG0_IMM8: 333 case EcmaOpcode::CALLARG1_IMM8_V8: 334 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 335 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 336 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 337 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 338 case EcmaOpcode::CALLTHIS0_IMM8_V8: 339 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 340 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 341 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 342 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 343 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 344 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: 345 return true; 346 default: 347 return false; 348 } 349 } 350 IsCreateObjectWithBufferOp(EcmaOpcode opcode)351 static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode) 352 { 353 switch (opcode) { 354 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: 355 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: 356 return true; 357 default: 358 return false; 359 } 360 } 361 IsCreateEmptyArrayOp(EcmaOpcode opcode)362 static bool IsCreateEmptyArrayOp(EcmaOpcode opcode) 363 { 364 switch (opcode) { 365 case EcmaOpcode::CREATEEMPTYARRAY_IMM8: 366 case EcmaOpcode::CREATEEMPTYARRAY_IMM16: 367 return true; 368 default: 369 return false; 370 } 371 } 372 IsCreateArrayWithBufferOp(EcmaOpcode opcode)373 static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode) 374 { 375 switch (opcode) { 376 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 377 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 378 return true; 379 default: 380 return false; 381 } 382 } 383 IsDefineClassWithBufferOp(EcmaOpcode opcode)384 static bool IsDefineClassWithBufferOp(EcmaOpcode opcode) 385 { 386 switch (opcode) { 387 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: 388 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: 389 return true; 390 default: 391 return false; 392 } 393 } 394 IsLdLexVarOp(EcmaOpcode opcode)395 static bool IsLdLexVarOp(EcmaOpcode opcode) 396 { 397 switch (opcode) { 398 case EcmaOpcode::LDLEXVAR_IMM4_IMM4: 399 case EcmaOpcode::LDLEXVAR_IMM8_IMM8: 400 case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: 401 return true; 402 default: 403 return false; 404 } 405 } 406 IsStLexVarOp(EcmaOpcode opcode)407 static bool IsStLexVarOp(EcmaOpcode opcode) 408 { 409 switch (opcode) { 410 case EcmaOpcode::STLEXVAR_IMM4_IMM4: 411 case EcmaOpcode::STLEXVAR_IMM8_IMM8: 412 case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16: 413 return true; 414 default: 415 return false; 416 } 417 } 418 IsCallOrAccessorOp(EcmaOpcode opcode)419 static bool IsCallOrAccessorOp(EcmaOpcode opcode) 420 { 421 switch (opcode) { 422 case EcmaOpcode::CALLARG0_IMM8: 423 case EcmaOpcode::CALLARG1_IMM8_V8: 424 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 425 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 426 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 427 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 428 case EcmaOpcode::CALLTHIS0_IMM8_V8: 429 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 430 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 431 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 432 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 433 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 434 case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: 435 case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: 436 case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: 437 case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: 438 case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: 439 case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: 440 case EcmaOpcode::STTHISBYNAME_IMM8_ID16: 441 case EcmaOpcode::STTHISBYNAME_IMM16_ID16: 442 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: 443 return true; 444 default: 445 return false; 446 } 447 } 448 IsDefineFunc(EcmaOpcode opcode)449 static bool IsDefineFunc(EcmaOpcode opcode) 450 { 451 switch (opcode) { 452 case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: 453 case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: 454 return true; 455 default: 456 return false; 457 } 458 } 459 460 private: ReadByte(const uint8_t * pc)461 static uint8_t ReadByte(const uint8_t *pc) 462 { 463 return *pc; 464 } ReadByte1(const uint8_t * pc)465 static uint8_t ReadByte1(const uint8_t *pc) 466 { 467 return *(pc + 1); // 1: byte1 468 } 469 BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); 470 471 std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{}; 472 std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{}; 473 std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{}; 474 std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{}; 475 std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{}; 476 }; 477 478 enum class ConstDataIDType : uint8_t { 479 StringIDType, 480 MethodIDType, 481 ArrayLiteralIDType, 482 ObjectLiteralIDType, 483 ClassLiteralIDType, 484 }; 485 486 class VirtualRegister { 487 public: VirtualRegister(VRegIDType id)488 explicit VirtualRegister(VRegIDType id) : id_(id) 489 { 490 } 491 ~VirtualRegister() = default; 492 SetId(VRegIDType id)493 void SetId(VRegIDType id) 494 { 495 id_ = id; 496 } 497 GetId()498 VRegIDType GetId() const 499 { 500 return id_; 501 } 502 503 private: 504 VRegIDType id_; 505 }; 506 507 class Immediate { 508 public: Immediate(ImmValueType value)509 explicit Immediate(ImmValueType value) : value_(value) 510 { 511 } 512 ~Immediate() = default; 513 SetValue(ImmValueType value)514 void SetValue(ImmValueType value) 515 { 516 value_ = value; 517 } 518 ToJSTaggedValueInt()519 ImmValueType ToJSTaggedValueInt() const 520 { 521 return value_ | JSTaggedValue::TAG_INT; 522 } 523 ToJSTaggedValueDouble()524 ImmValueType ToJSTaggedValueDouble() const 525 { 526 return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData(); 527 } 528 GetValue()529 ImmValueType GetValue() const 530 { 531 return value_; 532 } 533 534 private: 535 ImmValueType value_; 536 }; 537 538 539 class ICSlotId { 540 public: ICSlotId(ICSlotIdType id)541 explicit ICSlotId(ICSlotIdType id) : id_(id) 542 { 543 } 544 ~ICSlotId() = default; 545 SetId(ICSlotIdType id)546 void SetId(ICSlotIdType id) 547 { 548 id_ = id; 549 } 550 GetId()551 ICSlotIdType GetId() const 552 { 553 return id_; 554 } 555 556 private: 557 ICSlotIdType id_; 558 }; 559 560 class ConstDataId { 561 public: ConstDataId(ConstDataIDType type,uint16_t id)562 ConstDataId(ConstDataIDType type, uint16_t id) 563 :type_(type), id_(id) 564 { 565 } 566 ConstDataId(uint64_t bitfield)567 explicit ConstDataId(uint64_t bitfield) 568 { 569 type_ = ConstDataIDType(bitfield >> TYPE_SHIFT); 570 id_ = bitfield & ((1 << TYPE_SHIFT) - 1); 571 } 572 573 ~ConstDataId() = default; 574 SetId(uint16_t id)575 void SetId(uint16_t id) 576 { 577 id_ = id; 578 } 579 GetId()580 uint16_t GetId() const 581 { 582 return id_; 583 } 584 SetType(ConstDataIDType type)585 void SetType(ConstDataIDType type) 586 { 587 type_ = type; 588 } 589 GetType()590 ConstDataIDType GetType() const 591 { 592 return type_; 593 } 594 IsStringId()595 bool IsStringId() const 596 { 597 return type_ == ConstDataIDType::StringIDType; 598 } 599 IsMethodId()600 bool IsMethodId() const 601 { 602 return type_ == ConstDataIDType::MethodIDType; 603 } 604 IsClassLiteraId()605 bool IsClassLiteraId() const 606 { 607 return type_ == ConstDataIDType::ClassLiteralIDType; 608 } 609 IsObjectLiteralID()610 bool IsObjectLiteralID() const 611 { 612 return type_ == ConstDataIDType::ObjectLiteralIDType; 613 } 614 IsArrayLiteralID()615 bool IsArrayLiteralID() const 616 { 617 return type_ == ConstDataIDType::ArrayLiteralIDType; 618 } 619 CaculateBitField()620 uint64_t CaculateBitField() const 621 { 622 return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_; 623 } 624 625 private: 626 static constexpr int TYPE_SHIFT = 16; 627 ConstDataIDType type_; 628 uint16_t id_; 629 }; 630 631 class BytecodeInfo { 632 public: 633 // set of id, immediate and read register 634 std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {}; 635 std::vector<VRegIDType> vregOut {}; // write register 636 Deopt()637 bool Deopt() const 638 { 639 return metaData_.SupportDeopt(); 640 } 641 AccOut()642 bool AccOut() const 643 { 644 return metaData_.HasAccOut(); 645 } 646 AccIn()647 bool AccIn() const 648 { 649 return metaData_.HasAccIn(); 650 } 651 EnvIn()652 bool EnvIn() const 653 { 654 return metaData_.HasEnvIn(); 655 } 656 EnvOut()657 bool EnvOut() const 658 { 659 return metaData_.HasEnvOut(); 660 } 661 NoSideEffects()662 bool NoSideEffects() const 663 { 664 return metaData_.IsNoSideEffects(); 665 } 666 NoThrow()667 bool NoThrow() const 668 { 669 return metaData_.IsNoThrow(); 670 } 671 ThisObjectIn()672 bool ThisObjectIn() const 673 { 674 return metaData_.HasThisIn(); 675 } 676 GetSize()677 size_t GetSize() const 678 { 679 return metaData_.GetSize(); 680 } 681 IsDef()682 bool IsDef() const 683 { 684 return (!vregOut.empty()) || AccOut(); 685 } 686 IsOut(VRegIDType reg,uint32_t index)687 bool IsOut(VRegIDType reg, uint32_t index) const 688 { 689 bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index))); 690 return isDefined; 691 } 692 IsMov()693 bool IsMov() const 694 { 695 return metaData_.IsMov(); 696 } 697 IsJump()698 bool IsJump() const 699 { 700 return metaData_.IsJump(); 701 } 702 IsCondJump()703 bool IsCondJump() const 704 { 705 return metaData_.IsCondJump(); 706 } 707 IsReturn()708 bool IsReturn() const 709 { 710 return metaData_.IsReturn(); 711 } 712 IsThrow()713 bool IsThrow() const 714 { 715 return metaData_.IsThrow(); 716 } 717 IsSuspend()718 bool IsSuspend() const 719 { 720 return metaData_.IsSuspend(); 721 } 722 IsGeneratorResolve()723 bool IsGeneratorResolve() const 724 { 725 return metaData_.IsGeneratorResolve(); 726 } 727 IsDiscarded()728 bool IsDiscarded() const 729 { 730 return metaData_.IsDiscarded(); 731 } 732 IsSetConstant()733 bool IsSetConstant() const 734 { 735 return metaData_.IsSetConstant(); 736 } 737 IsGeneral()738 bool IsGeneral() const 739 { 740 return metaData_.IsGeneral(); 741 } 742 needFallThrough()743 bool needFallThrough() const 744 { 745 return !IsJump() && !IsReturn() && !IsThrow(); 746 } 747 IsGeneratorRelative()748 bool IsGeneratorRelative() const 749 { 750 return metaData_.IsGeneratorRelative(); 751 } 752 ComputeValueInputCount()753 size_t ComputeValueInputCount() const 754 { 755 return (AccIn() ? 1 : 0) + inputs.size(); 756 } 757 ComputeOutCount()758 size_t ComputeOutCount() const 759 { 760 return (AccOut() ? 1 : 0) + vregOut.size(); 761 } 762 IsBc(EcmaOpcode ecmaOpcode)763 bool IsBc(EcmaOpcode ecmaOpcode) const 764 { 765 return metaData_.GetOpcode() == ecmaOpcode; 766 } 767 HasFuncIn()768 bool HasFuncIn() const 769 { 770 return metaData_.HasFuncIn(); 771 } 772 HasNewTargetIn()773 bool HasNewTargetIn() const 774 { 775 return metaData_.HasNewTargetIn(); 776 } 777 HasArgcIn()778 bool HasArgcIn() const 779 { 780 return metaData_.HasArgcIn(); 781 } 782 HasFrameArgs()783 bool HasFrameArgs() const 784 { 785 return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn(); 786 } 787 HasFrameState()788 bool HasFrameState() const 789 { 790 return HasFrameArgs() || !NoThrow(); 791 } 792 IsCall()793 bool IsCall() const 794 { 795 return metaData_.IsCall(); 796 } 797 IsAccessorBC()798 bool IsAccessorBC() const 799 { 800 return metaData_.IsAccessorBC(); 801 } 802 HasDebuggerStmt()803 bool HasDebuggerStmt() const 804 { 805 return metaData_.HasDebuggerStmt(); 806 } 807 GetOpcode()808 inline EcmaOpcode GetOpcode() const 809 { 810 return metaData_.GetOpcode(); 811 } 812 813 static void InitBytecodeInfo(BytecodeCircuitBuilder *builder, 814 BytecodeInfo &info, const uint8_t* pc); 815 816 private: 817 BytecodeMetaData metaData_ { 0 }; 818 friend class BytecodeCircuitBuilder; 819 }; 820 821 class BytecodeIterator { 822 public: 823 static constexpr int INVALID_INDEX = -1; 824 BytecodeIterator() = default; BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)825 BytecodeIterator(BytecodeCircuitBuilder *builder, 826 uint32_t start, uint32_t end) 827 : builder_(builder), start_(start), end_(end) {} Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)828 void Reset(BytecodeCircuitBuilder *builder, 829 uint32_t start, uint32_t end) 830 { 831 builder_ = builder; 832 start_ = static_cast<int32_t>(start); 833 end_ = static_cast<int32_t>(end); 834 } 835 836 BytecodeIterator& operator++() 837 { 838 if (InRange()) { 839 index_++; 840 } 841 return *this; 842 } 843 BytecodeIterator& operator--() 844 { 845 if (InRange()) { 846 index_--; 847 } 848 return *this; 849 } 850 Goto(uint32_t i)851 void Goto(uint32_t i) 852 { 853 index_ = static_cast<int32_t>(i); 854 } 855 GotoStart()856 void GotoStart() 857 { 858 index_ = start_; 859 } 860 GotoEnd()861 void GotoEnd() 862 { 863 index_ = end_; 864 ASSERT(InRange()); 865 } 866 IsInRange(int idx)867 bool IsInRange(int idx) const 868 { 869 return (idx <= end_) && (idx >= start_); 870 } 871 InRange()872 bool InRange() const 873 { 874 return (index_ <= end_) && (index_ >= start_); 875 } 876 Done()877 bool Done() const 878 { 879 return !InRange(); 880 } 881 Index()882 uint32_t Index() const 883 { 884 return static_cast<uint32_t>(index_); 885 } 886 887 const BytecodeInfo &GetBytecodeInfo() const; 888 const uint8_t *PeekNextPc(size_t i) const; 889 const uint8_t *PeekPrevPc(size_t i) const; 890 891 private: 892 BytecodeCircuitBuilder *builder_ {nullptr}; 893 int32_t start_ {0}; 894 int32_t end_ {0}; 895 int32_t index_{ INVALID_INDEX }; 896 }; 897 898 class BytecodeCallArgc { 899 public: ComputeCallArgc(int gateNumIn,EcmaOpcode op)900 static int ComputeCallArgc(int gateNumIn, EcmaOpcode op) 901 { 902 switch (op) { 903 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 904 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 905 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 906 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 907 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 908 case EcmaOpcode::CALLTHIS0_IMM8_V8: 909 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: { 910 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this 911 } 912 default: { 913 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget 914 } 915 } 916 } 917 }; 918 } // panda::ecmascript::kungfu 919 #endif // ECMASCRIPT_COMPILER_BYTECODES_H 920