• 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 #include "profiling_loader.h"
17 #include "profiling_saver.h"
18 
19 namespace ark {
UpdateInlineCaches(pgo::AotProfilingData::AotCallSiteInlineCache * ic,std::vector<Class * > & runtimeClasses,pgo::AotProfilingData * profileData)20 void ProfilingSaver::UpdateInlineCaches(pgo::AotProfilingData::AotCallSiteInlineCache *ic,
21                                         std::vector<Class *> &runtimeClasses, pgo::AotProfilingData *profileData)
22 {
23     for (uint32_t i = 0; i < runtimeClasses.size(); i++) {
24         auto storedClass = ic->classes[i];
25 
26         auto runtimeCls = runtimeClasses[i];
27         // Megamorphic Call, update first item, and return.
28         if (i == 0 && CallSiteInlineCache::IsMegamorphic(runtimeCls)) {
29             ic->classes[i] = {ic->MEGAMORPHIC_FLAG, -1};
30             return;
31         }
32 
33         if (storedClass.first == runtimeCls->GetFileId().GetOffset()) {
34             continue;
35         }
36 
37         auto clsPandaFile = runtimeCls->GetPandaFile()->GetFullFileName();
38         auto pfIdx = profileData->GetPandaFileIdxByName(clsPandaFile);
39         auto clsIdx = runtimeCls->GetFileId().GetOffset();
40 
41         ic->classes[i] = {clsIdx, pfIdx};
42     }
43 }
44 
CreateInlineCaches(pgo::AotProfilingData::AotMethodProfilingData * profilingData,Span<CallSiteInlineCache> & runtimeICs,pgo::AotProfilingData * profileData)45 void ProfilingSaver::CreateInlineCaches(pgo::AotProfilingData::AotMethodProfilingData *profilingData,
46                                         Span<CallSiteInlineCache> &runtimeICs, pgo::AotProfilingData *profileData)
47 {
48     auto icCount = runtimeICs.size();
49     auto aotICs = profilingData->GetInlineCaches();
50     for (size_t i = 0; i < icCount; i++) {
51         aotICs[i] = {static_cast<uint32_t>(runtimeICs[i].GetBytecodePc()), {}};
52         pgo::AotProfilingData::AotCallSiteInlineCache::ClearClasses(aotICs[i].classes);
53         auto classes = runtimeICs[i].GetClassesCopy();
54         UpdateInlineCaches(&aotICs[i], classes, profileData);
55     }
56 }
57 
CreateBranchData(pgo::AotProfilingData::AotMethodProfilingData * profilingData,Span<BranchData> & runtimeBranch)58 void ProfilingSaver::CreateBranchData(pgo::AotProfilingData::AotMethodProfilingData *profilingData,
59                                       Span<BranchData> &runtimeBranch)
60 {
61     auto brCount = runtimeBranch.size();
62     auto aotBrs = profilingData->GetBranchData();
63 
64     for (size_t i = 0; i < brCount; i++) {
65         aotBrs[i] = {static_cast<uint32_t>(runtimeBranch[i].GetPc()),
66                      static_cast<uint64_t>(runtimeBranch[i].GetTakenCounter()),
67                      static_cast<uint64_t>(runtimeBranch[i].GetNotTakenCounter())};
68     }
69 }
70 
CreateThrowData(pgo::AotProfilingData::AotMethodProfilingData * profilingData,Span<ThrowData> & runtimeThrow)71 void ProfilingSaver::CreateThrowData(pgo::AotProfilingData::AotMethodProfilingData *profilingData,
72                                      Span<ThrowData> &runtimeThrow)
73 {
74     auto thCount = runtimeThrow.size();
75     auto aotThs = profilingData->GetThrowData();
76 
77     for (size_t i = 0; i < thCount; i++) {
78         aotThs[i] = {static_cast<uint32_t>(runtimeThrow[i].GetPc()),
79                      static_cast<uint64_t>(runtimeThrow[i].GetTakenCounter())};
80     }
81 }
82 
AddMethod(pgo::AotProfilingData * profileData,Method * method,int32_t pandaFileIdx)83 void ProfilingSaver::AddMethod(pgo::AotProfilingData *profileData, Method *method, int32_t pandaFileIdx)
84 {
85     auto *runtimeProfData = method->GetProfilingData();
86     if (UNLIKELY(runtimeProfData == nullptr)) {
87         return;
88     }
89     auto runtimeICs = runtimeProfData->GetInlineCaches();
90     uint32_t vcallsCount = runtimeICs.size();
91 
92     auto runtimeBrs = runtimeProfData->GetBranchData();
93     uint32_t branchCount = runtimeBrs.size();
94 
95     auto runtimeThs = runtimeProfData->GetThrowData();
96     uint32_t throwCount = runtimeThs.size();
97 
98     auto profilingData = pgo::AotProfilingData::AotMethodProfilingData(method->GetFileId().GetOffset(),
99                                                                        method->GetClass()->GetFileId().GetOffset(),
100                                                                        vcallsCount, branchCount, throwCount);
101     CreateInlineCaches(&profilingData, runtimeICs, profileData);
102     CreateBranchData(&profilingData, runtimeBrs);
103     CreateThrowData(&profilingData, runtimeThs);
104 
105     auto methodIdx = method->GetFileId().GetOffset();
106     profileData->AddMethod(pandaFileIdx, methodIdx, std::move(profilingData));
107 }
108 
AddProfiledMethods(pgo::AotProfilingData * profileData,PandaList<Method * > & profiledMethods,PandaList<Method * >::const_iterator profiledMethodsFinal)109 void ProfilingSaver::AddProfiledMethods(pgo::AotProfilingData *profileData, PandaList<Method *> &profiledMethods,
110                                         PandaList<Method *>::const_iterator profiledMethodsFinal)
111 {
112     auto pfMap = profileData->GetPandaFileMap();
113     bool notFinal = true;
114     for (auto it = profiledMethods.cbegin(); notFinal; it++) {
115         if ((*it) == (*profiledMethodsFinal)) {
116             notFinal = false;
117         }
118         auto method = *it;
119         ASSERT((method->GetProfilingData()) != nullptr);
120         if (method->GetProfilingData()->IsUpdateSinceLastSave()) {
121             method->GetProfilingData()->DataSaved();
122         } else {
123             continue;
124         }
125         auto pandaFileName = method->GetPandaFile()->GetFullFileName();
126         if (pfMap.find(PandaString(pandaFileName)) == pfMap.end()) {
127             continue;
128         }
129         auto pandaFileIdx = profileData->GetPandaFileIdxByName(pandaFileName);
130         AddMethod(profileData, method, pandaFileIdx);
131     }
132 }
133 
SaveProfile(const PandaString & saveFilePath,const PandaString & classCtxStr,PandaList<Method * > & profiledMethods,PandaList<Method * >::const_iterator profiledMethodsFinal,PandaUnorderedSet<std::string_view> & profiledPandaFiles)134 void ProfilingSaver::SaveProfile(const PandaString &saveFilePath, const PandaString &classCtxStr,
135                                  PandaList<Method *> &profiledMethods,
136                                  PandaList<Method *>::const_iterator profiledMethodsFinal,
137                                  PandaUnorderedSet<std::string_view> &profiledPandaFiles)
138 {
139     ProfilingLoader profilingLoader;
140     pgo::AotProfilingData profData;
141     // Load previous profile data if available
142     auto profileCtxOrError = profilingLoader.LoadProfile(saveFilePath);
143     if (!profileCtxOrError) {
144         LOG(INFO, RUNTIME) << "No previous profile data found. Saving new profile data.";
145     } else {
146         LOG(INFO, RUNTIME) << "Previous profile data found. Merging with new profile data.";
147         profData = std::move(profilingLoader.GetAotProfilingData());
148     }
149 
150     // Add new profile data to the existing data
151     profData.AddPandaFiles(profiledPandaFiles);
152     AddProfiledMethods(&profData, profiledMethods, profiledMethodsFinal);
153 
154     // Save the updated profile data
155     pgo::AotPgoFile pgoFile;
156     auto writtenBytes = pgoFile.Save(saveFilePath, &profData, classCtxStr);
157     if (writtenBytes > 0) {
158         LOG(INFO, RUNTIME) << "Profile data saved to " << saveFilePath << " with " << writtenBytes << " bytes.";
159     } else {
160         LOG(ERROR, RUNTIME) << "Failed to save profile data to " << saveFilePath << ".";
161     }
162 }
163 }  // namespace ark