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