• 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_PGO_PROFILER_TYPES_PGO_PROFILER_TYPE_H
17 #define ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILER_TYPE_H
18 
19 #include <stdint.h>
20 #include <string>
21 #include <variant>
22 #include <vector>
23 
24 #include "ecmascript/elements.h"
25 #include "ecmascript/mem/region.h"
26 #include "ecmascript/log_wrapper.h"
27 #include "ecmascript/pgo_profiler/pgo_utils.h"
28 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
29 #include "libpandabase/utils/bit_field.h"
30 #include "macros.h"
31 
32 namespace panda::ecmascript::pgo {
33 class PGOContext;
34 class PGOType {
35 public:
36     enum class TypeKind : uint8_t {
37         SCALAR_OP_TYPE,
38         RW_OP_TYPE,
39         DEFINE_OP_TYPE,
40     };
41     PGOType() = default;
PGOType(TypeKind kind)42     explicit PGOType(TypeKind kind) : kind_(kind) {}
43 
IsScalarOpType()44     bool IsScalarOpType() const
45     {
46         return kind_ == TypeKind::SCALAR_OP_TYPE;
47     }
48 
IsRwOpType()49     bool IsRwOpType() const
50     {
51         return kind_ == TypeKind::RW_OP_TYPE;
52     }
53 
IsDefineOpType()54     bool IsDefineOpType() const
55     {
56         return kind_ == TypeKind::DEFINE_OP_TYPE;
57     }
58 
59 private:
60     TypeKind kind_ {TypeKind::SCALAR_OP_TYPE};
61 };
62 
63 /**
64  * | INT    \          -> INT_OVERFLOW \
65  * |           NUMBER                    NUMBER_HETEROE1
66  * | DOUBLE /                          /
67  */
68 template <typename PGOProfileType>
69 class PGOSampleTemplate : public PGOType {
70 public:
71     static constexpr int WEIGHT_BITS = 11;
72     static constexpr int WEIGHT_START_BIT = 10;
73     static constexpr int WEIGHT_TRUE_START_BIT = WEIGHT_START_BIT + WEIGHT_BITS;
74     static constexpr int WEIGHT_MASK = (1 << WEIGHT_BITS) - 1;
75 
76     enum class Type : uint32_t {
77         NONE = 0x0ULL,
78         INT = 0x1ULL,                        // 00000001
79         INT_OVERFLOW = (0x1ULL << 1) | INT,  // 00000011
80         DOUBLE = 0x1ULL << 2,                // 00000100
81         NUMBER = INT | DOUBLE,               // 00000101
82         NUMBER1 = INT_OVERFLOW | DOUBLE,     // 00000111
83         BOOLEAN = 0x1ULL << 3,
84         UNDEFINED_OR_NULL = 0x1ULL << 4,
85         SPECIAL = 0x1ULL << 5,
86         BOOLEAN_OR_SPECIAL = BOOLEAN | SPECIAL,
87         STRING = 0x1ULL << 6,
88         BIG_INT = 0x1ULL << 7,
89         HEAP_OBJECT = 0x1ULL << 8,
90         HEAP_OR_UNDEFINED_OR_NULL = HEAP_OBJECT | UNDEFINED_OR_NULL,
91         ANY = (0x1ULL << WEIGHT_START_BIT) - 1,
92     };
93 
PGOSampleTemplate()94     PGOSampleTemplate() : type_(Type::NONE) {};
95 
PGOSampleTemplate(Type type)96     explicit PGOSampleTemplate(Type type) : type_(type) {};
PGOSampleTemplate(uint32_t type)97     explicit PGOSampleTemplate(uint32_t type) : type_(Type(type)) {};
PGOSampleTemplate(PGOProfileType type)98     explicit PGOSampleTemplate(PGOProfileType type) : type_(type) {}
99 
100     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)101     static PGOSampleTemplate ConvertFrom(PGOContext &context, const FromType &from)
102     {
103         if (from.IsProfileType()) {
104             return PGOSampleTemplate(PGOProfileType(context, from.GetProfileType()));
105         }
106         return PGOSampleTemplate(static_cast<PGOSampleTemplate::Type>(from.GetType()));
107     }
108 
109     static PGOSampleTemplate CreateProfileType(ApEntityId recordId, int32_t profileType,
110                                                typename ProfileType::Kind kind = ProfileType::Kind::ClassId,
111                                                bool isRoot = false)
112     {
113         return PGOSampleTemplate(PGOProfileType(recordId, profileType, kind, isRoot));
114     }
115 
NoneType()116     static PGOSampleTemplate NoneType()
117     {
118         return PGOSampleTemplate(Type::NONE);
119     }
120 
None()121     static int32_t None()
122     {
123         return static_cast<int32_t>(Type::NONE);
124     }
125 
AnyType()126     static int32_t AnyType()
127     {
128         return static_cast<int32_t>(Type::ANY);
129     }
130 
IntType()131     static int32_t IntType()
132     {
133         return static_cast<int32_t>(Type::INT);
134     }
135 
IntOverFlowType()136     static int32_t IntOverFlowType()
137     {
138         return static_cast<int32_t>(Type::INT_OVERFLOW);
139     }
140 
DoubleType()141     static int32_t DoubleType()
142     {
143         return static_cast<int32_t>(Type::DOUBLE);
144     }
145 
NumberType()146     static int32_t NumberType()
147     {
148         return static_cast<int32_t>(Type::NUMBER);
149     }
150 
HeapObjectType()151     static int32_t HeapObjectType()
152     {
153         return static_cast<int32_t>(Type::HEAP_OBJECT);
154     }
155 
UndefineOrNullType()156     static int32_t UndefineOrNullType()
157     {
158         return static_cast<int32_t>(Type::UNDEFINED_OR_NULL);
159     }
160 
BooleanType()161     static int32_t BooleanType()
162     {
163         return static_cast<int32_t>(Type::BOOLEAN);
164     }
165 
StringType()166     static int32_t StringType()
167     {
168         return static_cast<int32_t>(Type::STRING);
169     }
170 
BigIntType()171     static int32_t BigIntType()
172     {
173         return static_cast<int32_t>(Type::BIG_INT);
174     }
175 
SpecialType()176     static int32_t SpecialType()
177     {
178         return static_cast<int32_t>(Type::SPECIAL);
179     }
180 
CombineType(int32_t curType,int32_t newType)181     static int32_t CombineType(int32_t curType, int32_t newType)
182     {
183         return static_cast<int32_t>(static_cast<uint32_t>(curType) | static_cast<uint32_t>(newType));
184     }
185 
NoneProfileType()186     static PGOSampleTemplate NoneProfileType()
187     {
188         return PGOSampleTemplate(PGOProfileType());
189     }
190 
CombineType(PGOSampleTemplate type)191     PGOSampleTemplate CombineType(PGOSampleTemplate type)
192     {
193         if (type_.index() == 0) {
194             auto oldType = static_cast<uint32_t>(std::get<Type>(type_));
195             oldType = oldType & static_cast<uint32_t>(AnyType());
196             type_ =
197                 Type(oldType | static_cast<uint32_t>(std::get<Type>(type.type_)));
198         } else {
199             this->SetType(type);
200         }
201         return *this;
202     }
203 
CombineCallTargetType(PGOSampleTemplate type)204     PGOSampleTemplate CombineCallTargetType(PGOSampleTemplate type)
205     {
206         ASSERT(type_.index() == 1);
207         ProfileType::Kind oldKind = GetProfileType().GetKind();
208         ProfileType::Kind newKind = type.GetProfileType().GetKind();
209         uint32_t oldMethodId = GetProfileType().GetId();
210         uint32_t newMethodId = type.GetProfileType().GetId();
211         // If we have recorded a valid method if before, invalidate it.
212         if ((oldMethodId != 0) &&
213             ((oldKind != newKind) || (oldMethodId != newMethodId))) {
214             type_ = ProfileType::PROFILE_TYPE_NONE;
215         }
216         return *this;
217     }
218 
SetType(PGOSampleTemplate type)219     void SetType(PGOSampleTemplate type)
220     {
221         type_ = type.type_;
222     }
223 
GetTypeString()224     std::string GetTypeString() const
225     {
226         if (type_.index() == 0) {
227             return std::to_string(static_cast<uint32_t>(std::get<Type>(type_)));
228         } else {
229             return std::get<PGOProfileType>(type_).GetTypeString();
230         }
231     }
232 
ToString()233     std::string ToString() const
234     {
235         if (type_.index() == 0) {
236             auto type = std::get<Type>(type_);
237             switch (type) {
238                 case Type::NONE:
239                     return "none";
240                 case Type::INT:
241                     return "int";
242                 case Type::INT_OVERFLOW:
243                     return "int_overflow";
244                 case Type::DOUBLE:
245                     return "double";
246                 case Type::NUMBER:
247                     return "number";
248                 case Type::NUMBER1:
249                     return "number1";
250                 case Type::BOOLEAN:
251                     return "boolean";
252                 case Type::UNDEFINED_OR_NULL:
253                     return "undefined_or_null";
254                 case Type::SPECIAL:
255                     return "special";
256                 case Type::BOOLEAN_OR_SPECIAL:
257                     return "boolean_or_special";
258                 case Type::STRING:
259                     return "string";
260                 case Type::BIG_INT:
261                     return "big_int";
262                 case Type::HEAP_OBJECT:
263                     return "heap_object";
264                 case Type::HEAP_OR_UNDEFINED_OR_NULL:
265                     return "heap_or_undefined_or_null";
266                 case Type::ANY:
267                     return "any";
268                 default:
269                     LOG_ECMA(FATAL) << "this branch is unreachable";
270                     UNREACHABLE();
271             }
272         }
273         LOG_ECMA(FATAL) << "this branch is unreachable";
274         UNREACHABLE();
275     }
276 
IsProfileType()277     bool IsProfileType() const
278     {
279         return type_.index() == 1;
280     }
281 
GetProfileType()282     PGOProfileType GetProfileType() const
283     {
284         ASSERT(IsProfileType());
285         return std::get<PGOProfileType>(type_);
286     }
287 
GetPrimitiveType()288     Type GetPrimitiveType() const
289     {
290         auto type = static_cast<uint32_t>(std::get<Type>(type_));
291         return Type(type & static_cast<uint32_t>(AnyType()));
292     }
293 
GetWeight()294     uint32_t GetWeight() const
295     {
296         ASSERT(type_.index() == 0);
297         auto type = static_cast<uint32_t>(std::get<Type>(type_));
298         return type >> WEIGHT_START_BIT;
299     }
300 
IsAny()301     bool IsAny() const
302     {
303         return type_.index() == 0 && GetPrimitiveType() == Type::ANY;
304     }
305 
IsNone()306     bool IsNone() const
307     {
308         return type_.index() == 0 && GetPrimitiveType() == Type::NONE;
309     }
310 
IsInt()311     bool IsInt() const
312     {
313         return type_.index() == 0 && GetPrimitiveType() == Type::INT;
314     }
315 
IsIntOverFlow()316     bool IsIntOverFlow() const
317     {
318         return type_.index() == 0 && GetPrimitiveType() == Type::INT_OVERFLOW;
319     }
320 
IsDouble()321     bool IsDouble() const
322     {
323         return type_.index() == 0 && GetPrimitiveType() == Type::DOUBLE;
324     }
325 
IsString()326     bool IsString() const
327     {
328         return type_.index() == 0 && GetPrimitiveType() == Type::STRING;
329     }
330 
IsNumber()331     bool IsNumber() const
332     {
333         if (type_.index() != 0) {
334             return false;
335         }
336         auto primType = GetPrimitiveType();
337         switch (primType) {
338             case Type::INT:
339             case Type::INT_OVERFLOW:
340             case Type::DOUBLE:
341             case Type::NUMBER:
342             case Type::NUMBER1:
343                 return true;
344             default:
345                 return false;
346         }
347     }
348 
349     bool operator<(const PGOSampleTemplate &right) const
350     {
351         return type_ < right.type_;
352     }
353 
354     bool operator!=(const PGOSampleTemplate &right) const
355     {
356         return type_ != right.type_;
357     }
358 
359     bool operator==(const PGOSampleTemplate &right) const
360     {
361         return type_ == right.type_;
362     }
363 
GetType()364     Type GetType() const
365     {
366         ASSERT(!IsProfileType());
367         return std::get<Type>(type_);
368     }
369 
370 private:
371     std::variant<Type, PGOProfileType> type_;
372 };
373 
374 using PGOSampleType = PGOSampleTemplate<ProfileType>;
375 using PGOSampleTypeRef = PGOSampleTemplate<ProfileTypeRef>;
376 
377 template <typename PGOProfileType>
378 class PGOProtoChainTemplate {
379 public:
380     PGOProtoChainTemplate() = default;
PGOProtoChainTemplate(int32_t size,int32_t count)381     PGOProtoChainTemplate(int32_t size, int32_t count) : size_(size), count_(count) {};
382 
CreateProtoChain(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)383     static PGOProtoChainTemplate *CreateProtoChain(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain)
384     {
385         auto count = protoChain.size();
386         size_t size = sizeof(PGOProtoChainTemplate);
387         if (count != 0) {
388             size += sizeof(PGOProfileType) * (count - 1) * 2;   // 2 means mul by 2
389         }
390         auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size));
391         new (result) PGOProtoChainTemplate(size, count);
392         PGOProfileType *curPt = &(result->rootType_);
393         for (auto iter : protoChain) {
394             *curPt = iter.first;
395             curPt = curPt + 1;
396             *curPt = iter.second;
397             curPt = curPt + 1;
398         }
399         return result;
400     }
401 
DeleteProtoChain(PGOProtoChainTemplate * protoChain)402     static void DeleteProtoChain(PGOProtoChainTemplate *protoChain)
403     {
404         free(protoChain);
405     }
406 
407     template <typename FromType>
ConvertFrom(PGOContext & context,FromType * from)408     static PGOProtoChainTemplate *ConvertFrom(PGOContext &context, FromType *from)
409     {
410         auto count = from->GetCount();
411         size_t size = sizeof(PGOProtoChainTemplate);
412         if (count != 0) {
413             size += sizeof(PGOProfileType) * (static_cast<size_t>(count) - 1) * 2;   // 2 means mul by 2
414         }
415         auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size));
416         new (result) PGOProtoChainTemplate(size, count);
417         PGOProfileType *curPt = &(result->rootType_);
418         from->IterateProtoChain([&context, &curPt] (auto rootType, auto childType) {
419             *curPt = PGOProfileType(context, rootType);
420             curPt = curPt + 1;
421             *curPt = PGOProfileType(context, childType);
422             curPt = curPt + 1;
423         });
424         return result;
425     }
426 
427     template <typename Callback>
IterateProtoChain(Callback callback)428     void IterateProtoChain(Callback callback) const
429     {
430         for (int i = 0; i < count_; i++) {
431             callback(*(&rootType_ + i), *(&rootType_ + i + 1));
432         }
433     }
434 
GetCount()435     int32_t GetCount()
436     {
437         return count_;
438     }
439 
Size()440     int32_t Size()
441     {
442         return size_;
443     }
444 
445 private:
446     int32_t size_;
447     int32_t count_;
448     PGOProfileType rootType_ {PGOProfileType()};
449     PGOProfileType childType_ {PGOProfileType()};
450 };
451 
452 using PGOProtoChain = PGOProtoChainTemplate<ProfileType>;
453 using PGOProtoChainRef = PGOProtoChainTemplate<ProfileTypeRef>;
454 
455 enum class ProtoChainMarker : uint8_t {
456     EXSIT,
457     NOT_EXSIT,
458 };
459 
460 template <typename PGOProfileType>
461 class PGOObjectTemplate {
462 public:
463     PGOObjectTemplate() = default;
PGOObjectTemplate(PGOProfileType type)464     PGOObjectTemplate(PGOProfileType type) : receiverType_(type) {}
PGOObjectTemplate(PGOProfileType receiverRootType,PGOProfileType receiverType,PGOProfileType holdRootType,PGOProfileType holdType,PGOProfileType holdTraRootType,PGOProfileType holdTraType)465     PGOObjectTemplate(PGOProfileType receiverRootType, PGOProfileType receiverType, PGOProfileType holdRootType,
466         PGOProfileType holdType, PGOProfileType holdTraRootType, PGOProfileType holdTraType)
467         : receiverRootType_(receiverRootType), receiverType_(receiverType), holdRootType_(holdRootType),
468         holdType_(holdType), holdTraRootType_(holdTraRootType), holdTraType_(holdTraType) {}
469 
AddPrototypePt(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)470     void AddPrototypePt(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain)
471     {
472         protoChainMarker_ = ProtoChainMarker::EXSIT;
473         if (protoChain_ != nullptr) {
474             PGOProtoChainTemplate<PGOProfileType>::DeleteProtoChain(protoChain_);
475         }
476         protoChain_ = PGOProtoChainTemplate<PGOProfileType>::CreateProtoChain(protoChain);
477     }
478 
479     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)480     void ConvertFrom(PGOContext &context, const FromType &from)
481     {
482         receiverRootType_ = PGOProfileType(context, from.GetReceiverRootType());
483         receiverType_ = PGOProfileType(context, from.GetReceiverType());
484         holdRootType_ = PGOProfileType(context, from.GetHoldRootType());
485         holdType_ = PGOProfileType(context, from.GetHoldType());
486         holdTraRootType_ = PGOProfileType(context, from.GetHoldTraRootType());
487         holdTraType_ = PGOProfileType(context, from.GetHoldTraType());
488         protoChainMarker_ = from.GetProtoChainMarker();
489     }
490 
GetInfoString()491     std::string GetInfoString() const
492     {
493         std::string result = "(receiverRoot";
494         result += receiverRootType_.GetTypeString();
495         result += ", receiver";
496         result += receiverType_.GetTypeString();
497         result += ", holdRoot";
498         result += holdRootType_.GetTypeString();
499         result += ", hold";
500         result += holdType_.GetTypeString();
501         result += ", holdTraRoot";
502         result += holdTraRootType_.GetTypeString();
503         result += ", holdTra";
504         result += holdTraType_.GetTypeString();
505         result += ")";
506         return result;
507     }
508 
GetProfileType()509     PGOProfileType GetProfileType() const
510     {
511         return receiverType_;
512     }
513 
GetReceiverRootType()514     PGOProfileType GetReceiverRootType() const
515     {
516         return receiverRootType_;
517     }
518 
GetReceiverType()519     PGOProfileType GetReceiverType() const
520     {
521         return receiverType_;
522     }
523 
GetHoldRootType()524     PGOProfileType GetHoldRootType() const
525     {
526         return holdRootType_;
527     }
528 
GetHoldType()529     PGOProfileType GetHoldType() const
530     {
531         return holdType_;
532     }
533 
GetHoldTraRootType()534     PGOProfileType GetHoldTraRootType() const
535     {
536         return holdTraRootType_;
537     }
538 
GetHoldTraType()539     PGOProfileType GetHoldTraType() const
540     {
541         return holdTraType_;
542     }
543 
GetProtoChainMarker()544     ProtoChainMarker GetProtoChainMarker() const
545     {
546         return protoChainMarker_;
547     }
548 
GetProtoChain()549     PGOProtoChainTemplate<PGOProfileType> *GetProtoChain() const
550     {
551         return protoChain_;
552     }
553 
SetProtoChain(PGOProtoChainTemplate<PGOProfileType> * protoChain)554     void SetProtoChain(PGOProtoChainTemplate<PGOProfileType> *protoChain)
555     {
556         protoChain_ = protoChain;
557     }
558 
IsNone()559     bool IsNone() const
560     {
561         return receiverType_.IsNone();
562     }
563 
IsMegaStateType()564     bool IsMegaStateType() const
565     {
566         return receiverType_.IsMegaStateType();
567     }
568 
InConstructor()569     bool InConstructor() const
570     {
571         return receiverType_.IsConstructor();
572     }
573 
InElement()574     bool InElement() const
575     {
576         return receiverType_.IsBuiltinsArray();
577     }
578 
579     bool operator<(const PGOObjectTemplate &right) const
580     {
581         return receiverRootType_ < right.receiverRootType_ || receiverType_ < right.receiverType_ ||
582             holdRootType_ < right.holdRootType_ || holdType_ < right.holdType_ ||
583             holdTraRootType_ < right.holdTraRootType_ || holdTraType_ < right.holdTraType_;
584     }
585 
586     bool operator==(const PGOObjectTemplate &right) const
587     {
588         return receiverRootType_ == right.receiverRootType_ && receiverType_ == right.receiverType_ &&
589             holdRootType_ == right.holdRootType_ && holdType_ == right.holdType_ &&
590             holdTraRootType_ == right.holdTraRootType_ && holdTraType_ == right.holdTraType_;
591     }
592 
593 private:
594     PGOProfileType receiverRootType_ { PGOProfileType() };
595     PGOProfileType receiverType_ { PGOProfileType() };
596     PGOProfileType holdRootType_ { PGOProfileType() };
597     PGOProfileType holdType_ { PGOProfileType() };
598     PGOProfileType holdTraRootType_ { PGOProfileType() };
599     PGOProfileType holdTraType_ { PGOProfileType() };
600     ProtoChainMarker protoChainMarker_ {ProtoChainMarker::NOT_EXSIT};
601     PGOProtoChainTemplate<PGOProfileType> *protoChain_ { nullptr };
602 };
603 using PGOObjectInfo = PGOObjectTemplate<ProfileType>;
604 using PGOObjectInfoRef = PGOObjectTemplate<ProfileTypeRef>;
605 
606 template <typename PGOObjectInfoType>
607 class PGORWOpTemplate : public PGOType {
608 public:
PGORWOpTemplate()609     PGORWOpTemplate() : PGOType(TypeKind::RW_OP_TYPE) {};
610 
611     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)612     void ConvertFrom(PGOContext &context, const FromType &from)
613     {
614         count_ = std::min(from.GetCount(), static_cast<uint32_t>(POLY_CASE_NUM));
615         for (uint32_t index = 0; index < count_; index++) {
616             infos_[index].ConvertFrom(context, from.GetObjectInfo(index));
617         }
618     }
619 
Merge(const PGORWOpTemplate & type)620     void Merge(const PGORWOpTemplate &type)
621     {
622         for (uint32_t i = 0; i < type.count_; i++) {
623             AddObjectInfo(type.infos_[i]);
624         }
625     }
626 
AddObjectInfo(const PGOObjectInfoType & info)627     void AddObjectInfo(const PGOObjectInfoType &info)
628     {
629         if (info.IsNone()) {
630             return;
631         }
632         if (info.IsMegaStateType()) {
633             count_ = 0;
634             return;
635         }
636         uint32_t count = 0;
637         for (; count < count_; count++) {
638             if (infos_[count] == info) {
639                 return;
640             }
641         }
642         if (count < static_cast<uint32_t>(POLY_CASE_NUM)) {
643             infos_[count] = info;
644             count_++;
645         } else {
646             LOG_ECMA(DEBUG) << "Class type exceeds 4, discard";
647         }
648     }
649 
GetObjectInfo(uint32_t index)650     const PGOObjectInfoType &GetObjectInfo(uint32_t index) const
651     {
652         ASSERT(index < count_);
653         return infos_[index];
654     }
655 
GetCount()656     uint32_t GetCount() const
657     {
658         return count_;
659     }
660 
661 private:
662     static constexpr int POLY_CASE_NUM = 4;
663     uint32_t count_ = 0;
664     PGOObjectInfoType infos_[POLY_CASE_NUM];
665 };
666 using PGORWOpType = PGORWOpTemplate<PGOObjectInfo>;
667 using PGORWOpTypeRef = PGORWOpTemplate<PGOObjectInfoRef>;
668 
669 template <typename PGOProfileType>
670 class PGODefineOpTemplate : public PGOType {
671 public:
PGODefineOpTemplate()672     PGODefineOpTemplate() : PGOType(TypeKind::DEFINE_OP_TYPE), type_(PGOProfileType()) {};
PGODefineOpTemplate(PGOProfileType type)673     explicit PGODefineOpTemplate(PGOProfileType type) : PGOType(TypeKind::DEFINE_OP_TYPE), type_(type) {};
674 
675     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)676     void ConvertFrom(PGOContext &context, const FromType &from)
677     {
678         type_ = PGOProfileType(context, from.GetProfileType());
679         ctorPt_ = PGOProfileType(context, from.GetCtorPt());
680         protoPt_ = PGOProfileType(context, from.GetProtoTypePt());
681         kind_ = from.GetElementsKind();
682         elementsLength_ = from.GetElementsLength();
683         spaceFlag_ = from.GetSpaceFlag();
684     }
685 
GetTypeString()686     std::string GetTypeString() const
687     {
688         std::string result = "(local";
689         result += type_.GetTypeString();
690         result += ", ctor";
691         result += ctorPt_.GetTypeString();
692         result += ", proto";
693         result += protoPt_.GetTypeString();
694         result += ", elementsKind:";
695         result += std::to_string(static_cast<int32_t>(kind_));
696         if (elementsLength_ > 0 && spaceFlag_ != RegionSpaceFlag::UNINITIALIZED) {
697             result += ", size: ";
698             result += std::to_string(elementsLength_);
699             result += ", space; ";
700             result += ToSpaceTypeName(spaceFlag_);
701         }
702         return result;
703     }
704 
IsNone()705     bool IsNone() const
706     {
707         return type_.IsNone();
708     }
709 
GetProfileType()710     PGOProfileType GetProfileType() const
711     {
712         return type_;
713     }
714 
SetCtorPt(PGOProfileType type)715     void SetCtorPt(PGOProfileType type)
716     {
717         ctorPt_ = type;
718     }
719 
GetCtorPt()720     PGOProfileType GetCtorPt() const
721     {
722         return ctorPt_;
723     }
724 
SetProtoTypePt(PGOProfileType type)725     void SetProtoTypePt(PGOProfileType type)
726     {
727         protoPt_ = type;
728     }
729 
GetProtoTypePt()730     PGOProfileType GetProtoTypePt() const
731     {
732         return protoPt_;
733     }
734 
SetElementsKind(ElementsKind kind)735     void SetElementsKind(ElementsKind kind)
736     {
737         kind_ = kind;
738     }
739 
GetElementsKind()740     ElementsKind GetElementsKind() const
741     {
742         return kind_;
743     }
744 
SetElementsLength(uint32_t length)745     void SetElementsLength(uint32_t length)
746     {
747         elementsLength_ = length;
748     }
749 
GetElementsLength()750     uint32_t GetElementsLength() const
751     {
752         return elementsLength_;
753     }
754 
SetSpaceFlag(RegionSpaceFlag flag)755     void SetSpaceFlag(RegionSpaceFlag flag)
756     {
757         spaceFlag_ = flag;
758     }
759 
GetSpaceFlag()760     RegionSpaceFlag GetSpaceFlag() const
761     {
762         return spaceFlag_;
763     }
764 
765     bool operator<(const PGODefineOpTemplate &right) const
766     {
767         return this->GetProfileType() < right.GetProfileType();
768     }
769 
770 private:
771     PGOProfileType type_ { PGOProfileType() };
772     PGOProfileType ctorPt_ { PGOProfileType() };
773     PGOProfileType protoPt_ { PGOProfileType() };
774     uint32_t elementsLength_ { 0 };
775     ElementsKind kind_ { ElementsKind::NONE };
776     RegionSpaceFlag spaceFlag_  { RegionSpaceFlag::UNINITIALIZED };
777 };
778 
779 using PGODefineOpType = PGODefineOpTemplate<ProfileType>;
780 using PGODefineOpTypeRef = PGODefineOpTemplate<ProfileTypeRef>;
781 
782 class PGOTypeRef {
783 public:
PGOTypeRef()784     PGOTypeRef() : type_(nullptr) {}
785 
PGOTypeRef(PGOType * type)786     explicit PGOTypeRef(PGOType *type) : type_(type) {}
787 
PGOTypeRef(const PGOSampleType * type)788     explicit PGOTypeRef(const PGOSampleType *type) : type_(static_cast<const PGOType*>(type)) {}
789 
PGOTypeRef(const PGORWOpType * type)790     explicit PGOTypeRef(const PGORWOpType *type) : type_(static_cast<const PGOType*>(type)) {}
791 
PGOTypeRef(const PGODefineOpType * type)792     explicit PGOTypeRef(const PGODefineOpType *type) : type_(static_cast<const PGOType*>(type)) {}
793 
NoneType()794     static PGOTypeRef NoneType()
795     {
796         return PGOTypeRef();
797     }
798 
799     bool operator<(const PGOTypeRef &right) const
800     {
801         return type_ < right.type_;
802     }
803 
804     bool operator!=(const PGOTypeRef &right) const
805     {
806         return type_ != right.type_;
807     }
808 
809     bool operator==(const PGOTypeRef &right) const
810     {
811         return type_ == right.type_;
812     }
813 
IsValid()814     bool IsValid() const
815     {
816         return type_ != nullptr;
817     }
818 
IsValidCallMethodId()819     bool IsValidCallMethodId() const
820     {
821         if (type_ == nullptr) {
822             return false;
823         }
824         if (!type_->IsScalarOpType()) {
825             return false;
826         }
827         auto sampleType = static_cast<const PGOSampleType*>(type_);
828         if (sampleType->IsProfileType()) {
829             if (sampleType->GetProfileType().IsMethodId()) {
830                 return sampleType->GetProfileType().IsValidCallMethodId();
831             }
832         }
833         return false;
834     }
835 
GetCallMethodId()836     uint32_t GetCallMethodId() const
837     {
838         auto sampleType = static_cast<const PGOSampleType*>(type_);
839         return sampleType->GetProfileType().GetCallMethodId();
840     }
841 
GetValue()842     uint64_t GetValue() const
843     {
844         auto sampleType = static_cast<const PGOSampleType*>(type_);
845         return sampleType->GetProfileType().GetRaw();
846     }
847 
GetPGOSampleType()848     const PGOSampleType* GetPGOSampleType()
849     {
850         if (type_ == nullptr) {
851             static PGOSampleType noneType = PGOSampleType::NoneType();
852             return &noneType;
853         }
854         ASSERT(type_->IsScalarOpType());
855         return static_cast<const PGOSampleType*>(type_);
856     }
857 
GetPGORWOpType()858     const PGORWOpType* GetPGORWOpType()
859     {
860         if (type_ == nullptr) {
861             static PGORWOpType noneType;
862             return &noneType;
863         }
864         ASSERT(type_->IsRwOpType());
865         return static_cast<const PGORWOpType*>(type_);
866     }
867 
GetPGODefineOpType()868     const PGODefineOpType* GetPGODefineOpType()
869     {
870         if (type_ == nullptr) {
871             static PGODefineOpType noneType;
872             return &noneType;
873         }
874         ASSERT(type_->IsDefineOpType());
875         return static_cast<const PGODefineOpType*>(type_);
876     }
877 
878 private:
879     const PGOType *type_;
880 };
881 } // namespace panda::ecmascript::pgo
882 #endif  // ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILER_TYPE_H
883