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/mem/region.h" 26 #include "ecmascript/log_wrapper.h" 27 #include "ecmascript/pgo_profiler/pgo_utils.h" 28 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h" 29 #include "libpandabase/utils/bit_field.h" 30 #include "macros.h" 31 32 namespace panda::ecmascript::pgo { 33 class PGOContext; 34 class PGOType { 35 public: 36 enum class TypeKind : uint8_t { 37 SCALAR_OP_TYPE, 38 RW_OP_TYPE, 39 DEFINE_OP_TYPE, 40 }; 41 PGOType() = default; PGOType(TypeKind kind)42 explicit PGOType(TypeKind kind) : kind_(kind) {} 43 IsScalarOpType()44 bool IsScalarOpType() const 45 { 46 return kind_ == TypeKind::SCALAR_OP_TYPE; 47 } 48 IsRwOpType()49 bool IsRwOpType() const 50 { 51 return kind_ == TypeKind::RW_OP_TYPE; 52 } 53 IsDefineOpType()54 bool IsDefineOpType() const 55 { 56 return kind_ == TypeKind::DEFINE_OP_TYPE; 57 } 58 59 private: 60 TypeKind kind_ {TypeKind::SCALAR_OP_TYPE}; 61 }; 62 63 /** 64 * | INT \ -> INT_OVERFLOW \ 65 * | NUMBER NUMBER_HETEROE1 66 * | DOUBLE / / 67 */ 68 template <typename PGOProfileType> 69 class PGOSampleTemplate : public PGOType { 70 public: 71 static constexpr int WEIGHT_BITS = 11; 72 static constexpr int WEIGHT_START_BIT = 10; 73 static constexpr int WEIGHT_TRUE_START_BIT = WEIGHT_START_BIT + WEIGHT_BITS; 74 static constexpr int WEIGHT_MASK = (1 << WEIGHT_BITS) - 1; 75 76 enum class Type : uint32_t { 77 NONE = 0x0ULL, 78 INT = 0x1ULL, // 00000001 79 INT_OVERFLOW = (0x1ULL << 1) | INT, // 00000011 80 DOUBLE = 0x1ULL << 2, // 00000100 81 NUMBER = INT | DOUBLE, // 00000101 82 NUMBER1 = INT_OVERFLOW | DOUBLE, // 00000111 83 BOOLEAN = 0x1ULL << 3, 84 UNDEFINED_OR_NULL = 0x1ULL << 4, 85 SPECIAL = 0x1ULL << 5, 86 BOOLEAN_OR_SPECIAL = BOOLEAN | SPECIAL, 87 STRING = 0x1ULL << 6, 88 BIG_INT = 0x1ULL << 7, 89 HEAP_OBJECT = 0x1ULL << 8, 90 HEAP_OR_UNDEFINED_OR_NULL = HEAP_OBJECT | UNDEFINED_OR_NULL, 91 ANY = (0x1ULL << WEIGHT_START_BIT) - 1, 92 }; 93 PGOSampleTemplate()94 PGOSampleTemplate() : type_(Type::NONE) {}; 95 PGOSampleTemplate(Type type)96 explicit PGOSampleTemplate(Type type) : type_(type) {}; PGOSampleTemplate(uint32_t type)97 explicit PGOSampleTemplate(uint32_t type) : type_(Type(type)) {}; PGOSampleTemplate(PGOProfileType type)98 explicit PGOSampleTemplate(PGOProfileType type) : type_(type) {} 99 100 template <typename FromType> ConvertFrom(PGOContext & context,const FromType & from)101 static PGOSampleTemplate ConvertFrom(PGOContext &context, const FromType &from) 102 { 103 if (from.IsProfileType()) { 104 return PGOSampleTemplate(PGOProfileType(context, from.GetProfileType())); 105 } 106 return PGOSampleTemplate(static_cast<PGOSampleTemplate::Type>(from.GetType())); 107 } 108 109 static PGOSampleTemplate CreateProfileType(ApEntityId recordId, int32_t profileType, 110 typename ProfileType::Kind kind = ProfileType::Kind::ClassId, 111 bool isRoot = false) 112 { 113 return PGOSampleTemplate(PGOProfileType(recordId, profileType, kind, isRoot)); 114 } 115 NoneType()116 static PGOSampleTemplate NoneType() 117 { 118 return PGOSampleTemplate(Type::NONE); 119 } 120 None()121 static int32_t None() 122 { 123 return static_cast<int32_t>(Type::NONE); 124 } 125 AnyType()126 static int32_t AnyType() 127 { 128 return static_cast<int32_t>(Type::ANY); 129 } 130 IntType()131 static int32_t IntType() 132 { 133 return static_cast<int32_t>(Type::INT); 134 } 135 IntOverFlowType()136 static int32_t IntOverFlowType() 137 { 138 return static_cast<int32_t>(Type::INT_OVERFLOW); 139 } 140 DoubleType()141 static int32_t DoubleType() 142 { 143 return static_cast<int32_t>(Type::DOUBLE); 144 } 145 NumberType()146 static int32_t NumberType() 147 { 148 return static_cast<int32_t>(Type::NUMBER); 149 } 150 HeapObjectType()151 static int32_t HeapObjectType() 152 { 153 return static_cast<int32_t>(Type::HEAP_OBJECT); 154 } 155 UndefineOrNullType()156 static int32_t UndefineOrNullType() 157 { 158 return static_cast<int32_t>(Type::UNDEFINED_OR_NULL); 159 } 160 BooleanType()161 static int32_t BooleanType() 162 { 163 return static_cast<int32_t>(Type::BOOLEAN); 164 } 165 StringType()166 static int32_t StringType() 167 { 168 return static_cast<int32_t>(Type::STRING); 169 } 170 BigIntType()171 static int32_t BigIntType() 172 { 173 return static_cast<int32_t>(Type::BIG_INT); 174 } 175 SpecialType()176 static int32_t SpecialType() 177 { 178 return static_cast<int32_t>(Type::SPECIAL); 179 } 180 CombineType(int32_t curType,int32_t newType)181 static int32_t CombineType(int32_t curType, int32_t newType) 182 { 183 return static_cast<int32_t>(static_cast<uint32_t>(curType) | static_cast<uint32_t>(newType)); 184 } 185 NoneProfileType()186 static PGOSampleTemplate NoneProfileType() 187 { 188 return PGOSampleTemplate(PGOProfileType()); 189 } 190 CombineType(PGOSampleTemplate type)191 PGOSampleTemplate CombineType(PGOSampleTemplate type) 192 { 193 if (type_.index() == 0) { 194 auto oldType = static_cast<uint32_t>(std::get<Type>(type_)); 195 oldType = oldType & static_cast<uint32_t>(AnyType()); 196 type_ = 197 Type(oldType | static_cast<uint32_t>(std::get<Type>(type.type_))); 198 } else { 199 this->SetType(type); 200 } 201 return *this; 202 } 203 CombineCallTargetType(PGOSampleTemplate type)204 PGOSampleTemplate CombineCallTargetType(PGOSampleTemplate type) 205 { 206 ASSERT(type_.index() == 1); 207 ProfileType::Kind oldKind = GetProfileType().GetKind(); 208 ProfileType::Kind newKind = type.GetProfileType().GetKind(); 209 uint32_t oldMethodId = GetProfileType().GetId(); 210 uint32_t newMethodId = type.GetProfileType().GetId(); 211 // If we have recorded a valid method if before, invalidate it. 212 if ((oldMethodId != 0) && 213 ((oldKind != newKind) || (oldMethodId != newMethodId))) { 214 type_ = ProfileType::PROFILE_TYPE_NONE; 215 } 216 return *this; 217 } 218 SetType(PGOSampleTemplate type)219 void SetType(PGOSampleTemplate type) 220 { 221 type_ = type.type_; 222 } 223 GetTypeString()224 std::string GetTypeString() const 225 { 226 if (type_.index() == 0) { 227 return std::to_string(static_cast<uint32_t>(std::get<Type>(type_))); 228 } else { 229 return std::get<PGOProfileType>(type_).GetTypeString(); 230 } 231 } 232 ToString()233 std::string ToString() const 234 { 235 if (type_.index() == 0) { 236 auto type = std::get<Type>(type_); 237 switch (type) { 238 case Type::NONE: 239 return "none"; 240 case Type::INT: 241 return "int"; 242 case Type::INT_OVERFLOW: 243 return "int_overflow"; 244 case Type::DOUBLE: 245 return "double"; 246 case Type::NUMBER: 247 return "number"; 248 case Type::NUMBER1: 249 return "number1"; 250 case Type::BOOLEAN: 251 return "boolean"; 252 case Type::UNDEFINED_OR_NULL: 253 return "undefined_or_null"; 254 case Type::SPECIAL: 255 return "special"; 256 case Type::BOOLEAN_OR_SPECIAL: 257 return "boolean_or_special"; 258 case Type::STRING: 259 return "string"; 260 case Type::BIG_INT: 261 return "big_int"; 262 case Type::HEAP_OBJECT: 263 return "heap_object"; 264 case Type::HEAP_OR_UNDEFINED_OR_NULL: 265 return "heap_or_undefined_or_null"; 266 case Type::ANY: 267 return "any"; 268 default: 269 LOG_ECMA(FATAL) << "this branch is unreachable"; 270 UNREACHABLE(); 271 } 272 } 273 LOG_ECMA(FATAL) << "this branch is unreachable"; 274 UNREACHABLE(); 275 } 276 IsProfileType()277 bool IsProfileType() const 278 { 279 return type_.index() == 1; 280 } 281 GetProfileType()282 PGOProfileType GetProfileType() const 283 { 284 ASSERT(IsProfileType()); 285 return std::get<PGOProfileType>(type_); 286 } 287 GetPrimitiveType()288 Type GetPrimitiveType() const 289 { 290 auto type = static_cast<uint32_t>(std::get<Type>(type_)); 291 return Type(type & static_cast<uint32_t>(AnyType())); 292 } 293 GetWeight()294 uint32_t GetWeight() const 295 { 296 ASSERT(type_.index() == 0); 297 auto type = static_cast<uint32_t>(std::get<Type>(type_)); 298 return type >> WEIGHT_START_BIT; 299 } 300 IsAny()301 bool IsAny() const 302 { 303 return type_.index() == 0 && GetPrimitiveType() == Type::ANY; 304 } 305 IsNone()306 bool IsNone() const 307 { 308 return type_.index() == 0 && GetPrimitiveType() == Type::NONE; 309 } 310 IsInt()311 bool IsInt() const 312 { 313 return type_.index() == 0 && GetPrimitiveType() == Type::INT; 314 } 315 IsIntOverFlow()316 bool IsIntOverFlow() const 317 { 318 return type_.index() == 0 && GetPrimitiveType() == Type::INT_OVERFLOW; 319 } 320 IsDouble()321 bool IsDouble() const 322 { 323 return type_.index() == 0 && GetPrimitiveType() == Type::DOUBLE; 324 } 325 IsString()326 bool IsString() const 327 { 328 return type_.index() == 0 && GetPrimitiveType() == Type::STRING; 329 } 330 IsNumber()331 bool IsNumber() const 332 { 333 if (type_.index() != 0) { 334 return false; 335 } 336 auto primType = GetPrimitiveType(); 337 switch (primType) { 338 case Type::INT: 339 case Type::INT_OVERFLOW: 340 case Type::DOUBLE: 341 case Type::NUMBER: 342 case Type::NUMBER1: 343 return true; 344 default: 345 return false; 346 } 347 } 348 349 bool operator<(const PGOSampleTemplate &right) const 350 { 351 return type_ < right.type_; 352 } 353 354 bool operator!=(const PGOSampleTemplate &right) const 355 { 356 return type_ != right.type_; 357 } 358 359 bool operator==(const PGOSampleTemplate &right) const 360 { 361 return type_ == right.type_; 362 } 363 GetType()364 Type GetType() const 365 { 366 ASSERT(!IsProfileType()); 367 return std::get<Type>(type_); 368 } 369 370 private: 371 std::variant<Type, PGOProfileType> type_; 372 }; 373 374 using PGOSampleType = PGOSampleTemplate<ProfileType>; 375 using PGOSampleTypeRef = PGOSampleTemplate<ProfileTypeRef>; 376 377 template <typename PGOProfileType> 378 class PGOProtoChainTemplate { 379 public: 380 PGOProtoChainTemplate() = default; PGOProtoChainTemplate(int32_t size,int32_t count)381 PGOProtoChainTemplate(int32_t size, int32_t count) : size_(size), count_(count) {}; 382 CreateProtoChain(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)383 static PGOProtoChainTemplate *CreateProtoChain(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain) 384 { 385 auto count = protoChain.size(); 386 size_t size = sizeof(PGOProtoChainTemplate); 387 if (count != 0) { 388 size += sizeof(PGOProfileType) * (count - 1) * 2; // 2 means mul by 2 389 } 390 auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size)); 391 new (result) PGOProtoChainTemplate(size, count); 392 PGOProfileType *curPt = &(result->rootType_); 393 for (auto iter : protoChain) { 394 *curPt = iter.first; 395 curPt = curPt + 1; 396 *curPt = iter.second; 397 curPt = curPt + 1; 398 } 399 return result; 400 } 401 DeleteProtoChain(PGOProtoChainTemplate * protoChain)402 static void DeleteProtoChain(PGOProtoChainTemplate *protoChain) 403 { 404 free(protoChain); 405 } 406 407 template <typename FromType> ConvertFrom(PGOContext & context,FromType * from)408 static PGOProtoChainTemplate *ConvertFrom(PGOContext &context, FromType *from) 409 { 410 auto count = from->GetCount(); 411 size_t size = sizeof(PGOProtoChainTemplate); 412 if (count != 0) { 413 size += sizeof(PGOProfileType) * (static_cast<size_t>(count) - 1) * 2; // 2 means mul by 2 414 } 415 auto result = reinterpret_cast<PGOProtoChainTemplate *>(malloc(size)); 416 new (result) PGOProtoChainTemplate(size, count); 417 PGOProfileType *curPt = &(result->rootType_); 418 from->IterateProtoChain([&context, &curPt] (auto rootType, auto childType) { 419 *curPt = PGOProfileType(context, rootType); 420 curPt = curPt + 1; 421 *curPt = PGOProfileType(context, childType); 422 curPt = curPt + 1; 423 }); 424 return result; 425 } 426 427 template <typename Callback> IterateProtoChain(Callback callback)428 void IterateProtoChain(Callback callback) const 429 { 430 for (int i = 0; i < count_; i++) { 431 callback(*(&rootType_ + i), *(&rootType_ + i + 1)); 432 } 433 } 434 GetCount()435 int32_t GetCount() 436 { 437 return count_; 438 } 439 Size()440 int32_t Size() 441 { 442 return size_; 443 } 444 445 private: 446 int32_t size_; 447 int32_t count_; 448 PGOProfileType rootType_ {PGOProfileType()}; 449 PGOProfileType childType_ {PGOProfileType()}; 450 }; 451 452 using PGOProtoChain = PGOProtoChainTemplate<ProfileType>; 453 using PGOProtoChainRef = PGOProtoChainTemplate<ProfileTypeRef>; 454 455 enum class ProtoChainMarker : uint8_t { 456 EXSIT, 457 NOT_EXSIT, 458 }; 459 460 template <typename PGOProfileType> 461 class PGOObjectTemplate { 462 public: 463 PGOObjectTemplate() = default; PGOObjectTemplate(PGOProfileType type)464 PGOObjectTemplate(PGOProfileType type) : receiverType_(type) {} PGOObjectTemplate(PGOProfileType receiverRootType,PGOProfileType receiverType,PGOProfileType holdRootType,PGOProfileType holdType,PGOProfileType holdTraRootType,PGOProfileType holdTraType)465 PGOObjectTemplate(PGOProfileType receiverRootType, PGOProfileType receiverType, PGOProfileType holdRootType, 466 PGOProfileType holdType, PGOProfileType holdTraRootType, PGOProfileType holdTraType) 467 : receiverRootType_(receiverRootType), receiverType_(receiverType), holdRootType_(holdRootType), 468 holdType_(holdType), holdTraRootType_(holdTraRootType), holdTraType_(holdTraType) {} 469 AddPrototypePt(std::vector<std::pair<PGOProfileType,PGOProfileType>> protoChain)470 void AddPrototypePt(std::vector<std::pair<PGOProfileType, PGOProfileType>> protoChain) 471 { 472 protoChainMarker_ = ProtoChainMarker::EXSIT; 473 if (protoChain_ != nullptr) { 474 PGOProtoChainTemplate<PGOProfileType>::DeleteProtoChain(protoChain_); 475 } 476 protoChain_ = PGOProtoChainTemplate<PGOProfileType>::CreateProtoChain(protoChain); 477 } 478 479 template <typename FromType> ConvertFrom(PGOContext & context,const FromType & from)480 void ConvertFrom(PGOContext &context, const FromType &from) 481 { 482 receiverRootType_ = PGOProfileType(context, from.GetReceiverRootType()); 483 receiverType_ = PGOProfileType(context, from.GetReceiverType()); 484 holdRootType_ = PGOProfileType(context, from.GetHoldRootType()); 485 holdType_ = PGOProfileType(context, from.GetHoldType()); 486 holdTraRootType_ = PGOProfileType(context, from.GetHoldTraRootType()); 487 holdTraType_ = PGOProfileType(context, from.GetHoldTraType()); 488 protoChainMarker_ = from.GetProtoChainMarker(); 489 } 490 GetInfoString()491 std::string GetInfoString() const 492 { 493 std::string result = "(receiverRoot"; 494 result += receiverRootType_.GetTypeString(); 495 result += ", receiver"; 496 result += receiverType_.GetTypeString(); 497 result += ", holdRoot"; 498 result += holdRootType_.GetTypeString(); 499 result += ", hold"; 500 result += holdType_.GetTypeString(); 501 result += ", holdTraRoot"; 502 result += holdTraRootType_.GetTypeString(); 503 result += ", holdTra"; 504 result += holdTraType_.GetTypeString(); 505 result += ")"; 506 return result; 507 } 508 GetProfileType()509 PGOProfileType GetProfileType() const 510 { 511 return receiverType_; 512 } 513 GetReceiverRootType()514 PGOProfileType GetReceiverRootType() const 515 { 516 return receiverRootType_; 517 } 518 GetReceiverType()519 PGOProfileType GetReceiverType() const 520 { 521 return receiverType_; 522 } 523 GetHoldRootType()524 PGOProfileType GetHoldRootType() const 525 { 526 return holdRootType_; 527 } 528 GetHoldType()529 PGOProfileType GetHoldType() const 530 { 531 return holdType_; 532 } 533 GetHoldTraRootType()534 PGOProfileType GetHoldTraRootType() const 535 { 536 return holdTraRootType_; 537 } 538 GetHoldTraType()539 PGOProfileType GetHoldTraType() const 540 { 541 return holdTraType_; 542 } 543 GetProtoChainMarker()544 ProtoChainMarker GetProtoChainMarker() const 545 { 546 return protoChainMarker_; 547 } 548 GetProtoChain()549 PGOProtoChainTemplate<PGOProfileType> *GetProtoChain() const 550 { 551 return protoChain_; 552 } 553 SetProtoChain(PGOProtoChainTemplate<PGOProfileType> * protoChain)554 void SetProtoChain(PGOProtoChainTemplate<PGOProfileType> *protoChain) 555 { 556 protoChain_ = protoChain; 557 } 558 IsNone()559 bool IsNone() const 560 { 561 return receiverType_.IsNone(); 562 } 563 IsMegaStateType()564 bool IsMegaStateType() const 565 { 566 return receiverType_.IsMegaStateType(); 567 } 568 InConstructor()569 bool InConstructor() const 570 { 571 return receiverType_.IsConstructor(); 572 } 573 InElement()574 bool InElement() const 575 { 576 return receiverType_.IsBuiltinsArray(); 577 } 578 579 bool operator<(const PGOObjectTemplate &right) const 580 { 581 return receiverRootType_ < right.receiverRootType_ || receiverType_ < right.receiverType_ || 582 holdRootType_ < right.holdRootType_ || holdType_ < right.holdType_ || 583 holdTraRootType_ < right.holdTraRootType_ || holdTraType_ < right.holdTraType_; 584 } 585 586 bool operator==(const PGOObjectTemplate &right) const 587 { 588 return receiverRootType_ == right.receiverRootType_ && receiverType_ == right.receiverType_ && 589 holdRootType_ == right.holdRootType_ && holdType_ == right.holdType_ && 590 holdTraRootType_ == right.holdTraRootType_ && holdTraType_ == right.holdTraType_; 591 } 592 593 private: 594 PGOProfileType receiverRootType_ { PGOProfileType() }; 595 PGOProfileType receiverType_ { PGOProfileType() }; 596 PGOProfileType holdRootType_ { PGOProfileType() }; 597 PGOProfileType holdType_ { PGOProfileType() }; 598 PGOProfileType holdTraRootType_ { PGOProfileType() }; 599 PGOProfileType holdTraType_ { PGOProfileType() }; 600 ProtoChainMarker protoChainMarker_ {ProtoChainMarker::NOT_EXSIT}; 601 PGOProtoChainTemplate<PGOProfileType> *protoChain_ { nullptr }; 602 }; 603 using PGOObjectInfo = PGOObjectTemplate<ProfileType>; 604 using PGOObjectInfoRef = PGOObjectTemplate<ProfileTypeRef>; 605 606 template <typename PGOObjectInfoType> 607 class PGORWOpTemplate : public PGOType { 608 public: PGORWOpTemplate()609 PGORWOpTemplate() : PGOType(TypeKind::RW_OP_TYPE) {}; 610 611 template <typename FromType> ConvertFrom(PGOContext & context,const FromType & from)612 void ConvertFrom(PGOContext &context, const FromType &from) 613 { 614 count_ = std::min(from.GetCount(), static_cast<uint32_t>(POLY_CASE_NUM)); 615 for (uint32_t index = 0; index < count_; index++) { 616 infos_[index].ConvertFrom(context, from.GetObjectInfo(index)); 617 } 618 } 619 Merge(const PGORWOpTemplate & type)620 void Merge(const PGORWOpTemplate &type) 621 { 622 for (uint32_t i = 0; i < type.count_; i++) { 623 AddObjectInfo(type.infos_[i]); 624 } 625 } 626 AddObjectInfo(const PGOObjectInfoType & info)627 void AddObjectInfo(const PGOObjectInfoType &info) 628 { 629 if (info.IsNone()) { 630 return; 631 } 632 if (info.IsMegaStateType()) { 633 count_ = 0; 634 return; 635 } 636 uint32_t count = 0; 637 for (; count < count_; count++) { 638 if (infos_[count] == info) { 639 return; 640 } 641 } 642 if (count < static_cast<uint32_t>(POLY_CASE_NUM)) { 643 infos_[count] = info; 644 count_++; 645 } else { 646 LOG_ECMA(DEBUG) << "Class type exceeds 4, discard"; 647 } 648 } 649 GetObjectInfo(uint32_t index)650 const PGOObjectInfoType &GetObjectInfo(uint32_t index) const 651 { 652 ASSERT(index < count_); 653 return infos_[index]; 654 } 655 GetCount()656 uint32_t GetCount() const 657 { 658 return count_; 659 } 660 661 private: 662 static constexpr int POLY_CASE_NUM = 4; 663 uint32_t count_ = 0; 664 PGOObjectInfoType infos_[POLY_CASE_NUM]; 665 }; 666 using PGORWOpType = PGORWOpTemplate<PGOObjectInfo>; 667 using PGORWOpTypeRef = PGORWOpTemplate<PGOObjectInfoRef>; 668 669 template <typename PGOProfileType> 670 class PGODefineOpTemplate : public PGOType { 671 public: PGODefineOpTemplate()672 PGODefineOpTemplate() : PGOType(TypeKind::DEFINE_OP_TYPE), type_(PGOProfileType()) {}; PGODefineOpTemplate(PGOProfileType type)673 explicit PGODefineOpTemplate(PGOProfileType type) : PGOType(TypeKind::DEFINE_OP_TYPE), type_(type) {}; 674 675 template <typename FromType> ConvertFrom(PGOContext & context,const FromType & from)676 void ConvertFrom(PGOContext &context, const FromType &from) 677 { 678 type_ = PGOProfileType(context, from.GetProfileType()); 679 ctorPt_ = PGOProfileType(context, from.GetCtorPt()); 680 protoPt_ = PGOProfileType(context, from.GetProtoTypePt()); 681 kind_ = from.GetElementsKind(); 682 elementsLength_ = from.GetElementsLength(); 683 spaceFlag_ = from.GetSpaceFlag(); 684 } 685 GetTypeString()686 std::string GetTypeString() const 687 { 688 std::string result = "(local"; 689 result += type_.GetTypeString(); 690 result += ", ctor"; 691 result += ctorPt_.GetTypeString(); 692 result += ", proto"; 693 result += protoPt_.GetTypeString(); 694 result += ", elementsKind:"; 695 result += std::to_string(static_cast<int32_t>(kind_)); 696 if (elementsLength_ > 0 && spaceFlag_ != RegionSpaceFlag::UNINITIALIZED) { 697 result += ", size: "; 698 result += std::to_string(elementsLength_); 699 result += ", space; "; 700 result += ToSpaceTypeName(spaceFlag_); 701 } 702 return result; 703 } 704 IsNone()705 bool IsNone() const 706 { 707 return type_.IsNone(); 708 } 709 GetProfileType()710 PGOProfileType GetProfileType() const 711 { 712 return type_; 713 } 714 SetCtorPt(PGOProfileType type)715 void SetCtorPt(PGOProfileType type) 716 { 717 ctorPt_ = type; 718 } 719 GetCtorPt()720 PGOProfileType GetCtorPt() const 721 { 722 return ctorPt_; 723 } 724 SetProtoTypePt(PGOProfileType type)725 void SetProtoTypePt(PGOProfileType type) 726 { 727 protoPt_ = type; 728 } 729 GetProtoTypePt()730 PGOProfileType GetProtoTypePt() const 731 { 732 return protoPt_; 733 } 734 SetElementsKind(ElementsKind kind)735 void SetElementsKind(ElementsKind kind) 736 { 737 kind_ = kind; 738 } 739 GetElementsKind()740 ElementsKind GetElementsKind() const 741 { 742 return kind_; 743 } 744 SetElementsLength(uint32_t length)745 void SetElementsLength(uint32_t length) 746 { 747 elementsLength_ = length; 748 } 749 GetElementsLength()750 uint32_t GetElementsLength() const 751 { 752 return elementsLength_; 753 } 754 SetSpaceFlag(RegionSpaceFlag flag)755 void SetSpaceFlag(RegionSpaceFlag flag) 756 { 757 spaceFlag_ = flag; 758 } 759 GetSpaceFlag()760 RegionSpaceFlag GetSpaceFlag() const 761 { 762 return spaceFlag_; 763 } 764 765 bool operator<(const PGODefineOpTemplate &right) const 766 { 767 return this->GetProfileType() < right.GetProfileType(); 768 } 769 770 private: 771 PGOProfileType type_ { PGOProfileType() }; 772 PGOProfileType ctorPt_ { PGOProfileType() }; 773 PGOProfileType protoPt_ { PGOProfileType() }; 774 uint32_t elementsLength_ { 0 }; 775 ElementsKind kind_ { ElementsKind::NONE }; 776 RegionSpaceFlag spaceFlag_ { RegionSpaceFlag::UNINITIALIZED }; 777 }; 778 779 using PGODefineOpType = PGODefineOpTemplate<ProfileType>; 780 using PGODefineOpTypeRef = PGODefineOpTemplate<ProfileTypeRef>; 781 782 class PGOTypeRef { 783 public: PGOTypeRef()784 PGOTypeRef() : type_(nullptr) {} 785 PGOTypeRef(PGOType * type)786 explicit PGOTypeRef(PGOType *type) : type_(type) {} 787 PGOTypeRef(const PGOSampleType * type)788 explicit PGOTypeRef(const PGOSampleType *type) : type_(static_cast<const PGOType*>(type)) {} 789 PGOTypeRef(const PGORWOpType * type)790 explicit PGOTypeRef(const PGORWOpType *type) : type_(static_cast<const PGOType*>(type)) {} 791 PGOTypeRef(const PGODefineOpType * type)792 explicit PGOTypeRef(const PGODefineOpType *type) : type_(static_cast<const PGOType*>(type)) {} 793 NoneType()794 static PGOTypeRef NoneType() 795 { 796 return PGOTypeRef(); 797 } 798 799 bool operator<(const PGOTypeRef &right) const 800 { 801 return type_ < right.type_; 802 } 803 804 bool operator!=(const PGOTypeRef &right) const 805 { 806 return type_ != right.type_; 807 } 808 809 bool operator==(const PGOTypeRef &right) const 810 { 811 return type_ == right.type_; 812 } 813 IsValid()814 bool IsValid() const 815 { 816 return type_ != nullptr; 817 } 818 IsValidCallMethodId()819 bool IsValidCallMethodId() const 820 { 821 if (type_ == nullptr) { 822 return false; 823 } 824 if (!type_->IsScalarOpType()) { 825 return false; 826 } 827 auto sampleType = static_cast<const PGOSampleType*>(type_); 828 if (sampleType->IsProfileType()) { 829 if (sampleType->GetProfileType().IsMethodId()) { 830 return sampleType->GetProfileType().IsValidCallMethodId(); 831 } 832 } 833 return false; 834 } 835 GetCallMethodId()836 uint32_t GetCallMethodId() const 837 { 838 auto sampleType = static_cast<const PGOSampleType*>(type_); 839 return sampleType->GetProfileType().GetCallMethodId(); 840 } 841 GetValue()842 uint64_t GetValue() const 843 { 844 auto sampleType = static_cast<const PGOSampleType*>(type_); 845 return sampleType->GetProfileType().GetRaw(); 846 } 847 GetPGOSampleType()848 const PGOSampleType* GetPGOSampleType() 849 { 850 if (type_ == nullptr) { 851 static PGOSampleType noneType = PGOSampleType::NoneType(); 852 return &noneType; 853 } 854 ASSERT(type_->IsScalarOpType()); 855 return static_cast<const PGOSampleType*>(type_); 856 } 857 GetPGORWOpType()858 const PGORWOpType* GetPGORWOpType() 859 { 860 if (type_ == nullptr) { 861 static PGORWOpType noneType; 862 return &noneType; 863 } 864 ASSERT(type_->IsRwOpType()); 865 return static_cast<const PGORWOpType*>(type_); 866 } 867 GetPGODefineOpType()868 const PGODefineOpType* GetPGODefineOpType() 869 { 870 if (type_ == nullptr) { 871 static PGODefineOpType noneType; 872 return &noneType; 873 } 874 ASSERT(type_->IsDefineOpType()); 875 return static_cast<const PGODefineOpType*>(type_); 876 } 877 878 private: 879 const PGOType *type_; 880 }; 881 } // namespace panda::ecmascript::pgo 882 #endif // ECMASCRIPT_PGO_PROFILER_TYPES_PGO_PROFILER_TYPE_H 883