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