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