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