1 /* 2 * Copyright (c) 2021-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 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 "utils/expected.h" 25 26 namespace ark::compiler { 27 class RuntimeInterface; 28 29 class AotManager { 30 using BitSetElement = uint32_t; 31 static constexpr size_t MASK_WIDTH = BITS_PER_BYTE * sizeof(BitSetElement); 32 33 public: 34 explicit AotManager() = default; 35 36 NO_MOVE_SEMANTIC(AotManager); 37 NO_COPY_SEMANTIC(AotManager); 38 ~AotManager() = default; 39 40 Expected<bool, std::string> AddFile(const std::string &fileName, RuntimeInterface *runtime, uint32_t gcType, 41 bool force = false); 42 43 const AotFile *GetFile(const std::string &fileName) const; 44 45 const AotPandaFile *FindPandaFile(const std::string &fileName); 46 GetBootClassContext()47 PandaString GetBootClassContext() const 48 { 49 return bootClassContext_; 50 } 51 SetBootClassContext(PandaString context)52 void SetBootClassContext(PandaString context) 53 { 54 bootClassContext_ = std::move(context); 55 } 56 GetAppClassContext()57 PandaString GetAppClassContext() const 58 { 59 return appClassContext_; 60 } 61 SetAppClassContext(PandaString context)62 void SetAppClassContext(PandaString context) 63 { 64 appClassContext_ = std::move(context); 65 } 66 67 void VerifyClassHierarchy(); 68 GetAotStringRootsCount()69 uint32_t GetAotStringRootsCount() 70 { 71 // use counter to get roots count without acquiring vector's lock 72 // Atomic with acquire order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after 73 // the load which should become visible 74 return aotStringGcRootsCount_.load(std::memory_order_acquire); 75 } 76 77 void RegisterAotStringRoot(ObjectHeader **slot, bool isYoung); 78 79 template <typename Callback> VisitAotStringRoots(Callback cb,bool visitOnlyYoung)80 void VisitAotStringRoots(Callback cb, bool visitOnlyYoung) 81 { 82 ASSERT(aotStringGcRoots_.empty() || 83 (aotStringYoungSet_.size() - 1) == (aotStringGcRoots_.size() - 1) / MASK_WIDTH); 84 85 if (!visitOnlyYoung) { 86 for (auto root : aotStringGcRoots_) { 87 cb(root); 88 } 89 return; 90 } 91 92 if (!hasYoungAotStringRefs_) { 93 return; 94 } 95 96 // Atomic with acquire order reason: data race with aot_string_gc_roots_count_ with dependecies on reads after 97 // the load which should become visible 98 size_t totalRoots = aotStringGcRootsCount_.load(std::memory_order_acquire); 99 for (size_t idx = 0; idx < aotStringYoungSet_.size(); idx++) { 100 auto mask = aotStringYoungSet_[idx]; 101 if (mask == 0) { 102 continue; 103 } 104 for (size_t offset = 0; offset < MASK_WIDTH && idx * MASK_WIDTH + offset < totalRoots; offset++) { 105 if ((mask & (1ULL << offset)) != 0) { 106 cb(aotStringGcRoots_[idx * MASK_WIDTH + offset]); 107 } 108 } 109 } 110 } 111 112 template <typename Callback, typename IsYoungPredicate> UpdateAotStringRoots(Callback cb,IsYoungPredicate p)113 void UpdateAotStringRoots(Callback cb, IsYoungPredicate p) 114 { 115 ASSERT(aotStringGcRoots_.empty() || 116 (aotStringYoungSet_.size() - 1) == (aotStringGcRoots_.size() - 1) / MASK_WIDTH); 117 118 hasYoungAotStringRefs_ = false; 119 size_t idx = 0; 120 for (auto root : aotStringGcRoots_) { 121 cb(root); 122 uint64_t bitmask = 1ULL << (idx % MASK_WIDTH); 123 124 if ((aotStringYoungSet_[idx / MASK_WIDTH] & bitmask) != 0) { 125 bool isYoung = p(*root); 126 hasYoungAotStringRefs_ |= isYoung; 127 if (!isYoung) { 128 aotStringYoungSet_[idx / MASK_WIDTH] &= ~bitmask; 129 } 130 } 131 132 idx++; 133 } 134 } 135 InAotFileRange(uintptr_t pc)136 bool InAotFileRange(uintptr_t pc) 137 { 138 for (auto &aotFile : aotFiles_) { 139 auto code = reinterpret_cast<uintptr_t>(aotFile->GetCode()); 140 if (pc >= code && pc < code + reinterpret_cast<uintptr_t>(aotFile->GetCodeSize())) { 141 return true; 142 } 143 } 144 return false; 145 } 146 HasAotFiles()147 bool HasAotFiles() 148 { 149 return !aotFiles_.empty(); 150 } 151 152 private: 153 PandaVector<std::unique_ptr<AotFile>> aotFiles_; 154 PandaUnorderedMap<std::string, AotPandaFile> filesMap_; 155 PandaString bootClassContext_; 156 PandaString appClassContext_; 157 158 os::memory::RecursiveMutex aotStringRootsLock_; 159 PandaVector<ObjectHeader **> aotStringGcRoots_; 160 std::atomic_uint32_t aotStringGcRootsCount_ {0}; 161 bool hasYoungAotStringRefs_ {false}; 162 PandaVector<BitSetElement> aotStringYoungSet_; 163 }; 164 165 class AotClassContextCollector { 166 public: acc_(acc)167 explicit AotClassContextCollector(PandaString *acc, bool useAbsPath = true) : acc_(acc), useAbsPath_(useAbsPath) {}; 168 bool operator()(const panda_file::File &pf); 169 170 DEFAULT_MOVE_SEMANTIC(AotClassContextCollector); 171 DEFAULT_COPY_SEMANTIC(AotClassContextCollector); 172 ~AotClassContextCollector() = default; 173 174 private: 175 PandaString *acc_; 176 bool useAbsPath_; 177 }; 178 } // namespace ark::compiler 179 180 #endif // COMPILER_AOT_AOT_MANAGER_H 181