1 /*
2 * Copyright (c) 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 #include "ecmascript/pgo_profiler/pgo_info.h"
17
18 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
19 #include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
20 #include "ecmascript/pgo_profiler/pgo_profiler_info.h"
21 #include "ecmascript/pgo_profiler/pgo_trace.h"
22 #include "ecmascript/pgo_profiler/pgo_utils.h"
23
24 namespace panda::ecmascript::pgo {
25
PGOInfo(uint32_t hotnessThreshold)26 PGOInfo::PGOInfo(uint32_t hotnessThreshold): hotnessThreshold_(hotnessThreshold)
27 {
28 abcFilePool_ = std::make_shared<PGOAbcFilePool>();
29 pandaFileInfos_ = std::make_unique<PGOPandaFileInfos>();
30 PGOProfilerHeader::Build(&header_, PGOProfilerHeader::LastSize());
31 recordDetailInfos_ = std::make_shared<PGORecordDetailInfos>(hotnessThreshold_);
32 }
33
~PGOInfo()34 PGOInfo::~PGOInfo()
35 {
36 Clear();
37 }
38
GetHeader() const39 PGOProfilerHeader& PGOInfo::GetHeader() const
40 {
41 return *header_;
42 }
43
GetHeaderPtr() const44 PGOProfilerHeader* PGOInfo::GetHeaderPtr() const
45 {
46 return header_;
47 }
48
SetHeader(PGOProfilerHeader * header)49 void PGOInfo::SetHeader(PGOProfilerHeader* header)
50 {
51 header_ = header;
52 }
53
GetPandaFileInfos() const54 PGOPandaFileInfos& PGOInfo::GetPandaFileInfos() const
55 {
56 return *pandaFileInfos_;
57 }
58
SetPandaFileInfos(std::unique_ptr<PGOPandaFileInfos> pandaFileInfos)59 void PGOInfo::SetPandaFileInfos(std::unique_ptr<PGOPandaFileInfos> pandaFileInfos)
60 {
61 pandaFileInfos_ = std::move(pandaFileInfos);
62 }
63
GetAbcFilePool() const64 PGOAbcFilePool& PGOInfo::GetAbcFilePool() const
65 {
66 return *abcFilePool_;
67 }
68
GetAbcFilePoolPtr() const69 std::shared_ptr<PGOAbcFilePool> PGOInfo::GetAbcFilePoolPtr() const
70 {
71 return abcFilePool_;
72 }
73
SetAbcFilePool(std::shared_ptr<PGOAbcFilePool> abcFilePool)74 void PGOInfo::SetAbcFilePool(std::shared_ptr<PGOAbcFilePool> abcFilePool)
75 {
76 abcFilePool_ = abcFilePool;
77 }
78
GetRecordDetailInfos() const79 PGORecordDetailInfos& PGOInfo::GetRecordDetailInfos() const
80 {
81 return *recordDetailInfos_;
82 }
83
SetRecordDetailInfos(std::shared_ptr<PGORecordDetailInfos> recordDetailInfos)84 void PGOInfo::SetRecordDetailInfos(std::shared_ptr<PGORecordDetailInfos> recordDetailInfos)
85 {
86 recordDetailInfos_ = recordDetailInfos;
87 }
88
GetRecordDetailInfosPtr() const89 std::shared_ptr<PGORecordDetailInfos> PGOInfo::GetRecordDetailInfosPtr() const
90 {
91 return recordDetailInfos_;
92 }
93
SetHotnessThreshold(uint32_t threshold)94 void PGOInfo::SetHotnessThreshold(uint32_t threshold)
95 {
96 hotnessThreshold_ = threshold;
97 }
98
GetHotnessThreshold() const99 uint32_t PGOInfo::GetHotnessThreshold() const
100 {
101 return hotnessThreshold_;
102 }
103
SamplePandaFileInfoSafe(uint32_t checksum,const CString & abcName)104 void PGOInfo::SamplePandaFileInfoSafe(uint32_t checksum, const CString& abcName)
105 {
106 LockHolder lock(sampleMutexLock_);
107 ConcurrentGuard guard(v_, "SafeSamplePandaFileInfo");
108 ApEntityId entryId(0);
109 abcFilePool_->TryAddSafe(abcName, entryId);
110 pandaFileInfos_->SampleSafe(checksum, entryId);
111 }
112
Clear()113 void PGOInfo::Clear()
114 {
115 if (pandaFileInfos_) {
116 pandaFileInfos_->ClearSafe();
117 }
118 if (abcFilePool_) {
119 abcFilePool_->ClearSafe();
120 }
121 if (header_) {
122 PGOProfilerHeader::Destroy(&header_);
123 }
124 if (recordDetailInfos_) {
125 recordDetailInfos_->ClearSafe();
126 }
127 }
128
GetPandaFileIdSafe(const CString & abcName,ApEntityId & entryId)129 bool PGOInfo::GetPandaFileIdSafe(const CString& abcName, ApEntityId& entryId)
130 {
131 return abcFilePool_->GetEntryIdSafe(abcName, entryId);
132 }
133
GetPandaFileDescSafe(ApEntityId abcId,CString & desc)134 bool PGOInfo::GetPandaFileDescSafe(ApEntityId abcId, CString& desc)
135 {
136 return abcFilePool_->GetPandaFileDescSafe(abcId, desc);
137 }
138
MergeSafe(const PGORecordDetailInfos & recordInfos)139 void PGOInfo::MergeSafe(const PGORecordDetailInfos& recordInfos)
140 {
141 recordDetailInfos_->MergeSafe(recordInfos);
142 }
143
MergeSafe(const PGOPandaFileInfos & pandaFileInfos)144 void PGOInfo::MergeSafe(const PGOPandaFileInfos& pandaFileInfos)
145 {
146 pandaFileInfos_->MergeSafe(pandaFileInfos);
147 }
148
MergeSafe(const PGOInfo & other)149 void PGOInfo::MergeSafe(const PGOInfo& other)
150 {
151 MergeSafe(other.GetPandaFileInfos());
152 MergeSafe(other.GetRecordDetailInfos());
153 }
154
VerifyPandaFileMatched(const PGOPandaFileInfos & pandaFileInfos,const std::string & base,const std::string & incoming) const155 bool PGOInfo::VerifyPandaFileMatched(const PGOPandaFileInfos& pandaFileInfos,
156 const std::string& base,
157 const std::string& incoming) const
158 {
159 return GetPandaFileInfos().VerifyChecksum(pandaFileInfos, base, incoming);
160 }
161
MergeWithExistProfile(PGOInfo & rtInfo,PGOProfilerDecoder & decoder,const SaveTask * task)162 void PGOInfo::MergeWithExistProfile(PGOInfo& rtInfo, PGOProfilerDecoder& decoder, const SaveTask* task)
163 {
164 ClockScope start;
165 // inherit some info from runtime encoder
166 ASSERT(header_ != nullptr);
167 ASSERT(rtInfo.header_ != nullptr);
168 header_->SetVersion(rtInfo.header_->GetVersion());
169 ASSERT(abcFilePool_->GetPool()->Empty());
170 {
171 // copy abcFilePool from runtime to temp merger.
172 // Lock for avoid sampling fileInfos during merge, it will cause pandafile ApEntityId different in abcFilePool
173 // and pandaFileInfos, which will cause checksum verification failed or an ApEntityId only in one of pools.
174 // when PGOProfilerManager::MergeApFiles, ApEntityId in abcFilePool not exist will cause crash.
175 LockHolder lock(rtInfo.GetSampleMutexLock());
176 ConcurrentGuard guard(rtInfo.GetConcurrentGuardValue(), "MergeWithExistProfile");
177 abcFilePool_->CopySafe(rtInfo.GetAbcFilePoolPtr());
178 pandaFileInfos_->MergeSafe(rtInfo.GetPandaFileInfos());
179 }
180 if (task && task->IsTerminate()) {
181 return;
182 }
183 if (decoder.LoadFull(abcFilePool_)) {
184 MergeSafe(decoder.GetPandaFileInfos());
185 SetRecordDetailInfos(decoder.GetRecordDetailInfosPtr());
186 } else {
187 LOG_PGO(ERROR) << "fail to load ap: " << decoder.GetInPath();
188 }
189 if (task && task->IsTerminate()) {
190 return;
191 }
192 MergeSafe(rtInfo.GetRecordDetailInfos());
193 if (PGOTrace::GetInstance()->IsEnable()) {
194 PGOTrace::GetInstance()->SetMergeWithExistProfileTime(start.TotalSpentTime());
195 }
196 }
197
GetSampleMutexLock()198 Mutex& PGOInfo::GetSampleMutexLock()
199 {
200 return sampleMutexLock_;
201 }
202
GetConcurrentGuardValue()203 ConcurrentGuardValue& PGOInfo::GetConcurrentGuardValue()
204 {
205 return v_;
206 }
207 } // namespace panda::ecmascript::pgo
208