• 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/js_handle.h"
26 #include "ecmascript/js_hclass.h"
27 #include "ecmascript/js_primitive_ref.h"
28 #include "ecmascript/mem/region.h"
29 #include "ecmascript/log_wrapper.h"
30 #include "ecmascript/pgo_profiler/pgo_utils.h"
31 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
32 #include "libpandabase/utils/bit_field.h"
33 #include "libpandabase/macros.h"
34 
35 namespace panda::ecmascript::pgo {
36 class PGOContext;
37 class PGOType {
38 public:
39     enum class TypeKind : uint8_t {
40         SCALAR_OP_TYPE,
41         RW_OP_TYPE,
42         DEFINE_OP_TYPE,
43         PROTO_TRANSITION_TYPE,
44     };
45     PGOType() = default;
PGOType(TypeKind kind)46     explicit PGOType(TypeKind kind) : kind_(kind) {}
47 
IsScalarOpType()48     bool IsScalarOpType() const
49     {
50         return kind_ == TypeKind::SCALAR_OP_TYPE;
51     }
52 
IsRwOpType()53     bool IsRwOpType() const
54     {
55         return kind_ == TypeKind::RW_OP_TYPE;
56     }
57 
IsDefineOpType()58     bool IsDefineOpType() const
59     {
60         return kind_ == TypeKind::DEFINE_OP_TYPE;
61     }
62 
IsProtoTransitionType()63     bool IsProtoTransitionType() const
64     {
65         return kind_ == TypeKind::PROTO_TRANSITION_TYPE;
66     }
67 
68 private:
69     TypeKind kind_ {TypeKind::SCALAR_OP_TYPE};
70 };
71 
72 /**
73  * | INT    \          -> INT_OVERFLOW \
74  * |           NUMBER                    NUMBER_HETEROE1
75  * | DOUBLE /                          /
76  */
77 template <typename PGOProfileType>
78 class PGOSampleTemplate : public PGOType {
79 public:
80     static constexpr int WEIGHT_BITS = 11;
81     static constexpr int WEIGHT_START_BIT = 10;
82     static constexpr int WEIGHT_TRUE_START_BIT = WEIGHT_START_BIT + WEIGHT_BITS;
83     static constexpr int WEIGHT_MASK = (1 << WEIGHT_BITS) - 1;
84     static constexpr int WEIGHT_THRESHOLD = WEIGHT_MASK; // 2047
85 
86     enum class Type : uint32_t {
87         NONE = 0x0ULL,
88         INT = 0x1ULL,                        // 00000001
89         INT_OVERFLOW = (0x1ULL << 1) | INT,  // 00000011
90         DOUBLE = 0x1ULL << 2,                // 00000100
91         NUMBER = INT | DOUBLE,               // 00000101
92         NUMBER1 = INT_OVERFLOW | DOUBLE,     // 00000111
93         BOOLEAN = 0x1ULL << 3,
94         UNDEFINED_OR_NULL = 0x1ULL << 4,
95         SPECIAL = 0x1ULL << 5,
96         BOOLEAN_OR_SPECIAL = BOOLEAN | SPECIAL,
97         INTERN_STRING = 0x1ULL << 9,
98         STRING = (0x1ULL << 6) | INTERN_STRING,
99         NUMBER_OR_STRING = NUMBER | STRING,
100         BIG_INT = 0x1ULL << 7,
101         HEAP_OBJECT = 0x1ULL << 8,
102         HEAP_OR_UNDEFINED_OR_NULL = HEAP_OBJECT | UNDEFINED_OR_NULL,
103         ANY = (0x1ULL << WEIGHT_START_BIT) - 1,
104     };
105 
PGOSampleTemplate()106     PGOSampleTemplate() : type_(Type::NONE) {};
107 
PGOSampleTemplate(Type type)108     explicit PGOSampleTemplate(Type type) : type_(type) {};
PGOSampleTemplate(uint32_t type)109     explicit PGOSampleTemplate(uint32_t type) : type_(Type(type)) {};
PGOSampleTemplate(PGOProfileType type)110     explicit PGOSampleTemplate(PGOProfileType type) : type_(type) {}
111 
112     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)113     static PGOSampleTemplate ConvertFrom(PGOContext &context, const FromType &from)
114     {
115         if (from.IsProfileType()) {
116             return PGOSampleTemplate(PGOProfileType(context, from.GetProfileType()));
117         }
118         return PGOSampleTemplate(static_cast<PGOSampleTemplate::Type>(from.GetType()));
119     }
120 
121     static PGOSampleTemplate CreateProfileType(ApEntityId recordId, int32_t profileType,
122                                                typename ProfileType::Kind kind = ProfileType::Kind::ClassId,
123                                                bool isRoot = false)
124     {
125         return PGOSampleTemplate(PGOProfileType(recordId, profileType, kind, isRoot));
126     }
127 
NoneType()128     static PGOSampleTemplate NoneType()
129     {
130         return PGOSampleTemplate(Type::NONE);
131     }
132 
None()133     static int32_t None()
134     {
135         return static_cast<int32_t>(Type::NONE);
136     }
137 
AnyType()138     static int32_t AnyType()
139     {
140         return static_cast<int32_t>(Type::ANY);
141     }
142 
IntType()143     static int32_t IntType()
144     {
145         return static_cast<int32_t>(Type::INT);
146     }
147 
IntOverFlowType()148     static int32_t IntOverFlowType()
149     {
150         return static_cast<int32_t>(Type::INT_OVERFLOW);
151     }
152 
DoubleType()153     static int32_t DoubleType()
154     {
155         return static_cast<int32_t>(Type::DOUBLE);
156     }
157 
NumberType()158     static int32_t NumberType()
159     {
160         return static_cast<int32_t>(Type::NUMBER);
161     }
162 
HeapObjectType()163     static int32_t HeapObjectType()
164     {
165         return static_cast<int32_t>(Type::HEAP_OBJECT);
166     }
167 
UndefinedOrNullType()168     static int32_t UndefinedOrNullType()
169     {
170         return static_cast<int32_t>(Type::UNDEFINED_OR_NULL);
171     }
172 
BooleanType()173     static int32_t BooleanType()
174     {
175         return static_cast<int32_t>(Type::BOOLEAN);
176     }
177 
StringType()178     static int32_t StringType()
179     {
180         return static_cast<int32_t>(Type::STRING);
181     }
182 
InternStringType()183     static int32_t InternStringType()
184     {
185         return static_cast<int32_t>(Type::INTERN_STRING);
186     }
187 
NumberOrStringType()188     static int32_t NumberOrStringType()
189     {
190         return static_cast<int32_t>(Type::NUMBER_OR_STRING);
191     }
192 
BigIntType()193     static int32_t BigIntType()
194     {
195         return static_cast<int32_t>(Type::BIG_INT);
196     }
197 
SpecialType()198     static int32_t SpecialType()
199     {
200         return static_cast<int32_t>(Type::SPECIAL);
201     }
202 
CombineType(int32_t curType,int32_t newType)203     static int32_t CombineType(int32_t curType, int32_t newType)
204     {
205         return static_cast<int32_t>(static_cast<uint32_t>(curType) | static_cast<uint32_t>(newType));
206     }
207 
NoneProfileType()208     static PGOSampleTemplate NoneProfileType()
209     {
210         return PGOSampleTemplate(PGOProfileType());
211     }
212 
CombineType(PGOSampleTemplate type)213     PGOSampleTemplate CombineType(PGOSampleTemplate type)
214     {
215         if (IsPrimitiveType()) {
216             if (std::holds_alternative<PGOProfileType>(type.type_)) {
217                 LOG_ECMA(ERROR) << "The type is PGOProfileType, but need a Type";
218                 return *this;
219             }
220             auto oldType = static_cast<uint32_t>(std::get<Type>(type_));
221             oldType = oldType & static_cast<uint32_t>(AnyType());
222             type_ =
223                 Type(oldType | static_cast<uint32_t>(std::get<Type>(type.type_)));
224         } else {
225             this->SetType(type);
226         }
227         return *this;
228     }
229 
CombineCallTargetType(PGOSampleTemplate type)230     PGOSampleTemplate CombineCallTargetType(PGOSampleTemplate type)
231     {
232         ASSERT(type_.index() == 1);
233         ProfileType::Kind oldKind = GetProfileType().GetKind();
234         ProfileType::Kind newKind = type.GetProfileType().GetKind();
235         uint32_t oldMethodId = GetProfileType().GetId();
236         uint32_t newMethodId = type.GetProfileType().GetId();
237         // If we have recorded a valid method if before, invalidate it.
238         if ((oldMethodId != 0) &&
239             ((oldKind != newKind) || (oldMethodId != newMethodId))) {
240             type_ = ProfileType::PROFILE_TYPE_NONE;
241         }
242         return *this;
243     }
244 
SetType(PGOSampleTemplate type)245     void SetType(PGOSampleTemplate type)
246     {
247         type_ = type.type_;
248     }
249 
GetTypeString()250     std::string GetTypeString() const
251     {
252         if (IsPrimitiveType()) {
253             return std::to_string(static_cast<uint32_t>(std::get<Type>(type_)));
254         } else {
255             return std::get<PGOProfileType>(type_).GetTypeString();
256         }
257     }
258 
GetTypeJson(ProfileType::StringMap & type)259     void GetTypeJson(ProfileType::StringMap &type) const
260     {
261         if (IsPrimitiveType()) {
262             type.insert(std::make_pair(DumpJsonUtils::TYPE_NAME,
263                 std::to_string(static_cast<uint32_t>(std::get<Type>(type_)))));
264         } else {
265             type.insert(std::make_pair(DumpJsonUtils::TYPE_NAME, "Type"));
266             std::get<PGOProfileType>(type_).GetTypeJson(type);
267         }
268         if (IsScalarOpType()) {
269             if (!ToString().empty()) {
270                 type.insert(std::make_pair(DumpJsonUtils::TYPE_NAME, ToString()));
271             }
272         }
273     }
274 
ToString()275     std::string ToString() const
276     {
277         if (IsPrimitiveType()) {
278             auto type = std::get<Type>(type_);
279             switch (type) {
280                 case Type::NONE:
281                     return "none";
282                 case Type::INT:
283                     return "int";
284                 case Type::INT_OVERFLOW:
285                     return "int_overflow";
286                 case Type::DOUBLE:
287                     return "double";
288                 case Type::NUMBER:
289                     return "number";
290                 case Type::NUMBER1:
291                     return "number1";
292                 case Type::BOOLEAN:
293                     return "boolean";
294                 case Type::UNDEFINED_OR_NULL:
295                     return "undefined_or_null";
296                 case Type::SPECIAL:
297                     return "special";
298                 case Type::BOOLEAN_OR_SPECIAL:
299                     return "boolean_or_special";
300                 case Type::STRING:
301                     return "string";
302                 case Type::BIG_INT:
303                     return "big_int";
304                 case Type::HEAP_OBJECT:
305                     return "heap_object";
306                 case Type::HEAP_OR_UNDEFINED_OR_NULL:
307                     return "heap_or_undefined_or_null";
308                 case Type::ANY:
309                     return "any";
310                 default:
311                     return "";
312             }
313         }
314         return "";
315     }
316 
IsProfileType()317     bool IsProfileType() const
318     {
319         return type_.index() == 1;
320     }
321 
GetProfileType()322     PGOProfileType GetProfileType() const
323     {
324         ASSERT(IsProfileType());
325         return std::get<PGOProfileType>(type_);
326     }
327 
IsPrimitiveType()328     bool IsPrimitiveType() const
329     {
330         return type_.index() == 0;
331     }
332 
GetPrimitiveType()333     Type GetPrimitiveType() const
334     {
335         ASSERT(IsPrimitiveType());
336         auto type = static_cast<uint32_t>(std::get<Type>(type_));
337         return Type(type & static_cast<uint32_t>(AnyType()));
338     }
339 
GetWeight()340     uint32_t GetWeight() const
341     {
342         ASSERT(IsPrimitiveType());
343         auto type = static_cast<uint32_t>(std::get<Type>(type_));
344         return type >> WEIGHT_START_BIT;
345     }
346 
IsAny()347     bool IsAny() const
348     {
349         return IsPrimitiveType() && GetPrimitiveType() == Type::ANY;
350     }
351 
IsNone()352     bool IsNone() const
353     {
354         return IsPrimitiveType() && GetPrimitiveType() == Type::NONE;
355     }
356 
IsInt()357     bool IsInt() const
358     {
359         return IsPrimitiveType() && GetPrimitiveType() == Type::INT;
360     }
361 
IsIntOverFlow()362     bool IsIntOverFlow() const
363     {
364         return IsPrimitiveType() && GetPrimitiveType() == Type::INT_OVERFLOW;
365     }
366 
IsDouble()367     bool IsDouble() const
368     {
369         return IsPrimitiveType() && GetPrimitiveType() == Type::DOUBLE;
370     }
371 
IsString()372     bool IsString() const
373     {
374         return IsPrimitiveType() && GetPrimitiveType() == Type::STRING;
375     }
376 
IsInternString()377     bool IsInternString() const
378     {
379         return IsPrimitiveType() && GetPrimitiveType() == Type::INTERN_STRING;
380     }
381 
IsBigInt()382     bool IsBigInt() const
383     {
384         return type_.index() == 0 && GetPrimitiveType() == Type::BIG_INT;
385     }
386 
IsBoolean()387     bool IsBoolean() const
388     {
389         return type_.index() == 0 && GetPrimitiveType() == Type::BOOLEAN;
390     }
391 
IsHeapObject()392     bool IsHeapObject() const
393     {
394         return type_.index() == 0 && GetPrimitiveType() == Type::HEAP_OBJECT;
395     }
396 
IsUndefinedOrNull()397     bool IsUndefinedOrNull() const
398     {
399         return type_.index() == 0 && GetPrimitiveType() == Type::UNDEFINED_OR_NULL;
400     }
401 
IsNumber()402     bool IsNumber() const
403     {
404         if (type_.index() != 0) {
405             return false;
406         }
407         auto primType = GetPrimitiveType();
408         return primType == Type::NUMBER || primType == Type::NUMBER1;
409     }
410 
IsNumberOrString()411     bool IsNumberOrString() const
412     {
413         if (type_.index() != 0) {
414             return false;
415         }
416         auto primType = GetPrimitiveType();
417         return primType == Type::NUMBER_OR_STRING;
418     }
419 
HasNumber()420     bool HasNumber() const
421     {
422         if (type_.index() != 0) {
423             return false;
424         }
425         auto primType = GetPrimitiveType();
426         switch (primType) {
427             case Type::INT:
428             case Type::INT_OVERFLOW:
429             case Type::DOUBLE:
430             case Type::NUMBER:
431             case Type::NUMBER1:
432                 return true;
433             default:
434                 return false;
435         }
436     }
437 
IsProfileTypeNone()438     bool IsProfileTypeNone() const
439     {
440         return type_.index() == 1 && GetProfileType() == ProfileType::PROFILE_TYPE_NONE;
441     }
442 
443     bool operator<(const PGOSampleTemplate &right) const
444     {
445         return type_ < right.type_;
446     }
447 
448     bool operator!=(const PGOSampleTemplate &right) const
449     {
450         return type_ != right.type_;
451     }
452 
453     bool operator==(const PGOSampleTemplate &right) const
454     {
455         return type_ == right.type_;
456     }
457 
GetType()458     Type GetType() const
459     {
460         ASSERT(!IsProfileType());
461         return std::get<Type>(type_);
462     }
463 
464 private:
465     std::variant<Type, PGOProfileType> type_;
466 };
467 
468 using PGOSampleType = PGOSampleTemplate<ProfileType>;
469 using PGOSampleTypeRef = PGOSampleTemplate<ProfileTypeRef>;
470 
471 template <typename PGOProfileType>
472 class PGOProtoChainTemplate {
473 public:
474     static constexpr int32_t PROTO_CHAIN_MIN_COUNT = 0;
475     static constexpr int32_t PROTO_CHAIN_MAX_COUNT = 4096;
476 
477     PGOProtoChainTemplate() = default;
PGOProtoChainTemplate(int32_t size,int32_t count)478     PGOProtoChainTemplate(int32_t size, int32_t count) : size_(size), count_(count) {};
479 
CreateProtoChain(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)480     static PGOProtoChainTemplate *CreateProtoChain(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain)
481     {
482         auto count = protoChain.size();
483         size_t size = sizeof(PGOProtoChainTemplate);
484         if (count != 0) {
485             size += sizeof(PGOProfileType) * (count - 1) * 2;   // 2 means mul by 2
486         }
487         auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size));
488         if (result == nullptr) {
489             LOG_ECMA_MEM(FATAL) << "malloc failed";
490             UNREACHABLE();
491         }
492         new (result) PGOProtoChainTemplate(size, count);
493         PGOProfileType *curPt = &(result->rootType_);
494         for (auto iter : protoChain) {
495             *curPt = iter.first;
496             curPt = curPt + 1;
497             *curPt = iter.second;
498             curPt = curPt + 1;
499         }
500         return result;
501     }
502 
DeleteProtoChain(PGOProtoChainTemplate * protoChain)503     static void DeleteProtoChain(PGOProtoChainTemplate *protoChain)
504     {
505         free(protoChain);
506     }
507 
508     template <typename FromType>
ConvertFrom(PGOContext & context,FromType * from)509     static PGOProtoChainTemplate *ConvertFrom(PGOContext &context, FromType *from)
510     {
511         auto count = from->GetCount();
512         size_t size = sizeof(PGOProtoChainTemplate);
513         if (count != 0) {
514             size += sizeof(PGOProfileType) * (static_cast<size_t>(count) - 1) * 2;   // 2 means mul by 2
515         }
516         auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size));
517         if (result == nullptr) {
518             LOG_ECMA_MEM(FATAL) << "malloc failed";
519             UNREACHABLE();
520         }
521         new (result) PGOProtoChainTemplate(size, count);
522         PGOProfileType *curPt = &(result->rootType_);
523         from->IterateProtoChain([&context, &curPt] (auto rootType, auto childType) {
524             *curPt = PGOProfileType(context, rootType);
525             curPt = curPt + 1;
526             *curPt = PGOProfileType(context, childType);
527             curPt = curPt + 1;
528         });
529         return result;
530     }
531 
532     template <typename Callback>
IterateProtoChain(Callback callback)533     void IterateProtoChain(Callback callback) const
534     {
535         if (count_ < PROTO_CHAIN_MIN_COUNT || count_ > PROTO_CHAIN_MAX_COUNT) {
536             return;
537         }
538         for (int i = 0; i < count_; i++) {
539             callback(*(&rootType_ + i), *(&rootType_ + i + 1));
540         }
541     }
542 
GetCount()543     int32_t GetCount()
544     {
545         return count_;
546     }
547 
Size()548     int32_t Size()
549     {
550         return size_;
551     }
552 
553 private:
554     int32_t size_;
555     int32_t count_;
556     PGOProfileType rootType_ {PGOProfileType()};
557     PGOProfileType childType_ {PGOProfileType()};
558 };
559 
560 using PGOProtoChain = PGOProtoChainTemplate<ProfileType>;
561 using PGOProtoChainRef = PGOProtoChainTemplate<ProfileTypeRef>;
562 
563 enum class ProtoChainMarker : uint8_t {
564     EXSIT,
565     NOT_EXSIT,
566 };
567 
568 template <typename PGOProfileType, typename PGOSampleType>
569 class PGOObjectTemplate {
570 public:
571     PGOObjectTemplate() = default;
PGOObjectTemplate(PGOProfileType receiverType)572     PGOObjectTemplate(PGOProfileType receiverType) : receiverType_(receiverType) {}
PGOObjectTemplate(PGOProfileType receiverType,JSHClass * receiver)573     PGOObjectTemplate(PGOProfileType receiverType, JSHClass *receiver)
574         : receiverType_(receiverType), receiver_(receiver) {}
PGOObjectTemplate(PGOProfileType receiverType,JSHClass * receiver,JSHClass * hold,JSHClass * holdTra,PGOSampleType accessorMethod,PrimitiveType primitiveType)575     PGOObjectTemplate(PGOProfileType receiverType, JSHClass *receiver, JSHClass *hold, JSHClass *holdTra,
576                       PGOSampleType accessorMethod, PrimitiveType primitiveType)
577         : receiverType_(receiverType), receiver_(receiver), holder_(hold), holdTra_(holdTra),
578           accessorMethod_(accessorMethod), primitiveType_(primitiveType) {}
PGOObjectTemplate(PGOProfileType receiverRootType,PGOProfileType receiverType,PGOProfileType holdRootType,PGOProfileType holdType,PGOProfileType holdTraRootType,PGOProfileType holdTraType,PGOSampleType accessorMethod)579     PGOObjectTemplate(PGOProfileType receiverRootType,
580                       PGOProfileType receiverType, PGOProfileType holdRootType,
581                       PGOProfileType holdType, PGOProfileType holdTraRootType,
582                       PGOProfileType holdTraType, PGOSampleType accessorMethod)
583         : receiverRootType_(receiverRootType), receiverType_(receiverType),
584           holdRootType_(holdRootType), holdType_(holdType),
585           holdTraRootType_(holdTraRootType), holdTraType_(holdTraType),
586           accessorMethod_(accessorMethod) {}
587 
AddPrototypePt(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)588     void AddPrototypePt(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain)
589     {
590         protoChainMarker_ = ProtoChainMarker::EXSIT;
591         if (protoChain_ != nullptr) {
592             PGOProtoChainTemplate<PGOProfileType>::DeleteProtoChain(protoChain_);
593         }
594         protoChain_ = PGOProtoChainTemplate<PGOProfileType>::CreateProtoChain(protoChain);
595     }
596 
597     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)598     void ConvertFrom(PGOContext &context, const FromType &from)
599     {
600         receiverRootType_ = PGOProfileType(context, from.GetReceiverRootType());
601         receiverType_ = PGOProfileType(context, from.GetReceiverType());
602         holdRootType_ = PGOProfileType(context, from.GetHoldRootType());
603         holdType_ = PGOProfileType(context, from.GetHoldType());
604         holdTraRootType_ = PGOProfileType(context, from.GetHoldTraRootType());
605         holdTraType_ = PGOProfileType(context, from.GetHoldTraType());
606         accessorMethod_ = PGOSampleType::ConvertFrom(context, from.GetAccessorMethod());
607         protoChainMarker_ = from.GetProtoChainMarker();
608     }
609 
GetInfoString()610     std::string GetInfoString() const
611     {
612         std::string result = "      ";
613         result += "(\n        receiverRoot" + receiverRootType_.GetTypeString();
614         result += ",\n        receiver" + receiverType_.GetTypeString();
615         result += ",\n        holdRoot" + holdRootType_.GetTypeString();
616         result += ",\n        hold" + holdType_.GetTypeString();
617         result += ",\n        holdTraRoot" + holdTraRootType_.GetTypeString();
618         result += ",\n        holdTra" + holdTraType_.GetTypeString();
619         result += ",\n        accessorMethod:" + accessorMethod_.GetTypeString();
620         result += "\n      )";
621         return result;
622     }
623 
624     template <typename T>
AddTypeJson(const char * typeName,const T & type,std::string typeOffset,std::vector<ProfileType::StringMap> & typeArray)625     void AddTypeJson(const char *typeName, const T& type, std::string typeOffset,
626                      std::vector<ProfileType::StringMap> &typeArray) const
627     {
628         ProfileType::StringMap typeJson;
629         typeJson.insert(std::make_pair(DumpJsonUtils::TYPE_NAME, typeName));
630         typeJson.insert(std::make_pair(DumpJsonUtils::TYPE_OFFSET, typeOffset));
631         type.GetTypeJson(typeJson);
632         typeArray.push_back(typeJson);
633     }
634 
GetInfoJson(std::vector<ProfileType::StringMap> & typeArray,std::string typeoffset)635     void GetInfoJson(std::vector<ProfileType::StringMap> &typeArray, std::string typeoffset) const
636     {
637         AddTypeJson("receiverRootType", receiverRootType_, typeoffset, typeArray);
638         AddTypeJson("receiverType", receiverType_, typeoffset, typeArray);
639         AddTypeJson("holdRootType", holdRootType_, typeoffset, typeArray);
640         AddTypeJson("holdType", holdType_, typeoffset, typeArray);
641         AddTypeJson("holdTraRootType", holdTraRootType_, typeoffset, typeArray);
642         AddTypeJson("holdTraType", holdTraType_, typeoffset, typeArray);
643         AddTypeJson("accessorMethodType", accessorMethod_, typeoffset, typeArray);
644     }
645 
GetProfileType()646     PGOProfileType GetProfileType() const
647     {
648         return receiverType_;
649     }
650 
GetReceiverRootType()651     PGOProfileType GetReceiverRootType() const
652     {
653         return receiverRootType_;
654     }
655 
GetReceiverType()656     PGOProfileType GetReceiverType() const
657     {
658         return receiverType_;
659     }
660 
GetHoldRootType()661     PGOProfileType GetHoldRootType() const
662     {
663         return holdRootType_;
664     }
665 
GetHoldType()666     PGOProfileType GetHoldType() const
667     {
668         return holdType_;
669     }
670 
GetHoldTraRootType()671     PGOProfileType GetHoldTraRootType() const
672     {
673         return holdTraRootType_;
674     }
675 
GetHoldTraType()676     PGOProfileType GetHoldTraType() const
677     {
678         return holdTraType_;
679     }
680 
GetAccessorMethod()681     PGOSampleType GetAccessorMethod() const
682     {
683         return accessorMethod_;
684     }
685 
GetProtoChainMarker()686     ProtoChainMarker GetProtoChainMarker() const
687     {
688         return protoChainMarker_;
689     }
690 
GetProtoChain()691     PGOProtoChainTemplate<PGOProfileType> *GetProtoChain() const
692     {
693         return protoChain_;
694     }
695 
SetProtoChain(PGOProtoChainTemplate<PGOProfileType> * protoChain)696     void SetProtoChain(PGOProtoChainTemplate<PGOProfileType> *protoChain)
697     {
698         protoChain_ = protoChain;
699     }
700 
IsNone()701     bool IsNone() const
702     {
703         return receiverType_.IsNone();
704     }
705 
IsMegaStateType()706     bool IsMegaStateType() const
707     {
708         return receiverType_.IsMegaStateType();
709     }
710 
IsJITClassType()711     bool IsJITClassType() const
712     {
713         return receiverType_.IsJITClassType();
714     }
715 
InConstructor()716     bool InConstructor() const
717     {
718         return receiverType_.IsConstructor();
719     }
720 
InElement()721     bool InElement() const
722     {
723         return receiverType_.IsBuiltinsArray();
724     }
725 
726     bool operator<(const PGOObjectTemplate &right) const
727     {
728         if (receiverRootType_ != right.receiverRootType_) {
729             return receiverRootType_ < right.receiverRootType_;
730         }
731         if (receiverType_ != right.receiverType_) {
732             return receiverType_ < right.receiverType_;
733         }
734         if (holdRootType_ != right.holdRootType_) {
735             return holdRootType_ < right.holdRootType_;
736         }
737         if (holdType_ != right.holdType_) {
738             return holdType_ < right.holdType_;
739         }
740         if (holdTraRootType_ != right.holdTraRootType_) {
741             return holdTraRootType_ < right.holdTraRootType_;
742         }
743         return holdTraType_ < right.holdTraType_;
744     }
745 
746     bool operator==(const PGOObjectTemplate &right) const
747     {
748         return receiverRootType_ == right.receiverRootType_ && receiverType_ == right.receiverType_ &&
749             holdRootType_ == right.holdRootType_ && holdType_ == right.holdType_ &&
750             holdTraRootType_ == right.holdTraRootType_ && holdTraType_ == right.holdTraType_ &&
751             receiver_ == right.receiver_ && holder_ == right.holder_ && holdTra_ == right.holdTra_;
752     }
753 
754     // Only Use For JIT
GetReceiverHclass()755     JSHClass* GetReceiverHclass() const
756     {
757         ASSERT(receiverType_.IsJITClassType() || receiverType_.IsBuiltinsType());
758         return receiver_;
759     }
GetHolderHclass()760     JSHClass* GetHolderHclass() const
761     {
762         ASSERT(receiverType_.IsJITClassType());
763         return holder_;
764     }
GetHolderTraHclass()765     JSHClass* GetHolderTraHclass() const
766     {
767         ASSERT(receiverType_.IsJITClassType());
768         return holdTra_;
769     }
770 
GetPrimitiveType()771     PrimitiveType GetPrimitiveType() const
772     {
773         return primitiveType_;
774     }
775 
776 private:
777     PGOProfileType receiverRootType_ { PGOProfileType() };
778     PGOProfileType receiverType_ { PGOProfileType() };
779     PGOProfileType holdRootType_ { PGOProfileType() };
780     PGOProfileType holdType_ { PGOProfileType() };
781     PGOProfileType holdTraRootType_ { PGOProfileType() };
782     PGOProfileType holdTraType_ { PGOProfileType() };
783     JSHClass* receiver_  {nullptr};
784     JSHClass* holder_ {nullptr};
785     JSHClass *holdTra_ {nullptr};
786     PGOSampleType accessorMethod_ { PGOSampleType() };
787     ProtoChainMarker protoChainMarker_ {ProtoChainMarker::NOT_EXSIT};
788     PGOProtoChainTemplate<PGOProfileType> *protoChain_ { nullptr };
789     PrimitiveType primitiveType_ = PrimitiveType::PRIMITIVE_TYPE_INVALID;
790 };
791 using PGOObjectInfo = PGOObjectTemplate<ProfileType, PGOSampleType>;
792 using PGOObjectInfoRef = PGOObjectTemplate<ProfileTypeRef, PGOSampleTypeRef>;
793 
794 template <typename PGOObjectInfoType>
795 class PGORWOpTemplate : public PGOType {
796 public:
PGORWOpTemplate()797     PGORWOpTemplate() : PGOType(TypeKind::RW_OP_TYPE) {};
798 
799     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)800     void ConvertFrom(PGOContext &context, const FromType &from)
801     {
802         count_ = std::min(from.GetCount(), static_cast<uint32_t>(POLY_CASE_NUM));
803         for (uint32_t index = 0; index < count_; index++) {
804             infos_[index].ConvertFrom(context, from.GetObjectInfo(index));
805         }
806     }
807 
SetName(JSHandle<JSTaggedValue> name)808     void SetName(JSHandle<JSTaggedValue> name)
809     {
810         name_ = name;
811     }
812 
SetNameIdx(uint32_t nameIdx)813     void SetNameIdx(uint32_t nameIdx)
814     {
815         nameIdx_ = nameIdx;
816     }
817 
GetNameIdx()818     uint32_t GetNameIdx() const
819     {
820         return nameIdx_;
821     }
822 
GetName()823     JSHandle<JSTaggedValue> GetName() const
824     {
825         return name_;
826     }
827 
Merge(const PGORWOpTemplate & type)828     void Merge(const PGORWOpTemplate &type)
829     {
830         for (uint32_t i = 0; i < type.count_; i++) {
831             AddObjectInfo(type.infos_[i]);
832         }
833     }
834 
AddObjectInfo(const PGOObjectInfoType & info)835     void AddObjectInfo(const PGOObjectInfoType &info)
836     {
837         if (info.IsNone()) {
838             return;
839         }
840         if (info.IsMegaStateType()) {
841             count_ = 1;
842             infos_[0] = info;
843             return;
844         }
845         uint32_t count = 0;
846         for (; count < count_; count++) {
847             if (infos_[count] == info) {
848                 return;
849             }
850         }
851         if (count < static_cast<uint32_t>(POLY_CASE_NUM)) {
852             infos_[count] = info;
853             count_++;
854         } else {
855             LOG_ECMA(DEBUG) << "Class type exceeds 4, discard";
856         }
857     }
858 
GetObjectInfo(uint32_t index)859     const PGOObjectInfoType &GetObjectInfo(uint32_t index) const
860     {
861         ASSERT(index < count_);
862         return infos_[index];
863     }
864 
GetCount()865     uint32_t GetCount() const
866     {
867         return count_;
868     }
869 
870 private:
871     static constexpr int POLY_CASE_NUM = 4;
872     uint32_t count_ = 0;
873     uint32_t nameIdx_ = -1;
874     JSHandle<JSTaggedValue> name_;
875     PGOObjectInfoType infos_[POLY_CASE_NUM];
876 };
877 using PGORWOpType = PGORWOpTemplate<PGOObjectInfo>;
878 using PGORWOpTypeRef = PGORWOpTemplate<PGOObjectInfoRef>;
879 
880 template <typename PGOProfileType>
881 class PGODefineOpTemplate : public PGOType {
882 public:
PGODefineOpTemplate()883     PGODefineOpTemplate() : PGOType(TypeKind::DEFINE_OP_TYPE), type_(PGOProfileType()) {};
PGODefineOpTemplate(PGOProfileType type)884     explicit PGODefineOpTemplate(PGOProfileType type) : PGOType(TypeKind::DEFINE_OP_TYPE), type_(type) {};
PGODefineOpTemplate(PGOProfileType type,JSHClass * hclass)885     explicit PGODefineOpTemplate(PGOProfileType type, JSHClass* hclass) : PGOType(TypeKind::DEFINE_OP_TYPE),
886                                                                           type_(type), receiver_(hclass) {};
887 
888     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)889     void ConvertFrom(PGOContext &context, const FromType &from)
890     {
891         type_ = PGOProfileType(context, from.GetProfileType());
892         ctorPt_ = PGOProfileType(context, from.GetCtorPt());
893         protoPt_ = PGOProfileType(context, from.GetPrototypePt());
894         kind_ = from.GetElementsKind();
895         elementsLength_ = from.GetElementsLength();
896         spaceFlag_ = from.GetSpaceFlag();
897     }
898 
GetTypeString()899     std::string GetTypeString() const
900     {
901         std::string result = "";
902         result += "      local" + type_.GetTypeString();
903         result += ",\n      ctor" + ctorPt_.GetTypeString();
904         result += ",\n      proto" + protoPt_.GetTypeString();
905         result += ",\n      elementsKind:" + std::to_string(static_cast<int32_t>(kind_));
906         if (elementsLength_ > 0 && spaceFlag_ != RegionSpaceFlag::UNINITIALIZED) {
907             result += ",\n      size: " + std::to_string(elementsLength_);
908             result += ",\n      space; " + ToSpaceTypeName(spaceFlag_);
909         }
910         return result;
911     }
912 
913     template <typename T>
AddTypeJson(const char * typeName,const T & type,std::string typeOffset,std::vector<ProfileType::StringMap> & sameOffsetTypeArray)914     void AddTypeJson(const char *typeName, const T& type, std::string typeOffset,
915                      std::vector<ProfileType::StringMap> &sameOffsetTypeArray) const
916     {
917         ProfileType::StringMap typeJson;
918         typeJson.insert(std::make_pair(DumpJsonUtils::TYPE_NAME, typeName));
919         typeJson.insert(std::make_pair(DumpJsonUtils::TYPE_NAME, typeOffset));
920         type.GetTypeJson(typeJson);
921         sameOffsetTypeArray.push_back(typeJson);
922     }
923 
GetTypeJson(std::vector<ProfileType::StringMap> & sameOffsetTypeArray,std::string typeOffset)924     void GetTypeJson(std::vector<ProfileType::StringMap> &sameOffsetTypeArray,
925                      std::string typeOffset) const
926     {
927         AddTypeJson("localType", type_, typeOffset, sameOffsetTypeArray);
928         AddTypeJson("ctorType", ctorPt_, typeOffset, sameOffsetTypeArray);
929         AddTypeJson("protoType", protoPt_, typeOffset, sameOffsetTypeArray);
930     }
931 
IsNone()932     bool IsNone() const
933     {
934         return type_.IsNone();
935     }
936 
GetProfileType()937     PGOProfileType GetProfileType() const
938     {
939         return type_;
940     }
941 
SetCtorPt(PGOProfileType type)942     void SetCtorPt(PGOProfileType type)
943     {
944         ctorPt_ = type;
945     }
946 
GetCtorPt()947     PGOProfileType GetCtorPt() const
948     {
949         return ctorPt_;
950     }
951 
SetPrototypePt(PGOProfileType type)952     void SetPrototypePt(PGOProfileType type)
953     {
954         protoPt_ = type;
955     }
956 
GetPrototypePt()957     PGOProfileType GetPrototypePt() const
958     {
959         return protoPt_;
960     }
961 
SetElementsKind(ElementsKind kind)962     void SetElementsKind(ElementsKind kind)
963     {
964         kind_ = kind;
965     }
966 
GetElementsKind()967     ElementsKind GetElementsKind() const
968     {
969         return kind_;
970     }
971 
SetElementsLength(uint32_t length)972     void SetElementsLength(uint32_t length)
973     {
974         elementsLength_ = length;
975     }
976 
GetElementsLength()977     uint32_t GetElementsLength() const
978     {
979         return elementsLength_;
980     }
981 
SetSpaceFlag(RegionSpaceFlag flag)982     void SetSpaceFlag(RegionSpaceFlag flag)
983     {
984         spaceFlag_ = flag;
985     }
986 
GetSpaceFlag()987     RegionSpaceFlag GetSpaceFlag() const
988     {
989         return spaceFlag_;
990     }
991 
992     bool operator<(const PGODefineOpTemplate &right) const
993     {
994         return this->GetProfileType() < right.GetProfileType();
995     }
996 
GetReceiver()997     JSHClass* GetReceiver() const
998     {
999         ASSERT(type_.IsJITClassType());
1000         return receiver_;
1001     }
1002 
1003 private:
1004     PGOProfileType type_ { PGOProfileType() };
1005     PGOProfileType ctorPt_ { PGOProfileType() };
1006     PGOProfileType protoPt_ { PGOProfileType() };
1007     uint32_t elementsLength_ { 0 };
1008     ElementsKind kind_ { ElementsKind::NONE };
1009     RegionSpaceFlag spaceFlag_  { RegionSpaceFlag::UNINITIALIZED };
1010     JSHClass* receiver_ {nullptr};
1011 };
1012 
1013 using PGODefineOpType = PGODefineOpTemplate<ProfileType>;
1014 using PGODefineOpTypeRef = PGODefineOpTemplate<ProfileTypeRef>;
1015 
1016 template <typename PGOProfileType>
1017 class PGOProtoTransitionTemplate : public PGOType {
1018 public:
PGOProtoTransitionTemplate()1019     PGOProtoTransitionTemplate() : PGOType(TypeKind::PROTO_TRANSITION_TYPE), ihcType_(PGOProfileType()) {};
PGOProtoTransitionTemplate(PGOProfileType type)1020     explicit PGOProtoTransitionTemplate(PGOProfileType type) : PGOType(TypeKind::PROTO_TRANSITION_TYPE),
1021                                                                ihcType_(type) {}
1022 
1023     template <typename FromType>
ConvertFrom(PGOContext & context,const FromType & from)1024     void ConvertFrom(PGOContext &context, const FromType &from)
1025     {
1026         ihcType_ = PGOProfileType(context, from.GetIhcType());
1027         baseRootPt_ = PGOProfileType(context, from.GetBaseType().first);
1028         basePt_ = PGOProfileType(context, from.GetBaseType().second);
1029         transIhcType_ = PGOProfileType(context, from.GetTransitionType());
1030         transProtoPt_ = PGOProfileType(context, from.GetTransitionProtoPt());
1031     }
1032 
GetTypeString()1033     std::string GetTypeString() const
1034     {
1035         std::string result = "(ihc";
1036         result += ihcType_.GetTypeString();
1037         result += ", baseRoot";
1038         result += baseRootPt_.GetTypeString();
1039         result += ", base";
1040         result += basePt_.GetTypeString();
1041         result += ", transIhc";
1042         result += transIhcType_.GetTypeString();
1043         result += ", transProto";
1044         result += transProtoPt_.GetTypeString();
1045         result += ")";
1046         return result;
1047     }
1048 
IsNone()1049     bool IsNone() const
1050     {
1051         return ihcType_.IsNone() || transIhcType_.IsNone();
1052     }
1053 
IsProtoTransitionNone()1054     bool IsProtoTransitionNone() const
1055     {
1056         return transIhcType_.IsNone();
1057     }
1058 
GetIhcType()1059     PGOProfileType GetIhcType() const
1060     {
1061         return ihcType_;
1062     }
1063 
SetBaseType(PGOProfileType rootType,PGOProfileType type)1064     void SetBaseType(PGOProfileType rootType, PGOProfileType type)
1065     {
1066         baseRootPt_ = rootType;
1067         basePt_ = type;
1068     }
1069 
GetBaseType()1070     std::pair<PGOProfileType, PGOProfileType> GetBaseType() const
1071     {
1072         return std::make_pair(baseRootPt_, basePt_);
1073     }
1074 
SetTransitionType(PGOProfileType type)1075     void SetTransitionType(PGOProfileType type)
1076     {
1077         transIhcType_ = type;
1078     }
1079 
GetTransitionType()1080     PGOProfileType GetTransitionType() const
1081     {
1082         return transIhcType_;
1083     }
1084 
SetTransitionProtoPt(PGOProfileType type)1085     void SetTransitionProtoPt(PGOProfileType type)
1086     {
1087         transProtoPt_ = type;
1088     }
1089 
GetTransitionProtoPt()1090     PGOProfileType GetTransitionProtoPt() const
1091     {
1092         return transProtoPt_;
1093     }
1094 
1095     bool operator<(const PGOProtoTransitionTemplate &right) const
1096     {
1097         return this->GetIhcType() < right.GetIhcType();
1098     }
1099 
IsSameProtoTransition(const PGOProtoTransitionTemplate & type)1100     bool IsSameProtoTransition(const PGOProtoTransitionTemplate &type) const
1101     {
1102         return (GetBaseType().first == type.GetBaseType().first) &&
1103                (GetBaseType().second == type.GetBaseType().second) &&
1104                (GetTransitionType() == type.GetTransitionType()) &&
1105                (GetTransitionProtoPt() == type.GetTransitionProtoPt());
1106     }
1107 
1108     // only support mono-state prototype transition now
CombineType(const PGOProtoTransitionTemplate & type)1109     PGOProtoTransitionTemplate CombineType(const PGOProtoTransitionTemplate &type)
1110     {
1111         ASSERT(GetIhcType() == type.GetIhcType());
1112         if (IsProtoTransitionNone() || IsSameProtoTransition(type)) {
1113             return *this;
1114         }
1115         // clear all except for key
1116         SetBaseType(PGOProfileType(), PGOProfileType());
1117         SetTransitionType(PGOProfileType());
1118         SetTransitionProtoPt(PGOProfileType());
1119         return *this;
1120     }
1121 
1122 private:
1123     PGOProfileType ihcType_ { PGOProfileType() };  // key
1124     PGOProfileType baseRootPt_ { PGOProfileType() };
1125     PGOProfileType basePt_ { PGOProfileType() };
1126     PGOProfileType transIhcType_ { PGOProfileType() };
1127     PGOProfileType transProtoPt_ { PGOProfileType() };
1128 };
1129 using PGOProtoTransitionType = PGOProtoTransitionTemplate<ProfileType>;
1130 using PGOProtoTransitionTypeRef = PGOProtoTransitionTemplate<ProfileTypeRef>;
1131 
1132 class PGOTypeRef {
1133 public:
PGOTypeRef()1134     PGOTypeRef() : type_(nullptr) {}
1135 
PGOTypeRef(PGOType * type)1136     explicit PGOTypeRef(PGOType *type) : type_(type) {}
1137 
PGOTypeRef(const PGOSampleType * type)1138     explicit PGOTypeRef(const PGOSampleType *type) : type_(static_cast<const PGOType*>(type)) {}
1139 
PGOTypeRef(const PGORWOpType * type)1140     explicit PGOTypeRef(const PGORWOpType *type) : type_(static_cast<const PGOType*>(type)) {}
1141 
PGOTypeRef(const PGODefineOpType * type)1142     explicit PGOTypeRef(const PGODefineOpType *type) : type_(static_cast<const PGOType*>(type)) {}
1143 
PGOTypeRef(const PGOProtoTransitionType * type)1144     explicit PGOTypeRef(const PGOProtoTransitionType *type) : type_(static_cast<const PGOType*>(type)) {}
1145 
NoneType()1146     static PGOTypeRef NoneType()
1147     {
1148         return PGOTypeRef();
1149     }
1150 
1151     bool operator<(const PGOTypeRef &right) const
1152     {
1153         return type_ < right.type_;
1154     }
1155 
1156     bool operator!=(const PGOTypeRef &right) const
1157     {
1158         return type_ != right.type_;
1159     }
1160 
1161     bool operator==(const PGOTypeRef &right) const
1162     {
1163         return type_ == right.type_;
1164     }
1165 
IsValid()1166     bool IsValid() const
1167     {
1168         return type_ != nullptr;
1169     }
1170 
IsValidCallMethodId()1171     bool IsValidCallMethodId() const
1172     {
1173         if (type_ == nullptr) {
1174             return false;
1175         }
1176         if (!type_->IsScalarOpType()) {
1177             return false;
1178         }
1179         auto sampleType = static_cast<const PGOSampleType*>(type_);
1180         if (sampleType->IsProfileType()) {
1181             if (sampleType->GetProfileType().IsMethodId()) {
1182                 return sampleType->GetProfileType().IsValidCallMethodId();
1183             }
1184             if (sampleType->GetProfileType().IsClassType()) {
1185                 return sampleType->GetProfileType().IsValidClassConstructorMethodId();
1186             }
1187         }
1188         return false;
1189     }
1190 
IsDefOpValidCallMethodId()1191     bool IsDefOpValidCallMethodId() const
1192     {
1193         if (type_ == nullptr) {
1194             return false;
1195         }
1196         if (!type_->IsDefineOpType()) {
1197             return false;
1198         }
1199         auto sampleType = static_cast<const PGODefineOpType*>(type_);
1200         if (sampleType->GetProfileType().IsMethodId()) {
1201             return sampleType->GetProfileType().IsValidCallMethodId();
1202         }
1203         if (sampleType->GetProfileType().IsJITClassType()) {
1204             return sampleType->GetProfileType().IsValidClassConstructorMethodId();
1205         }
1206         return false;
1207     }
1208 
GetCallMethodId()1209     uint32_t GetCallMethodId() const
1210     {
1211         auto sampleType = static_cast<const PGOSampleType*>(type_);
1212         if (sampleType->GetProfileType().IsClassType()) {
1213             return sampleType->GetProfileType().GetClassConstructorMethodId();
1214         }
1215         return sampleType->GetProfileType().GetCallMethodId();
1216     }
1217 
GetDefOpCallMethodId()1218     uint32_t GetDefOpCallMethodId() const
1219     {
1220         auto sampleType = static_cast<const PGODefineOpType*>(type_);
1221         if (sampleType->GetProfileType().IsJITClassType()) {
1222             return sampleType->GetProfileType().GetClassConstructorMethodId();
1223         }
1224         return sampleType->GetProfileType().GetCallMethodId();
1225     }
1226 
GetValue()1227     uint64_t GetValue() const
1228     {
1229         auto sampleType = static_cast<const PGOSampleType*>(type_);
1230         return sampleType->GetProfileType().GetRaw();
1231     }
1232 
GetPGOSampleType()1233     const PGOSampleType* GetPGOSampleType() const
1234     {
1235         if (type_ == nullptr) {
1236             static PGOSampleType noneType = PGOSampleType::NoneType();
1237             return &noneType;
1238         }
1239         ASSERT(type_->IsScalarOpType());
1240         return static_cast<const PGOSampleType*>(type_);
1241     }
1242 
IsPGOSampleType()1243     bool IsPGOSampleType() const
1244     {
1245         if (type_ == nullptr) {
1246             return false;
1247         }
1248         return type_->IsScalarOpType();
1249     }
1250 
HasNumber()1251     bool HasNumber() const
1252     {
1253         return GetPGOSampleType()->HasNumber();
1254     }
1255 
IsBoolean()1256     bool IsBoolean() const
1257     {
1258         return GetPGOSampleType()->IsBoolean();
1259     }
1260 
IsUndefinedOrNull()1261     bool IsUndefinedOrNull() const
1262     {
1263         return GetPGOSampleType()->IsUndefinedOrNull();
1264     }
1265 
IsString()1266     bool IsString() const
1267     {
1268         return GetPGOSampleType()->IsString();
1269     }
1270 
IsInternString()1271     bool IsInternString() const
1272     {
1273         return GetPGOSampleType()->IsInternString();
1274     }
1275 
IsHeapObject()1276     bool IsHeapObject() const
1277     {
1278         return GetPGOSampleType()->IsHeapObject();
1279     }
1280 
IsNumberOrString()1281     bool IsNumberOrString() const
1282     {
1283         return GetPGOSampleType()->IsNumberOrString();
1284     }
1285 
GetPGORWOpType()1286     const PGORWOpType* GetPGORWOpType()
1287     {
1288         if (type_ == nullptr) {
1289             static PGORWOpType noneType;
1290             return &noneType;
1291         }
1292         ASSERT(type_->IsRwOpType());
1293         return static_cast<const PGORWOpType*>(type_);
1294     }
1295 
GetPGODefineOpType()1296     const PGODefineOpType* GetPGODefineOpType()
1297     {
1298         if (type_ == nullptr) {
1299             static PGODefineOpType noneType;
1300             return &noneType;
1301         }
1302         ASSERT(type_->IsDefineOpType());
1303         return static_cast<const PGODefineOpType*>(type_);
1304     }
1305 
1306 private:
1307     const PGOType *type_;
1308 };
1309 } // namespace panda::ecmascript::pgo
1310 #endif  // ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILER_TYPE_H
1311