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