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