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 static void InitBytecodeFlags(EcmaOpcode &opcode, uint32_t &flags); 251 static void InitBytecodeKind(EcmaOpcode &opcode, BytecodeKind &kind); 252 253 static void InitNoSideEffectFlag(EcmaOpcode &opcode, uint32_t &flags); 254 static void InitNoGCFlag(EcmaOpcode &opcode, uint32_t &flags); 255 static void InitNoThrowFlag(EcmaOpcode &opcode, uint32_t &flags); 256 static void InitReadThisObjectFlag(EcmaOpcode &opcode, uint32_t &flags); 257 static void InitSupportDeoptFlag(EcmaOpcode &opcode, uint32_t &flags); 258 static void InitReadACCFlag(EcmaOpcode &opcode, uint32_t &flags); 259 static void InitDebuggerFlag(EcmaOpcode &opcode, uint32_t &flags); 260 static void InitReadFuncFlag(EcmaOpcode &opcode, uint32_t &flags); 261 static void InitWriteEnvFlag(EcmaOpcode &opcode, uint32_t &flags); 262 static void InitReadEnvFlag(EcmaOpcode &opcode, uint32_t &flags); 263 static void InitReadNewTargetFlag(EcmaOpcode &opcode, uint32_t &flags); 264 static void InitReadArgcFlag(EcmaOpcode &opcode, uint32_t &flags); 265 266 static bool InitMovKind(EcmaOpcode &opcode, BytecodeKind &kind); 267 static bool InitSetConstantKind(EcmaOpcode &opcode, BytecodeKind &kind); 268 static bool InitCallBCKind(EcmaOpcode &opcode, BytecodeKind &kind); 269 static bool InitRetrunKind(EcmaOpcode &opcode, BytecodeKind &kind); 270 static bool InitSuspendKind(EcmaOpcode &opcode, BytecodeKind &kind); 271 static bool InitResumeKind(EcmaOpcode &opcode, BytecodeKind &kind); 272 static bool InitDiscardedKind(EcmaOpcode &opcode, BytecodeKind &kind); 273 static bool InitThrowKind(EcmaOpcode &opcode, BytecodeKind &kind); 274 static bool InitConditionJumpKind(EcmaOpcode &opcode, BytecodeKind &kind); 275 static bool InitJumpIMMKind(EcmaOpcode &opcode, BytecodeKind &kind); 276 static bool InitGeneratorResolveKind(EcmaOpcode &opcode, BytecodeKind &kind); 277 static bool InitAccessorKind(EcmaOpcode &opcode, BytecodeKind &kind); 278 279 static size_t GetVRegCount(const BytecodeInstruction &inst); 280 HasFlag(BytecodeFlags flag)281 inline bool HasFlag(BytecodeFlags flag) const 282 { 283 return (GetFlags() & flag) == flag; 284 } 285 GetFlags()286 inline BytecodeFlags GetFlags() const 287 { 288 return FlagsField::Get(value_); 289 } 290 GetKind()291 inline BytecodeKind GetKind() const 292 { 293 return KindField::Get(value_); 294 } 295 296 uint64_t value_ {0}; 297 friend class Bytecodes; 298 friend class BytecodeInfo; 299 friend class BytecodeCircuitBuilder; 300 }; 301 302 class Bytecodes { 303 public: 304 static constexpr uint32_t NUM_BYTECODES = 0xFF; 305 static constexpr uint32_t OPCODE_MASK = 0xFF00; 306 static constexpr uint32_t BYTE_SIZE = 8; 307 static constexpr uint32_t CALLRUNTIME_PREFIX_OPCODE_INDEX = 251; 308 static constexpr uint32_t DEPRECATED_PREFIX_OPCODE_INDEX = 252; 309 static constexpr uint32_t WIDE_PREFIX_OPCODE_INDEX = 253; 310 static constexpr uint32_t THROW_PREFIX_OPCODE_INDEX = 254; 311 static constexpr uint32_t MIN_PREFIX_OPCODE_INDEX = CALLRUNTIME_PREFIX_OPCODE_INDEX; 312 313 static constexpr uint32_t LAST_OPCODE = 314 static_cast<uint32_t>(EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8); 315 static constexpr uint32_t LAST_DEPRECATED_OPCODE = 316 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_DYNAMICIMPORT_PREF_V8); 317 static constexpr uint32_t LAST_WIDE_OPCODE = 318 static_cast<uint32_t>(EcmaOpcode::WIDE_STPATCHVAR_PREF_IMM16); 319 static constexpr uint32_t LAST_THROW_OPCODE = 320 static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16); 321 static constexpr uint32_t LAST_CALLRUNTIME_OPCODE = 322 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_WIDELDSENDABLELOCALMODULEVAR_PREF_IMM16); 323 324 static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX == 325 static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE)); 326 static_assert(DEPRECATED_PREFIX_OPCODE_INDEX == 327 static_cast<uint32_t>(EcmaOpcode::DEPRECATED_LDLEXENV_PREF_NONE)); 328 static_assert(WIDE_PREFIX_OPCODE_INDEX == 329 static_cast<uint32_t>(EcmaOpcode::WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8)); 330 static_assert(THROW_PREFIX_OPCODE_INDEX == 331 static_cast<uint32_t>(EcmaOpcode::THROW_PREF_NONE)); 332 333 Bytecodes(); 334 Bytecodes(const Bytecodes&) = delete; 335 void operator=(const Bytecodes&) = delete; 336 GetOpcode(const uint8_t * pc)337 static EcmaOpcode GetOpcode(const uint8_t *pc) 338 { 339 uint8_t primary = ReadByte(pc); 340 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 341 uint8_t secondary = ReadByte1(pc); 342 return static_cast<EcmaOpcode>((secondary << 8U) | primary); // 8: byte size 343 } 344 return static_cast<EcmaOpcode>(primary); 345 } 346 GetBytecodeMetaData(const uint8_t * pc)347 BytecodeMetaData GetBytecodeMetaData(const uint8_t *pc) const 348 { 349 uint8_t primary = ReadByte(pc); 350 if (primary >= MIN_PREFIX_OPCODE_INDEX) { 351 uint8_t secondary = ReadByte1(pc); 352 if (primary == CALLRUNTIME_PREFIX_OPCODE_INDEX) { 353 return callRuntimeBytecodes_[secondary]; 354 } else if (primary == DEPRECATED_PREFIX_OPCODE_INDEX) { 355 return deprecatedBytecodes_[secondary]; 356 } else if (primary == WIDE_PREFIX_OPCODE_INDEX) { 357 return wideBytecodes_[secondary]; 358 } else { 359 ASSERT(primary == THROW_PREFIX_OPCODE_INDEX); 360 return throwBytecodes_[secondary]; 361 } 362 } 363 return bytecodes_[primary]; 364 } 365 IsCallOp(EcmaOpcode opcode)366 static bool IsCallOp(EcmaOpcode opcode) 367 { 368 switch (opcode) { 369 case EcmaOpcode::CALLARG0_IMM8: 370 case EcmaOpcode::CALLARG1_IMM8_V8: 371 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 372 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 373 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 374 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 375 case EcmaOpcode::CALLTHIS0_IMM8_V8: 376 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 377 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 378 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 379 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 380 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 381 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: 382 return true; 383 default: 384 return false; 385 } 386 } 387 IsCreateObjectWithBufferOp(EcmaOpcode opcode)388 static bool IsCreateObjectWithBufferOp(EcmaOpcode opcode) 389 { 390 switch (opcode) { 391 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM8_ID16: 392 case EcmaOpcode::CREATEOBJECTWITHBUFFER_IMM16_ID16: 393 return true; 394 default: 395 return false; 396 } 397 } 398 IsCreateEmptyArrayOp(EcmaOpcode opcode)399 static bool IsCreateEmptyArrayOp(EcmaOpcode opcode) 400 { 401 switch (opcode) { 402 case EcmaOpcode::CREATEEMPTYARRAY_IMM8: 403 case EcmaOpcode::CREATEEMPTYARRAY_IMM16: 404 return true; 405 default: 406 return false; 407 } 408 } 409 IsCreateArrayWithBufferOp(EcmaOpcode opcode)410 static bool IsCreateArrayWithBufferOp(EcmaOpcode opcode) 411 { 412 switch (opcode) { 413 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16: 414 case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16: 415 return true; 416 default: 417 return false; 418 } 419 } 420 IsDefineClassWithBufferOp(EcmaOpcode opcode)421 static bool IsDefineClassWithBufferOp(EcmaOpcode opcode) 422 { 423 switch (opcode) { 424 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM8_ID16_ID16_IMM16_V8: 425 case EcmaOpcode::DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8: 426 return true; 427 default: 428 return false; 429 } 430 } 431 IsLdLexVarOp(EcmaOpcode opcode)432 static bool IsLdLexVarOp(EcmaOpcode opcode) 433 { 434 switch (opcode) { 435 case EcmaOpcode::LDLEXVAR_IMM4_IMM4: 436 case EcmaOpcode::LDLEXVAR_IMM8_IMM8: 437 case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16: 438 return true; 439 default: 440 return false; 441 } 442 } 443 IsStLexVarOp(EcmaOpcode opcode)444 static bool IsStLexVarOp(EcmaOpcode opcode) 445 { 446 switch (opcode) { 447 case EcmaOpcode::STLEXVAR_IMM4_IMM4: 448 case EcmaOpcode::STLEXVAR_IMM8_IMM8: 449 case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16: 450 return true; 451 default: 452 return false; 453 } 454 } 455 IsCallOrAccessorOp(EcmaOpcode opcode)456 static bool IsCallOrAccessorOp(EcmaOpcode opcode) 457 { 458 switch (opcode) { 459 case EcmaOpcode::CALLARG0_IMM8: 460 case EcmaOpcode::CALLARG1_IMM8_V8: 461 case EcmaOpcode::CALLARGS2_IMM8_V8_V8: 462 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8: 463 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: 464 case EcmaOpcode::WIDE_CALLRANGE_PREF_IMM16_V8: 465 case EcmaOpcode::CALLTHIS0_IMM8_V8: 466 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 467 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 468 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 469 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 470 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 471 case EcmaOpcode::LDOBJBYNAME_IMM8_ID16: 472 case EcmaOpcode::LDOBJBYNAME_IMM16_ID16: 473 case EcmaOpcode::LDTHISBYNAME_IMM8_ID16: 474 case EcmaOpcode::LDTHISBYNAME_IMM16_ID16: 475 case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: 476 case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: 477 case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: 478 case EcmaOpcode::DEFINEPROPERTYBYNAME_IMM8_ID16_V8: 479 case EcmaOpcode::STTHISBYNAME_IMM8_ID16: 480 case EcmaOpcode::STTHISBYNAME_IMM16_ID16: 481 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: 482 return true; 483 default: 484 return false; 485 } 486 } 487 IsDefineFunc(EcmaOpcode opcode)488 static bool IsDefineFunc(EcmaOpcode opcode) 489 { 490 switch (opcode) { 491 case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8: 492 case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8: 493 return true; 494 default: 495 return false; 496 } 497 } 498 499 private: ReadByte(const uint8_t * pc)500 static uint8_t ReadByte(const uint8_t *pc) 501 { 502 return *pc; 503 } ReadByte1(const uint8_t * pc)504 static uint8_t ReadByte1(const uint8_t *pc) 505 { 506 return *(pc + 1); // 1: byte1 507 } 508 BytecodeMetaData InitBytecodeMetaData(const uint8_t *pc); 509 510 std::array<BytecodeMetaData, NUM_BYTECODES> bytecodes_{}; 511 std::array<BytecodeMetaData, NUM_BYTECODES> callRuntimeBytecodes_{}; 512 std::array<BytecodeMetaData, NUM_BYTECODES> deprecatedBytecodes_{}; 513 std::array<BytecodeMetaData, NUM_BYTECODES> wideBytecodes_{}; 514 std::array<BytecodeMetaData, NUM_BYTECODES> throwBytecodes_{}; 515 }; 516 517 enum class ConstDataIDType : uint8_t { 518 StringIDType, 519 MethodIDType, 520 ArrayLiteralIDType, 521 ObjectLiteralIDType, 522 ClassLiteralIDType, 523 }; 524 525 class VirtualRegister { 526 public: VirtualRegister(VRegIDType id)527 explicit VirtualRegister(VRegIDType id) : id_(id) 528 { 529 } 530 ~VirtualRegister() = default; 531 SetId(VRegIDType id)532 void SetId(VRegIDType id) 533 { 534 id_ = id; 535 } 536 GetId()537 VRegIDType GetId() const 538 { 539 return id_; 540 } 541 542 private: 543 VRegIDType id_; 544 }; 545 546 class Immediate { 547 public: Immediate(ImmValueType value)548 explicit Immediate(ImmValueType value) : value_(value) 549 { 550 } 551 ~Immediate() = default; 552 SetValue(ImmValueType value)553 void SetValue(ImmValueType value) 554 { 555 value_ = value; 556 } 557 ToJSTaggedValueInt()558 ImmValueType ToJSTaggedValueInt() const 559 { 560 return value_ | JSTaggedValue::TAG_INT; 561 } 562 ToJSTaggedValueDouble()563 ImmValueType ToJSTaggedValueDouble() const 564 { 565 return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData(); 566 } 567 GetValue()568 ImmValueType GetValue() const 569 { 570 return value_; 571 } 572 573 private: 574 ImmValueType value_; 575 }; 576 577 578 class ICSlotId { 579 public: ICSlotId(ICSlotIdType id)580 explicit ICSlotId(ICSlotIdType id) : id_(id) 581 { 582 } 583 ~ICSlotId() = default; 584 SetId(ICSlotIdType id)585 void SetId(ICSlotIdType id) 586 { 587 id_ = id; 588 } 589 GetId()590 ICSlotIdType GetId() const 591 { 592 return id_; 593 } 594 595 private: 596 ICSlotIdType id_; 597 }; 598 599 class ConstDataId { 600 public: ConstDataId(ConstDataIDType type,uint16_t id)601 ConstDataId(ConstDataIDType type, uint16_t id) 602 :type_(type), id_(id) 603 { 604 } 605 ConstDataId(uint64_t bitfield)606 explicit ConstDataId(uint64_t bitfield) 607 { 608 type_ = ConstDataIDType(bitfield >> TYPE_SHIFT); 609 id_ = bitfield & ((1 << TYPE_SHIFT) - 1); 610 } 611 612 ~ConstDataId() = default; 613 SetId(uint16_t id)614 void SetId(uint16_t id) 615 { 616 id_ = id; 617 } 618 GetId()619 uint16_t GetId() const 620 { 621 return id_; 622 } 623 SetType(ConstDataIDType type)624 void SetType(ConstDataIDType type) 625 { 626 type_ = type; 627 } 628 GetType()629 ConstDataIDType GetType() const 630 { 631 return type_; 632 } 633 IsStringId()634 bool IsStringId() const 635 { 636 return type_ == ConstDataIDType::StringIDType; 637 } 638 IsMethodId()639 bool IsMethodId() const 640 { 641 return type_ == ConstDataIDType::MethodIDType; 642 } 643 IsClassLiteraId()644 bool IsClassLiteraId() const 645 { 646 return type_ == ConstDataIDType::ClassLiteralIDType; 647 } 648 IsObjectLiteralID()649 bool IsObjectLiteralID() const 650 { 651 return type_ == ConstDataIDType::ObjectLiteralIDType; 652 } 653 IsArrayLiteralID()654 bool IsArrayLiteralID() const 655 { 656 return type_ == ConstDataIDType::ArrayLiteralIDType; 657 } 658 CaculateBitField()659 uint64_t CaculateBitField() const 660 { 661 return (static_cast<uint8_t>(type_) << TYPE_SHIFT) | id_; 662 } 663 664 private: 665 static constexpr int TYPE_SHIFT = 16; 666 ConstDataIDType type_; 667 uint16_t id_; 668 }; 669 670 class BytecodeInfo { 671 public: 672 // set of id, immediate and read register 673 std::vector<std::variant<ConstDataId, ICSlotId, Immediate, VirtualRegister>> inputs {}; 674 std::vector<VRegIDType> vregOut {}; // write register 675 Deopt()676 bool Deopt() const 677 { 678 return metaData_.SupportDeopt(); 679 } 680 AccOut()681 bool AccOut() const 682 { 683 return metaData_.HasAccOut(); 684 } 685 AccIn()686 bool AccIn() const 687 { 688 return metaData_.HasAccIn(); 689 } 690 EnvIn()691 bool EnvIn() const 692 { 693 return metaData_.HasEnvIn(); 694 } 695 EnvOut()696 bool EnvOut() const 697 { 698 return metaData_.HasEnvOut(); 699 } 700 NoSideEffects()701 bool NoSideEffects() const 702 { 703 return metaData_.IsNoSideEffects(); 704 } 705 NoThrow()706 bool NoThrow() const 707 { 708 return metaData_.IsNoThrow(); 709 } 710 ThisObjectIn()711 bool ThisObjectIn() const 712 { 713 return metaData_.HasThisIn(); 714 } 715 GetSize()716 size_t GetSize() const 717 { 718 return metaData_.GetSize(); 719 } 720 IsDef()721 bool IsDef() const 722 { 723 return (!vregOut.empty()) || AccOut(); 724 } 725 IsOut(VRegIDType reg,uint32_t index)726 bool IsOut(VRegIDType reg, uint32_t index) const 727 { 728 bool isDefined = (!vregOut.empty() && (reg == vregOut.at(index))); 729 return isDefined; 730 } 731 IsMov()732 bool IsMov() const 733 { 734 return metaData_.IsMov(); 735 } 736 IsJump()737 bool IsJump() const 738 { 739 return metaData_.IsJump(); 740 } 741 IsCondJump()742 bool IsCondJump() const 743 { 744 return metaData_.IsCondJump(); 745 } 746 IsReturn()747 bool IsReturn() const 748 { 749 return metaData_.IsReturn(); 750 } 751 IsThrow()752 bool IsThrow() const 753 { 754 return metaData_.IsThrow(); 755 } 756 IsSuspend()757 bool IsSuspend() const 758 { 759 return metaData_.IsSuspend(); 760 } 761 IsGeneratorResolve()762 bool IsGeneratorResolve() const 763 { 764 return metaData_.IsGeneratorResolve(); 765 } 766 IsDiscarded()767 bool IsDiscarded() const 768 { 769 return metaData_.IsDiscarded(); 770 } 771 IsSetConstant()772 bool IsSetConstant() const 773 { 774 return metaData_.IsSetConstant(); 775 } 776 IsGeneral()777 bool IsGeneral() const 778 { 779 return metaData_.IsGeneral(); 780 } 781 needFallThrough()782 bool needFallThrough() const 783 { 784 return !IsJump() && !IsReturn() && !IsThrow() && !IsInsufficientProfile(); 785 } 786 IsGeneratorRelative()787 bool IsGeneratorRelative() const 788 { 789 return metaData_.IsGeneratorRelative(); 790 } 791 ComputeValueInputCount()792 size_t ComputeValueInputCount() const 793 { 794 return (AccIn() ? 1 : 0) + inputs.size(); 795 } 796 ComputeOutCount()797 size_t ComputeOutCount() const 798 { 799 return (AccOut() ? 1 : 0) + vregOut.size(); 800 } 801 IsBc(EcmaOpcode ecmaOpcode)802 bool IsBc(EcmaOpcode ecmaOpcode) const 803 { 804 return metaData_.GetOpcode() == ecmaOpcode; 805 } 806 HasFuncIn()807 bool HasFuncIn() const 808 { 809 return metaData_.HasFuncIn(); 810 } 811 HasNewTargetIn()812 bool HasNewTargetIn() const 813 { 814 return metaData_.HasNewTargetIn(); 815 } 816 HasArgcIn()817 bool HasArgcIn() const 818 { 819 return metaData_.HasArgcIn(); 820 } 821 HasFrameArgs()822 bool HasFrameArgs() const 823 { 824 return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn(); 825 } 826 HasFrameState()827 bool HasFrameState() const 828 { 829 return HasFrameArgs() || !NoThrow(); 830 } 831 IsCall()832 bool IsCall() const 833 { 834 return metaData_.IsCall(); 835 } 836 IsAccessorBC()837 bool IsAccessorBC() const 838 { 839 return metaData_.IsAccessorBC(); 840 } 841 HasDebuggerStmt()842 bool HasDebuggerStmt() const 843 { 844 return metaData_.HasDebuggerStmt(); 845 } 846 GetOpcode()847 inline EcmaOpcode GetOpcode() const 848 { 849 return metaData_.GetOpcode(); 850 } 851 IsInsufficientProfile()852 inline bool IsInsufficientProfile() const 853 { 854 return isInsufficientProfile_; 855 } 856 857 static void InitBytecodeInfo(BytecodeCircuitBuilder *builder, 858 BytecodeInfo &info, const uint8_t* pc); 859 860 private: 861 void SetInsufficientProfile(BytecodeCircuitBuilder *builder, const uint8_t *pc); 862 863 BytecodeMetaData metaData_ { 0 }; 864 bool isInsufficientProfile_ {false}; 865 friend class BytecodeCircuitBuilder; 866 }; 867 868 class BytecodeIterator { 869 public: 870 static constexpr int INVALID_INDEX = -1; 871 BytecodeIterator() = default; BytecodeIterator(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)872 BytecodeIterator(BytecodeCircuitBuilder *builder, 873 uint32_t start, uint32_t end) 874 : builder_(builder), start_(start), end_(end) {} Reset(BytecodeCircuitBuilder * builder,uint32_t start,uint32_t end)875 void Reset(BytecodeCircuitBuilder *builder, 876 uint32_t start, uint32_t end) 877 { 878 builder_ = builder; 879 start_ = static_cast<int32_t>(start); 880 end_ = static_cast<int32_t>(end); 881 } 882 883 BytecodeIterator& operator++() 884 { 885 if (InRange()) { 886 index_++; 887 } 888 return *this; 889 } 890 BytecodeIterator& operator--() 891 { 892 if (InRange()) { 893 index_--; 894 } 895 return *this; 896 } 897 Goto(uint32_t i)898 void Goto(uint32_t i) 899 { 900 index_ = static_cast<int32_t>(i); 901 } 902 GotoStart()903 void GotoStart() 904 { 905 index_ = start_; 906 } 907 GotoEnd()908 void GotoEnd() 909 { 910 index_ = end_; 911 ASSERT(InRange()); 912 } 913 IsInRange(int idx)914 bool IsInRange(int idx) const 915 { 916 return (idx <= end_) && (idx >= start_); 917 } 918 InRange()919 bool InRange() const 920 { 921 return (index_ <= end_) && (index_ >= start_); 922 } 923 Done()924 bool Done() const 925 { 926 return !InRange(); 927 } 928 Index()929 uint32_t Index() const 930 { 931 return static_cast<uint32_t>(index_); 932 } 933 934 const BytecodeInfo &GetBytecodeInfo() const; 935 const uint8_t *PeekNextPc(size_t i) const; 936 const uint8_t *PeekPrevPc(size_t i) const; 937 938 private: 939 BytecodeCircuitBuilder *builder_ {nullptr}; 940 int32_t start_ {0}; 941 int32_t end_ {0}; 942 int32_t index_{ INVALID_INDEX }; 943 }; 944 945 class BytecodeCallArgc { 946 public: ComputeCallArgc(int gateNumIn,EcmaOpcode op)947 static int ComputeCallArgc(int gateNumIn, EcmaOpcode op) 948 { 949 switch (op) { 950 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8: 951 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8: 952 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8: 953 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: 954 case EcmaOpcode::WIDE_CALLTHISRANGE_PREF_IMM16_V8: 955 case EcmaOpcode::CALLTHIS0_IMM8_V8: 956 case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8: { 957 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget, this 958 } 959 default: { 960 return gateNumIn + NUM_MANDATORY_JSFUNC_ARGS - 1; // 1: calltarget 961 } 962 } 963 } 964 }; 965 } // panda::ecmascript::kungfu 966 #endif // ECMASCRIPT_COMPILER_BYTECODES_H 967