• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_CLASS_TABLE_H_
18 #define ART_RUNTIME_CLASS_TABLE_H_
19 
20 #include <string>
21 #include <utility>
22 #include <vector>
23 
24 #include "base/allocator.h"
25 #include "base/hash_set.h"
26 #include "base/macros.h"
27 #include "base/mutex.h"
28 #include "gc_root.h"
29 #include "obj_ptr.h"
30 
31 namespace art {
32 
33 class OatFile;
34 
35 namespace linker {
36 class ImageWriter;
37 }  // namespace linker
38 
39 namespace linker {
40 class OatWriter;
41 }  // namespace linker
42 
43 namespace mirror {
44 class Class;
45 class ClassLoader;
46 class Object;
47 }  // namespace mirror
48 
49 // Each loader has a ClassTable
50 class ClassTable {
51  public:
52   class TableSlot {
53    public:
TableSlot()54     TableSlot() : data_(0u) {}
55 
TableSlot(const TableSlot & copy)56     TableSlot(const TableSlot& copy) : data_(copy.data_.load(std::memory_order_relaxed)) {}
57 
58     explicit TableSlot(ObjPtr<mirror::Class> klass);
59 
60     TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
61     TableSlot(uint32_t ptr, uint32_t descriptor_hash);
62 
63     TableSlot& operator=(const TableSlot& copy) {
64       data_.store(copy.data_.load(std::memory_order_relaxed), std::memory_order_relaxed);
65       return *this;
66     }
67 
Data()68     uint32_t Data() const {
69       return data_.load(std::memory_order_relaxed);
70     }
71 
72     bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_);
73 
Hash()74     uint32_t Hash() const {
75       return MaskHash(data_.load(std::memory_order_relaxed));
76     }
77 
NonHashData()78     uint32_t NonHashData() const {
79       return RemoveHash(Data());
80     }
81 
RemoveHash(uint32_t hash)82     static uint32_t RemoveHash(uint32_t hash) {
83       return hash & ~kHashMask;
84     }
85 
MaskHash(uint32_t hash)86     static uint32_t MaskHash(uint32_t hash) {
87       return hash & kHashMask;
88     }
89 
MaskedHashEquals(uint32_t other)90     bool MaskedHashEquals(uint32_t other) const {
91       return MaskHash(other) == Hash();
92     }
93 
94     template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
95     ObjPtr<mirror::Class> Read() const REQUIRES_SHARED(Locks::mutator_lock_);
96 
97     // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
98     template<typename Visitor>
99     void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;
100 
101     template<typename Visitor>
102     class ClassAndRootVisitor;
103 
104    private:
105     // Extract a raw pointer from an address.
106     static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
107         REQUIRES_SHARED(Locks::mutator_lock_);
108 
109     static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
110         REQUIRES_SHARED(Locks::mutator_lock_);
111 
112     // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
113     mutable Atomic<uint32_t> data_;
114     static constexpr uint32_t kHashMask = kObjectAlignment - 1;
115   };
116 
117   using DescriptorHashPair = std::pair<const char*, uint32_t>;
118 
119   class ClassDescriptorHash {
120    public:
121     // uint32_t for cross compilation.
122     uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
123     // uint32_t for cross compilation.
124     uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
125   };
126 
127   class ClassDescriptorEquals {
128    public:
129     // Same class loader and descriptor.
130     bool operator()(const TableSlot& a, const TableSlot& b) const
131         NO_THREAD_SAFETY_ANALYSIS;
132     // Same descriptor.
133     bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
134         NO_THREAD_SAFETY_ANALYSIS;
135   };
136 
137   class TableSlotEmptyFn {
138    public:
MakeEmpty(TableSlot & item)139     void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
140       item = TableSlot();
141       DCHECK(IsEmpty(item));
142     }
IsEmpty(const TableSlot & item)143     bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
144       return item.IsNull();
145     }
146   };
147 
148   // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
149   // should be compared for a matching class descriptor and class loader.
150   using ClassSet = HashSet<TableSlot,
151                            TableSlotEmptyFn,
152                            ClassDescriptorHash,
153                            ClassDescriptorEquals,
154                            TrackingAllocator<TableSlot, kAllocatorTagClassTable>>;
155 
156   ClassTable();
157 
158   // Freeze the current class tables by allocating a new table and never updating or modifying the
159   // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
160   void FreezeSnapshot()
161       REQUIRES(!lock_)
162       REQUIRES_SHARED(Locks::mutator_lock_);
163 
164   // Returns the number of classes in previous snapshots defined by `defining_loader`.
165   size_t NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
166       REQUIRES(!lock_)
167       REQUIRES_SHARED(Locks::mutator_lock_);
168 
169   // Returns all off the classes in the lastest snapshot defined by `defining_loader`.
170   size_t NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
171       REQUIRES(!lock_)
172       REQUIRES_SHARED(Locks::mutator_lock_);
173 
174   // Returns the number of classes in previous snapshots no matter the defining loader.
175   size_t NumReferencedZygoteClasses() const
176       REQUIRES(!lock_)
177       REQUIRES_SHARED(Locks::mutator_lock_);
178 
179   // Returns all off the classes in the lastest snapshot no matter the defining loader.
180   size_t NumReferencedNonZygoteClasses() const
181       REQUIRES(!lock_)
182       REQUIRES_SHARED(Locks::mutator_lock_);
183 
184   // Returns the number of classes in the class table.
185   size_t Size() const
186       REQUIRES(!lock_)
187       REQUIRES_SHARED(Locks::mutator_lock_);
188 
189   // Update a class in the table with the new class. Returns the existing class which was replaced.
190   ObjPtr<mirror::Class> UpdateClass(const char* descriptor,
191                                     ObjPtr<mirror::Class> new_klass,
192                                     size_t hash)
193       REQUIRES(!lock_)
194       REQUIRES_SHARED(Locks::mutator_lock_);
195 
196   // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
197   template<class Visitor>
198   void VisitRoots(Visitor& visitor)
199       NO_THREAD_SAFETY_ANALYSIS
200       REQUIRES(!lock_)
201       REQUIRES_SHARED(Locks::mutator_lock_);
202 
203   template<class Visitor>
204   void VisitRoots(const Visitor& visitor)
205       NO_THREAD_SAFETY_ANALYSIS
206       REQUIRES(!lock_)
207       REQUIRES_SHARED(Locks::mutator_lock_);
208 
209   template<class Visitor>
210   void VisitClassesAndRoots(Visitor& visitor)
211       NO_THREAD_SAFETY_ANALYSIS
212       REQUIRES(!lock_)
213       REQUIRES_SHARED(Locks::mutator_lock_);
214 
215   // Stops visit if the visitor returns false.
216   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
217   bool Visit(Visitor& visitor)
218       REQUIRES(!lock_)
219       REQUIRES_SHARED(Locks::mutator_lock_);
220   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
221   bool Visit(const Visitor& visitor)
222       REQUIRES(!lock_)
223       REQUIRES_SHARED(Locks::mutator_lock_);
224 
225   // Return the first class that matches the descriptor. Returns null if there are none.
226   ObjPtr<mirror::Class> Lookup(const char* descriptor, size_t hash)
227       REQUIRES(!lock_)
228       REQUIRES_SHARED(Locks::mutator_lock_);
229 
230   // Return the first class that matches the descriptor of klass. Returns null if there are none.
231   // Used for tests and debug-build checks.
232   ObjPtr<mirror::Class> LookupByDescriptor(ObjPtr<mirror::Class> klass)
233       REQUIRES(!lock_)
234       REQUIRES_SHARED(Locks::mutator_lock_);
235 
236   void Insert(ObjPtr<mirror::Class> klass)
237       REQUIRES(!lock_)
238       REQUIRES_SHARED(Locks::mutator_lock_);
239 
240   void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
241       REQUIRES(!lock_)
242       REQUIRES_SHARED(Locks::mutator_lock_);
243 
244   // Return true if we inserted the strong root, false if it already exists.
245   bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
246       REQUIRES(!lock_)
247       REQUIRES_SHARED(Locks::mutator_lock_);
248 
249   // Return true if we inserted the oat file, false if it already exists.
250   bool InsertOatFile(const OatFile* oat_file)
251       REQUIRES(!lock_)
252       REQUIRES_SHARED(Locks::mutator_lock_);
253 
254   // Read a table from ptr and put it at the front of the class set.
255   size_t ReadFromMemory(uint8_t* ptr)
256       REQUIRES(!lock_)
257       REQUIRES_SHARED(Locks::mutator_lock_);
258 
259   // Add a class set to the front of classes.
260   void AddClassSet(ClassSet&& set)
261       REQUIRES(!lock_)
262       REQUIRES_SHARED(Locks::mutator_lock_);
263 
264   // Clear strong roots (other than classes themselves).
265   void ClearStrongRoots()
266       REQUIRES(!lock_)
267       REQUIRES_SHARED(Locks::mutator_lock_);
268 
269   // Filter strong roots (other than classes themselves).
270   template <typename Filter>
271   void RemoveStrongRoots(const Filter& filter)
272       REQUIRES(!lock_)
273       REQUIRES_SHARED(Locks::mutator_lock_);
274 
GetLock()275   ReaderWriterMutex& GetLock() {
276     return lock_;
277   }
278 
279  private:
280   size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
281                                     const ClassSet& set) const
282       REQUIRES(lock_)
283       REQUIRES_SHARED(Locks::mutator_lock_);
284 
285   // Return true if we inserted the oat file, false if it already exists.
286   bool InsertOatFileLocked(const OatFile* oat_file)
287       REQUIRES(lock_)
288       REQUIRES_SHARED(Locks::mutator_lock_);
289 
290   // Lock to guard inserting and removing.
291   mutable ReaderWriterMutex lock_;
292   // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
293   std::vector<ClassSet> classes_ GUARDED_BY(lock_);
294   // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
295   // loader which may not be owned by the class loader must be held strongly live. Also dex caches
296   // are held live to prevent them being unloading once they have classes in them.
297   std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
298   // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
299   std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);
300 
301   friend class linker::ImageWriter;  // for InsertWithoutLocks.
302 };
303 
304 }  // namespace art
305 
306 #endif  // ART_RUNTIME_CLASS_TABLE_H_
307