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