• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_BASE_INFO_H
17 #define ECMASCRIPT_PGO_PROFILER_AP_FILE_BASE_INFO_H
18 
19 #include <cstdint>
20 
21 #include "ecmascript/common.h"
22 #include "libpandafile/file.h"
23 #include "macros.h"
24 
25 #include "ecmascript/base/file_header.h"
26 
27 namespace panda::ecmascript::pgo {
28 class PGOProfilerHeader;
29 
30 struct SectionInfo {
31     uint32_t offset_ {0};
32     // reserve
33     uint32_t size_ {0};
34     uint32_t number_ {0};
35 };
36 
37 /**
38   |----PGOProfilerHeader
39   |--------MAGIC(8)
40   |------------{ 'P', 'A', 'N', 'D', 'A', '\0', '\0', '\0' }
41   |--------VERSION(4)
42   |------------{ '0', '0', '0', '0' }
43   |--------CHECKSUM(4)
44   |------------{ checksum }
45   |--------FILE_SIZE(4)
46   |------------{ fileSize }
47   |--------HEADER_SIZE(4)
48   |------------{ headerSize, from MAGIC to SECTION_NUMBER }
49   |--------ENDIAN_TAG(4)
50   |------------{ ENDIAN_TAG }
51   |--------SECTION_NUMBER(4)
52   |------------{ 4 }
53   |--------PANDA_FILE_INFO_SECTION_INFO(12)
54   |------------{ offset, size (reserve), number1 }
55   |--------RECORD_INFO_SECTION_INFO(12)
56   |------------{ offset, size (reserve), number2 }
57   |--------LAYOUT_DESC_SECTION_INFO(12)
58   |------------{ offset, size (reserve), number3 }
59   |--------RECORD_POOL(12)
60   |------------{ offset, size (reserve), recordPoolCount }
61   |
62   |----Section1: PGOPandaFileInfos(number1)
63   |--------[{ size, CHECK_SUM }, { size, CHECK_SUM }, ...]
64   |
65   |----Section2: PGORecordDetailInfos(number2)
66   |--------[ PGOMethodInfoMap(number4)
67   |------------{ recordId, offset, size, number4 }
68   |------------[ PGOMethodInfo(size1)
69   |----------------{ size1, entityId, count, mode, methodName,
70   |-------------------- [{ size, offset, profileTypeId }, { size, offset, profileTypeId }, ...]},
71   |------------  PGOMethodInfo(size1)
72   |----------------{ size1, entityId, count, mode, methodName,
73   |-------------------- [{ size, offset, profileTypeId }, { size, offset, profileTypeId }, ...]},
74   |--------------... ]
75   |--------  PGOMethodInfoMap()
76   |--------... ]
77   |
78   |----Section3: PGHClassLayoutDescs(number3)
79   |--------{ offset, size, number5 }
80   |--------[ PGOHClassLayoutDescInner(size)
81   |------------{ size, profileTypeId, superProfileTypeId, count, ptCount, ctorCount,
82   |---------------- [{ size, handle, key }, { size, heandle, key }, ...]}
83   |--------  PGOHClassLayoutDescInner(size)
84   |------------{ size, profileTypeId, superProfileTypeId, count, ptCount, ctorCount,
85   |---------------- [{ size, handle, key }, { size, heandle, key }, ...]}
86   |
87   |----Section4: PGORecord(recordPoolCount)
88   |--------{ offset, size, recordItemCount }
89   |--------[ recordId, recordName ](recordItemCount)
90   |
91   |----Section5: ProfileTypes(ProfileTypePoolCount)
92   |--------{ offset, size, profileTypeItemCount }
93   |--------[ profileTypeId, profileType(64bit) ](profileTypeItemCount)
94  */
95 class PGOProfilerHeader : public base::FileHeaderElastic {
96 public:
97     static constexpr VersionType TYPE_MINI_VERSION = {0, 0, 0, 2};
98     static constexpr VersionType METHOD_CHECKSUM_MINI_VERSION = {0, 0, 0, 4};
99     static constexpr VersionType USE_HCLASS_TYPE_MINI_VERSION = {0, 0, 0, 5};
100     static constexpr VersionType FILE_CONSISTENCY_MINI_VERSION = {0, 0, 0, 6};
101     static constexpr VersionType TRACK_FIELD_MINI_VERSION = {0, 0, 0, 7};
102     static constexpr VersionType ELEMENTS_KIND_MINI_VERSION = {0, 0, 0, 8};
103     static constexpr VersionType RECORD_POOL_MINI_VERSION = {0, 0, 0, 9};
104     static constexpr VersionType WIDE_CLASS_TYPE_MINI_VERSION = {0, 0, 0, 10};
105     static constexpr VersionType PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION = {0, 0, 0, 11};
106     static constexpr VersionType ELEMENTS_TRACK_INFO_MINI_VERSION = {0, 0, 0, 12};
107     static constexpr VersionType FILE_SIZE_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
108     static constexpr VersionType HEADER_SIZE_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
109     static constexpr VersionType ELASTIC_HEADER_MINI_VERSION = FILE_CONSISTENCY_MINI_VERSION;
110     static constexpr VersionType LAST_VERSION = {0, 0, 0, 12};
111     static constexpr size_t SECTION_SIZE = 6;
112     static constexpr size_t PANDA_FILE_SECTION_INDEX = 0;
113     static constexpr size_t RECORD_INFO_SECTION_INDEX = 1;
114     static constexpr size_t LAYOUT_DESC_SECTION_INDEX = 2;
115     static constexpr size_t RECORD_POOL_SECTION_INDEX = 3;
116     static constexpr size_t CLASS_TYPE_POOL_SECTION_INDEX = 4;
117     static constexpr size_t ABC_FILE_POOL_SECTION_INDEX = 5;
118 
PGOProfilerHeader()119     PGOProfilerHeader() : base::FileHeaderElastic(LAST_VERSION), sectionNumber_(SECTION_SIZE)
120     {
121         GetPandaInfoSection()->offset_ = Size();
122         SetHeaderSize(Size());
123     }
124 
LastSize()125     static size_t LastSize()
126     {
127         return sizeof(PGOProfilerHeader) + (SECTION_SIZE - 1) * sizeof(SectionInfo);
128     }
129 
Size(uint32_t sectionNumber)130     static size_t Size(uint32_t sectionNumber)
131     {
132         return sizeof(PGOProfilerHeader) + (sectionNumber - 1) * sizeof(SectionInfo);
133     }
134 
Size()135     size_t Size() const
136     {
137         return Size(sectionNumber_);
138     }
139 
Verify()140     bool Verify() const
141     {
142         return VerifyVersion("apPath file", LAST_VERSION, IsStrictMatch());
143     }
144 
Verify(void * buffer,size_t bufferSize)145     bool Verify(void *buffer, size_t bufferSize) const
146     {
147         if (!Verify()) {
148             return false;
149         }
150         if (!VerifyConsistency(buffer, bufferSize)) {
151             return false;
152         }
153         if (!VerifyFileSize(bufferSize)) {
154             return false;
155         }
156         return true;
157     }
158 
159     bool VerifyFileSize(size_t bufferSize) const;
160 
161     bool VerifyConsistency(void *buffer, size_t bufferSize) const;
162 
Build(PGOProfilerHeader ** header,size_t size)163     static void Build(PGOProfilerHeader **header, size_t size)
164     {
165         *header = reinterpret_cast<PGOProfilerHeader *>(malloc(size));
166         new (*header) PGOProfilerHeader();
167     }
168 
Destroy(PGOProfilerHeader ** header)169     static void Destroy(PGOProfilerHeader **header)
170     {
171         if (*header != nullptr) {
172             free(*header);
173             *header = nullptr;
174         }
175     }
176 
177     // Copy Header.
178     static bool ParseFromBinary(void *buffer, size_t bufferSize, PGOProfilerHeader **header);
179     void ProcessToBinary(std::fstream &fileStream) const;
180 
181     bool ParseFromText(std::ifstream &stream);
182     bool ProcessToText(std::ofstream &stream) const;
183 
GetPandaInfoSection()184     SectionInfo *GetPandaInfoSection() const
185     {
186         return GetSectionInfo(PANDA_FILE_SECTION_INDEX);
187     }
188 
GetRecordInfoSection()189     SectionInfo *GetRecordInfoSection() const
190     {
191         return GetSectionInfo(RECORD_INFO_SECTION_INDEX);
192     }
193 
GetLayoutDescSection()194     SectionInfo *GetLayoutDescSection() const
195     {
196         return GetSectionInfo(LAYOUT_DESC_SECTION_INDEX);
197     }
198 
GetRecordPoolSection()199     SectionInfo *GetRecordPoolSection() const
200     {
201         return GetSectionInfo(RECORD_POOL_SECTION_INDEX);
202     }
203 
GetProfileTypeSection()204     SectionInfo *GetProfileTypeSection() const
205     {
206         return GetSectionInfo(CLASS_TYPE_POOL_SECTION_INDEX);
207     }
208 
GetAbcFilePoolSection()209     SectionInfo *GetAbcFilePoolSection() const
210     {
211         return GetSectionInfo(ABC_FILE_POOL_SECTION_INDEX);
212     }
213 
SupportType()214     bool SupportType() const
215     {
216         return CompatibleVerify(TYPE_MINI_VERSION);
217     }
218 
SupportMethodChecksum()219     bool SupportMethodChecksum() const
220     {
221         return CompatibleVerify(METHOD_CHECKSUM_MINI_VERSION);
222     }
223 
SupportUseHClassType()224     bool SupportUseHClassType() const
225     {
226         return CompatibleVerify(USE_HCLASS_TYPE_MINI_VERSION);
227     }
228 
SupportFileConsistency()229     bool SupportFileConsistency() const
230     {
231         return CompatibleVerify(FILE_CONSISTENCY_MINI_VERSION);
232     }
233 
SupportFileSize()234     bool SupportFileSize() const
235     {
236         return CompatibleVerify(FILE_SIZE_MINI_VERSION);
237     }
238 
SupportHeaderSize()239     bool SupportHeaderSize() const
240     {
241         return CompatibleVerify(HEADER_SIZE_MINI_VERSION);
242     }
243 
SupportTrackField()244     bool SupportTrackField() const
245     {
246         return CompatibleVerify(TRACK_FIELD_MINI_VERSION);
247     }
248 
SupportElementsKind()249     bool SupportElementsKind() const
250     {
251         return CompatibleVerify(ELEMENTS_KIND_MINI_VERSION);
252     }
253 
SupportRecordPool()254     bool SupportRecordPool() const
255     {
256         return CompatibleVerify(RECORD_POOL_MINI_VERSION);
257     }
258 
SupportWideProfileType()259     bool SupportWideProfileType() const
260     {
261         return CompatibleVerify(WIDE_CLASS_TYPE_MINI_VERSION);
262     }
263 
SupportProfileTypeWithAbcId()264     bool SupportProfileTypeWithAbcId() const
265     {
266         return CompatibleVerify(PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION);
267     }
268 
SupportElementsTrackInfo()269     bool SupportElementsTrackInfo() const
270     {
271         return CompatibleVerify(ELEMENTS_TRACK_INFO_MINI_VERSION);
272     }
273 
IsStrictMatch()274     static bool IsStrictMatch()
275     {
276         return strictMatch_;
277     }
278 
279     // just for test
SetStrictMatch(bool strictMatch)280     static void SetStrictMatch(bool strictMatch)
281     {
282         strictMatch_ = strictMatch;
283     }
284 
285     NO_COPY_SEMANTIC(PGOProfilerHeader);
286     NO_MOVE_SEMANTIC(PGOProfilerHeader);
287 
288 private:
289     static bool BuildFromLegacy(void *buffer, PGOProfilerHeader **header);
290     static bool BuildFromElastic(void *buffer, size_t bufferSize, PGOProfilerHeader **header);
291 
GetSectionInfo(size_t index)292     SectionInfo *GetSectionInfo(size_t index) const
293     {
294         if (index >= sectionNumber_) {
295             return nullptr;
296         }
297         return const_cast<SectionInfo *>(&sectionInfos_) + index;
298     }
299 
300     uint32_t sectionNumber_ {SECTION_SIZE};
301     SectionInfo sectionInfos_;
302     static bool strictMatch_;
303 };
304 
305 class PGOProfilerHeaderLegacy : public base::FileHeaderBase {
306 public:
307     static constexpr size_t SECTION_SIZE = 3;
308     static constexpr VersionType LAST_VERSION = {0, 0, 0, 5};
PGOProfilerHeaderLegacy()309     PGOProfilerHeaderLegacy() : base::FileHeaderBase(LAST_VERSION), sectionNumber_(SECTION_SIZE) {};
310 
GetSectionNumber()311     const uint32_t &GetSectionNumber() const
312     {
313         return sectionNumber_;
314     }
315 
316 private:
317     uint32_t sectionNumber_ {SECTION_SIZE};
318     SectionInfo sectionInfos_;
319 };
320 
321 class PGOFileDataInterface {
322 public:
323     PGOFileDataInterface() = default;
324     virtual ~PGOFileDataInterface() = default;
325     virtual uint32_t ProcessToBinary(PGOContext &context, std::fstream &stream) = 0;
326     virtual uint32_t ParseFromBinary(PGOContext &context, void **buffer, PGOProfilerHeader const *header) = 0;
327     virtual bool ProcessToText(std::ofstream &stream) = 0;
328     // not support yet
ParseFromText(std::ifstream & stream)329     virtual bool ParseFromText([[maybe_unused]] std::ifstream &stream)
330     {
331         return true;
332     };
333 
334 private:
335     NO_COPY_SEMANTIC(PGOFileDataInterface);
336     NO_MOVE_SEMANTIC(PGOFileDataInterface);
337 };
338 
339 class PGOFileSectionInterface : public PGOFileDataInterface {
340 public:
341     PGOFileSectionInterface() = default;
342     ~PGOFileSectionInterface() override = default;
343     virtual bool Support(PGOProfilerHeader const *header) const = 0;
344     virtual SectionInfo *GetSection(PGOProfilerHeader const *header) const = 0;
345 
ParseSectionFromBinary(PGOContext & context,void * buffer,PGOProfilerHeader const * header,PGOFileSectionInterface & section)346     static bool ParseSectionFromBinary(PGOContext &context, void *buffer, PGOProfilerHeader const *header,
347                                        PGOFileSectionInterface &section)
348     {
349         if (section.Support(header)) {
350             SectionInfo *info = section.GetSection(header);
351             if (info == nullptr) {
352                 return false;
353             }
354             void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_);
355             section.ParseFromBinary(context, &addr, header);
356         }
357         return true;
358     }
359 
ProcessSectionToBinary(PGOContext & context,std::fstream & fileStream,PGOProfilerHeader * const header,PGOFileSectionInterface & section)360     static bool ProcessSectionToBinary(PGOContext &context, std::fstream &fileStream, PGOProfilerHeader *const header,
361                                        PGOFileSectionInterface &section)
362     {
363         auto *info = section.GetSection(header);
364         if (info == nullptr) {
365             return false;
366         }
367         info->offset_ = static_cast<uint32_t>(fileStream.tellp());
368         info->number_ = section.ProcessToBinary(context, fileStream);
369         info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_;
370         return true;
371     }
372 
373 private:
374     NO_COPY_SEMANTIC(PGOFileSectionInterface);
375     NO_MOVE_SEMANTIC(PGOFileSectionInterface);
376 };
377 } // namespace panda::ecmascript::pgo
378 #endif  // ECMASCRIPT_PGO_PROFILER_AP_FILE_BASE_INFO_H