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