• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 COMPILER_AOT_AOT_MANAGER_H
17 #define COMPILER_AOT_AOT_MANAGER_H
18 
19 #include "aot_file.h"
20 #include "file.h"
21 #include "utils/arena_containers.h"
22 #include "runtime/include/mem/panda_containers.h"
23 #include "runtime/include/mem/panda_string.h"
24 #include "runtime/include/method.h"
25 #include "utils/expected.h"
26 
27 namespace ark::compiler {
28 class RuntimeInterface;
29 
30 class AotManager {
31     using BitSetElement = uint32_t;
32     static constexpr size_t MASK_WIDTH = BITS_PER_BYTE * sizeof(BitSetElement);
33 
34 public:
35     explicit AotManager() = default;
36 
37     NO_MOVE_SEMANTIC(AotManager);
38     NO_COPY_SEMANTIC(AotManager);
39     ~AotManager() = default;
40 
41     Expected<bool, std::string> AddFile(const std::string &fileName, RuntimeInterface *runtime, uint32_t gcType,
42                                         bool force = false);
43 
44     const AotFile *GetFile(const std::string &fileName) const;
45 
46     const AotPandaFile *FindPandaFile(const std::string &fileName);
47 
GetBootClassContext()48     PandaString GetBootClassContext() const
49     {
50         return bootClassContext_;
51     }
52 
53     void ParseClassContextToFile(std::string_view context);
54 
SetBootClassContext(PandaString context)55     void SetBootClassContext(PandaString context)
56     {
57         bootClassContext_ = std::move(context);
58         ParseClassContextToFile(bootClassContext_);
59     }
60 
GetAppClassContext()61     PandaString GetAppClassContext() const
62     {
63         return appClassContext_;
64     }
65 
SetAppClassContext(PandaString context)66     void SetAppClassContext(PandaString context)
67     {
68         appClassContext_ = std::move(context);
69         ParseClassContextToFile(appClassContext_);
70     }
71 
72     void VerifyClassHierarchy();
73 
GetAotStringRootsCount()74     uint32_t GetAotStringRootsCount()
75     {
76         // use counter to get roots count without acquiring vector's lock
77         // Atomic with acquire order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after
78         // the load which should become visible
79         return aotStringGcRootsCount_.load(std::memory_order_acquire);
80     }
81 
82     void RegisterAotStringRoot(ObjectHeader **slot, bool isYoung);
83 
84     template <typename Callback>
VisitAotStringRoots(Callback cb,bool visitOnlyYoung)85     void VisitAotStringRoots(Callback cb, bool visitOnlyYoung)
86     {
87         ASSERT(aotStringGcRoots_.empty() ||
88                (aotStringYoungSet_.size() - 1) == (aotStringGcRoots_.size() - 1) / MASK_WIDTH);
89 
90         if (!visitOnlyYoung) {
91             for (auto root : aotStringGcRoots_) {
92                 cb(root);
93             }
94             return;
95         }
96 
97         if (!hasYoungAotStringRefs_) {
98             return;
99         }
100 
101         // Atomic with acquire order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after
102         // the load which should become visible
103         size_t totalRoots = aotStringGcRootsCount_.load(std::memory_order_acquire);
104         for (size_t idx = 0; idx < aotStringYoungSet_.size(); idx++) {
105             auto mask = aotStringYoungSet_[idx];
106             if (mask == 0) {
107                 continue;
108             }
109             for (size_t offset = 0; offset < MASK_WIDTH && idx * MASK_WIDTH + offset < totalRoots; offset++) {
110                 if ((mask & (1ULL << offset)) != 0) {
111                     cb(aotStringGcRoots_[idx * MASK_WIDTH + offset]);
112                 }
113             }
114         }
115     }
116 
117     template <typename Callback, typename IsYoungPredicate>
UpdateAotStringRoots(Callback cb,IsYoungPredicate p)118     void UpdateAotStringRoots(Callback cb, IsYoungPredicate p)
119     {
120         ASSERT(aotStringGcRoots_.empty() ||
121                (aotStringYoungSet_.size() - 1) == (aotStringGcRoots_.size() - 1) / MASK_WIDTH);
122 
123         hasYoungAotStringRefs_ = false;
124         size_t idx = 0;
125         for (auto root : aotStringGcRoots_) {
126             cb(root);
127             uint64_t bitmask = 1ULL << (idx % MASK_WIDTH);
128 
129             if ((aotStringYoungSet_[idx / MASK_WIDTH] & bitmask) != 0) {
130                 bool isYoung = p(*root);
131                 hasYoungAotStringRefs_ |= isYoung;
132                 if (!isYoung) {
133                     aotStringYoungSet_[idx / MASK_WIDTH] &= ~bitmask;
134                 }
135             }
136 
137             idx++;
138         }
139     }
140 
InAotFileRange(uintptr_t pc)141     bool InAotFileRange(uintptr_t pc)
142     {
143         for (auto &aotFile : aotFiles_) {
144             auto code = reinterpret_cast<uintptr_t>(aotFile->GetCode());
145             if (pc >= code && pc < code + reinterpret_cast<uintptr_t>(aotFile->GetCodeSize())) {
146                 return true;
147             }
148         }
149         return false;
150     }
151 
HasAotFiles()152     bool HasAotFiles()
153     {
154         return !aotFiles_.empty();
155     }
156 
TryAddMethodToProfile(Method * method)157     void TryAddMethodToProfile(Method *method)
158     {
159         auto pfName = method->GetPandaFile()->GetFullFileName();
160         if (profiledPandaFiles_.find(pfName) != profiledPandaFiles_.end()) {
161             os::memory::LockHolder lock {profiledMethodsLock_};
162             profiledMethods_.push_back(method);
163         }
164     }
165 
HasProfiledMethods()166     bool HasProfiledMethods()
167     {
168         os::memory::LockHolder lock {profiledMethodsLock_};
169         return !profiledMethods_.empty();
170     }
171 
GetProfiledMethodsFinal()172     PandaList<Method *>::const_iterator GetProfiledMethodsFinal() const
173     {
174         os::memory::LockHolder lock {profiledMethodsLock_};
175         return --profiledMethods_.cend();
176     }
177 
GetProfiledMethods()178     PandaList<Method *> &GetProfiledMethods()
179     {
180         return profiledMethods_;
181     }
182 
GetProfiledPandaFiles()183     PandaUnorderedSet<std::string_view> &GetProfiledPandaFiles()
184     {
185         return profiledPandaFiles_;
186     }
187 
188 private:
189     PandaVector<std::unique_ptr<AotFile>> aotFiles_;
190     PandaUnorderedMap<std::string, AotPandaFile> filesMap_;
191     PandaString bootClassContext_;
192     PandaString appClassContext_;
193 
194     mutable os::memory::Mutex profiledMethodsLock_;
195     PandaList<Method *> profiledMethods_ GUARDED_BY(profiledMethodsLock_);
196     PandaUnorderedSet<std::string_view> profiledPandaFiles_;
197 
198     os::memory::RecursiveMutex aotStringRootsLock_;
199     PandaVector<ObjectHeader **> aotStringGcRoots_;
200     std::atomic_uint32_t aotStringGcRootsCount_ {0};
201     bool hasYoungAotStringRefs_ {false};
202     PandaVector<BitSetElement> aotStringYoungSet_;
203 };
204 
205 class AotClassContextCollector {
206 public:
207     // CC-OFFNXT(G.NAM.03-CPP) project code style
208     static constexpr char DELIMETER = ':';
209     // CC-OFFNXT(G.NAM.03-CPP) project code style
210     static constexpr char HASH_DELIMETER = '*';
acc_(acc)211     explicit AotClassContextCollector(PandaString *acc, bool useAbsPath = true) : acc_(acc), useAbsPath_(useAbsPath) {};
212     bool operator()(const panda_file::File &pf);
213 
214     DEFAULT_MOVE_SEMANTIC(AotClassContextCollector);
215     DEFAULT_COPY_SEMANTIC(AotClassContextCollector);
216     ~AotClassContextCollector() = default;
217 
218 private:
219     PandaString *acc_;
220     bool useAbsPath_;
221 };
222 }  // namespace ark::compiler
223 
224 #endif  // COMPILER_AOT_AOT_MANAGER_H
225