1 /** 2 * Copyright (c) 2021-2022 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 panda::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 &file_name, RuntimeInterface *runtime, uint32_t gc_type, 41 bool force = false); 42 43 const AotFile *GetFile(const std::string &file_name) const; 44 45 const AotPandaFile *FindPandaFile(const std::string &file_name); 46 GetBootClassContext()47 PandaString GetBootClassContext() const 48 { 49 return boot_class_context_; 50 } 51 SetBootClassContext(PandaString context)52 void SetBootClassContext(PandaString context) 53 { 54 boot_class_context_ = std::move(context); 55 } 56 GetAppClassContext()57 PandaString GetAppClassContext() const 58 { 59 return app_class_context_; 60 } 61 SetAppClassContext(PandaString context)62 void SetAppClassContext(PandaString context) 63 { 64 app_class_context_ = std::move(context); 65 } 66 67 void VerifyClassHierarchy(bool only_boot = false); 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 aot_string_gc_roots_count_.load(std::memory_order_acquire); 75 } 76 77 void RegisterAotStringRoot(ObjectHeader **slot, bool is_young); 78 79 template <typename Callback> VisitAotStringRoots(Callback cb,bool visit_only_young)80 void VisitAotStringRoots(Callback cb, bool visit_only_young) 81 { 82 ASSERT(aot_string_gc_roots_.empty() || 83 (aot_string_young_set_.size() - 1) == (aot_string_gc_roots_.size() - 1) / MASK_WIDTH); 84 85 if (!visit_only_young) { 86 for (auto root : aot_string_gc_roots_) { 87 cb(root); 88 } 89 return; 90 } 91 92 if (!has_young_aot_string_refs_) { 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 total_roots = aot_string_gc_roots_count_.load(std::memory_order_acquire); 99 for (size_t idx = 0; idx < aot_string_young_set_.size(); idx++) { 100 auto mask = aot_string_young_set_[idx]; 101 if (mask == 0) { 102 continue; 103 } 104 for (size_t offset = 0; offset < MASK_WIDTH && idx * MASK_WIDTH + offset < total_roots; offset++) { 105 if ((mask & (1ULL << offset)) != 0) { 106 cb(aot_string_gc_roots_[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(aot_string_gc_roots_.empty() || 116 (aot_string_young_set_.size() - 1) == (aot_string_gc_roots_.size() - 1) / MASK_WIDTH); 117 118 has_young_aot_string_refs_ = false; 119 size_t idx = 0; 120 for (auto root : aot_string_gc_roots_) { 121 cb(root); 122 uint64_t bitmask = 1ULL << (idx % MASK_WIDTH); 123 124 if ((aot_string_young_set_[idx / MASK_WIDTH] & bitmask) != 0) { 125 bool is_young = p(*root); 126 has_young_aot_string_refs_ |= is_young; 127 if (!is_young) { 128 aot_string_young_set_[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 &aot_file : aot_files_) { 139 auto code = reinterpret_cast<uintptr_t>(aot_file->GetCode()); 140 if (pc >= code && pc < code + reinterpret_cast<uintptr_t>(aot_file->GetCodeSize())) { 141 return true; 142 } 143 } 144 return false; 145 } 146 HasAotFiles()147 bool HasAotFiles() 148 { 149 return !aot_files_.empty(); 150 } 151 152 private: 153 PandaVector<std::unique_ptr<AotFile>> aot_files_; 154 PandaUnorderedMap<std::string, AotPandaFile> files_map_; 155 PandaString boot_class_context_; 156 PandaString app_class_context_; 157 158 os::memory::RecursiveMutex aot_string_roots_lock_; 159 PandaVector<ObjectHeader **> aot_string_gc_roots_; 160 std::atomic_uint32_t aot_string_gc_roots_count_ {0}; 161 bool has_young_aot_string_refs_ {false}; 162 PandaVector<BitSetElement> aot_string_young_set_; 163 }; 164 165 class AotClassContextCollector { 166 public: AotClassContextCollector(PandaString * acc)167 explicit AotClassContextCollector(PandaString *acc) : acc_(acc) {}; 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 }; 177 } // namespace panda::compiler 178 179 #endif // COMPILER_AOT_AOT_MANAGER_H 180