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_AP_FILE_PGO_METHOD_TYPE_SET_H 17 #define ECMASCRIPT_PGO_PROFILER_AP_FILE_PGO_METHOD_TYPE_SET_H 18 19 #include <set> 20 21 #include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h" 22 #include "ecmascript/pgo_profiler/pgo_utils.h" 23 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h" 24 25 namespace panda::ecmascript::pgo { 26 class PGOMethodTypeSet { 27 public: 28 static constexpr int METHOD_TYPE_INFO_INDEX = 4; 29 static constexpr int METHOD_TYPE_INFO_COUNT = 2; 30 static constexpr int METHOD_OFFSET_INDEX = 0; 31 static constexpr int METHOD_TYPE_INDEX = 1; 32 static constexpr uint32_t MAX_METHOD_TYPE_SIZE = 512 * 1024 * 1024; 33 34 PGOMethodTypeSet() = default; Clear()35 void Clear() 36 { 37 scalarOpTypeInfos_.clear(); 38 rwScalarOpTypeInfos_.clear(); 39 objDefOpTypeInfos_.clear(); 40 } 41 AddType(uint32_t offset,PGOSampleType type)42 void AddType(uint32_t offset, PGOSampleType type) 43 { 44 auto result = scalarOpTypeInfos_.find(ScalarOpTypeInfo(offset, type)); 45 if (result != scalarOpTypeInfos_.end()) { 46 auto combineType = result->GetType().CombineType(type); 47 const_cast<ScalarOpTypeInfo &>(*result).SetType(combineType); 48 } else { 49 scalarOpTypeInfos_.emplace(offset, type); 50 } 51 } 52 AddCallTargetType(uint32_t offset,PGOSampleType type)53 void AddCallTargetType(uint32_t offset, PGOSampleType type) 54 { 55 auto result = scalarOpTypeInfos_.find(ScalarOpTypeInfo(offset, type)); 56 if (result != scalarOpTypeInfos_.end()) { 57 auto combineType = result->GetType().CombineCallTargetType(type); 58 const_cast<ScalarOpTypeInfo &>(*result).SetType(combineType); 59 } else { 60 scalarOpTypeInfos_.emplace(offset, type); 61 } 62 } 63 AddObjectInfo(uint32_t offset,const PGOObjectInfo & info)64 void AddObjectInfo(uint32_t offset, const PGOObjectInfo &info) 65 { 66 auto result = rwScalarOpTypeInfos_.find(RWScalarOpTypeInfo(offset)); 67 if (result != rwScalarOpTypeInfos_.end()) { 68 const_cast<RWScalarOpTypeInfo &>(*result).AddObjectInfo(info); 69 } else { 70 rwScalarOpTypeInfos_.emplace(offset, info); 71 } 72 } 73 AddDefine(uint32_t offset,PGODefineOpType type)74 void AddDefine(uint32_t offset, PGODefineOpType type) 75 { 76 auto result = objDefOpTypeInfos_.find(ObjDefOpTypeInfo(offset, type)); 77 if (result != objDefOpTypeInfos_.end()) { 78 if (type.GetProfileType().IsArrayLiteralType()) { 79 const_cast<PGODefineOpTemplate<ProfileType> *>(&((*result).GetTypeRef())) 80 ->SetElementsKind(type.GetElementsKind()); 81 const_cast<PGODefineOpTemplate<ProfileType> *>(&((*result).GetTypeRef())) 82 ->SetSpaceFlag(type.GetSpaceFlag()); 83 } 84 return; 85 } 86 objDefOpTypeInfos_.emplace(offset, type); 87 } 88 89 template <typename Callback> GetTypeInfo(Callback callback)90 void GetTypeInfo(Callback callback) 91 { 92 for (const auto &typeInfo : scalarOpTypeInfos_) { 93 const auto &type = typeInfo.GetTypeRef(); 94 callback(typeInfo.GetOffset(), &type); 95 } 96 for (const auto &typeInfo : rwScalarOpTypeInfos_) { 97 const auto &type = typeInfo.GetTypeRef(); 98 callback(typeInfo.GetOffset(), &type); 99 } 100 for (const auto &typeInfo : objDefOpTypeInfos_) { 101 const auto &type = typeInfo.GetTypeRef(); 102 callback(typeInfo.GetOffset(), &type); 103 } 104 } 105 106 void Merge(const PGOMethodTypeSet *info); 107 static void SkipFromBinary(void **buffer); 108 109 bool ParseFromBinary(PGOContext& context, void** addr, size_t bufferSize); 110 bool ProcessToBinary(PGOContext &context, std::stringstream &stream) const; 111 112 bool ParseFromText(const std::string &typeString); 113 void ProcessToText(std::string &text) const; 114 115 void ProcessToJson(ProfileType::VariantVector &typeArray) const; 116 117 NO_COPY_SEMANTIC(PGOMethodTypeSet); 118 NO_MOVE_SEMANTIC(PGOMethodTypeSet); 119 120 private: 121 enum class InfoType : uint8_t { 122 NONE, 123 OP_TYPE, 124 DEFINE_CLASS_TYPE = 3, 125 USE_HCLASS_TYPE 126 }; 127 128 class TypeInfoHeader { 129 public: TypeInfoHeader(InfoType type,uint32_t offset)130 TypeInfoHeader(InfoType type, uint32_t offset) : infoType_(type), offset_(offset) {} TypeInfoHeader(uint32_t size,InfoType type,uint32_t offset)131 TypeInfoHeader(uint32_t size, InfoType type, uint32_t offset) 132 : size_(size), infoType_(type), offset_(offset) {} 133 GetInfoType()134 InfoType GetInfoType() 135 { 136 return infoType_; 137 } 138 Size()139 int32_t Size() const 140 { 141 return size_; 142 } 143 GetOffset()144 uint32_t GetOffset() const 145 { 146 return offset_; 147 } 148 149 protected: 150 uint32_t size_ {0}; 151 InfoType infoType_ {InfoType::NONE}; 152 uint32_t offset_ {0}; 153 }; 154 155 template <typename RWOpType, typename ObjectInfoType> 156 class RWScalarOpTemplate : public TypeInfoHeader { 157 public: RWScalarOpTemplate(uint32_t offset)158 explicit RWScalarOpTemplate(uint32_t offset) : TypeInfoHeader(InfoType::USE_HCLASS_TYPE, offset) {}; RWScalarOpTemplate(uint32_t offset,ObjectInfoType info)159 RWScalarOpTemplate(uint32_t offset, ObjectInfoType info) 160 : TypeInfoHeader(sizeof(RWScalarOpTemplate), InfoType::USE_HCLASS_TYPE, offset) 161 { 162 type_.AddObjectInfo(info); 163 } 164 165 template <typename FromType> ConvertFrom(PGOContext & context,const FromType & from)166 void ConvertFrom(PGOContext &context, const FromType &from) 167 { 168 size_ = sizeof(RWScalarOpTemplate); 169 type_.ConvertFrom(context, from.GetTypeRef()); 170 } 171 172 bool operator<(const RWScalarOpTemplate &right) const 173 { 174 return offset_ < right.offset_; 175 } 176 GetCount()177 int32_t GetCount() const 178 { 179 return type_.GetCount(); 180 } 181 Merge(const RWScalarOpTemplate & type)182 void Merge(const RWScalarOpTemplate &type) 183 { 184 type_.Merge(type.type_); 185 } 186 AddObjectInfo(const ObjectInfoType & info)187 void AddObjectInfo(const ObjectInfoType &info) 188 { 189 type_.AddObjectInfo(info); 190 } 191 GetTypeRef()192 const RWOpType &GetTypeRef() const 193 { 194 return type_; 195 } 196 ProcessToText(std::string & text)197 void ProcessToText(std::string &text) const 198 { 199 text += std::to_string(GetOffset()); 200 text += DumpUtils::BLOCK_START; 201 text += DumpUtils::ARRAY_START + DumpUtils::NEW_LINE; 202 bool isFirst = true; 203 for (uint32_t i = 0; i < type_.GetCount(); i++) { 204 if (!isFirst) { 205 text += DumpUtils::SPACE + DumpUtils::BLOCK_SEPARATOR + DumpUtils::NEW_LINE; 206 } 207 isFirst = false; 208 text += type_.GetObjectInfo(i).GetInfoString(); 209 } 210 text += DumpUtils::NEW_LINE + DumpUtils::ALIGN + DumpUtils::ALIGN + DumpUtils::ARRAY_END; 211 } 212 ProcessToJson(ProfileType::MapVector & typeArray)213 void ProcessToJson(ProfileType::MapVector &typeArray) const 214 { 215 for (uint32_t i = 0; i < type_.GetCount(); i++) { 216 std::vector<ProfileType::StringMap> sameOffsetTypeArray; 217 type_.GetObjectInfo(i).GetInfoJson(sameOffsetTypeArray, std::to_string(GetOffset())); 218 typeArray.push_back(sameOffsetTypeArray); 219 } 220 } 221 222 private: 223 RWOpType type_; 224 }; 225 using RWScalarOpTypeInfo = RWScalarOpTemplate<PGORWOpType, PGOObjectInfo>; 226 using RWScalarOpTypeInfoRef = RWScalarOpTemplate<PGORWOpTypeRef, PGOObjectInfoRef>; 227 228 template <typename SampleType> 229 class ScalarOpTemplate : public TypeInfoHeader { 230 public: ScalarOpTemplate(uint32_t offset,SampleType type)231 ScalarOpTemplate(uint32_t offset, SampleType type) 232 : TypeInfoHeader(sizeof(ScalarOpTemplate), InfoType::OP_TYPE, offset), type_(type) {} 233 234 bool operator<(const ScalarOpTemplate &right) const 235 { 236 return offset_ < right.offset_; 237 } 238 SetType(SampleType type)239 void SetType(SampleType type) 240 { 241 if (type_ != type) { 242 type_ = type; 243 } 244 } 245 Merge(const ScalarOpTemplate & typeInfo)246 void Merge(const ScalarOpTemplate &typeInfo) 247 { 248 SampleType combineType = GetType().CombineType(typeInfo.GetType()); 249 SetType(combineType); 250 } 251 GetType()252 SampleType GetType() const 253 { 254 return type_; 255 } 256 GetTypeRef()257 const SampleType &GetTypeRef() const 258 { 259 return type_; 260 } 261 262 protected: ScalarOpTemplate(uint32_t size,InfoType infoType,uint32_t offset,SampleType type)263 ScalarOpTemplate(uint32_t size, InfoType infoType, uint32_t offset, SampleType type) 264 : TypeInfoHeader(size, infoType, offset), type_(type) {} 265 266 private: 267 SampleType type_; 268 }; 269 using ScalarOpTypeInfo = ScalarOpTemplate<PGOSampleType>; 270 using ScalarOpTypeInfoRef = ScalarOpTemplate<PGOSampleTypeRef>; 271 272 template <typename PGODefineOpType> 273 class ObjDefOpTemplate : public TypeInfoHeader { 274 public: ObjDefOpTemplate(uint32_t offset,PGODefineOpType type)275 ObjDefOpTemplate(uint32_t offset, PGODefineOpType type) 276 : TypeInfoHeader(sizeof(ObjDefOpTemplate), InfoType::DEFINE_CLASS_TYPE, offset), type_(type) {} 277 278 bool operator<(const ObjDefOpTemplate &right) const 279 { 280 if (this->offset_ != right.GetOffset()) { 281 return this->offset_ < right.GetOffset(); 282 } 283 return this->GetType() < right.GetType(); 284 } 285 ProcessToText(std::string & text)286 void ProcessToText(std::string &text) const 287 { 288 text += std::to_string(this->GetOffset()); 289 text += DumpUtils::BLOCK_START; 290 text += DumpUtils::ARRAY_START + DumpUtils::NEW_LINE; 291 text += this->GetType().GetTypeString(); 292 text += DumpUtils::NEW_LINE + DumpUtils::ALIGN + DumpUtils::ALIGN + DumpUtils::ARRAY_END; 293 } 294 ProcessToJson(std::vector<ProfileType::StringMap> & sameOffsetTypeArray)295 void ProcessToJson(std::vector<ProfileType::StringMap> &sameOffsetTypeArray) const 296 { 297 this->GetType().GetTypeJson(sameOffsetTypeArray, std::to_string(this->GetOffset())); 298 } 299 GetType()300 PGODefineOpType GetType() const 301 { 302 return type_; 303 } 304 GetTypeRef()305 const PGODefineOpType &GetTypeRef() const 306 { 307 return type_; 308 } 309 310 protected: ObjDefOpTemplate(uint32_t size,InfoType infoType,uint32_t offset,PGODefineOpType type)311 ObjDefOpTemplate( 312 uint32_t size, InfoType infoType, uint32_t offset, PGODefineOpType type) 313 : TypeInfoHeader(size, infoType, offset), type_(type) {} 314 private: 315 PGODefineOpType type_; 316 }; 317 318 bool ParseProtoChainsFromBinary( 319 PGOContext& context, RWScalarOpTypeInfo& info, void** addr, void* buffer, size_t bufferSize); 320 321 using ObjDefOpTypeInfo = ObjDefOpTemplate<PGODefineOpType>; 322 using ObjDefOpTypeInfoRef = ObjDefOpTemplate<PGODefineOpTypeRef>; 323 324 std::set<ScalarOpTypeInfo> scalarOpTypeInfos_; 325 std::set<RWScalarOpTypeInfo> rwScalarOpTypeInfos_; 326 std::set<ObjDefOpTypeInfo> objDefOpTypeInfos_; 327 }; 328 } // namespace panda::ecmascript::pgo 329 #endif // ECMASCRIPT_PGO_PROFILER_AP_FILE_PGO_METHOD_TYPE_SET_H 330