1 /* 2 * Copyright (c) 2023 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_TYPE_INFO_ACCESSORS_H 17 #define ECMASCRIPT_COMPILER_TYPE_INFO_ACCESSORS_H 18 19 #include "ecmascript/compiler/argument_accessor.h" 20 #include "ecmascript/compiler/pgo_type/pgo_type_manager.h" 21 #include "ecmascript/ts_types/ts_manager.h" 22 23 namespace panda::ecmascript::kungfu { 24 class TypeInfoAccessor { 25 public: TypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)26 TypeInfoAccessor(const JSThread *thread, Circuit* circuit, GateRef gate) 27 : thread_(thread), 28 acc_(circuit), 29 argAcc_(circuit), 30 gate_(gate) 31 { 32 tsManager_ = thread_->GetCurrentEcmaContext()->GetTSManager(); 33 ptManager_ = thread_->GetCurrentEcmaContext()->GetPTManager(); 34 } 35 GetGate()36 GateRef GetGate() const 37 { 38 return gate_; 39 } 40 GetPGOType()41 PGOTypeRef GetPGOType() const 42 { 43 return acc_.TryGetPGOType(GetGate()); 44 } 45 46 static bool IsTrustedType(GateAccessor acc, GateRef gate); 47 48 static bool IsTrustedStringType( 49 const JSThread *thread, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate); 50 51 static JSTaggedValue GetStringFromConstantPool(const JSThread *thread, uint32_t methodId, uint32_t index); 52 53 protected: 54 const JSThread *thread_ {nullptr}; 55 GateAccessor acc_; 56 ArgumentAccessor argAcc_; 57 GateRef gate_; 58 TSManager *tsManager_ {nullptr}; 59 PGOTypeManager *ptManager_ {nullptr}; 60 }; 61 62 class BinOpTypeInfoAccessor final : public TypeInfoAccessor { 63 public: 64 BinOpTypeInfoAccessor(const JSThread *thread, 65 Circuit *circuit, 66 GateRef gate, 67 bool convertNumberType = false); 68 NO_COPY_SEMANTIC(BinOpTypeInfoAccessor); 69 NO_MOVE_SEMANTIC(BinOpTypeInfoAccessor); 70 71 bool HasNumberType() const; 72 73 bool HasStringType() const; 74 LeftOrRightIsUndefinedOrNull()75 bool LeftOrRightIsUndefinedOrNull() const 76 { 77 return acc_.IsUndefinedOrNull(left_) || acc_.IsUndefinedOrNull(right_); 78 } 79 80 private: 81 bool convertNumberType_; 82 GateRef left_; 83 GateRef right_; 84 }; 85 86 class UnOpTypeInfoAccessor : public TypeInfoAccessor { 87 public: 88 UnOpTypeInfoAccessor(const JSThread *thread, 89 Circuit *circuit, 90 GateRef gate); 91 NO_COPY_SEMANTIC(UnOpTypeInfoAccessor); 92 NO_MOVE_SEMANTIC(UnOpTypeInfoAccessor); 93 94 bool ValueIsNumberType() const; 95 ValueIsPrimitiveNumberType()96 bool ValueIsPrimitiveNumberType() const 97 { 98 return GetValueGateType().IsPrimitiveNumberType(); 99 } 100 ValueIsBooleanType()101 bool ValueIsBooleanType() const 102 { 103 return GetValueGateType().IsBooleanType(); 104 } 105 GetValue()106 GateRef GetValue() const 107 { 108 return value_; 109 } 110 GetValueGateType()111 GateType GetValueGateType() const 112 { 113 return acc_.GetGateType(value_); 114 } 115 116 protected: 117 GateRef value_; 118 }; 119 120 class ConditionJumpTypeInfoAccessor final : public UnOpTypeInfoAccessor { 121 public: ConditionJumpTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)122 ConditionJumpTypeInfoAccessor(const JSThread *thread, 123 Circuit *circuit, 124 GateRef gate) 125 : UnOpTypeInfoAccessor(thread, circuit, gate) {} 126 NO_COPY_SEMANTIC(ConditionJumpTypeInfoAccessor); 127 NO_MOVE_SEMANTIC(ConditionJumpTypeInfoAccessor); 128 GetBranchWeight()129 uint32_t GetBranchWeight() const 130 { 131 return acc_.TryGetPGOType(value_).GetPGOSampleType()->GetWeight(); 132 } 133 }; 134 135 class NewObjRangeTypeInfoAccessor final : public UnOpTypeInfoAccessor { 136 public: NewObjRangeTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)137 NewObjRangeTypeInfoAccessor(const JSThread *thread, 138 Circuit *circuit, 139 GateRef gate) 140 : UnOpTypeInfoAccessor(thread, circuit, gate), hclassIndex_(-1) {} 141 NO_COPY_SEMANTIC(NewObjRangeTypeInfoAccessor); 142 NO_MOVE_SEMANTIC(NewObjRangeTypeInfoAccessor); 143 144 bool FindHClass(); 145 GetHClassIndex()146 int GetHClassIndex() const 147 { 148 return hclassIndex_; 149 } 150 151 private: 152 int hclassIndex_; 153 }; 154 155 class NewBuiltinCtorTypeInfoAccessor final : public UnOpTypeInfoAccessor { 156 public: NewBuiltinCtorTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)157 NewBuiltinCtorTypeInfoAccessor(const JSThread *thread, 158 Circuit *circuit, 159 GateRef gate) 160 : UnOpTypeInfoAccessor(thread, circuit, gate) {} 161 NO_COPY_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); 162 NO_MOVE_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); 163 IsBuiltinModule()164 bool IsBuiltinModule() const 165 { 166 return GetCtorGT().IsBuiltinModule(); 167 } 168 IsBuiltinConstructor(BuiltinTypeId type)169 bool IsBuiltinConstructor(BuiltinTypeId type) 170 { 171 return tsManager_->IsBuiltinConstructor(type, GetCtorGT()); 172 } 173 174 private: GetCtorGT()175 GlobalTSTypeRef GetCtorGT() const 176 { 177 return GetValueGateType().GetGTRef(); 178 } 179 }; 180 181 class TypeOfTypeInfoAccessor final : public UnOpTypeInfoAccessor { 182 public: TypeOfTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)183 TypeOfTypeInfoAccessor(const JSThread *thread, 184 Circuit *circuit, 185 GateRef gate) 186 : UnOpTypeInfoAccessor(thread, circuit, gate) {} 187 NO_COPY_SEMANTIC(TypeOfTypeInfoAccessor); 188 NO_MOVE_SEMANTIC(TypeOfTypeInfoAccessor); 189 190 bool IsIllegalType() const; 191 }; 192 193 class SuperCallTypeInfoAccessor final : public TypeInfoAccessor { 194 public: 195 SuperCallTypeInfoAccessor(const JSThread *thread, 196 Circuit *circuit, 197 GateRef gate); 198 NO_COPY_SEMANTIC(SuperCallTypeInfoAccessor); 199 NO_MOVE_SEMANTIC(SuperCallTypeInfoAccessor); 200 IsClassTypeKind()201 bool IsClassTypeKind() const 202 { 203 return tsManager_->IsClassTypeKind(acc_.GetGateType(ctor_)); 204 } 205 IsFunctionTypeKind()206 bool IsFunctionTypeKind() const 207 { 208 return tsManager_->IsFunctionTypeKind(acc_.GetGateType(ctor_)); 209 } 210 GetCtor()211 GateRef GetCtor() const 212 { 213 return ctor_; 214 } 215 216 private: 217 GateRef ctor_; 218 }; 219 220 class CallTypeInfoAccessor : public TypeInfoAccessor { 221 public: CallTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)222 CallTypeInfoAccessor(const JSThread *thread, 223 Circuit *circuit, 224 GateRef gate) 225 : TypeInfoAccessor(thread, circuit, gate), 226 argc_(0), 227 func_(Circuit::NullGate()) 228 {} 229 GetArgc()230 size_t GetArgc() const 231 { 232 return argc_; 233 } 234 GetFunc()235 GateRef GetFunc() const 236 { 237 return func_; 238 } 239 GetFuncGateType()240 GateType GetFuncGateType() const 241 { 242 return acc_.GetGateType(func_); 243 } 244 IsFunctionTypeKind()245 bool IsFunctionTypeKind() const 246 { 247 return tsManager_->IsFunctionTypeKind(acc_.GetGateType(func_)); 248 } 249 IsHotnessFunc()250 bool IsHotnessFunc() const 251 { 252 return tsManager_->IsHotnessFunc(GetFunctionGT()); 253 } 254 GetFunctionTypeLength()255 uint32_t GetFunctionTypeLength() const 256 { 257 return tsManager_->GetFunctionTypeLength(GetFunctionGT()); 258 } 259 IsNoGC()260 bool IsNoGC() const 261 { 262 return tsManager_->IsNoGC(GetFunctionGT()); 263 } 264 FastCallFlagIsVaild()265 bool FastCallFlagIsVaild() const 266 { 267 return tsManager_->FastCallFlagIsVaild(GetFunctionGT()); 268 } 269 GetMethodIndex()270 int GetMethodIndex() const 271 { 272 return tsManager_->GetMethodIndex(GetFunctionGT()); 273 } 274 MethodOffsetIsVaild()275 bool MethodOffsetIsVaild() const 276 { 277 return tsManager_->MethodOffsetIsVaild(GetFunctionGT()); 278 } 279 CanFastCall()280 bool CanFastCall() const 281 { 282 return tsManager_->CanFastCall(GetFunctionGT()); 283 } 284 GetFuncMethodOffset()285 uint32_t GetFuncMethodOffset() const 286 { 287 return tsManager_->GetFuncMethodOffset(GetFunctionGT()); 288 } 289 290 BuiltinsStubCSigns::ID TryGetPGOBuiltinId() const; 291 292 BuiltinsStubCSigns::ID TryGetBuiltinId(BuiltinTypeId id) const; 293 294 protected: GetFunctionGT()295 GlobalTSTypeRef GetFunctionGT() const 296 { 297 return acc_.GetGateType(func_).GetGTRef(); 298 } 299 300 size_t argc_; 301 GateRef func_; 302 }; 303 304 class GetIteratorTypeInfoAccessor final : public CallTypeInfoAccessor { 305 public: 306 GetIteratorTypeInfoAccessor(const JSThread *thread, 307 Circuit *circuit, 308 GateRef gate); 309 NO_COPY_SEMANTIC(GetIteratorTypeInfoAccessor); 310 NO_MOVE_SEMANTIC(GetIteratorTypeInfoAccessor); 311 GetCallee()312 GateRef GetCallee() 313 { 314 return func_; 315 } 316 }; 317 318 class CallArg0TypeInfoAccessor final : public CallTypeInfoAccessor { 319 public: 320 CallArg0TypeInfoAccessor(const JSThread *thread, 321 Circuit *circuit, 322 GateRef gate); 323 NO_COPY_SEMANTIC(CallArg0TypeInfoAccessor); 324 NO_MOVE_SEMANTIC(CallArg0TypeInfoAccessor); 325 }; 326 327 class CallArg1TypeInfoAccessor final : public CallTypeInfoAccessor { 328 public: 329 CallArg1TypeInfoAccessor(const JSThread *thread, 330 Circuit *circuit, 331 GateRef gate); 332 NO_COPY_SEMANTIC(CallArg1TypeInfoAccessor); 333 NO_MOVE_SEMANTIC(CallArg1TypeInfoAccessor); 334 GetValue()335 GateRef GetValue() 336 { 337 return value_; 338 } 339 GetValueGateType()340 GateType GetValueGateType() 341 { 342 return acc_.GetGateType(value_); 343 } 344 345 private: 346 GateRef value_; 347 }; 348 349 class CallArg2TypeInfoAccessor final : public CallTypeInfoAccessor { 350 public: 351 CallArg2TypeInfoAccessor(const JSThread *thread, 352 Circuit *circuit, 353 GateRef gate); 354 NO_COPY_SEMANTIC(CallArg2TypeInfoAccessor); 355 NO_MOVE_SEMANTIC(CallArg2TypeInfoAccessor); 356 }; 357 358 class CallArg3TypeInfoAccessor final : public CallTypeInfoAccessor { 359 public: 360 CallArg3TypeInfoAccessor(const JSThread *thread, 361 Circuit *circuit, 362 GateRef gate); 363 NO_COPY_SEMANTIC(CallArg3TypeInfoAccessor); 364 NO_MOVE_SEMANTIC(CallArg3TypeInfoAccessor); 365 }; 366 367 class CallRangeTypeInfoAccessor final : public CallTypeInfoAccessor { 368 public: 369 CallRangeTypeInfoAccessor(const JSThread *thread, 370 Circuit *circuit, 371 GateRef gate); 372 NO_COPY_SEMANTIC(CallRangeTypeInfoAccessor); 373 NO_MOVE_SEMANTIC(CallRangeTypeInfoAccessor); 374 }; 375 376 class CallThisTypeInfoAccessor : public CallTypeInfoAccessor { 377 public: CallThisTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)378 CallThisTypeInfoAccessor(const JSThread *thread, 379 Circuit *circuit, 380 GateRef gate) 381 : CallTypeInfoAccessor(thread, circuit, gate) 382 { 383 thisObj_ = acc_.GetValueIn(gate, 0); 384 } 385 NO_COPY_SEMANTIC(CallThisTypeInfoAccessor); 386 NO_MOVE_SEMANTIC(CallThisTypeInfoAccessor); 387 388 bool CanOptimizeAsFastCall(); 389 GetThisObj()390 GateRef GetThisObj() const 391 { 392 return thisObj_; 393 } 394 protected: 395 GateRef thisObj_; 396 }; 397 398 class CallThis0TypeInfoAccessor final : public CallThisTypeInfoAccessor { 399 public: 400 CallThis0TypeInfoAccessor(const JSThread *thread, 401 Circuit *circuit, 402 GateRef gate); 403 NO_COPY_SEMANTIC(CallThis0TypeInfoAccessor); 404 NO_MOVE_SEMANTIC(CallThis0TypeInfoAccessor); 405 }; 406 407 class CallThis1TypeInfoAccessor final : public CallThisTypeInfoAccessor { 408 public: 409 CallThis1TypeInfoAccessor(const JSThread *thread, 410 Circuit *circuit, 411 GateRef gate); 412 NO_COPY_SEMANTIC(CallThis1TypeInfoAccessor); 413 NO_MOVE_SEMANTIC(CallThis1TypeInfoAccessor); 414 GetArg0()415 GateRef GetArg0() const 416 { 417 return a0_; 418 } 419 Arg0IsNumberType()420 bool Arg0IsNumberType() const 421 { 422 return acc_.GetGateType(a0_).IsNumberType(); 423 } 424 425 private: 426 GateRef a0_; 427 }; 428 429 class CallThis2TypeInfoAccessor final : public CallThisTypeInfoAccessor { 430 public: 431 CallThis2TypeInfoAccessor(const JSThread *thread, 432 Circuit *circuit, 433 GateRef gate); 434 NO_COPY_SEMANTIC(CallThis2TypeInfoAccessor); 435 NO_MOVE_SEMANTIC(CallThis2TypeInfoAccessor); 436 }; 437 438 class CallThis3TypeInfoAccessor final : public CallThisTypeInfoAccessor { 439 public: 440 CallThis3TypeInfoAccessor(const JSThread *thread, 441 Circuit *circuit, 442 GateRef gate); 443 NO_COPY_SEMANTIC(CallThis3TypeInfoAccessor); 444 NO_MOVE_SEMANTIC(CallThis3TypeInfoAccessor); 445 GetArgs()446 std::vector<GateRef> GetArgs() 447 { 448 return { thisObj_, a0_, a1_, a2_ }; 449 } 450 451 private: 452 GateRef a0_; 453 GateRef a1_; 454 GateRef a2_; 455 }; 456 457 class CallThisRangeTypeInfoAccessor final : public CallThisTypeInfoAccessor { 458 public: 459 CallThisRangeTypeInfoAccessor(const JSThread *thread, 460 Circuit *circuit, 461 GateRef gate); 462 NO_COPY_SEMANTIC(CallThisRangeTypeInfoAccessor); 463 NO_MOVE_SEMANTIC(CallThisRangeTypeInfoAccessor); 464 }; 465 466 enum CallKind : uint8_t { 467 CALL, 468 CALL_THIS, 469 CALL_INIT, 470 CALL_SETTER, 471 CALL_GETTER, 472 INVALID 473 }; 474 475 class InlineTypeInfoAccessor final : public TypeInfoAccessor { 476 public: 477 InlineTypeInfoAccessor(const JSThread *thread, 478 Circuit *circuit, 479 GateRef gate, 480 GateRef receiver, 481 CallKind kind); 482 IsEnableNormalInline()483 bool IsEnableNormalInline() const 484 { 485 return IsFunctionTypeKind() || IsValidCallMethodId(); 486 } 487 IsEnableAccessorInline()488 bool IsEnableAccessorInline() const 489 { 490 if (plr_.IsAccessor() && IsClassInstanceTypeKind()) { 491 GlobalTSTypeRef gt = GetAccessorFuncGT(); 492 if (!gt.IsDefault()) { 493 return true; 494 } 495 } 496 return false; 497 } 498 IsFunctionTypeKind()499 bool IsFunctionTypeKind() const 500 { 501 return tsManager_->IsFunctionTypeKind(acc_.GetGateType(receiver_)); 502 } 503 IsClassInstanceTypeKind()504 bool IsClassInstanceTypeKind() const 505 { 506 return tsManager_->IsClassInstanceTypeKind(acc_.GetGateType(receiver_)); 507 } 508 IsValidCallMethodId()509 bool IsValidCallMethodId() const 510 { 511 return GetPGOType().IsValidCallMethodId(); 512 } 513 GetFuncMethodOffsetFromPGO()514 uint32_t GetFuncMethodOffsetFromPGO() const 515 { 516 if (GetPGOType().IsValidCallMethodId()) { 517 return GetPGOType().GetCallMethodId(); 518 } 519 return 0; 520 } 521 GetReceiverGT()522 GateType GetReceiverGT() const 523 { 524 return acc_.GetGateType(receiver_); 525 } 526 527 uint32_t GetCallMethodId() const; 528 GetCallGate()529 GateRef GetCallGate() const 530 { 531 return GetGate(); 532 } 533 IsCallInit()534 bool IsCallInit() const 535 { 536 return kind_ == CallKind::CALL_INIT; 537 } 538 IsCallThis()539 bool IsCallThis() const 540 { 541 return kind_ == CallKind::CALL_THIS || kind_ == CallKind::CALL_INIT; 542 } 543 IsNormalCall()544 bool IsNormalCall() const 545 { 546 return kind_ == CallKind::CALL || kind_ == CallKind::CALL_THIS || kind_ == CallKind::CALL_INIT; 547 } 548 IsCallAccessor()549 bool IsCallAccessor() const 550 { 551 return kind_ == CallKind::CALL_SETTER || kind_ == CallKind::CALL_GETTER; 552 } 553 IsCallGetter()554 bool IsCallGetter() const 555 { 556 return kind_ == CallKind::CALL_GETTER; 557 } 558 IsCallSetter()559 bool IsCallSetter() const 560 { 561 return kind_ == CallKind::CALL_SETTER; 562 } 563 GetType()564 uint32_t GetType() const 565 { 566 uint32_t type = 0; 567 if (IsFunctionTypeKind()) { 568 type = GetReceiverGT().Value(); 569 } 570 if (type == 0) { 571 if (IsNormalCall() && IsValidCallMethodId()) { 572 type = GetPGOType().GetValue(); 573 } 574 } 575 return type; 576 } 577 GetPlr()578 PropertyLookupResult GetPlr() const 579 { 580 return plr_; 581 } 582 583 private: 584 PropertyLookupResult GetAccessorPlr() const; 585 GlobalTSTypeRef GetAccessorFuncGT() const; 586 587 GateRef receiver_; 588 CallKind kind_ {CallKind::INVALID}; 589 PropertyLookupResult plr_ { PropertyLookupResult() }; 590 }; 591 592 class ObjectAccessTypeInfoAccessor : public TypeInfoAccessor { 593 public: 594 class ObjectAccessInfo final { 595 public: 596 explicit ObjectAccessInfo(int hclassIndex = -1, PropertyLookupResult plr = PropertyLookupResult()) hclassIndex_(hclassIndex)597 : hclassIndex_(hclassIndex), plr_(plr) {} 598 Set(int hclassIndex,PropertyLookupResult plr)599 void Set(int hclassIndex, PropertyLookupResult plr) 600 { 601 hclassIndex_ = hclassIndex; 602 plr_ = plr; 603 } 604 HClassIndex()605 int HClassIndex() const 606 { 607 return hclassIndex_; 608 } 609 Plr()610 PropertyLookupResult Plr() const 611 { 612 return plr_; 613 } 614 615 private: 616 int hclassIndex_; 617 PropertyLookupResult plr_; 618 }; 619 620 enum AccessMode : uint8_t { 621 LOAD = 0, 622 STORE 623 }; 624 ObjectAccessTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)625 ObjectAccessTypeInfoAccessor(const JSThread *thread, 626 Circuit *circuit, 627 GateRef gate, 628 Chunk *chunk, 629 AccessMode mode) 630 : TypeInfoAccessor(thread, circuit, gate), 631 chunk_(chunk), 632 mode_(mode), 633 key_(Circuit::NullGate()), 634 receiver_(Circuit::NullGate()) 635 {} 636 NO_COPY_SEMANTIC(ObjectAccessTypeInfoAccessor); 637 NO_MOVE_SEMANTIC(ObjectAccessTypeInfoAccessor); 638 639 JSTaggedValue GetKeyTaggedValue() const; 640 GetKey()641 GateRef GetKey() const 642 { 643 return key_; 644 } 645 GetReceiver()646 GateRef GetReceiver() const 647 { 648 return receiver_; 649 } 650 GetReceiverGateType()651 GateType GetReceiverGateType() const 652 { 653 return tsManager_->TryNarrowUnionType(acc_.GetGateType(receiver_)); 654 } 655 656 protected: 657 Chunk *chunk_; 658 AccessMode mode_; 659 GateRef key_; 660 GateRef receiver_; 661 }; 662 663 class ObjAccByNameTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 664 public: ObjAccByNameTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)665 ObjAccByNameTypeInfoAccessor(const JSThread *thread, 666 Circuit *circuit, 667 GateRef gate, 668 Chunk *chunk, 669 AccessMode mode) 670 : ObjectAccessTypeInfoAccessor(thread, circuit, gate, chunk, mode), 671 hasIllegalType_(false), 672 accessInfos_(chunk), 673 checkerInfos_(chunk) 674 {} 675 676 NO_COPY_SEMANTIC(ObjAccByNameTypeInfoAccessor); 677 NO_MOVE_SEMANTIC(ObjAccByNameTypeInfoAccessor); 678 HasIllegalType()679 bool HasIllegalType() const 680 { 681 return hasIllegalType_; 682 } 683 GetExpectedHClassIndex(size_t index)684 int GetExpectedHClassIndex(size_t index) const 685 { 686 ASSERT(index < checkerInfos_.size()); 687 return checkerInfos_[index].HClassIndex(); 688 } 689 GetAccessInfo(size_t index)690 ObjectAccessInfo GetAccessInfo(size_t index) const 691 { 692 ASSERT(index < accessInfos_.size()); 693 return accessInfos_[index]; 694 } 695 696 protected: 697 bool GeneratePlr(ProfileTyper type, ObjectAccessInfo &info, JSTaggedValue key) const; 698 699 bool hasIllegalType_; 700 ChunkVector<ObjectAccessInfo> accessInfos_; 701 ChunkVector<ObjectAccessInfo> checkerInfos_; 702 }; 703 704 class LoadObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 705 public: 706 LoadObjByNameTypeInfoAccessor(const JSThread *thread, 707 Circuit *circuit, 708 GateRef gate, 709 Chunk *chunk); 710 NO_COPY_SEMANTIC(LoadObjByNameTypeInfoAccessor); 711 NO_MOVE_SEMANTIC(LoadObjByNameTypeInfoAccessor); 712 GetTypeCount()713 size_t GetTypeCount() 714 { 715 return types_.size(); 716 } 717 TypesIsEmpty()718 bool TypesIsEmpty() 719 { 720 return types_.size() == 0; 721 } 722 IsMono()723 bool IsMono() 724 { 725 return types_.size() == 1; 726 } 727 IsReceiverEqHolder(size_t index)728 bool IsReceiverEqHolder(size_t index) 729 { 730 ASSERT(index < types_.size()); 731 return types_[index].first == types_[index].second; 732 } 733 734 private: 735 void FetchPGORWTypesDual(); 736 737 bool GenerateObjectAccessInfo(); 738 739 ChunkVector<std::pair<ProfileTyper, ProfileTyper>> types_; 740 }; 741 742 class StoreObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 743 public: 744 StoreObjByNameTypeInfoAccessor(const JSThread *thread, 745 Circuit *circuit, 746 GateRef gate, 747 Chunk *chunk); 748 NO_COPY_SEMANTIC(StoreObjByNameTypeInfoAccessor); 749 NO_MOVE_SEMANTIC(StoreObjByNameTypeInfoAccessor); 750 GetTypeCount()751 size_t GetTypeCount() 752 { 753 return types_.size(); 754 } 755 TypesIsEmpty()756 bool TypesIsEmpty() 757 { 758 return types_.size() == 0; 759 } 760 IsMono()761 bool IsMono() 762 { 763 return types_.size() == 1; 764 } 765 IsReceiverEqHolder(size_t index)766 bool IsReceiverEqHolder(size_t index) const 767 { 768 return std::get<0>(types_[index]) == std::get<1>(types_[index]); 769 } 770 IsReceiverNoEqNewHolder(size_t index)771 bool IsReceiverNoEqNewHolder(size_t index) const 772 { 773 return std::get<0>(types_[index]) != std::get<2>(types_[index]); // 2 means 3rd object 774 } 775 IsHolderEqNewHolder(size_t index)776 bool IsHolderEqNewHolder(size_t index) const 777 { 778 return std::get<1>(types_[index]) == std::get<2>(types_[index]); // 2 means 3rd object 779 } 780 GetValue()781 GateRef GetValue() const 782 { 783 return value_; 784 } 785 786 private: 787 void FetchPGORWTypesDual(); 788 789 bool GenerateObjectAccessInfo(); 790 791 ChunkVector<std::tuple<ProfileTyper, ProfileTyper, ProfileTyper>> types_; 792 GateRef value_; 793 }; 794 795 class InstanceOfTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 796 public: 797 InstanceOfTypeInfoAccessor(const JSThread *thread, 798 Circuit *circuit, 799 GateRef gate, 800 Chunk *chunk); 801 NO_COPY_SEMANTIC(InstanceOfTypeInfoAccessor); 802 NO_MOVE_SEMANTIC(InstanceOfTypeInfoAccessor); 803 GetTypeCount()804 size_t GetTypeCount() 805 { 806 return types_.size(); 807 } 808 TypesIsEmpty()809 bool TypesIsEmpty() 810 { 811 return types_.size() == 0; 812 } 813 IsMono()814 bool IsMono() 815 { 816 return types_.size() == 1; 817 } 818 819 JSTaggedValue GetKeyTaggedValue() const; 820 GetTarget()821 GateRef GetTarget() const 822 { 823 return target_; 824 } 825 826 private: 827 void FetchPGORWTypesDual(); 828 829 bool ClassInstanceIsCallable(ProfileTyper type) const; 830 831 bool GenerateObjectAccessInfo(); 832 833 ChunkVector<std::pair<ProfileTyper, ProfileTyper>> types_; 834 GateRef target_; 835 }; 836 837 class AccBuiltinObjTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 838 public: AccBuiltinObjTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)839 AccBuiltinObjTypeInfoAccessor(const JSThread *thread, 840 Circuit *circuit, 841 GateRef gate, 842 Chunk *chunk, 843 AccessMode mode) 844 : ObjectAccessTypeInfoAccessor(thread, circuit, gate, chunk, mode), types_(chunk_) 845 {} 846 NO_COPY_SEMANTIC(AccBuiltinObjTypeInfoAccessor); 847 NO_MOVE_SEMANTIC(AccBuiltinObjTypeInfoAccessor); 848 IsMono()849 bool IsMono() const 850 { 851 return types_.size() == 1 || 852 IsAllString(); 853 } 854 IsBuiltinsString()855 bool IsBuiltinsString() const 856 { 857 return types_[0].IsBuiltinsString(); 858 } 859 IsBuiltinsArray()860 bool IsBuiltinsArray() const 861 { 862 return types_[0].IsBuiltinsArray(); 863 } 864 IsBuiltinInstanceType(BuiltinTypeId type)865 bool IsBuiltinInstanceType(BuiltinTypeId type) const 866 { 867 return tsManager_->IsBuiltinInstanceType(type, GetReceiverGateType()); 868 } 869 TryGetHeapMode()870 OnHeapMode TryGetHeapMode() const 871 { 872 return acc_.TryGetOnHeapMode(gate_); 873 } 874 TryConvertKeyToInt()875 uint32_t TryConvertKeyToInt() const 876 { 877 return static_cast<uint32_t>(acc_.GetConstantValue(GetKey())); 878 } 879 KeyIsNumberType()880 bool KeyIsNumberType() const 881 { 882 return acc_.GetGateType(key_).IsNumberType(); 883 } 884 IsArrayTypeKind()885 bool IsArrayTypeKind() const 886 { 887 return tsManager_->IsArrayTypeKind(GetReceiverGateType()); 888 } 889 TryGetArrayElementsKind()890 ElementsKind TryGetArrayElementsKind() const 891 { 892 [[maybe_unused]] bool condition = IsArrayTypeKind() || (IsMono() && IsBuiltinsArray()); 893 ASSERT(condition); 894 return acc_.TryGetArrayElementsKind(gate_); 895 } 896 IsValidTypedArrayType()897 bool IsValidTypedArrayType() const 898 { 899 return tsManager_->IsValidTypedArrayType(GetReceiverGateType()); 900 } 901 902 protected: 903 bool IsAllString() const; 904 void FetchBuiltinsTypes(); 905 bool CheckDuplicatedBuiltinType(ProfileType newType) const; 906 907 ChunkVector<ProfileType> types_; 908 }; 909 910 class LoadBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { 911 public: 912 LoadBulitinObjTypeInfoAccessor(const JSThread *thread, 913 Circuit *circuit, 914 GateRef gate, 915 Chunk *chunk); 916 NO_COPY_SEMANTIC(LoadBulitinObjTypeInfoAccessor); 917 NO_MOVE_SEMANTIC(LoadBulitinObjTypeInfoAccessor); 918 IsStringType()919 bool IsStringType() const 920 { 921 return GetReceiverGateType().IsStringType(); 922 } 923 IsArrayType()924 bool IsArrayType() const 925 { 926 GateType temp = GetReceiverGateType(); 927 return tsManager_->IsArrayTypeKind(temp) || 928 tsManager_->IsBuiltinInstanceType(BuiltinTypeId::ARRAY, temp); 929 } 930 GetTypedArrayBuiltinId()931 BuiltinTypeId GetTypedArrayBuiltinId() const 932 { 933 ASSERT(IsValidTypedArrayType()); 934 return tsManager_->GetTypedArrayBuiltinId(GetReceiverGateType()); 935 } 936 }; 937 938 class StoreBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { 939 public: 940 StoreBulitinObjTypeInfoAccessor(const JSThread *thread, 941 Circuit *circuit, 942 GateRef gate, 943 Chunk *chunk); 944 NO_COPY_SEMANTIC(StoreBulitinObjTypeInfoAccessor); 945 NO_MOVE_SEMANTIC(StoreBulitinObjTypeInfoAccessor); 946 ValueIsNumberType()947 bool ValueIsNumberType() const 948 { 949 return acc_.GetGateType(value_).IsNumberType(); 950 } 951 GetValue()952 GateRef GetValue() const 953 { 954 return value_; 955 } 956 957 private: 958 GateRef value_; 959 }; 960 961 class GlobalObjAccTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 962 public: GlobalObjAccTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate,AccessMode mode)963 GlobalObjAccTypeInfoAccessor(const JSThread *thread, 964 Circuit *circuit, 965 GateRef gate, 966 AccessMode mode) 967 : ObjectAccessTypeInfoAccessor(thread, circuit, gate, nullptr, mode) {} 968 969 NO_COPY_SEMANTIC(GlobalObjAccTypeInfoAccessor); 970 NO_MOVE_SEMANTIC(GlobalObjAccTypeInfoAccessor); 971 }; 972 973 class LoadGlobalObjByNameTypeInfoAccessor final : public GlobalObjAccTypeInfoAccessor { 974 public: LoadGlobalObjByNameTypeInfoAccessor(const JSThread * thread,Circuit * circuit,GateRef gate)975 LoadGlobalObjByNameTypeInfoAccessor(const JSThread *thread, 976 Circuit *circuit, 977 GateRef gate) 978 : GlobalObjAccTypeInfoAccessor(thread, circuit, gate, AccessMode::LOAD) 979 { 980 key_ = acc_.GetValueIn(gate, 1); 981 } 982 NO_COPY_SEMANTIC(LoadGlobalObjByNameTypeInfoAccessor); 983 NO_MOVE_SEMANTIC(LoadGlobalObjByNameTypeInfoAccessor); 984 }; 985 986 class CreateObjWithBufferTypeInfoAccessor : public TypeInfoAccessor { 987 public: 988 CreateObjWithBufferTypeInfoAccessor(const JSThread *thread, 989 Circuit *circuit, 990 GateRef gate, 991 const CString &recordName); 992 993 NO_COPY_SEMANTIC(CreateObjWithBufferTypeInfoAccessor); 994 NO_MOVE_SEMANTIC(CreateObjWithBufferTypeInfoAccessor); 995 996 JSTaggedValue GetHClass() const; 997 GetObjHandle()998 JSHandle<JSObject> GetObjHandle() const 999 { 1000 return objHandle_; 1001 } 1002 GetIndex()1003 GateRef GetIndex() const 1004 { 1005 return index_; 1006 } 1007 CanOptimize()1008 bool CanOptimize() const 1009 { 1010 TaggedArray *properties = TaggedArray::Cast(objHandle_->GetProperties()); 1011 TaggedArray *elements = TaggedArray::Cast(objHandle_->GetElements()); 1012 return properties->GetLength() == 0 && elements->GetLength() == 0; 1013 } 1014 1015 private: 1016 void Init(); 1017 1018 const CString &recordName_; 1019 JSHandle<JSObject> objHandle_; 1020 GateRef index_; 1021 }; 1022 } // panda::ecmascript::kungfu 1023 #endif // ECMASCRIPT_COMPILER_TYPE_INFO_ACCESSORS_H 1024