1 /** 2 * Copyright (c) 2025 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 PGO_FILE_BUILDER_H 17 #define PGO_FILE_BUILDER_H 18 19 #include "pgo_header.h" 20 #include "aot_profiling_data.h" 21 #include "utils/span.h" 22 #include "runtime/include/mem/panda_string.h" 23 #include "runtime/include/mem/panda_containers.h" 24 25 namespace ark::pgo { 26 27 class AotPgoFile { 28 public: 29 class Buffer { 30 public: Buffer()31 Buffer() : buffer_(0), bufferSize_(0), currSize_(0) {} 32 Buffer(uint32_t size)33 explicit Buffer(uint32_t size) 34 : buffer_(size > 1_MB ? LOG(FATAL, RUNTIME) << "Allocated of huge memory is not allowed" : size), 35 bufferSize_(size), 36 currSize_(0) 37 { 38 } 39 GetBuffer()40 Span<uint8_t> GetBuffer() 41 { 42 Span<uint8_t> buffer(buffer_.data(), bufferSize_); 43 return buffer; 44 } 45 46 template <typename T> CopyToBuffer(const T * from,size_t size,size_t beginIndex)47 uint32_t CopyToBuffer(const T *from, size_t size, size_t beginIndex) 48 { 49 const char *data = reinterpret_cast<const char *>(from); 50 if (beginIndex >= bufferSize_) { 51 return 0; 52 } 53 auto maxSize {bufferSize_ - beginIndex}; 54 errno_t res = memcpy_s(&buffer_[beginIndex], maxSize, data, size); 55 if (res != 0) { 56 return 0; 57 } 58 currSize_ += size; 59 return size; 60 } 61 WriteBuffer(std::ofstream & fd)62 void WriteBuffer(std::ofstream &fd) 63 { 64 fd.write(reinterpret_cast<const char *>(buffer_.data()), currSize_); 65 66 if (!fd) { 67 return; 68 } 69 } 70 71 private: 72 PandaVector<uint8_t> buffer_; 73 uint32_t bufferSize_; 74 uint32_t currSize_; 75 }; 76 77 uint32_t Save(const PandaString &fileName, AotProfilingData *profObject, const PandaString &classCtxStr); 78 79 static Expected<AotProfilingData, PandaString> Load(const PandaString &fileName, PandaString &classCtxStr, 80 PandaVector<PandaString> &pandaFiles); 81 82 private: 83 static constexpr std::array MAGIC = {'.', 'a', 'p', '\0'}; // CC-OFF(G.NAM.03-CPP) project code style 84 static constexpr std::array VERSION = {'0', '0', '1', '\0'}; // CC-OFF(G.NAM.03-CPP) project code style 85 static constexpr uint32_t MAGIC_SIZE = 4; // CC-OFF(G.NAM.03-CPP) project code style 86 static constexpr uint32_t VERSION_SIZE = 4; // CC-OFF(G.NAM.03-CPP) project code style 87 88 enum ProfileType : uint32_t { NO = 0x00, VCALL = 0x01, BRANCH = 0x02, THROW = 0x04, ALL = 0xFFFFFFFF }; 89 // CC-OFFNXT(G.NAM.03-CPP) project code style 90 static constexpr uint32_t PROFILE_TYPE = ProfileType::VCALL | ProfileType::BRANCH | ProfileType::THROW; 91 92 enum FileType : uint32_t { PFILE = 0, BOOT = 1, APP = 2 }; 93 94 enum SectionType : uint32_t { 95 UNKNOW_SECTION = 0, 96 FILE_HEADER = 1, 97 PANDA_FILES = 2, 98 SECTIONS_INFO = 3, 99 METHODS = 4 100 }; 101 102 // CC-OFFNXT(G.FUN.01-CPP) Decreasing the number of arguments will decrease the clarity of the code. 103 static uint32_t WriteFileHeader(std::ofstream &fd, const std::array<char, MAGIC_SIZE> &magic, 104 const std::array<char, VERSION_SIZE> &version, uint32_t versionPType, 105 uint32_t savedPType, const PandaString &classCtxStr); 106 107 static uint32_t WriteSectionInfosSection(std::ofstream &fd, PandaVector<SectionInfo> §ionInfos); 108 GetSectionInfosSectionSize(uint32_t sectionNumer)109 static uint32_t GetSectionInfosSectionSize(uint32_t sectionNumer) 110 { 111 return sectionNumer * sizeof(SectionInfo) + sizeof(SectionsInfoSectionHeader); 112 } 113 114 static uint32_t GetMaxMethodSectionSize(AotProfilingData::MethodsMap &methods); 115 static uint32_t GetMethodSectionProf(AotProfilingData::MethodsMap &methods); 116 static uint32_t WriteInlineCachesToStream(uint32_t streamBegin, Buffer *buffer, 117 Span<AotProfilingData::AotCallSiteInlineCache> inlineCaches); 118 static uint32_t WriteBranchDataToStream(uint32_t streamBegin, Buffer *buffer, 119 Span<AotProfilingData::AotBranchData> branches); 120 static uint32_t WriteThrowDataToStream(uint32_t streamBegin, Buffer *buffer, 121 Span<AotProfilingData::AotThrowData> throws); 122 uint32_t WriteMethodsSection(std::ofstream &fd, int32_t pandaFileIdx, uint32_t *checkSum, 123 AotProfilingData::MethodsMap &methods); 124 uint32_t WriteMethodSubSection(uint32_t &currPos, Buffer *buffer, uint32_t methodIdx, 125 AotProfilingData::AotMethodProfilingData &methodProfData); 126 127 using FileToMethodsMap = PandaMap<PandaFileIdxType, AotProfilingData::MethodsMap>; 128 uint32_t WriteAllMethodsSections(std::ofstream &fd, FileToMethodsMap &methods); 129 uint32_t WritePandaFilesSection(std::ofstream &fd, PandaMap<int32_t, std::string_view> &pandaFileMap); 130 uint32_t GetSectionNumbers(FileToMethodsMap &methods); 131 uint32_t GetSavedTypes(FileToMethodsMap &allMethodsMap); 132 133 PandaVector<SectionInfo> sectionInfos_; 134 135 template <typename T> 136 static std::ifstream &Read(std::ifstream &inputFile, T *dst, size_t n = 1, uint32_t *checkSum = nullptr) 137 { 138 return ReadBytes(inputFile, reinterpret_cast<char *>(dst), sizeof(T) * n, checkSum); 139 } 140 141 static std::ifstream &ReadBytes(std::ifstream &inputFile, char *dst, size_t n, uint32_t *checkSum = nullptr); 142 143 static Expected<PandaVector<PandaString>, PandaString> ReadPandaFilesSection(std::ifstream &inputFile); 144 145 static Expected<PandaVector<SectionInfo>, PandaString> ReadSectionInfos(std::ifstream &inputFile); 146 147 template <typename T> 148 static Expected<size_t, PandaString> ReadProfileData(std::ifstream &inputFile, const AotProfileDataHeader &header, 149 PandaVector<T> &data, uint32_t &checkSum); 150 151 static Expected<uint32_t, PandaString> ReadMethodsSection(std::ifstream &inputFile, AotProfilingData &data); 152 static Expected<AotProfilingData::AotMethodProfilingData, PandaString> ReadMethodSubSection( 153 std::ifstream &inputFile, uint32_t &checkSum); 154 155 static Expected<std::pair<PgoHeader, PandaString>, PandaString> ReadFileHeader(std::ifstream &inputFile); 156 157 static Expected<size_t, PandaString> ReadAllMethodsSections(std::ifstream &inputFile, 158 PandaVector<SectionInfo> §ionInfos, 159 AotProfilingData &data); 160 }; 161 162 } // namespace ark::pgo 163 164 #endif // PGO_FILE_BUILDER_H 165