• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &sectionInfos);
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> &sectionInfos,
159                                                                 AotProfilingData &data);
160 };
161 
162 }  // namespace ark::pgo
163 
164 #endif  // PGO_FILE_BUILDER_H
165