• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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