blob: 19c29b5768f565795980595cd578f5628a2cd8fe [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
Vladimir Marko74527972016-11-29 15:57:32 +000035namespace linker {
36class ImageWriter;
37} // namespace linker
38
39namespace linker {
40class OatWriter;
41} // namespace linker
42
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070043namespace mirror {
Igor Murashkin2ffb7032017-11-08 13:35:21 -080044class Class;
45class ClassLoader;
46class Object;
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070047} // namespace mirror
48
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070049// Each loader has a ClassTable
50class ClassTable {
51 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -080052 class TableSlot {
53 public:
54 TableSlot() : data_(0u) {}
55
56 TableSlot(const TableSlot& copy) : data_(copy.data_.LoadRelaxed()) {}
57
58 explicit TableSlot(ObjPtr<mirror::Class> klass);
59
60 TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
61
62 TableSlot& operator=(const TableSlot& copy) {
63 data_.StoreRelaxed(copy.data_.LoadRelaxed());
64 return *this;
65 }
66
67 bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
68 return Read<kWithoutReadBarrier>() == nullptr;
69 }
70
71 uint32_t Hash() const {
72 return MaskHash(data_.LoadRelaxed());
73 }
74
75 static uint32_t MaskHash(uint32_t hash) {
76 return hash & kHashMask;
77 }
78
79 bool MaskedHashEquals(uint32_t other) const {
80 return MaskHash(other) == Hash();
81 }
82
Mathieu Chartierdb70ce52016-12-12 11:06:59 -080083 static uint32_t HashDescriptor(ObjPtr<mirror::Class> klass)
84 REQUIRES_SHARED(Locks::mutator_lock_);
85
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -080086 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
87 mirror::Class* Read() const REQUIRES_SHARED(Locks::mutator_lock_);
88
89 // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
90 template<typename Visitor>
91 void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;
92
93 private:
94 // Extract a raw pointer from an address.
95 static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
96 REQUIRES_SHARED(Locks::mutator_lock_);
97
98 static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
99 REQUIRES_SHARED(Locks::mutator_lock_);
100
101 // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
102 mutable Atomic<uint32_t> data_;
103 static const uint32_t kHashMask = kObjectAlignment - 1;
104 };
105
106 using DescriptorHashPair = std::pair<const char*, uint32_t>;
107
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800108 class ClassDescriptorHashEquals {
109 public:
110 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800111 uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800112 // Same class loader and descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800113 bool operator()(const TableSlot& a, const TableSlot& b) const
Mathieu Chartier6beced42016-11-15 15:51:31 -0800114 NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800115 // Same descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800116 bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800117 NO_THREAD_SAFETY_ANALYSIS;
118 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800119 uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800120 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800121
122 class TableSlotEmptyFn {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800123 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800124 void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
125 item = TableSlot();
126 DCHECK(IsEmpty(item));
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800127 }
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800128 bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800129 return item.IsNull();
130 }
131 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800132
133 // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
134 // should be compared for a matching class descriptor and class loader.
135 typedef HashSet<TableSlot,
136 TableSlotEmptyFn,
137 ClassDescriptorHashEquals,
138 ClassDescriptorHashEquals,
139 TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800140
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700141 ClassTable();
142
143 // Used by image writer for checking.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700144 bool Contains(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700145 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700146 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700147
148 // Freeze the current class tables by allocating a new table and never updating or modifying the
149 // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
150 void FreezeSnapshot()
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700151 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700152 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700153
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000154 // Returns the number of classes in previous snapshots defined by `defining_loader`.
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000155 size_t NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
156 REQUIRES(!lock_)
157 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700158
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000159 // Returns all off the classes in the lastest snapshot defined by `defining_loader`.
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000160 size_t NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
161 REQUIRES(!lock_)
162 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700163
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000164 // Returns the number of classes in previous snapshots no matter the defining loader.
165 size_t NumReferencedZygoteClasses() const
166 REQUIRES(!lock_)
167 REQUIRES_SHARED(Locks::mutator_lock_);
168
169 // Returns all off the classes in the lastest snapshot no matter the defining loader.
170 size_t NumReferencedNonZygoteClasses() const
171 REQUIRES(!lock_)
172 REQUIRES_SHARED(Locks::mutator_lock_);
173
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700174 // Update a class in the table with the new class. Returns the existing class which was replaced.
175 mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700176 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700177 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700178
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700179 // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
180 template<class Visitor>
181 void VisitRoots(Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700182 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700183 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700184 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700185
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700186 template<class Visitor>
187 void VisitRoots(const Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700188 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700189 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700190 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700191
Mathieu Chartier1aa8ec22016-02-01 10:34:47 -0800192 // Stops visit if the visitor returns false.
Alexey Grebenkinab2ce842018-02-01 19:09:59 +0300193 template <typename Visitor, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
Mathieu Chartier1aa8ec22016-02-01 10:34:47 -0800194 bool Visit(Visitor& visitor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700195 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700196 REQUIRES_SHARED(Locks::mutator_lock_);
Alexey Grebenkinab2ce842018-02-01 19:09:59 +0300197 template <typename Visitor, ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
Mathieu Chartierdb70ce52016-12-12 11:06:59 -0800198 bool Visit(const Visitor& visitor)
199 REQUIRES(!lock_)
200 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700201
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800202 // Return the first class that matches the descriptor. Returns null if there are none.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700203 mirror::Class* Lookup(const char* descriptor, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700204 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700205 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700206
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800207 // Return the first class that matches the descriptor of klass. Returns null if there are none.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700208 mirror::Class* LookupByDescriptor(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700209 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700210 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800211
Vladimir Markocd556b02017-02-03 11:47:34 +0000212 // Try to insert a class and return the inserted class if successful. If another class
213 // with the same descriptor is already in the table, return the existing entry.
214 ObjPtr<mirror::Class> TryInsert(ObjPtr<mirror::Class> klass)
215 REQUIRES(!lock_)
216 REQUIRES_SHARED(Locks::mutator_lock_);
217
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700218 void Insert(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700219 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700220 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700221
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700222 void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700223 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700224 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700225
226 // Returns true if the class was found and removed, false otherwise.
227 bool Remove(const char* descriptor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700228 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700229 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier00310e02015-10-17 12:46:42 -0700230
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700231 // Return true if we inserted the strong root, false if it already exists.
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700232 bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700233 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700234 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700235
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000236 // Return true if we inserted the oat file, false if it already exists.
237 bool InsertOatFile(const OatFile* oat_file)
238 REQUIRES(!lock_)
239 REQUIRES_SHARED(Locks::mutator_lock_);
240
Mathieu Chartier41dc8ce2015-12-04 15:07:48 -0800241 // Combines all of the tables into one class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800242 size_t WriteToMemory(uint8_t* ptr) const
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700243 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700244 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800245
246 // Read a table from ptr and put it at the front of the class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800247 size_t ReadFromMemory(uint8_t* ptr)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700248 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700249 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800250
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800251 // Add a class set to the front of classes.
252 void AddClassSet(ClassSet&& set)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700253 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700254 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700255
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700256 // Clear strong roots (other than classes themselves).
257 void ClearStrongRoots()
258 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700259 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700260
Mathieu Chartier72041a02017-07-14 18:23:25 -0700261 // Filter strong roots (other than classes themselves).
262 template <typename Filter>
263 void RemoveStrongRoots(const Filter& filter)
264 REQUIRES(!lock_)
265 REQUIRES_SHARED(Locks::mutator_lock_);
266
Mathieu Chartier92091bd2016-05-10 18:13:20 -0700267 ReaderWriterMutex& GetLock() {
268 return lock_;
269 }
270
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800271 private:
Mathieu Chartier8c19d242017-03-06 12:35:10 -0800272 // Only copies classes.
Vladimir Marko6ad2f6d2017-01-18 15:22:59 +0000273 void CopyWithoutLocks(const ClassTable& source_table) NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700274 void InsertWithoutLocks(ObjPtr<mirror::Class> klass) NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier496577f2016-09-20 15:33:31 -0700275
Vladimir Markoc5798bf2016-12-09 10:20:54 +0000276 size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
277 const ClassSet& set) const
278 REQUIRES(lock_)
279 REQUIRES_SHARED(Locks::mutator_lock_);
280
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000281 // Return true if we inserted the oat file, false if it already exists.
282 bool InsertOatFileLocked(const OatFile* oat_file)
283 REQUIRES(lock_)
284 REQUIRES_SHARED(Locks::mutator_lock_);
285
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700286 // Lock to guard inserting and removing.
287 mutable ReaderWriterMutex lock_;
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700288 // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700289 std::vector<ClassSet> classes_ GUARDED_BY(lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700290 // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
291 // loader which may not be owned by the class loader must be held strongly live. Also dex caches
292 // are held live to prevent them being unloading once they have classes in them.
293 std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
Vladimir Markoaad75c62016-10-03 08:46:48 +0000294 // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
295 std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);
Mathieu Chartier496577f2016-09-20 15:33:31 -0700296
Vladimir Marko74527972016-11-29 15:57:32 +0000297 friend class linker::ImageWriter; // for InsertWithoutLocks.
298 friend class linker::OatWriter; // for boot class TableSlot address lookup.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700299};
300
301} // namespace art
302
303#endif // ART_RUNTIME_CLASS_TABLE_H_