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_PROFILE_TYPE_H 17 #define ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILE_TYPE_H 18 19 #include <cstdint> 20 #include <optional> 21 #include <string> 22 #include <variant> 23 24 #include "ecmascript/builtin_entries.h" 25 #include "ecmascript/elements.h" 26 #include "ecmascript/global_index.h" 27 #include "ecmascript/js_hclass.h" 28 #include "ecmascript/log.h" 29 #include "ecmascript/log_wrapper.h" 30 #include "ecmascript/pgo_profiler/pgo_context.h" 31 #include "ecmascript/pgo_profiler/pgo_utils.h" 32 #include "ecmascript/on_heap.h" 33 #include "libpandabase/utils/bit_field.h" 34 #include "macros.h" 35 36 namespace panda::ecmascript::pgo { 37 class ProfileTypeRef; 38 class PGOContext; 39 40 using ApEntityId = pgo::ApEntityId; 41 42 class ProfileType { 43 public: 44 enum class Kind : uint8_t { 45 ClassId, 46 ObjectLiteralId, 47 ArrayLiteralId, 48 BuiltinsId, 49 LegacyKind = BuiltinsId, 50 MethodId, // method offset of js function 51 BuiltinFunctionId, // function index of registered function 52 RecordClassId, 53 PrototypeId, 54 ConstructorId, 55 MegaStateKinds, 56 TotalKinds, 57 UnknowId, 58 GlobalsId, 59 JITClassId, 60 TransitionClassId, // function class id after set prototype 61 TransitionPrototypeId, // function prototype id after set prototype 62 NapiId, 63 InvalidId, 64 }; 65 66 static constexpr uint32_t RECORD_ID_FOR_BUNDLE = 1; 67 static constexpr uint32_t HUGE_ABC_ID = 500; 68 69 static PUBLIC_API const ProfileType PROFILE_TYPE_NONE; 70 71 static constexpr uint32_t ID_BITFIELD_NUM = 32; // 0-31 72 static constexpr uint32_t ABC_ID_BITFIELD_NUM = 10; // 32-41 73 static constexpr uint32_t KIND_BITFIELD_NUM = 8; // 42 - 49 74 using IdBits = BitField<uint32_t, 0, ID_BITFIELD_NUM>; 75 using AbcIdBits = IdBits::NextField<uint32_t, ABC_ID_BITFIELD_NUM>; 76 using KindBits = AbcIdBits::NextField<Kind, KIND_BITFIELD_NUM>; 77 using IsRootBits = KindBits::NextFlag; // 50 78 using EverOutOfBoundsBits = IsRootBits::NextFlag; // 51 79 80 using StringMap = std::multimap<std::string, std::string>; 81 using MapVector = std::vector<std::vector<StringMap>>; 82 using VariantVector = std::vector<std::variant<StringMap, MapVector, std::vector<StringMap>>>; 83 using VariantMap = std::multimap<std::string, std::variant<std::string, VariantVector>>; 84 using jModuleType = std::multimap<std::string, std::variant<std::string, std::vector<VariantMap>>>; 85 86 class BuiltinsId { 87 public: 88 static constexpr uint32_t BUILTINS_ID_NUM = 16; 89 using BuiltinsIdBits = BitField<JSType, 0, BUILTINS_ID_NUM>; 90 91 explicit BuiltinsId() = default; BuiltinsId(uint32_t id)92 explicit BuiltinsId(uint32_t id) : id_(id) {} 93 GetId()94 uint32_t GetId() const 95 { 96 return id_; 97 } 98 SetBuiltinsId(JSType type)99 BuiltinsId SetBuiltinsId(JSType type) 100 { 101 id_ = BuiltinsIdBits::Update(id_, type); 102 return *this; 103 } 104 GetBuiltinsId()105 JSType GetBuiltinsId() const 106 { 107 return BuiltinsIdBits::Decode(id_); 108 } 109 GetIdToString()110 virtual std::string GetIdToString() const 111 { 112 std::stringstream ss; 113 ss << "("; 114 ss << GetId(); 115 ss << ")"; 116 return ss.str(); 117 } 118 119 protected: 120 uint32_t id_ { 0 }; 121 }; 122 123 class BuiltinsArrayId : public BuiltinsId { 124 public: 125 // BuilitinsArray second bit field 126 static constexpr uint32_t OLD_ELEMENTS_KIND_BITFIELD_NUM = 5; 127 static constexpr uint32_t NEW_ELEMENTS_KIND_BITFIELD_NUM = 5; 128 using OldElementsKindBits = BuiltinsIdBits::NextField<ElementsKind, OLD_ELEMENTS_KIND_BITFIELD_NUM>; 129 using NewElementsKindBits = OldElementsKindBits::NextField<ElementsKind, NEW_ELEMENTS_KIND_BITFIELD_NUM>; 130 131 explicit BuiltinsArrayId() = default; BuiltinsArrayId(uint32_t id)132 explicit BuiltinsArrayId(uint32_t id) : BuiltinsId(id) {} 133 UpdateElementsKind(ElementsKind kind)134 BuiltinsArrayId UpdateElementsKind(ElementsKind kind) 135 { 136 id_ = OldElementsKindBits::Update(id_, kind); 137 return *this; 138 } 139 GetElementsKind()140 ElementsKind GetElementsKind() const 141 { 142 return OldElementsKindBits::Decode(id_); 143 } 144 UpdateTransitionElementsKind(ElementsKind kind)145 BuiltinsArrayId UpdateTransitionElementsKind(ElementsKind kind) 146 { 147 id_ = NewElementsKindBits::Update(id_, kind); 148 return *this; 149 } 150 GetTransitionElementsKind()151 ElementsKind GetTransitionElementsKind() const 152 { 153 return NewElementsKindBits::Decode(id_); 154 } 155 GetIdToString()156 std::string GetIdToString() const override 157 { 158 std::stringstream ss; 159 ss << "("; 160 ss << static_cast<uint32_t>(BuiltinsId::GetBuiltinsId()) << ", "; 161 ss << static_cast<uint32_t>(GetElementsKind()) << ", "; 162 ss << static_cast<uint32_t>(GetTransitionElementsKind()); 163 ss << ")"; 164 return ss.str(); 165 } 166 }; 167 168 class BuiltinsTypedArrayId : public BuiltinsId { 169 public: 170 // BuilitinsTypedArray second bit field 171 static constexpr uint8_t ON_HEAP_MODE_BITFIELD_NUM = 2; 172 using OnHeapModeBits = BuiltinsArrayId::NewElementsKindBits::NextField<OnHeapMode, ON_HEAP_MODE_BITFIELD_NUM>; 173 174 explicit BuiltinsTypedArrayId() = default; BuiltinsTypedArrayId(uint32_t id)175 explicit BuiltinsTypedArrayId(uint32_t id) : BuiltinsId(id) {} 176 UpdateOnHeapMode(OnHeapMode onHeapMode)177 BuiltinsTypedArrayId UpdateOnHeapMode(OnHeapMode onHeapMode) 178 { 179 id_ = OnHeapModeBits::Update(id_, onHeapMode); 180 return *this; 181 } 182 GetOnHeapMode()183 OnHeapMode GetOnHeapMode() const 184 { 185 return OnHeapModeBits::Decode(id_); 186 } 187 GetIdToString()188 std::string GetIdToString() const override 189 { 190 std::stringstream ss; 191 ss << "("; 192 ss << static_cast<uint32_t>(BuiltinsId::GetBuiltinsId()) << ", "; 193 auto builtinsArrayId = BuiltinsArrayId(GetId()); 194 ss << static_cast<uint32_t>(builtinsArrayId.GetElementsKind()) << ", "; 195 ss << static_cast<uint32_t>(builtinsArrayId.GetTransitionElementsKind()) << ", "; 196 ss << static_cast<uint32_t>(GetOnHeapMode()); 197 ss << ")"; 198 return ss.str(); 199 } 200 }; 201 202 static_assert(KindBits::IsValid(Kind::TotalKinds)); 203 204 ProfileType() = default; ProfileType(uint64_t rawType)205 explicit ProfileType(uint64_t rawType) : type_(rawType) {}; 206 ProfileType(PGOContext &context, ProfileTypeRef typeRef); 207 ProfileType(ApEntityId abcId, uint32_t type, Kind kind = Kind::ClassId, bool root = false, 208 bool everOutOfBounds = false) 209 { 210 if (UNLIKELY(!IdBits::IsValid(type))) { 211 type_ = 0; 212 } else { 213 UpdateAbcId(abcId); 214 UpdateId(type); 215 UpdateKind(kind); 216 UpdateIsRootFlag(root); 217 UpdateEverOutOfBounds(everOutOfBounds); 218 } 219 } 220 CreateMegaType()221 static ProfileType CreateMegaType() 222 { 223 ProfileType type; 224 type.UpdateKind(Kind::MegaStateKinds); 225 return type; 226 } 227 228 static std::optional<ProfileType> CreateFromProfileTypeRef(PGOContext &context, ProfileTypeRef typeRef); 229 CreateJITType()230 static ProfileType CreateJITType() 231 { 232 ProfileType type; 233 type.UpdateKind(Kind::JITClassId); 234 return type; 235 } 236 CreateBuiltinsArray(ApEntityId abcId,JSType type,ElementsKind kind,ElementsKind transitionKind,bool everOutOfBounds)237 static ProfileType CreateBuiltinsArray(ApEntityId abcId, JSType type, ElementsKind kind, 238 ElementsKind transitionKind, bool everOutOfBounds) 239 { 240 auto id = BuiltinsArrayId().UpdateElementsKind(kind).UpdateTransitionElementsKind(transitionKind) 241 .SetBuiltinsId(type).GetId(); 242 return ProfileType(abcId, id, Kind::BuiltinsId, false, everOutOfBounds); 243 } 244 CreateBuiltinsTypedArray(ApEntityId abcId,JSType type,OnHeapMode onHeap,bool everOutOfBounds)245 static ProfileType CreateBuiltinsTypedArray(ApEntityId abcId, JSType type, OnHeapMode onHeap, 246 bool everOutOfBounds) 247 { 248 auto id = BuiltinsTypedArrayId().UpdateOnHeapMode(onHeap).SetBuiltinsId(type).GetId(); 249 return ProfileType(abcId, id, Kind::BuiltinsId, false, everOutOfBounds); 250 } 251 CreateBuiltins(ApEntityId abcId,JSType type)252 static ProfileType CreateBuiltins(ApEntityId abcId, JSType type) 253 { 254 auto id = BuiltinsId().SetBuiltinsId(type).GetId(); 255 return ProfileType(abcId, id, Kind::BuiltinsId); 256 } 257 CreateGlobals(ApEntityId abcId,GlobalIndex globalsId)258 static ProfileType CreateGlobals(ApEntityId abcId, GlobalIndex globalsId) 259 { 260 auto id = globalsId.GetGlobalIndex(); 261 return ProfileType(abcId, id, Kind::GlobalsId); 262 } 263 264 ProfileType &Remap(const PGOContext &context); 265 IsNone()266 bool IsNone() const 267 { 268 return type_ == PROFILE_TYPE_NONE.type_; 269 } 270 GetRaw()271 uint64_t GetRaw() const 272 { 273 return type_; 274 } 275 IsRootType()276 bool IsRootType() const 277 { 278 return IsRootBits::Decode(type_); 279 } 280 IsEverOutOfBounds()281 bool IsEverOutOfBounds() const 282 { 283 return EverOutOfBoundsBits::Decode(type_); 284 } 285 IsGlobalsType()286 bool IsGlobalsType() const 287 { 288 return GetKind() == Kind::GlobalsId; 289 } 290 IsBuiltinsType()291 bool IsBuiltinsType() const 292 { 293 return GetKind() == Kind::BuiltinsId; 294 } 295 IsClassType()296 bool IsClassType() const 297 { 298 return GetKind() == Kind::ClassId; 299 } 300 IsJITClassType()301 bool IsJITClassType() const 302 { 303 return GetKind() == Kind::JITClassId; 304 } 305 IsMethodId()306 bool IsMethodId() const 307 { 308 return GetKind() == Kind::MethodId; 309 } 310 IsBuiltinFunctionId()311 bool IsBuiltinFunctionId() const 312 { 313 return GetKind() == Kind::BuiltinFunctionId; 314 } 315 IsArrayLiteralType()316 bool IsArrayLiteralType() const 317 { 318 return GetKind() == Kind::ArrayLiteralId; 319 } 320 IsObjectLiteralType()321 bool IsObjectLiteralType() const 322 { 323 return GetKind() == Kind::ObjectLiteralId; 324 } 325 IsConstructor()326 bool IsConstructor() const 327 { 328 return GetKind() == Kind::ConstructorId; 329 } 330 IsPrototype()331 bool IsPrototype() const 332 { 333 return GetKind() == Kind::PrototypeId; 334 } 335 IsTransitionClassType()336 bool IsTransitionClassType() const 337 { 338 return GetKind() == Kind::TransitionClassId; 339 } 340 IsTransitionPrototype()341 bool IsTransitionPrototype() const 342 { 343 return GetKind() == Kind::TransitionPrototypeId; 344 } 345 IsNapiType()346 bool IsNapiType() const 347 { 348 return GetKind() == Kind::NapiId; 349 } 350 IsInvalidType()351 bool IsInvalidType() const 352 { 353 return GetKind() == Kind::InvalidId; 354 } 355 IsTransitionType()356 bool IsTransitionType() const 357 { 358 return IsTransitionClassType() || IsTransitionPrototype(); 359 } 360 IsMegaStateType()361 bool IsMegaStateType() const 362 { 363 return GetKind() == Kind::MegaStateKinds; 364 } 365 IsGeneralizedClassType()366 bool IsGeneralizedClassType() const 367 { 368 return IsClassType() || IsTransitionClassType(); 369 } 370 IsGeneralizedPrototype()371 bool IsGeneralizedPrototype() const 372 { 373 return IsPrototype() || IsTransitionPrototype(); 374 } 375 GetId()376 uint32_t GetId() const 377 { 378 return IdBits::Decode(type_); 379 } 380 GetKind()381 Kind GetKind() const 382 { 383 return KindBits::Decode(type_); 384 } 385 GetAbcId()386 ApEntityId GetAbcId() const 387 { 388 return AbcIdBits::Decode(type_); 389 } 390 UpdateAbcId(ApEntityId abcId)391 void UpdateAbcId(ApEntityId abcId) 392 { 393 if (abcId > HUGE_ABC_ID) { 394 LOG_ECMA(FATAL) << "huge abcId: " << abcId; // only for debug purpose, do not merge to release version 395 } 396 type_ = AbcIdBits::Update(type_, abcId); 397 } 398 399 bool operator<(const ProfileType &right) const 400 { 401 return type_ < right.type_; 402 } 403 404 bool operator!=(const ProfileType &right) const 405 { 406 return type_ != right.type_; 407 } 408 409 bool operator==(const ProfileType &right) const 410 { 411 return type_ == right.type_; 412 } 413 GetTypeString()414 std::string GetTypeString() const 415 { 416 std::stringstream stream; 417 stream << "Type: " << "(isRoot: " << IsRootType() << 418 ", ever out of bounds: " << IsEverOutOfBounds() << 419 ", kind: " << std::showbase << std::dec << static_cast<uint32_t>(GetKind()) << 420 ", abcId: " << GetAbcId() << ", id: " << GetId() << ")"; 421 return stream.str(); 422 } 423 GetTypeJson(StringMap & type)424 void GetTypeJson(StringMap &type) const 425 { 426 type.insert(std::make_pair(DumpJsonUtils::IS_ROOT, IsRootType() ? "true" : "false")); 427 type.insert(std::make_pair(DumpJsonUtils::KIND, std::to_string(static_cast<double>(GetKind())))); 428 type.insert(std::make_pair(DumpJsonUtils::ABC_ID, std::to_string(GetAbcId()))); 429 std::string strId; 430 if (IsBuiltinsArray()) { 431 auto arrayId = BuiltinsArrayId(GetId()); 432 strId = arrayId.GetIdToString(); 433 } else if (IsBuiltinsTypeArray()) { 434 auto typedArrayId = BuiltinsTypedArrayId(GetId()); 435 strId = typedArrayId.GetIdToString(); 436 } else { 437 auto builtinsId = BuiltinsId(GetId()); 438 strId = builtinsId.GetIdToString(); 439 } 440 type.insert(std::make_pair(DumpJsonUtils::ID, strId)); 441 } 442 443 friend std::ostream& operator<<(std::ostream& os, const ProfileType& type) 444 { 445 os << type.GetTypeString(); 446 return os; 447 } 448 UpdateId(uint32_t id)449 void UpdateId(uint32_t id) 450 { 451 type_ = IdBits::Update(type_, id); 452 } 453 UpdateKind(Kind kind)454 void UpdateKind(Kind kind) 455 { 456 type_ = KindBits::Update(type_, kind); 457 } 458 UpdateIsRootFlag(bool root)459 void UpdateIsRootFlag(bool root) 460 { 461 type_ = IsRootBits::Update(type_, root); 462 } 463 UpdateEverOutOfBounds(bool val)464 void UpdateEverOutOfBounds(bool val) 465 { 466 type_ = EverOutOfBoundsBits::Update(type_, val); 467 } 468 IsValidCallMethodId()469 bool IsValidCallMethodId() const 470 { 471 return GetCallMethodId() > 0; 472 } 473 IsValidClassConstructorMethodId()474 bool IsValidClassConstructorMethodId() const 475 { 476 return GetClassConstructorMethodId() > 0; 477 } 478 GetCallMethodId()479 uint32_t GetCallMethodId() const 480 { 481 ASSERT(IsMethodId()); 482 return GetId(); 483 } 484 GetClassConstructorMethodId()485 uint32_t GetClassConstructorMethodId() const 486 { 487 ASSERT(IsClassType()); 488 return GetId(); 489 } 490 GetBuiltinsType()491 JSType GetBuiltinsType() const 492 { 493 ASSERT(IsBuiltinsType()); 494 auto builtinsId = BuiltinsId(GetId()); 495 return builtinsId.GetBuiltinsId(); 496 } 497 GetGlobalsId()498 GlobalIndex GetGlobalsId() const 499 { 500 ASSERT(IsGlobalsType()); 501 auto globalsId = GlobalIndex(GetId()); 502 return globalsId; 503 } 504 GetElementsKindBeforeTransition()505 ElementsKind GetElementsKindBeforeTransition() const 506 { 507 ASSERT(IsBuiltinsArray()); 508 auto builtinsArrayId = BuiltinsArrayId(GetId()); 509 return builtinsArrayId.GetElementsKind(); 510 } 511 GetElementsKindAfterTransition()512 ElementsKind GetElementsKindAfterTransition() const 513 { 514 ASSERT(IsBuiltinsArray()); 515 auto builtinsArrayId = BuiltinsArrayId(GetId()); 516 return builtinsArrayId.GetTransitionElementsKind(); 517 } 518 IsBuiltinsMap()519 bool IsBuiltinsMap() const 520 { 521 if (IsBuiltinsType()) { 522 JSType type = GetBuiltinsType(); 523 return type == JSType::JS_MAP; 524 } 525 return false; 526 } 527 IsBuiltinsString()528 bool IsBuiltinsString() const 529 { 530 if (IsBuiltinsType()) { 531 JSType type = GetBuiltinsType(); 532 return type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST; 533 } 534 return false; 535 } 536 IsBuiltinsArray()537 bool IsBuiltinsArray() const 538 { 539 if (IsBuiltinsType()) { 540 JSType type = GetBuiltinsType(); 541 return type == JSType::JS_ARRAY; 542 } 543 return false; 544 } 545 IsBuiltinsTypeArray()546 bool IsBuiltinsTypeArray() const 547 { 548 if (IsBuiltinsType()) { 549 JSType type = GetBuiltinsType(); 550 return type > JSType::JS_TYPED_ARRAY_FIRST && type <= JSType::JS_TYPED_ARRAY_LAST; 551 } 552 return false; 553 } 554 555 private: UpdateId(uint64_t type)556 void UpdateId(uint64_t type) 557 { 558 type_ = IdBits::Update(type_, type); 559 } 560 561 uint64_t type_ {0}; 562 }; 563 564 struct HashProfileType { operatorHashProfileType565 uint64_t operator()(const ProfileType &profileType) const 566 { 567 return profileType.GetRaw(); 568 } 569 }; 570 571 class ProfileTypeRef { 572 public: 573 ProfileTypeRef() = default; ProfileTypeRef(ApEntityId type)574 explicit ProfileTypeRef(ApEntityId type) 575 { 576 UpdateId(type); 577 } 578 579 ProfileTypeRef(PGOContext &context, const ProfileType &type); 580 581 ProfileTypeRef &Remap(const PGOContext &context); 582 IsNone()583 bool IsNone() const 584 { 585 return typeId_ == 0; 586 } 587 IsBuiltinsArray()588 bool IsBuiltinsArray() const 589 { 590 return false; 591 } 592 IsConstructor()593 bool IsConstructor() const 594 { 595 return false; 596 } 597 IsMegaStateType()598 bool IsMegaStateType() const 599 { 600 return false; 601 } 602 GetId()603 ApEntityId GetId() const 604 { 605 return typeId_; 606 } 607 608 bool operator<(const ProfileTypeRef &right) const 609 { 610 return typeId_ < right.typeId_; 611 } 612 613 bool operator==(const ProfileTypeRef &right) const 614 { 615 return typeId_ == right.typeId_; 616 } 617 GetTypeString()618 std::string GetTypeString() const 619 { 620 return std::to_string(typeId_); 621 } 622 UpdateId(ApEntityId typeId)623 void UpdateId(ApEntityId typeId) 624 { 625 typeId_ = typeId; 626 } 627 628 private: 629 ApEntityId typeId_ {0}; 630 }; 631 static_assert(sizeof(ProfileTypeRef) == sizeof(uint32_t)); 632 633 class ProfileTypeLegacy { 634 public: 635 static constexpr uint32_t ID_BITFIELD_NUM = 29; 636 static constexpr uint32_t KIND_BITFIELD_NUM = 3; 637 using IdBits = BitField<uint32_t, 0, ID_BITFIELD_NUM>; 638 using KindBits = IdBits::NextField<ProfileType::Kind, KIND_BITFIELD_NUM>; 639 640 // legacy size check. for version lower than WIDE_CLASS_TYPE_MINI_VERSION, we should consider the legacy scenario. 641 static_assert(KindBits::IsValid(ProfileType::Kind::LegacyKind)); 642 643 explicit ProfileTypeLegacy(uint32_t type, ProfileType::Kind kind = ProfileType::Kind::ClassId) 644 { 645 if (!IdBits::IsValid(type)) { 646 type_ = 0; 647 } else { 648 UpdateId(type); 649 UpdateKind(kind); 650 } 651 } 652 ProfileTypeLegacy(ProfileTypeRef profileTypeRef)653 explicit ProfileTypeLegacy(ProfileTypeRef profileTypeRef) : type_(profileTypeRef.GetId()) {} 654 IsNone()655 bool IsNone() const 656 { 657 return type_ == 0; 658 } 659 GetRaw()660 uint32_t GetRaw() const 661 { 662 return type_; 663 } 664 GetId()665 uint32_t GetId() const 666 { 667 return IdBits::Decode(type_); 668 } 669 GetKind()670 ProfileType::Kind GetKind() const 671 { 672 return KindBits::Decode(type_); 673 } 674 675 private: UpdateId(uint32_t type)676 void UpdateId(uint32_t type) 677 { 678 type_ = IdBits::Update(type_, type); 679 } 680 UpdateKind(ProfileType::Kind kind)681 void UpdateKind(ProfileType::Kind kind) 682 { 683 type_ = KindBits::Update(type_, kind); 684 } 685 uint32_t type_ {0}; 686 }; 687 688 class TraProfileType { 689 public: TraProfileType(ProfileType root,ProfileType child)690 TraProfileType(ProfileType root, ProfileType child) : root_(root), child_(child) {} 691 692 private: 693 ProfileType root_; 694 ProfileType child_; 695 }; 696 } // namespace panda::ecmascript::pgo 697 #endif // ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILE_TYPE_H 698