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