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