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/aot_compiler_preprocessor.h" 20 #include "ecmascript/compiler/argument_accessor.h" 21 #include "ecmascript/compiler/pgo_type/pgo_type_manager.h" 22 #include "ecmascript/enum_conversion.h" 23 #include "ecmascript/global_index.h" 24 #include "ecmascript/jspandafile/program_object.h" 25 #include "ecmascript/mem/chunk.h" 26 #include "libpandafile/index_accessor.h" 27 28 namespace panda::ecmascript::kungfu { 29 class TypeInfoAccessor { 30 public: TypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)31 TypeInfoAccessor(const CompilationEnv *env, Circuit* circuit, GateRef gate) 32 : compilationEnv_(env), 33 acc_(circuit), 34 argAcc_(circuit), 35 gate_(gate) 36 { 37 pgoType_ = acc_.TryGetPGOType(gate); 38 // NOTICE-PGO: wx delete in part3 39 ptManager_ = compilationEnv_->GetPTManager(); 40 isAot_ = compilationEnv_->IsAotCompiler(); 41 } 42 GetGate()43 inline GateRef GetGate() const 44 { 45 return gate_; 46 } 47 48 static bool IsTrustedBooleanType(GateAccessor acc, GateRef gate); 49 50 static bool IsTrustedNumberType(GateAccessor acc, GateRef gate); 51 52 static bool IsTrustedStringType( 53 const CompilationEnv *env, Circuit *circuit, Chunk *chunk, GateAccessor acc, GateRef gate); 54 IsTrustedBooleanOrNumberOrStringType(const CompilationEnv * env,Circuit * circuit,Chunk * chunk,GateAccessor acc,GateRef gate)55 static inline bool IsTrustedBooleanOrNumberOrStringType(const CompilationEnv *env, Circuit *circuit, 56 Chunk *chunk, GateAccessor acc, GateRef gate) 57 { 58 return IsTrustedBooleanType(acc, gate) || IsTrustedNumberType(acc, gate) || 59 IsTrustedStringType(env, circuit, chunk, acc, gate); 60 } 61 IsAot()62 inline bool IsAot() const 63 { 64 return isAot_; 65 } 66 67 static bool IsTrustedNotSameType(const CompilationEnv *env, Circuit *circuit, Chunk *chunk, 68 GateAccessor acc, GateRef left, GateRef right); 69 70 BuiltinsStubCSigns::ID TryGetPGOBuiltinMethodId() const; 71 72 static constexpr uint32_t INVALID_LEN = std::numeric_limits<uint32_t>::max(); 73 74 protected: 75 ParamType PGOSampleTypeToParamType() const; 76 static ParamType PGOBuiltinTypeToParamType(ProfileType pgoType); 77 bool IsMegaType() const; 78 79 const CompilationEnv *compilationEnv_ {nullptr}; 80 GateAccessor acc_; 81 ArgumentAccessor argAcc_; 82 GateRef gate_; 83 PGOTypeRef pgoType_; 84 // NOTICE-PGO: wx delete in part3 85 PGOTypeManager *ptManager_ {nullptr}; 86 bool isAot_; 87 }; 88 89 class BinOpTypeInfoAccessor final : public TypeInfoAccessor { 90 public: BinOpTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)91 BinOpTypeInfoAccessor(const CompilationEnv *env, 92 Circuit *circuit, 93 GateRef gate) 94 : TypeInfoAccessor(env, circuit, gate) 95 { 96 left_ = acc_.GetValueIn(gate, 0); // 0: left 97 right_ = acc_.GetValueIn(gate, 1); // 1: right 98 } 99 NO_COPY_SEMANTIC(BinOpTypeInfoAccessor); 100 NO_MOVE_SEMANTIC(BinOpTypeInfoAccessor); 101 GetLeftGate()102 inline GateRef GetLeftGate() const 103 { 104 return left_; 105 } 106 GetReightGate()107 inline GateRef GetReightGate() const 108 { 109 return right_; 110 } 111 HasNumberType()112 inline bool HasNumberType() const 113 { 114 if (LeftOrRightIsUndefinedOrNull()) { 115 return false; 116 } 117 return pgoType_.HasNumber(); 118 } 119 IsStringType()120 inline bool IsStringType() const 121 { 122 if (LeftOrRightIsUndefinedOrNull()) { 123 return false; 124 } 125 return pgoType_.IsString(); 126 } 127 IsNumberOrStringType()128 inline bool IsNumberOrStringType() const 129 { 130 if (LeftOrRightIsUndefinedOrNull()) { 131 return false; 132 } 133 return pgoType_.IsNumberOrString(); 134 } 135 LeftOrRightIsUndefinedOrNull()136 inline bool LeftOrRightIsUndefinedOrNull() const 137 { 138 return acc_.IsUndefinedOrNullOrHole(left_) || acc_.IsUndefinedOrNullOrHole(right_); 139 } 140 GetParamType()141 inline ParamType GetParamType() const 142 { 143 if (LeftOrRightIsUndefinedOrNull()) { 144 return ParamType::AnyType(); 145 } 146 return PGOSampleTypeToParamType(); 147 } 148 149 private: 150 GateRef left_; 151 GateRef right_; 152 }; 153 154 class UnOpTypeInfoAccessor : public TypeInfoAccessor { 155 public: UnOpTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)156 UnOpTypeInfoAccessor(const CompilationEnv *env, 157 Circuit *circuit, 158 GateRef gate) 159 : TypeInfoAccessor(env, circuit, gate) 160 { 161 value_ = acc_.GetValueIn(gate, 0); // 0: value 162 } 163 NO_COPY_SEMANTIC(UnOpTypeInfoAccessor); 164 NO_MOVE_SEMANTIC(UnOpTypeInfoAccessor); 165 GetValue()166 inline GateRef GetValue() const 167 { 168 return value_; 169 } 170 HasNumberType()171 inline bool HasNumberType() const 172 { 173 return pgoType_.HasNumber(); 174 } 175 IsBooleanType()176 inline bool IsBooleanType() const 177 { 178 return pgoType_.IsBoolean(); 179 } 180 GetParamType()181 inline ParamType GetParamType() const 182 { 183 return PGOSampleTypeToParamType(); 184 } 185 GetValueGateType()186 GateType GetValueGateType() const 187 { 188 return acc_.GetGateType(value_); 189 } 190 191 protected: 192 GateRef value_ {Circuit::NullGate()}; 193 }; 194 195 class ConditionJumpTypeInfoAccessor final : public UnOpTypeInfoAccessor { 196 public: ConditionJumpTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)197 ConditionJumpTypeInfoAccessor(const CompilationEnv *env, 198 Circuit *circuit, 199 GateRef gate) 200 : UnOpTypeInfoAccessor(env, circuit, gate) {} 201 NO_COPY_SEMANTIC(ConditionJumpTypeInfoAccessor); 202 NO_MOVE_SEMANTIC(ConditionJumpTypeInfoAccessor); 203 GetBranchWeight()204 uint32_t GetBranchWeight() const 205 { 206 return acc_.TryGetPGOType(value_).GetPGOSampleType()->GetWeight(); 207 } 208 }; 209 210 class NewObjRangeTypeInfoAccessor final : public UnOpTypeInfoAccessor { 211 public: 212 class AccessorStrategy { 213 public: 214 virtual ~AccessorStrategy() = default; 215 virtual bool IsValidCallMethodId() const = 0; 216 virtual uint32_t GetCallMethodId() const = 0; 217 virtual bool FindHClass() const = 0; 218 virtual JSTaggedValue GetHClass() const = 0; 219 }; 220 221 class AotAccessorStrategy : public AccessorStrategy { 222 public: AotAccessorStrategy(NewObjRangeTypeInfoAccessor & parent)223 explicit AotAccessorStrategy(NewObjRangeTypeInfoAccessor &parent) : parent_(parent) 224 { 225 } 226 IsValidCallMethodId()227 bool IsValidCallMethodId() const override 228 { 229 return parent_.pgoType_.IsValidCallMethodId(); 230 } 231 GetCallMethodId()232 uint32_t GetCallMethodId() const override 233 { 234 ASSERT(IsValidCallMethodId()); 235 return parent_.pgoType_.GetCallMethodId(); 236 } 237 bool FindHClass() const override; 238 JSTaggedValue GetHClass() const override; 239 240 private: 241 NewObjRangeTypeInfoAccessor &parent_; 242 }; 243 244 class JitAccessorStrategy : public AccessorStrategy { 245 public: JitAccessorStrategy(NewObjRangeTypeInfoAccessor & parent)246 explicit JitAccessorStrategy(NewObjRangeTypeInfoAccessor &parent) : parent_(parent) 247 { 248 } 249 IsValidCallMethodId()250 bool IsValidCallMethodId() const override 251 { 252 return parent_.pgoType_.IsDefOpValidCallMethodId(); 253 } 254 GetCallMethodId()255 uint32_t GetCallMethodId() const override 256 { 257 ASSERT(IsValidCallMethodId()); 258 return parent_.pgoType_.GetDefOpCallMethodId(); 259 } 260 bool FindHClass() const override; 261 JSTaggedValue GetHClass() const override; 262 263 private: 264 NewObjRangeTypeInfoAccessor &parent_; 265 }; 266 NewObjRangeTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)267 NewObjRangeTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk* chunk) 268 : UnOpTypeInfoAccessor(env, circuit, gate), hclassIndex_(-1), traHClassIndex_(-1) 269 { 270 if (IsAot()) { 271 strategy_ = chunk->New<AotAccessorStrategy>(*this); 272 } else { 273 strategy_ = chunk->New<JitAccessorStrategy>(*this); 274 } 275 } 276 NO_COPY_SEMANTIC(NewObjRangeTypeInfoAccessor); 277 NO_MOVE_SEMANTIC(NewObjRangeTypeInfoAccessor); 278 FindHClass()279 bool FindHClass() 280 { 281 return strategy_->FindHClass(); 282 } GetHClass()283 JSTaggedValue GetHClass() 284 { 285 return strategy_->GetHClass(); 286 } 287 IsValidCallMethodId()288 bool IsValidCallMethodId() const 289 { 290 return strategy_->IsValidCallMethodId(); 291 } 292 GetCallMethodId()293 uint32_t GetCallMethodId() const 294 { 295 ASSERT(IsValidCallMethodId()); 296 return strategy_->GetCallMethodId(); 297 } 298 GetHClassIndex()299 int GetHClassIndex() const 300 { 301 if (traHClassIndex_ != -1) { 302 return traHClassIndex_; 303 } 304 return hclassIndex_; 305 } 306 307 private: 308 int hclassIndex_; 309 int traHClassIndex_ {-1}; 310 AccessorStrategy* strategy_; 311 312 friend class AotAccessorStrategy; 313 friend class JitAccessorStrategy; 314 }; 315 316 class NewBuiltinCtorTypeInfoAccessor final : public UnOpTypeInfoAccessor { 317 public: NewBuiltinCtorTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)318 NewBuiltinCtorTypeInfoAccessor(const CompilationEnv *env, 319 Circuit *circuit, 320 GateRef gate) 321 : UnOpTypeInfoAccessor(env, circuit, gate) {} 322 NO_COPY_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); 323 NO_MOVE_SEMANTIC(NewBuiltinCtorTypeInfoAccessor); 324 IsBuiltinId(BuiltinsStubCSigns::ID id)325 bool IsBuiltinId(BuiltinsStubCSigns::ID id) 326 { 327 if (pgoType_.IsPGOSampleType()) { 328 return TryGetPGOBuiltinMethodId() == id; 329 } else { 330 return false; 331 } 332 } 333 334 private: GetCtorGT()335 GlobalTSTypeRef GetCtorGT() const 336 { 337 return GetValueGateType().GetGTRef(); 338 } 339 }; 340 341 class TypeOfTypeInfoAccessor final : public UnOpTypeInfoAccessor { 342 public: TypeOfTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)343 TypeOfTypeInfoAccessor(const CompilationEnv *env, 344 Circuit *circuit, 345 GateRef gate) 346 : UnOpTypeInfoAccessor(env, circuit, gate) {} 347 NO_COPY_SEMANTIC(TypeOfTypeInfoAccessor); 348 NO_MOVE_SEMANTIC(TypeOfTypeInfoAccessor); 349 350 bool IsIllegalType() const; 351 }; 352 353 class SuperCallTypeInfoAccessor final : public TypeInfoAccessor { 354 public: 355 SuperCallTypeInfoAccessor(const CompilationEnv *env, 356 Circuit *circuit, 357 GateRef gate, 358 const JSPandaFile *jsPandaFile = nullptr, 359 const CallMethodFlagMap *callMethodFlagMap = nullptr); 360 NO_COPY_SEMANTIC(SuperCallTypeInfoAccessor); 361 NO_MOVE_SEMANTIC(SuperCallTypeInfoAccessor); 362 IsValidCallMethodId()363 bool IsValidCallMethodId() const 364 { 365 return pgoType_.IsValidCallMethodId(); 366 } 367 GetMethodId()368 uint32_t GetMethodId() const 369 { 370 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 371 return 0; 372 } 373 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 374 if (!profileType->IsNone()) { 375 return profileType->GetProfileType().GetId(); 376 } 377 return 0; 378 } 379 GetCtor()380 GateRef GetCtor() const 381 { 382 return ctor_; 383 } 384 385 protected: 386 const JSPandaFile *jsPandaFile_; 387 const CallMethodFlagMap *callMethodFlagMap_; 388 389 private: 390 GateRef ctor_; 391 }; 392 393 class CallTypeInfoAccessor : public TypeInfoAccessor { 394 public: 395 CallTypeInfoAccessor(const CompilationEnv *env, 396 Circuit *circuit, 397 GateRef gate, 398 const JSPandaFile *jsPandaFile = nullptr, 399 const CallMethodFlagMap *callMethodFlagMap = nullptr) TypeInfoAccessor(env,circuit,gate)400 : TypeInfoAccessor(env, circuit, gate), 401 argc_(0), 402 func_(Circuit::NullGate()), 403 jsPandaFile_(jsPandaFile), 404 callMethodFlagMap_(callMethodFlagMap) 405 {} 406 GetArgc()407 size_t GetArgc() const 408 { 409 return argc_; 410 } 411 GetFunc()412 GateRef GetFunc() const 413 { 414 return func_; 415 } 416 GetFuncGateType()417 GateType GetFuncGateType() const 418 { 419 return acc_.GetGateType(func_); 420 } 421 IsValidCallMethodId()422 bool IsValidCallMethodId() const 423 { 424 return pgoType_.IsValidCallMethodId(); 425 } 426 IsHotnessFunc()427 bool IsHotnessFunc() const 428 { 429 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 430 return false; 431 } 432 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 433 bool haveProfileType = !profileType->IsNone(); 434 if (haveProfileType) { 435 CString fileDesc = jsPandaFile_->GetNormalizedFileDesc(); 436 uint32_t methodId = profileType->GetProfileType().GetId(); 437 return callMethodFlagMap_->IsAotCompile(fileDesc, methodId); 438 } 439 return false; 440 } 441 GetFunctionTypeLength()442 uint32_t GetFunctionTypeLength() const 443 { 444 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 445 return INVALID_LEN; 446 } 447 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 448 bool haveProfileType = !profileType->IsNone(); 449 if (haveProfileType) { 450 uint32_t methodId = profileType->GetProfileType().GetId(); 451 MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId); 452 if (UNLIKELY(targetMethodLiteral == nullptr)) { 453 return INVALID_LEN; 454 } 455 456 return targetMethodLiteral->GetNumArgsWithCallField(); 457 } 458 return INVALID_LEN; 459 } 460 IsNoGC()461 bool IsNoGC() const 462 { 463 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 464 return false; 465 } 466 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 467 bool haveProfileType = !profileType->IsNone(); 468 if (haveProfileType) { 469 uint32_t methodId = profileType->GetProfileType().GetId(); 470 MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId); 471 if (UNLIKELY(targetMethodLiteral == nullptr)) { 472 return false; 473 } 474 return targetMethodLiteral->IsNoGC(); 475 } 476 return false; 477 } 478 GetMethodIndex()479 int GetMethodIndex() const 480 { 481 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 482 return -1; 483 } 484 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 485 bool haveProfileType = !profileType->IsNone(); 486 if (haveProfileType) { 487 uint32_t methodId = profileType->GetProfileType().GetId(); 488 panda_file::IndexAccessor indexAccessor(*(jsPandaFile_->GetPandaFile()), 489 panda_file::File::EntityId(methodId)); 490 uint32_t cpId = static_cast<uint32_t>(indexAccessor.GetHeaderIndex()); 491 ConstantPool *constpoolHandle = 492 ConstantPool::Cast(compilationEnv_->FindConstpool(jsPandaFile_, cpId).GetTaggedObject()); 493 return constpoolHandle->GetMethodIndexByEntityId(panda_file::File::EntityId(methodId)); 494 } 495 return -1; 496 } 497 GetPandaFile()498 const JSPandaFile *GetPandaFile() const 499 { 500 return jsPandaFile_; 501 } 502 GetMethodId()503 uint32_t GetMethodId() const 504 { 505 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 506 return 0; 507 } 508 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 509 if (!profileType->IsNone()) { 510 return profileType->GetProfileType().GetId(); 511 } 512 return 0; 513 } 514 MethodOffsetIsVaild()515 bool MethodOffsetIsVaild() const 516 { 517 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 518 return !profileType->IsNone(); 519 } 520 CanFastCall()521 bool CanFastCall() const 522 { 523 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 524 return false; 525 } 526 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 527 bool haveProfileType = !profileType->IsNone(); 528 if (haveProfileType) { 529 CString fileDesc = jsPandaFile_->GetNormalizedFileDesc(); 530 uint32_t methodId = profileType->GetProfileType().GetId(); 531 return (callMethodFlagMap_->IsAotCompile(fileDesc, methodId) || 532 callMethodFlagMap_->IsJitCompile(fileDesc, methodId)) && 533 callMethodFlagMap_->IsFastCall(fileDesc, methodId); 534 } 535 return false; 536 } 537 GetFuncMethodOffset()538 uint32_t GetFuncMethodOffset() const 539 { 540 if (jsPandaFile_ == nullptr || callMethodFlagMap_ == nullptr) { 541 return false; 542 } 543 auto profileType = acc_.TryGetPGOType(gate_).GetPGOSampleType(); 544 bool haveProfileType = !profileType->IsNone(); 545 if (haveProfileType) { 546 uint32_t methodId = profileType->GetProfileType().GetId(); 547 MethodLiteral *targetMethodLiteral = jsPandaFile_->FindMethodLiteral(methodId); 548 if (UNLIKELY(targetMethodLiteral == nullptr)) { 549 return false; 550 } 551 return targetMethodLiteral->GetMethodId().GetOffset(); 552 } 553 return 0; 554 } 555 556 protected: 557 size_t argc_; 558 GateRef func_; 559 const JSPandaFile *jsPandaFile_; 560 const CallMethodFlagMap *callMethodFlagMap_; 561 }; 562 563 class GetIteratorTypeInfoAccessor final : public CallTypeInfoAccessor { 564 public: 565 GetIteratorTypeInfoAccessor(const CompilationEnv *env, 566 Circuit *circuit, 567 GateRef gate, 568 const JSPandaFile *jsPandaFile = nullptr, 569 const CallMethodFlagMap *callMethodFlagMap = nullptr); 570 NO_COPY_SEMANTIC(GetIteratorTypeInfoAccessor); 571 NO_MOVE_SEMANTIC(GetIteratorTypeInfoAccessor); 572 GetCallee()573 GateRef GetCallee() 574 { 575 return func_; 576 } 577 }; 578 579 class CallArg0TypeInfoAccessor final : public CallTypeInfoAccessor { 580 public: 581 CallArg0TypeInfoAccessor(const CompilationEnv *env, 582 Circuit *circuit, 583 GateRef gate, 584 const JSPandaFile *jsPandaFile = nullptr, 585 const CallMethodFlagMap *callMethodFlagMap = nullptr); 586 NO_COPY_SEMANTIC(CallArg0TypeInfoAccessor); 587 NO_MOVE_SEMANTIC(CallArg0TypeInfoAccessor); 588 }; 589 590 class CallArg1TypeInfoAccessor final : public CallTypeInfoAccessor { 591 public: 592 CallArg1TypeInfoAccessor(const CompilationEnv *env, 593 Circuit *circuit, 594 GateRef gate, 595 const JSPandaFile *jsPandaFile = nullptr, 596 const CallMethodFlagMap *callMethodFlagMap = nullptr); 597 NO_COPY_SEMANTIC(CallArg1TypeInfoAccessor); 598 NO_MOVE_SEMANTIC(CallArg1TypeInfoAccessor); 599 GetValue()600 GateRef GetValue() 601 { 602 return value_; 603 } 604 GetValueGateType()605 GateType GetValueGateType() 606 { 607 return acc_.GetGateType(value_); 608 } 609 610 private: 611 GateRef value_; 612 }; 613 614 class CallArg2TypeInfoAccessor final : public CallTypeInfoAccessor { 615 public: 616 CallArg2TypeInfoAccessor(const CompilationEnv *env, 617 Circuit *circuit, 618 GateRef gate, 619 const JSPandaFile *jsPandaFile = nullptr, 620 const CallMethodFlagMap *callMethodFlagMap = nullptr); 621 NO_COPY_SEMANTIC(CallArg2TypeInfoAccessor); 622 NO_MOVE_SEMANTIC(CallArg2TypeInfoAccessor); 623 }; 624 625 class CallArg3TypeInfoAccessor final : public CallTypeInfoAccessor { 626 public: 627 CallArg3TypeInfoAccessor(const CompilationEnv *env, 628 Circuit *circuit, 629 GateRef gate, 630 const JSPandaFile *jsPandaFile = nullptr, 631 const CallMethodFlagMap *callMethodFlagMap = nullptr); 632 NO_COPY_SEMANTIC(CallArg3TypeInfoAccessor); 633 NO_MOVE_SEMANTIC(CallArg3TypeInfoAccessor); 634 }; 635 636 class CallRangeTypeInfoAccessor final : public CallTypeInfoAccessor { 637 public: 638 CallRangeTypeInfoAccessor(const CompilationEnv *env, 639 Circuit *circuit, 640 GateRef gate, 641 const JSPandaFile *jsPandaFile = nullptr, 642 const CallMethodFlagMap *callMethodFlagMap = nullptr); 643 NO_COPY_SEMANTIC(CallRangeTypeInfoAccessor); 644 NO_MOVE_SEMANTIC(CallRangeTypeInfoAccessor); 645 }; 646 647 class CallThisTypeInfoAccessor : public CallTypeInfoAccessor { 648 public: 649 CallThisTypeInfoAccessor(const CompilationEnv *env, 650 Circuit *circuit, 651 GateRef gate, 652 const JSPandaFile *jsPandaFile = nullptr, 653 const CallMethodFlagMap *callMethodFlagMap = nullptr) CallTypeInfoAccessor(env,circuit,gate,jsPandaFile,callMethodFlagMap)654 : CallTypeInfoAccessor(env, circuit, gate, jsPandaFile, callMethodFlagMap) 655 { 656 thisObj_ = acc_.GetValueIn(gate, 0); 657 } 658 NO_COPY_SEMANTIC(CallThisTypeInfoAccessor); 659 NO_MOVE_SEMANTIC(CallThisTypeInfoAccessor); 660 661 bool CanOptimizeAsFastCall(); 662 GetThisObj()663 GateRef GetThisObj() const 664 { 665 return thisObj_; 666 } 667 protected: 668 GateRef thisObj_; 669 }; 670 671 class CallThis0TypeInfoAccessor final : public CallThisTypeInfoAccessor { 672 public: 673 CallThis0TypeInfoAccessor(const CompilationEnv *env, 674 Circuit *circuit, 675 GateRef gate, 676 const JSPandaFile *jsPandaFile = nullptr, 677 const CallMethodFlagMap *callMethodFlagMap = nullptr); 678 NO_COPY_SEMANTIC(CallThis0TypeInfoAccessor); 679 NO_MOVE_SEMANTIC(CallThis0TypeInfoAccessor); 680 }; 681 682 class CallThis1TypeInfoAccessor final : public CallThisTypeInfoAccessor { 683 public: 684 CallThis1TypeInfoAccessor(const CompilationEnv *env, 685 Circuit *circuit, 686 GateRef gate, 687 const JSPandaFile *jsPandaFile = nullptr, 688 const CallMethodFlagMap *callMethodFlagMap = nullptr); 689 NO_COPY_SEMANTIC(CallThis1TypeInfoAccessor); 690 NO_MOVE_SEMANTIC(CallThis1TypeInfoAccessor); 691 GetArg0()692 GateRef GetArg0() const 693 { 694 return a0_; 695 } 696 GetArgs()697 std::vector<GateRef> GetArgs() 698 { 699 return { thisObj_, a0_ }; 700 } 701 Arg0IsNumberType()702 bool Arg0IsNumberType() const 703 { 704 return acc_.GetGateType(a0_).IsNumberType(); 705 } 706 707 private: 708 GateRef a0_; 709 }; 710 711 class CallThis2TypeInfoAccessor final : public CallThisTypeInfoAccessor { 712 public: 713 CallThis2TypeInfoAccessor(const CompilationEnv *env, 714 Circuit *circuit, 715 GateRef gate, 716 const JSPandaFile *jsPandaFile = nullptr, 717 const CallMethodFlagMap *callMethodFlagMap = nullptr); 718 NO_COPY_SEMANTIC(CallThis2TypeInfoAccessor); 719 NO_MOVE_SEMANTIC(CallThis2TypeInfoAccessor); 720 }; 721 722 class CallThis3TypeInfoAccessor final : public CallThisTypeInfoAccessor { 723 public: 724 CallThis3TypeInfoAccessor(const CompilationEnv *env, 725 Circuit *circuit, 726 GateRef gate, 727 const JSPandaFile *jsPandaFile = nullptr, 728 const CallMethodFlagMap *callMethodFlagMap = nullptr); 729 NO_COPY_SEMANTIC(CallThis3TypeInfoAccessor); 730 NO_MOVE_SEMANTIC(CallThis3TypeInfoAccessor); 731 GetArgs()732 std::vector<GateRef> GetArgs() 733 { 734 return { thisObj_, a0_, a1_, a2_ }; 735 } 736 737 private: 738 GateRef a0_; 739 GateRef a1_; 740 GateRef a2_; 741 }; 742 743 class CallThisRangeTypeInfoAccessor final : public CallThisTypeInfoAccessor { 744 public: 745 CallThisRangeTypeInfoAccessor(const CompilationEnv *env, 746 Circuit *circuit, 747 GateRef gate, 748 const JSPandaFile *jsPandaFile = nullptr, 749 const CallMethodFlagMap *callMethodFlagMap = nullptr); 750 NO_COPY_SEMANTIC(CallThisRangeTypeInfoAccessor); 751 NO_MOVE_SEMANTIC(CallThisRangeTypeInfoAccessor); 752 }; 753 754 enum CallKind : uint8_t { 755 CALL, 756 CALL_THIS, 757 CALL_INIT, 758 CALL_SETTER, 759 CALL_GETTER, 760 INVALID 761 }; 762 763 class InlineTypeInfoAccessor final : public TypeInfoAccessor { 764 public: 765 InlineTypeInfoAccessor(const CompilationEnv *env, 766 Circuit *circuit, 767 GateRef gate, 768 GateRef receiver, 769 CallKind kind); 770 IsEnableNormalInline()771 bool IsEnableNormalInline() const 772 { 773 return IsValidCallMethodId(); 774 } 775 IsEnableAccessorInline()776 bool IsEnableAccessorInline() const 777 { 778 if (plr_.IsAccessor()) { 779 const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate_).GetPGORWOpType(); 780 auto pgoType = pgoTypes->GetObjectInfo(0); 781 if (pgoType.GetAccessorMethod().GetProfileType().IsValidCallMethodId()) { 782 return true; 783 } 784 } 785 return false; 786 } 787 IsValidCallMethodId()788 bool IsValidCallMethodId() const 789 { 790 return pgoType_.IsValidCallMethodId(); 791 } 792 GetFuncMethodOffsetFromPGO()793 uint32_t GetFuncMethodOffsetFromPGO() const 794 { 795 if (IsValidCallMethodId()) { 796 return pgoType_.GetCallMethodId(); 797 } 798 return 0; 799 } 800 GetReceiverGT()801 GateType GetReceiverGT() const 802 { 803 return acc_.GetGateType(receiver_); 804 } 805 806 uint32_t GetCallMethodId() const; 807 GetCallGate()808 GateRef GetCallGate() const 809 { 810 return GetGate(); 811 } 812 IsCallInit()813 bool IsCallInit() const 814 { 815 return kind_ == CallKind::CALL_INIT; 816 } 817 IsCallThis()818 bool IsCallThis() const 819 { 820 return kind_ == CallKind::CALL_THIS || kind_ == CallKind::CALL_INIT; 821 } 822 IsNormalCall()823 bool IsNormalCall() const 824 { 825 return kind_ == CallKind::CALL || kind_ == CallKind::CALL_THIS || kind_ == CallKind::CALL_INIT; 826 } 827 IsCallAccessor()828 bool IsCallAccessor() const 829 { 830 return kind_ == CallKind::CALL_SETTER || kind_ == CallKind::CALL_GETTER; 831 } 832 IsCallGetter()833 bool IsCallGetter() const 834 { 835 return kind_ == CallKind::CALL_GETTER; 836 } 837 IsCallSetter()838 bool IsCallSetter() const 839 { 840 return kind_ == CallKind::CALL_SETTER; 841 } 842 GetType()843 uint32_t GetType() const 844 { 845 return GetFuncMethodOffsetFromPGO(); 846 } 847 GetPlr()848 PropertyLookupResult GetPlr() const 849 { 850 return plr_; 851 } 852 853 private: 854 PropertyLookupResult GetAccessorPlr() const; 855 PropertyLookupResult GetAccessorPlrInJIT() const; 856 bool InitPropAndCheck(JSTaggedValue &prop) const; 857 858 GateRef receiver_; 859 CallKind kind_ {CallKind::INVALID}; 860 PropertyLookupResult plr_ { PropertyLookupResult() }; 861 }; 862 863 class ObjectAccessTypeInfoAccessor : public TypeInfoAccessor { 864 public: 865 class ObjectAccessInfo final { 866 public: 867 explicit ObjectAccessInfo(int hclassIndex = -1, PropertyLookupResult plr = PropertyLookupResult()) hclassIndex_(hclassIndex)868 : hclassIndex_(hclassIndex), plr_(plr), hclass_(nullptr) {} 869 Set(int hclassIndex,PropertyLookupResult plr)870 void Set(int hclassIndex, PropertyLookupResult plr) 871 { 872 hclassIndex_ = hclassIndex; 873 plr_ = plr; 874 } 875 Set(JSHClass * hclass,PropertyLookupResult plr)876 void Set(JSHClass* hclass, PropertyLookupResult plr) 877 { 878 hclass_ = hclass; 879 plr_ = plr; 880 } 881 HClassIndex()882 int HClassIndex() const 883 { 884 return hclassIndex_; 885 } 886 Plr()887 PropertyLookupResult Plr() const 888 { 889 return plr_; 890 } 891 892 private: 893 int hclassIndex_; 894 PropertyLookupResult plr_; 895 JSHClass* hclass_; 896 }; 897 898 enum AccessMode : uint8_t { 899 LOAD = 0, 900 STORE 901 }; 902 ObjectAccessTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)903 ObjectAccessTypeInfoAccessor(const CompilationEnv *env, 904 Circuit *circuit, 905 GateRef gate, 906 Chunk *chunk, 907 AccessMode mode) 908 : TypeInfoAccessor(env, circuit, gate), 909 chunk_(chunk), 910 mode_(mode), 911 key_(Circuit::NullGate()), 912 receiver_(Circuit::NullGate()) 913 {} 914 NO_COPY_SEMANTIC(ObjectAccessTypeInfoAccessor); 915 NO_MOVE_SEMANTIC(ObjectAccessTypeInfoAccessor); 916 917 JSTaggedValue GetKeyTaggedValue() const; 918 GetKey()919 GateRef GetKey() const 920 { 921 return key_; 922 } 923 GetReceiver()924 GateRef GetReceiver() const 925 { 926 return receiver_; 927 } 928 IsMegaType(const PGORWOpType * pgoTypes)929 static bool IsMegaType(const PGORWOpType *pgoTypes) 930 { 931 for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) { 932 auto temp = pgoTypes->GetObjectInfo(i); 933 if (temp.GetReceiverType().IsMegaStateType()) { 934 return true; 935 } 936 } 937 return false; 938 } 939 940 protected: 941 Chunk *chunk_; 942 AccessMode mode_; 943 GateRef key_; 944 GateRef receiver_; 945 }; 946 947 class ObjAccByNameTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 948 public: ObjAccByNameTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)949 ObjAccByNameTypeInfoAccessor(const CompilationEnv *env, 950 Circuit *circuit, 951 GateRef gate, 952 Chunk *chunk, 953 AccessMode mode) 954 : ObjectAccessTypeInfoAccessor(env, circuit, gate, chunk, mode), 955 hasIllegalType_(false), 956 accessInfos_(chunk), 957 checkerInfos_(chunk) 958 {} 959 960 NO_COPY_SEMANTIC(ObjAccByNameTypeInfoAccessor); 961 NO_MOVE_SEMANTIC(ObjAccByNameTypeInfoAccessor); 962 HasIllegalType()963 bool HasIllegalType() const 964 { 965 return hasIllegalType_; 966 } 967 GetExpectedHClassIndex(size_t index)968 int GetExpectedHClassIndex(size_t index) const 969 { 970 ASSERT(index < checkerInfos_.size()); 971 return checkerInfos_[index].HClassIndex(); 972 } 973 GetAccessInfo(size_t index)974 ObjectAccessInfo GetAccessInfo(size_t index) const 975 { 976 ASSERT(index < accessInfos_.size()); 977 return accessInfos_[index]; 978 } 979 980 protected: 981 bool GeneratePlr(ProfileTyper type, ObjectAccessInfo &info, JSTaggedValue key) const; 982 bool GeneratePlrInJIT(JSHClass* hclass, ObjectAccessInfo &info, JSTaggedValue key) const; 983 984 bool hasIllegalType_; 985 ChunkVector<ObjectAccessInfo> accessInfos_; 986 ChunkVector<ObjectAccessInfo> checkerInfos_; 987 }; 988 989 class LoadPrivatePropertyTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 990 public: 991 class AccessorStrategy { 992 public: 993 virtual ~AccessorStrategy() = default; 994 virtual bool TypesIsEmpty() const = 0; 995 virtual bool IsMono() const = 0; 996 virtual void FetchPGORWTypesDual() = 0; 997 virtual bool GenerateObjectAccessInfo() = 0; 998 }; 999 1000 class AotAccessorStrategy : public AccessorStrategy { 1001 public: AotAccessorStrategy(LoadPrivatePropertyTypeInfoAccessor & parent)1002 explicit AotAccessorStrategy(LoadPrivatePropertyTypeInfoAccessor &parent) : parent_(parent) 1003 { 1004 } 1005 TypesIsEmpty()1006 bool TypesIsEmpty() const override 1007 { 1008 return parent_.types_.empty(); 1009 } 1010 IsMono()1011 bool IsMono() const override 1012 { 1013 return parent_.types_.size() == 1; 1014 } 1015 1016 void FetchPGORWTypesDual() override; 1017 bool GenerateObjectAccessInfo() override; 1018 1019 private: 1020 LoadPrivatePropertyTypeInfoAccessor &parent_; 1021 }; 1022 1023 class JitAccessorStrategy : public AccessorStrategy { 1024 public: JitAccessorStrategy(LoadPrivatePropertyTypeInfoAccessor & parent)1025 explicit JitAccessorStrategy(LoadPrivatePropertyTypeInfoAccessor &parent) : parent_(parent) 1026 { 1027 } 1028 TypesIsEmpty()1029 bool TypesIsEmpty() const override 1030 { 1031 return parent_.jitTypes_.empty(); 1032 } 1033 IsMono()1034 bool IsMono() const override 1035 { 1036 return parent_.jitTypes_.size() == 1; 1037 } 1038 1039 void FetchPGORWTypesDual() override; 1040 bool GenerateObjectAccessInfo() override; 1041 1042 private: 1043 LoadPrivatePropertyTypeInfoAccessor &parent_; 1044 }; 1045 LoadPrivatePropertyTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)1046 LoadPrivatePropertyTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) 1047 : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE), types_(chunk_), jitTypes_(chunk_) 1048 { 1049 levelIndex_ = acc_.GetValueIn(gate, 1); // 1: levelIndex 1050 slotIndex_ = acc_.GetValueIn(gate, 2); // 2: slotIndex 1051 lexicalEnv_ = acc_.GetValueIn(gate, 3); // 3: lexicalEnv 1052 receiver_ = acc_.GetValueIn(gate, 4); // 4: acc as receiver 1053 if (IsAot()) { 1054 strategy_ = chunk_->New<AotAccessorStrategy>(*this); 1055 } else { 1056 strategy_ = chunk_->New<JitAccessorStrategy>(*this); 1057 } 1058 strategy_->FetchPGORWTypesDual(); 1059 hasIllegalType_ = !strategy_->GenerateObjectAccessInfo(); 1060 } 1061 NO_COPY_SEMANTIC(LoadPrivatePropertyTypeInfoAccessor); 1062 NO_MOVE_SEMANTIC(LoadPrivatePropertyTypeInfoAccessor); 1063 IsMono()1064 bool IsMono() const 1065 { 1066 return strategy_->IsMono(); 1067 } 1068 TypesIsEmpty()1069 bool TypesIsEmpty() const 1070 { 1071 return strategy_->TypesIsEmpty(); 1072 } 1073 GetLevelIndex()1074 GateRef GetLevelIndex() const 1075 { 1076 return levelIndex_; 1077 } 1078 GetSlotIndex()1079 GateRef GetSlotIndex() const 1080 { 1081 return slotIndex_; 1082 } 1083 GetLexicalEnv()1084 GateRef GetLexicalEnv() const 1085 { 1086 return lexicalEnv_; 1087 } 1088 IsAccessor()1089 bool IsAccessor() const 1090 { 1091 return isAccessor_; 1092 } 1093 1094 private: 1095 void FetchPGORWTypesDual(); 1096 bool GenerateObjectAccessInfo(); 1097 1098 void FetchPGORWTypesDualInJIT(); 1099 bool GenerateObjectAccessInfoInJIT(); 1100 JSTaggedValue GetKeyTaggedValue() const; 1101 1102 ChunkVector<std::pair<ProfileTyper, ProfileTyper>> types_; 1103 ChunkVector<pgo::PGOObjectInfo> jitTypes_; 1104 GateRef levelIndex_; 1105 GateRef slotIndex_; 1106 GateRef lexicalEnv_; 1107 bool isAccessor_{false}; 1108 AccessorStrategy* strategy_; 1109 friend class AotAccessorStrategy; 1110 friend class JitAccessorStrategy; 1111 }; 1112 1113 class StorePrivatePropertyTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 1114 public: 1115 class AccessorStrategy { 1116 public: 1117 virtual ~AccessorStrategy() = default; 1118 virtual bool TypesIsEmpty() const = 0; 1119 virtual bool IsMono() const = 0; 1120 virtual void FetchPGORWTypesDual() = 0; 1121 virtual bool GenerateObjectAccessInfo() = 0; 1122 }; 1123 1124 class AotAccessorStrategy : public AccessorStrategy { 1125 public: AotAccessorStrategy(StorePrivatePropertyTypeInfoAccessor & parent)1126 explicit AotAccessorStrategy(StorePrivatePropertyTypeInfoAccessor &parent) : parent_(parent) 1127 { 1128 } 1129 TypesIsEmpty()1130 bool TypesIsEmpty() const override 1131 { 1132 return parent_.types_.empty(); 1133 } 1134 IsMono()1135 bool IsMono() const override 1136 { 1137 return parent_.types_.size() == 1; 1138 } 1139 1140 void FetchPGORWTypesDual() override; 1141 bool GenerateObjectAccessInfo() override; 1142 1143 private: 1144 StorePrivatePropertyTypeInfoAccessor &parent_; 1145 }; 1146 1147 class JitAccessorStrategy : public AccessorStrategy { 1148 public: JitAccessorStrategy(StorePrivatePropertyTypeInfoAccessor & parent)1149 explicit JitAccessorStrategy(StorePrivatePropertyTypeInfoAccessor &parent) : parent_(parent) 1150 { 1151 } 1152 TypesIsEmpty()1153 bool TypesIsEmpty() const override 1154 { 1155 return parent_.jitTypes_.empty(); 1156 } 1157 IsMono()1158 bool IsMono() const override 1159 { 1160 return parent_.jitTypes_.size() == 1; 1161 } 1162 1163 void FetchPGORWTypesDual() override; 1164 bool GenerateObjectAccessInfo() override; 1165 1166 private: 1167 StorePrivatePropertyTypeInfoAccessor &parent_; 1168 }; 1169 StorePrivatePropertyTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk)1170 StorePrivatePropertyTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk) 1171 : ObjAccByNameTypeInfoAccessor(env, circuit, gate, chunk, AccessMode::STORE), types_(chunk_), jitTypes_(chunk) 1172 { 1173 levelIndex_ = acc_.GetValueIn(gate, 1); // 1: levelIndex 1174 slotIndex_ = acc_.GetValueIn(gate, 2); // 2: slotIndex 1175 receiver_ = acc_.GetValueIn(gate, 3); // 3: receiver 1176 lexicalEnv_ = acc_.GetValueIn(gate, 4); // 4: lexicalEnv 1177 value_ = acc_.GetValueIn(gate, 5); // 5: acc as value 1178 if (IsAot()) { 1179 strategy_ = chunk_->New<AotAccessorStrategy>(*this); 1180 } else { 1181 strategy_ = chunk_->New<JitAccessorStrategy>(*this); 1182 } 1183 strategy_->FetchPGORWTypesDual(); 1184 hasIllegalType_ = !strategy_->GenerateObjectAccessInfo(); 1185 } 1186 NO_COPY_SEMANTIC(StorePrivatePropertyTypeInfoAccessor); 1187 NO_MOVE_SEMANTIC(StorePrivatePropertyTypeInfoAccessor); 1188 IsMono()1189 bool IsMono() const 1190 { 1191 return strategy_->IsMono(); 1192 } 1193 TypesIsEmpty()1194 bool TypesIsEmpty() const 1195 { 1196 return strategy_->TypesIsEmpty(); 1197 } 1198 GetValue()1199 GateRef GetValue() const 1200 { 1201 return value_; 1202 } 1203 GetLevelIndex()1204 GateRef GetLevelIndex() const 1205 { 1206 return levelIndex_; 1207 } 1208 GetSlotIndex()1209 GateRef GetSlotIndex() const 1210 { 1211 return slotIndex_; 1212 } 1213 GetLexicalEnv()1214 GateRef GetLexicalEnv() const 1215 { 1216 return lexicalEnv_; 1217 } 1218 IsAccessor()1219 bool IsAccessor() const 1220 { 1221 return isAccessor_; 1222 } 1223 1224 private: 1225 JSTaggedValue GetKeyTaggedValue() const; 1226 1227 ChunkVector<std::tuple<ProfileTyper, ProfileTyper, ProfileTyper>> types_; 1228 ChunkVector<pgo::PGOObjectInfo> jitTypes_; 1229 GateRef value_; 1230 GateRef levelIndex_; 1231 GateRef slotIndex_; 1232 GateRef lexicalEnv_; 1233 bool isAccessor_{false}; 1234 AccessorStrategy* strategy_; 1235 friend class AotAccessorStrategy; 1236 friend class JitAccessorStrategy; 1237 }; 1238 1239 class LoadObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 1240 public: 1241 class AccessorStrategy { 1242 public: 1243 virtual ~AccessorStrategy() = default; 1244 virtual size_t GetTypeCount() const = 0; 1245 virtual bool TypesIsEmpty() const = 0; 1246 virtual bool IsMono() const = 0; 1247 virtual bool IsReceiverEqHolder(size_t index) const = 0; 1248 virtual void FetchPGORWTypesDual() = 0; 1249 virtual bool GenerateObjectAccessInfo() = 0; 1250 }; 1251 1252 class AotAccessorStrategy : public AccessorStrategy { 1253 public: AotAccessorStrategy(LoadObjByNameTypeInfoAccessor & parent)1254 explicit AotAccessorStrategy(LoadObjByNameTypeInfoAccessor &parent) : parent_(parent) 1255 { 1256 } 1257 GetTypeCount()1258 size_t GetTypeCount() const override 1259 { 1260 return parent_.types_.size(); 1261 } 1262 TypesIsEmpty()1263 bool TypesIsEmpty() const override 1264 { 1265 return parent_.types_.empty(); 1266 } 1267 IsMono()1268 bool IsMono() const override 1269 { 1270 return parent_.types_.size() == 1; 1271 } 1272 IsReceiverEqHolder(size_t index)1273 bool IsReceiverEqHolder(size_t index) const override 1274 { 1275 ASSERT(index < parent_.types_.size()); 1276 return parent_.types_[index].first == parent_.types_[index].second; 1277 } 1278 1279 void FetchPGORWTypesDual() override; 1280 bool GenerateObjectAccessInfo() override; 1281 1282 private: 1283 LoadObjByNameTypeInfoAccessor &parent_; 1284 }; 1285 1286 class JitAccessorStrategy : public AccessorStrategy { 1287 public: JitAccessorStrategy(LoadObjByNameTypeInfoAccessor & parent)1288 explicit JitAccessorStrategy(LoadObjByNameTypeInfoAccessor &parent) : parent_(parent) 1289 { 1290 } 1291 GetTypeCount()1292 size_t GetTypeCount() const override 1293 { 1294 return parent_.jitTypes_.size(); 1295 } 1296 TypesIsEmpty()1297 bool TypesIsEmpty() const override 1298 { 1299 return parent_.jitTypes_.empty(); 1300 } 1301 IsMono()1302 bool IsMono() const override 1303 { 1304 return parent_.jitTypes_.size() == 1; 1305 } 1306 IsReceiverEqHolder(size_t index)1307 bool IsReceiverEqHolder(size_t index) const override 1308 { 1309 return parent_.jitTypes_[index].GetReceiverHclass() == parent_.jitTypes_[index].GetHolderHclass(); 1310 } 1311 1312 void FetchPGORWTypesDual() override; 1313 bool GenerateObjectAccessInfo() override; 1314 1315 private: 1316 LoadObjByNameTypeInfoAccessor &parent_; 1317 }; 1318 LoadObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); 1319 NO_COPY_SEMANTIC(LoadObjByNameTypeInfoAccessor); 1320 NO_MOVE_SEMANTIC(LoadObjByNameTypeInfoAccessor); 1321 GetTypeCount()1322 size_t GetTypeCount() 1323 { 1324 return strategy_->GetTypeCount(); 1325 } 1326 TypesIsEmpty()1327 bool TypesIsEmpty() 1328 { 1329 return strategy_->TypesIsEmpty(); 1330 } 1331 IsMono()1332 bool IsMono() 1333 { 1334 return strategy_->IsMono(); 1335 } 1336 IsReceiverEqHolder(size_t index)1337 bool IsReceiverEqHolder(size_t index) 1338 { 1339 return strategy_->IsReceiverEqHolder(index); 1340 } 1341 1342 private: 1343 ChunkVector<std::pair<ProfileTyper, ProfileTyper>> types_; 1344 ChunkVector<pgo::PGOObjectInfo> jitTypes_; 1345 1346 AccessorStrategy* strategy_; 1347 friend class AotAccessorStrategy; 1348 friend class JitAccessorStrategy; 1349 }; 1350 1351 class StoreObjByNameTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 1352 public: 1353 class AccessorStrategy { 1354 public: 1355 virtual ~AccessorStrategy() = default; 1356 virtual size_t GetTypeCount() const = 0; 1357 virtual bool TypesIsEmpty() const = 0; 1358 virtual bool IsMono() const = 0; 1359 virtual bool IsReceiverEqHolder(size_t index) const = 0; 1360 virtual bool IsReceiverNoEqNewHolder(size_t index) const = 0; 1361 virtual bool IsHolderEqNewHolder(size_t index) const = 0; 1362 virtual void FetchPGORWTypesDual() = 0; 1363 virtual bool GenerateObjectAccessInfo() = 0; 1364 }; 1365 1366 class AotAccessorStrategy : public AccessorStrategy { 1367 public: AotAccessorStrategy(StoreObjByNameTypeInfoAccessor & parent)1368 explicit AotAccessorStrategy(StoreObjByNameTypeInfoAccessor &parent) : parent_(parent) 1369 { 1370 } 1371 GetTypeCount()1372 size_t GetTypeCount() const override 1373 { 1374 return parent_.types_.size(); 1375 } 1376 TypesIsEmpty()1377 bool TypesIsEmpty() const override 1378 { 1379 return parent_.types_.empty(); 1380 } 1381 IsMono()1382 bool IsMono() const override 1383 { 1384 return parent_.types_.size() == 1; 1385 } 1386 IsReceiverEqHolder(size_t index)1387 bool IsReceiverEqHolder(size_t index) const override 1388 { 1389 return std::get<HclassIndex::Reciver>(parent_.types_[index]) == 1390 std::get<HclassIndex::Holder>(parent_.types_[index]); 1391 } 1392 IsReceiverNoEqNewHolder(size_t index)1393 bool IsReceiverNoEqNewHolder(size_t index) const override 1394 { 1395 return std::get<HclassIndex::Reciver>(parent_.types_[index]) != 1396 std::get<HclassIndex::HolderTra>(parent_.types_[index]); 1397 } 1398 IsHolderEqNewHolder(size_t index)1399 bool IsHolderEqNewHolder(size_t index) const override 1400 { 1401 return std::get<HclassIndex::Holder>(parent_.types_[index]) == 1402 std::get<HclassIndex::HolderTra>(parent_.types_[index]); 1403 } 1404 void FetchPGORWTypesDual() override; 1405 bool GenerateObjectAccessInfo() override; 1406 1407 private: 1408 StoreObjByNameTypeInfoAccessor &parent_; 1409 }; 1410 1411 class JitAccessorStrategy : public AccessorStrategy { 1412 public: JitAccessorStrategy(StoreObjByNameTypeInfoAccessor & parent)1413 explicit JitAccessorStrategy(StoreObjByNameTypeInfoAccessor &parent) : parent_(parent) 1414 { 1415 } 1416 GetTypeCount()1417 size_t GetTypeCount() const override 1418 { 1419 return parent_.jitTypes_.size(); 1420 } 1421 TypesIsEmpty()1422 bool TypesIsEmpty() const override 1423 { 1424 return parent_.jitTypes_.empty(); 1425 } 1426 IsMono()1427 bool IsMono() const override 1428 { 1429 return parent_.jitTypes_.size() == 1; 1430 } 1431 IsReceiverEqHolder(size_t index)1432 bool IsReceiverEqHolder(size_t index) const override 1433 { 1434 return parent_.jitTypes_[index].GetReceiverHclass() == parent_.jitTypes_[index].GetHolderHclass(); 1435 } 1436 IsReceiverNoEqNewHolder(size_t index)1437 bool IsReceiverNoEqNewHolder(size_t index) const override 1438 { 1439 return parent_.jitTypes_[index].GetReceiverHclass() != parent_.jitTypes_[index].GetHolderTraHclass(); 1440 } 1441 IsHolderEqNewHolder(size_t index)1442 bool IsHolderEqNewHolder(size_t index) const override 1443 { 1444 return parent_.jitTypes_[index].GetHolderHclass() == parent_.jitTypes_[index].GetHolderTraHclass(); 1445 } 1446 void FetchPGORWTypesDual() override; 1447 bool GenerateObjectAccessInfo() override; 1448 1449 private: 1450 StoreObjByNameTypeInfoAccessor &parent_; 1451 }; 1452 1453 StoreObjByNameTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); 1454 NO_COPY_SEMANTIC(StoreObjByNameTypeInfoAccessor); 1455 NO_MOVE_SEMANTIC(StoreObjByNameTypeInfoAccessor); 1456 GetTypeCount()1457 size_t GetTypeCount() 1458 { 1459 return strategy_->GetTypeCount(); 1460 } 1461 TypesIsEmpty()1462 bool TypesIsEmpty() 1463 { 1464 return strategy_->TypesIsEmpty(); 1465 } 1466 IsMono()1467 bool IsMono() 1468 { 1469 return strategy_->IsMono(); 1470 } 1471 IsReceiverEqHolder(size_t index)1472 bool IsReceiverEqHolder(size_t index) const 1473 { 1474 return strategy_->IsReceiverEqHolder(index); 1475 } 1476 IsReceiverNoEqNewHolder(size_t index)1477 bool IsReceiverNoEqNewHolder(size_t index) const 1478 { 1479 return strategy_->IsReceiverNoEqNewHolder(index); 1480 } 1481 IsHolderEqNewHolder(size_t index)1482 bool IsHolderEqNewHolder(size_t index) const 1483 { 1484 return strategy_->IsHolderEqNewHolder(index); 1485 } 1486 GetValue()1487 GateRef GetValue() const 1488 { 1489 return value_; 1490 } 1491 1492 private: 1493 enum HclassIndex { 1494 Reciver = 0, 1495 Holder, 1496 HolderTra 1497 }; 1498 ChunkVector<std::tuple<ProfileTyper, ProfileTyper, ProfileTyper>> types_; 1499 ChunkVector<pgo::PGOObjectInfo> jitTypes_; 1500 GateRef value_; 1501 AccessorStrategy* strategy_; 1502 friend class AotAccessorStrategy; 1503 friend class JitAccessorStrategy; 1504 }; 1505 1506 class InstanceOfTypeInfoAccessor final : public ObjAccByNameTypeInfoAccessor { 1507 public: 1508 class AccessorStrategy { 1509 public: 1510 virtual ~AccessorStrategy() = default; 1511 virtual size_t GetTypeCount() const = 0; 1512 virtual bool TypesIsEmpty() const = 0; 1513 virtual bool IsMono() const = 0; 1514 virtual void FetchPGORWTypesDual() = 0; 1515 virtual bool GenerateObjectAccessInfo() = 0; 1516 virtual bool ClassInstanceIsCallable(ProfileTyper type) const = 0; 1517 virtual bool ClassInstanceIsCallable(JSHClass *hclass) const = 0; 1518 }; 1519 1520 class AotAccessorStrategy : public AccessorStrategy { 1521 public: AotAccessorStrategy(InstanceOfTypeInfoAccessor & parent)1522 explicit AotAccessorStrategy(InstanceOfTypeInfoAccessor &parent) : parent_(parent) 1523 { 1524 } 1525 GetTypeCount()1526 size_t GetTypeCount() const override 1527 { 1528 return parent_.types_.size(); 1529 } 1530 TypesIsEmpty()1531 bool TypesIsEmpty() const override 1532 { 1533 return parent_.types_.empty(); 1534 } 1535 IsMono()1536 bool IsMono() const override 1537 { 1538 return parent_.types_.size() == 1; 1539 } 1540 1541 void FetchPGORWTypesDual() override; 1542 bool GenerateObjectAccessInfo() override; 1543 bool ClassInstanceIsCallable(ProfileTyper type) const override; ClassInstanceIsCallable(JSHClass * hclass)1544 bool ClassInstanceIsCallable([[maybe_unused]] JSHClass *hclass) const override 1545 { 1546 ASSERT(0); 1547 return false; 1548 } 1549 1550 private: 1551 InstanceOfTypeInfoAccessor &parent_; 1552 }; 1553 1554 class JitAccessorStrategy : public AccessorStrategy { 1555 public: JitAccessorStrategy(InstanceOfTypeInfoAccessor & parent)1556 explicit JitAccessorStrategy(InstanceOfTypeInfoAccessor &parent) : parent_(parent) 1557 { 1558 } 1559 GetTypeCount()1560 size_t GetTypeCount() const override 1561 { 1562 return parent_.jitTypes_.size(); 1563 } 1564 TypesIsEmpty()1565 bool TypesIsEmpty() const override 1566 { 1567 return parent_.jitTypes_.empty(); 1568 } 1569 IsMono()1570 bool IsMono() const override 1571 { 1572 return parent_.jitTypes_.size() == 1; 1573 } 1574 void FetchPGORWTypesDual() override; 1575 bool GenerateObjectAccessInfo() override; 1576 bool ClassInstanceIsCallable(JSHClass *hclass) const override; ClassInstanceIsCallable(ProfileTyper type)1577 bool ClassInstanceIsCallable([[maybe_unused]] ProfileTyper type) const override 1578 { 1579 ASSERT(0); 1580 return false; 1581 } 1582 1583 private: 1584 InstanceOfTypeInfoAccessor &parent_; 1585 }; 1586 1587 InstanceOfTypeInfoAccessor(const CompilationEnv *env, Circuit *circuit, GateRef gate, Chunk *chunk); 1588 NO_COPY_SEMANTIC(InstanceOfTypeInfoAccessor); 1589 NO_MOVE_SEMANTIC(InstanceOfTypeInfoAccessor); 1590 GetTypeCount()1591 size_t GetTypeCount() 1592 { 1593 return strategy_->GetTypeCount(); 1594 } 1595 TypesIsEmpty()1596 bool TypesIsEmpty() 1597 { 1598 return strategy_->TypesIsEmpty(); 1599 } 1600 IsMono()1601 bool IsMono() 1602 { 1603 return strategy_->IsMono(); 1604 } 1605 1606 JSTaggedValue GetKeyTaggedValue() const; 1607 GetTarget()1608 GateRef GetTarget() const 1609 { 1610 return target_; 1611 } 1612 1613 private: 1614 ChunkVector<std::pair<ProfileTyper, ProfileTyper>> types_; 1615 ChunkVector<pgo::PGOObjectInfo> jitTypes_; 1616 GateRef target_; 1617 AccessorStrategy* strategy_; 1618 1619 friend class AotAccessorStrategy; 1620 friend class JitAccessorStrategy; 1621 }; 1622 1623 class AccBuiltinObjTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 1624 public: AccBuiltinObjTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,Chunk * chunk,AccessMode mode)1625 AccBuiltinObjTypeInfoAccessor(const CompilationEnv *env, 1626 Circuit *circuit, 1627 GateRef gate, 1628 Chunk *chunk, 1629 AccessMode mode) 1630 : ObjectAccessTypeInfoAccessor(env, circuit, gate, chunk, mode), types_(chunk_) 1631 {} 1632 NO_COPY_SEMANTIC(AccBuiltinObjTypeInfoAccessor); 1633 NO_MOVE_SEMANTIC(AccBuiltinObjTypeInfoAccessor); 1634 IsMono()1635 bool IsMono() const 1636 { 1637 return types_.size() == 1 || IsMonoBuiltins(); 1638 } 1639 GetTypeCount()1640 size_t GetTypeCount() 1641 { 1642 return types_.size(); 1643 } 1644 IsBuiltinsMap()1645 bool IsBuiltinsMap() const 1646 { 1647 return types_[0].IsBuiltinsMap(); 1648 } 1649 IsBuiltinsString()1650 bool IsBuiltinsString() const 1651 { 1652 return types_[0].IsBuiltinsString(); 1653 } 1654 IsBuiltinsArray()1655 bool IsBuiltinsArray() const 1656 { 1657 return types_[0].IsBuiltinsArray(); 1658 } 1659 IsBuiltinsTypeArray()1660 bool IsBuiltinsTypeArray() const 1661 { 1662 return types_[0].IsBuiltinsTypeArray(); 1663 } 1664 IsStoreOutOfBounds()1665 bool IsStoreOutOfBounds() const 1666 { 1667 ASSERT(types_.size() > 0); 1668 return types_[0].IsEverOutOfBounds(); 1669 } 1670 HasNoType()1671 bool HasNoType() const 1672 { 1673 return types_.empty(); 1674 } 1675 GetBuiltinsJSType()1676 JSType GetBuiltinsJSType() const 1677 { 1678 if (types_[0].IsBuiltinsType()) { 1679 return types_[0].GetBuiltinsType(); 1680 } 1681 return JSType::INVALID; 1682 } 1683 GetParamType()1684 ParamType GetParamType() const 1685 { 1686 ASSERT(IsMono()); 1687 return TypeInfoAccessor::PGOBuiltinTypeToParamType(types_[0]); 1688 } 1689 IsPolyBuiltinsArray()1690 bool IsPolyBuiltinsArray() const 1691 { 1692 if (types_.size() == 0) { 1693 return false; 1694 } 1695 for (size_t i = 0; i < types_.size(); ++i) { 1696 if (!types_[i].IsBuiltinsArray()) { 1697 return false; 1698 } 1699 } 1700 return true; 1701 } 1702 GetElementsKindBeforeTransition(size_t index)1703 ElementsKind GetElementsKindBeforeTransition(size_t index) 1704 { 1705 ProfileType currType = types_[index]; 1706 return currType.GetElementsKindBeforeTransition(); 1707 } 1708 GetElementsKindAfterTransition(size_t index)1709 ElementsKind GetElementsKindAfterTransition(size_t index) 1710 { 1711 ProfileType currType = types_[index]; 1712 return currType.GetElementsKindAfterTransition(); 1713 } 1714 IsBuiltinsType()1715 bool IsBuiltinsType() const 1716 { 1717 return IsMono() && types_[0].IsBuiltinsType(); 1718 } 1719 IsGlobalsType()1720 bool IsGlobalsType() const 1721 { 1722 return IsMono() && types_[0].IsGlobalsType(); 1723 } 1724 GetBuiltinsTypeId()1725 std::optional<BuiltinTypeId> GetBuiltinsTypeId() const 1726 { 1727 if (!IsMono()) { 1728 return std::nullopt; 1729 } 1730 auto type = types_[0].GetBuiltinsType(); 1731 return ToBuiltinsTypeId(type); 1732 } 1733 GetGlobalsId()1734 std::optional<GlobalIndex> GetGlobalsId() const 1735 { 1736 return types_[0].GetGlobalsId(); 1737 } 1738 TryGetHeapMode()1739 OnHeapMode TryGetHeapMode() const 1740 { 1741 return acc_.TryGetOnHeapMode(gate_); 1742 } 1743 TryConvertKeyToInt()1744 uint32_t TryConvertKeyToInt() const 1745 { 1746 return static_cast<uint32_t>(acc_.GetConstantValue(GetKey())); 1747 } 1748 1749 // Default get is elementsKind before possible transition TryGetArrayElementsKind()1750 ElementsKind TryGetArrayElementsKind() const 1751 { 1752 [[maybe_unused]] bool condition = (IsMono() && IsBuiltinsArray()); 1753 ASSERT(condition); 1754 return acc_.TryGetArrayElementsKind(gate_); 1755 } 1756 TryGetArrayElementsKindAfterTransition()1757 ElementsKind TryGetArrayElementsKindAfterTransition() const 1758 { 1759 [[maybe_unused]] bool condition = (IsMono() && IsBuiltinsArray()); 1760 ASSERT(condition); 1761 return acc_.TryGetArrayElementsKindAfterTransition(gate_); 1762 } 1763 1764 protected: 1765 bool IsMonoBuiltins() const; 1766 bool IsStringMonoBuiltins() const; 1767 void FetchBuiltinsTypes(); 1768 bool CheckDuplicatedBuiltinType(ProfileType newType) const; 1769 1770 ChunkVector<ProfileType> types_; 1771 }; 1772 1773 class LoadBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { 1774 public: 1775 LoadBulitinObjTypeInfoAccessor(const CompilationEnv *env, 1776 Circuit *circuit, 1777 GateRef gate, 1778 Chunk *chunk); 1779 NO_COPY_SEMANTIC(LoadBulitinObjTypeInfoAccessor); 1780 NO_MOVE_SEMANTIC(LoadBulitinObjTypeInfoAccessor); 1781 }; 1782 1783 class StoreBulitinObjTypeInfoAccessor final : public AccBuiltinObjTypeInfoAccessor { 1784 public: 1785 StoreBulitinObjTypeInfoAccessor(const CompilationEnv *env, 1786 Circuit *circuit, 1787 GateRef gate, 1788 Chunk *chunk); 1789 NO_COPY_SEMANTIC(StoreBulitinObjTypeInfoAccessor); 1790 NO_MOVE_SEMANTIC(StoreBulitinObjTypeInfoAccessor); 1791 ValueIsNumberType()1792 bool ValueIsNumberType() const 1793 { 1794 return acc_.GetGateType(value_).IsNumberType(); 1795 } 1796 GetValue()1797 GateRef GetValue() const 1798 { 1799 return value_; 1800 } 1801 1802 private: 1803 GateRef value_ {Circuit::NullGate()}; 1804 }; 1805 1806 class GlobalObjAccTypeInfoAccessor : public ObjectAccessTypeInfoAccessor { 1807 public: GlobalObjAccTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate,AccessMode mode)1808 GlobalObjAccTypeInfoAccessor(const CompilationEnv *env, 1809 Circuit *circuit, 1810 GateRef gate, 1811 AccessMode mode) 1812 : ObjectAccessTypeInfoAccessor(env, circuit, gate, nullptr, mode) {} 1813 1814 NO_COPY_SEMANTIC(GlobalObjAccTypeInfoAccessor); 1815 NO_MOVE_SEMANTIC(GlobalObjAccTypeInfoAccessor); 1816 }; 1817 1818 class LoadGlobalObjByNameTypeInfoAccessor final : public GlobalObjAccTypeInfoAccessor { 1819 public: LoadGlobalObjByNameTypeInfoAccessor(const CompilationEnv * env,Circuit * circuit,GateRef gate)1820 LoadGlobalObjByNameTypeInfoAccessor(const CompilationEnv *env, 1821 Circuit *circuit, 1822 GateRef gate) 1823 : GlobalObjAccTypeInfoAccessor(env, circuit, gate, AccessMode::LOAD) 1824 { 1825 key_ = acc_.GetValueIn(gate, 1); 1826 } 1827 NO_COPY_SEMANTIC(LoadGlobalObjByNameTypeInfoAccessor); 1828 NO_MOVE_SEMANTIC(LoadGlobalObjByNameTypeInfoAccessor); 1829 }; 1830 1831 class CreateObjWithBufferTypeInfoAccessor : public TypeInfoAccessor { 1832 public: 1833 CreateObjWithBufferTypeInfoAccessor(const CompilationEnv *env, 1834 Circuit *circuit, 1835 GateRef gate, 1836 const CString &recordName, 1837 Chunk* chunk); 1838 1839 NO_COPY_SEMANTIC(CreateObjWithBufferTypeInfoAccessor); 1840 NO_MOVE_SEMANTIC(CreateObjWithBufferTypeInfoAccessor); 1841 1842 class AccessorStrategy { 1843 public: 1844 virtual ~AccessorStrategy() = default; 1845 virtual JSTaggedValue GetHClass() const = 0; 1846 }; 1847 1848 class AotAccessorStrategy : public AccessorStrategy { 1849 public: AotAccessorStrategy(CreateObjWithBufferTypeInfoAccessor & parent)1850 explicit AotAccessorStrategy(CreateObjWithBufferTypeInfoAccessor &parent) : parent_(parent) 1851 { 1852 } 1853 1854 JSTaggedValue GetHClass() const override; 1855 1856 private: 1857 CreateObjWithBufferTypeInfoAccessor &parent_; 1858 }; 1859 1860 class JitAccessorStrategy : public AccessorStrategy { 1861 public: JitAccessorStrategy(CreateObjWithBufferTypeInfoAccessor & parent)1862 explicit JitAccessorStrategy(CreateObjWithBufferTypeInfoAccessor &parent) : parent_(parent) 1863 { 1864 } 1865 1866 JSTaggedValue GetHClass() const override; 1867 1868 private: 1869 CreateObjWithBufferTypeInfoAccessor &parent_; 1870 }; 1871 GetHClass()1872 JSTaggedValue GetHClass() const 1873 { 1874 return strategy_->GetHClass(); 1875 } 1876 1877 JSTaggedValue GetObject() const; 1878 GetIndex()1879 GateRef GetIndex() const 1880 { 1881 return index_; 1882 } 1883 CanOptimize()1884 bool CanOptimize() const 1885 { 1886 JSTaggedValue obj = GetObject(); 1887 if (obj.IsUndefined()) { 1888 return false; 1889 } 1890 JSObject *jsObj = JSObject::Cast(obj); 1891 TaggedArray *properties = TaggedArray::Cast(jsObj->GetProperties()); 1892 TaggedArray *elements = TaggedArray::Cast(jsObj->GetElements()); 1893 return properties->GetLength() == 0 && elements->GetLength() == 0; 1894 } 1895 1896 private: 1897 void Init(); 1898 1899 const CString &recordName_; 1900 GateRef index_; 1901 AccessorStrategy* strategy_; 1902 1903 friend class AotAccessorStrategy; 1904 friend class JitAccessorStrategy; 1905 }; 1906 } // panda::ecmascript::kungfu 1907 #endif // ECMASCRIPT_COMPILER_TYPE_INFO_ACCESSORS_H 1908