• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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