blob: 8616dfba93d10747a02aa85b9c809dd01a5a27b6 [file] [log] [blame]
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -07001/*
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"
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070028#include "gc_root.h"
Mathieu Chartierbc5a7952016-10-17 15:46:31 -070029#include "obj_ptr.h"
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070030
31namespace art {
32
Vladimir Markoaad75c62016-10-03 08:46:48 +000033class OatFile;
34
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070035namespace mirror {
Andreas Gamped482e732017-04-24 17:59:09 -070036 class Class;
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070037 class ClassLoader;
Andreas Gamped482e732017-04-24 17:59:09 -070038 class Object;
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070039} // namespace mirror
40
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070041// Each loader has a ClassTable
42class ClassTable {
43 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -080044 class TableSlot {
45 public:
46 TableSlot() : data_(0u) {}
47
48 TableSlot(const TableSlot& copy) : data_(copy.data_.LoadRelaxed()) {}
49
50 explicit TableSlot(ObjPtr<mirror::Class> klass);
51
52 TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
53
54 TableSlot& operator=(const TableSlot& copy) {
55 data_.StoreRelaxed(copy.data_.LoadRelaxed());
56 return *this;
57 }
58
59 bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
60 return Read<kWithoutReadBarrier>() == nullptr;
61 }
62
63 uint32_t Hash() const {
64 return MaskHash(data_.LoadRelaxed());
65 }
66
67 static uint32_t MaskHash(uint32_t hash) {
68 return hash & kHashMask;
69 }
70
71 bool MaskedHashEquals(uint32_t other) const {
72 return MaskHash(other) == Hash();
73 }
74
Mathieu Chartierdb70ce52016-12-12 11:06:59 -080075 static uint32_t HashDescriptor(ObjPtr<mirror::Class> klass)
76 REQUIRES_SHARED(Locks::mutator_lock_);
77
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -080078 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
79 mirror::Class* Read() const REQUIRES_SHARED(Locks::mutator_lock_);
80
81 // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
82 template<typename Visitor>
83 void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;
84
85 private:
86 // Extract a raw pointer from an address.
87 static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
88 REQUIRES_SHARED(Locks::mutator_lock_);
89
90 static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
91 REQUIRES_SHARED(Locks::mutator_lock_);
92
93 // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
94 mutable Atomic<uint32_t> data_;
95 static const uint32_t kHashMask = kObjectAlignment - 1;
96 };
97
98 using DescriptorHashPair = std::pair<const char*, uint32_t>;
99
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800100 class ClassDescriptorHashEquals {
101 public:
102 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800103 uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800104 // Same class loader and descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800105 bool operator()(const TableSlot& a, const TableSlot& b) const
Mathieu Chartier6beced42016-11-15 15:51:31 -0800106 NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800107 // Same descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800108 bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800109 NO_THREAD_SAFETY_ANALYSIS;
110 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800111 uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800112 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800113
114 class TableSlotEmptyFn {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800115 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800116 void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
117 item = TableSlot();
118 DCHECK(IsEmpty(item));
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800119 }
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800120 bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800121 return item.IsNull();
122 }
123 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800124
125 // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
126 // should be compared for a matching class descriptor and class loader.
127 typedef HashSet<TableSlot,
128 TableSlotEmptyFn,
129 ClassDescriptorHashEquals,
130 ClassDescriptorHashEquals,
131 TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800132
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700133 ClassTable();
134
135 // Used by image writer for checking.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700136 bool Contains(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700137 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700138 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700139
140 // Freeze the current class tables by allocating a new table and never updating or modifying the
141 // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
142 void FreezeSnapshot()
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700143 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700144 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700145
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000146 // Returns the number of classes in previous snapshots defined by `defining_loader`.
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000147 size_t NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
148 REQUIRES(!lock_)
149 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700150
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000151 // Returns all off the classes in the lastest snapshot defined by `defining_loader`.
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000152 size_t NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
153 REQUIRES(!lock_)
154 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700155
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000156 // Returns the number of classes in previous snapshots no matter the defining loader.
157 size_t NumReferencedZygoteClasses() const
158 REQUIRES(!lock_)
159 REQUIRES_SHARED(Locks::mutator_lock_);
160
161 // Returns all off the classes in the lastest snapshot no matter the defining loader.
162 size_t NumReferencedNonZygoteClasses() const
163 REQUIRES(!lock_)
164 REQUIRES_SHARED(Locks::mutator_lock_);
165
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700166 // Update a class in the table with the new class. Returns the existing class which was replaced.
167 mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700168 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700169 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700170
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700171 // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
172 template<class Visitor>
173 void VisitRoots(Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700174 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700175 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700176 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700177
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700178 template<class Visitor>
179 void VisitRoots(const Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700180 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700181 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700182 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700183
Mathieu Chartier1aa8ec22016-02-01 10:34:47 -0800184 // Stops visit if the visitor returns false.
185 template <typename Visitor>
186 bool Visit(Visitor& visitor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700187 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700188 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierdb70ce52016-12-12 11:06:59 -0800189 template <typename Visitor>
190 bool Visit(const Visitor& visitor)
191 REQUIRES(!lock_)
192 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700193
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800194 // Return the first class that matches the descriptor. Returns null if there are none.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700195 mirror::Class* Lookup(const char* descriptor, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700196 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700197 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700198
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800199 // Return the first class that matches the descriptor of klass. Returns null if there are none.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700200 mirror::Class* LookupByDescriptor(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700201 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700202 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800203
Vladimir Markocd556b02017-02-03 11:47:34 +0000204 // Try to insert a class and return the inserted class if successful. If another class
205 // with the same descriptor is already in the table, return the existing entry.
206 ObjPtr<mirror::Class> TryInsert(ObjPtr<mirror::Class> klass)
207 REQUIRES(!lock_)
208 REQUIRES_SHARED(Locks::mutator_lock_);
209
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700210 void Insert(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700211 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700212 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700213
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700214 void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700215 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700216 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700217
218 // Returns true if the class was found and removed, false otherwise.
219 bool Remove(const char* descriptor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700220 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700221 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier00310e02015-10-17 12:46:42 -0700222
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700223 // Return true if we inserted the strong root, false if it already exists.
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700224 bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700225 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700226 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700227
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000228 // Return true if we inserted the oat file, false if it already exists.
229 bool InsertOatFile(const OatFile* oat_file)
230 REQUIRES(!lock_)
231 REQUIRES_SHARED(Locks::mutator_lock_);
232
Mathieu Chartier41dc8ce2015-12-04 15:07:48 -0800233 // Combines all of the tables into one class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800234 size_t WriteToMemory(uint8_t* ptr) const
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700235 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700236 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800237
238 // Read a table from ptr and put it at the front of the class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800239 size_t ReadFromMemory(uint8_t* ptr)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700240 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700241 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800242
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800243 // Add a class set to the front of classes.
244 void AddClassSet(ClassSet&& set)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700245 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700246 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700247
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700248 // Clear strong roots (other than classes themselves).
249 void ClearStrongRoots()
250 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700251 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700252
Mathieu Chartier92091bd2016-05-10 18:13:20 -0700253 ReaderWriterMutex& GetLock() {
254 return lock_;
255 }
256
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800257 private:
Mathieu Chartier8c19d242017-03-06 12:35:10 -0800258 // Only copies classes.
Vladimir Marko6ad2f6d2017-01-18 15:22:59 +0000259 void CopyWithoutLocks(const ClassTable& source_table) NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700260 void InsertWithoutLocks(ObjPtr<mirror::Class> klass) NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier496577f2016-09-20 15:33:31 -0700261
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000262 size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
263 const ClassSet& set) const
264 REQUIRES(lock_)
265 REQUIRES_SHARED(Locks::mutator_lock_);
266
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000267 // Return true if we inserted the oat file, false if it already exists.
268 bool InsertOatFileLocked(const OatFile* oat_file)
269 REQUIRES(lock_)
270 REQUIRES_SHARED(Locks::mutator_lock_);
271
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700272 // Lock to guard inserting and removing.
273 mutable ReaderWriterMutex lock_;
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700274 // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700275 std::vector<ClassSet> classes_ GUARDED_BY(lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700276 // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
277 // loader which may not be owned by the class loader must be held strongly live. Also dex caches
278 // are held live to prevent them being unloading once they have classes in them.
279 std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
Vladimir Markoaad75c62016-10-03 08:46:48 +0000280 // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
281 std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);
Mathieu Chartier496577f2016-09-20 15:33:31 -0700282
283 friend class ImageWriter; // for InsertWithoutLocks.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700284};
285
286} // namespace art
287
288#endif // ART_RUNTIME_CLASS_TABLE_H_