blob: fe0bbb37264f310d86a510e976c0c4b1b34273e6 [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"
28#include "dex_file.h"
29#include "gc_root.h"
Mathieu Chartierbc5a7952016-10-17 15:46:31 -070030#include "obj_ptr.h"
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070031#include "object_callbacks.h"
32#include "runtime.h"
33
34namespace art {
35
Vladimir Markoaad75c62016-10-03 08:46:48 +000036class OatFile;
37
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070038namespace mirror {
39 class ClassLoader;
40} // namespace mirror
41
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070042// Each loader has a ClassTable
43class ClassTable {
44 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -080045 class TableSlot {
46 public:
47 TableSlot() : data_(0u) {}
48
49 TableSlot(const TableSlot& copy) : data_(copy.data_.LoadRelaxed()) {}
50
51 explicit TableSlot(ObjPtr<mirror::Class> klass);
52
53 TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
54
55 TableSlot& operator=(const TableSlot& copy) {
56 data_.StoreRelaxed(copy.data_.LoadRelaxed());
57 return *this;
58 }
59
60 bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
61 return Read<kWithoutReadBarrier>() == nullptr;
62 }
63
64 uint32_t Hash() const {
65 return MaskHash(data_.LoadRelaxed());
66 }
67
68 static uint32_t MaskHash(uint32_t hash) {
69 return hash & kHashMask;
70 }
71
72 bool MaskedHashEquals(uint32_t other) const {
73 return MaskHash(other) == Hash();
74 }
75
76 template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
77 mirror::Class* Read() const REQUIRES_SHARED(Locks::mutator_lock_);
78
79 // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
80 template<typename Visitor>
81 void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;
82
83 private:
84 // Extract a raw pointer from an address.
85 static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
86 REQUIRES_SHARED(Locks::mutator_lock_);
87
88 static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
89 REQUIRES_SHARED(Locks::mutator_lock_);
90
91 // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
92 mutable Atomic<uint32_t> data_;
93 static const uint32_t kHashMask = kObjectAlignment - 1;
94 };
95
96 using DescriptorHashPair = std::pair<const char*, uint32_t>;
97
Mathieu Chartier88027bd2016-03-02 16:08:31 -080098 class ClassDescriptorHashEquals {
99 public:
100 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800101 uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800102 // Same class loader and descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800103 bool operator()(const TableSlot& a, const TableSlot& b) const
Mathieu Chartier6beced42016-11-15 15:51:31 -0800104 NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800105 // Same descriptor.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800106 bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800107 NO_THREAD_SAFETY_ANALYSIS;
108 // uint32_t for cross compilation.
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800109 uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800110 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800111
112 class TableSlotEmptyFn {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800113 public:
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800114 void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
115 item = TableSlot();
116 DCHECK(IsEmpty(item));
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800117 }
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800118 bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800119 return item.IsNull();
120 }
121 };
Mathieu Chartier58c3f6a2016-12-01 14:21:11 -0800122
123 // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
124 // should be compared for a matching class descriptor and class loader.
125 typedef HashSet<TableSlot,
126 TableSlotEmptyFn,
127 ClassDescriptorHashEquals,
128 ClassDescriptorHashEquals,
129 TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800130
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700131 ClassTable();
132
133 // Used by image writer for checking.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700134 bool Contains(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700135 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700136 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700137
138 // Freeze the current class tables by allocating a new table and never updating or modifying the
139 // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
140 void FreezeSnapshot()
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700141 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700142 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700143
144 // Returns the number of classes in previous snapshots.
Vladimir Marko2c8c6b62016-12-01 17:42:00 +0000145 size_t NumZygoteClasses() const REQUIRES(!lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700146
147 // Returns all off the classes in the lastest snapshot.
Vladimir Marko2c8c6b62016-12-01 17:42:00 +0000148 size_t NumNonZygoteClasses() const REQUIRES(!lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700149
150 // Update a class in the table with the new class. Returns the existing class which was replaced.
151 mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700152 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700153 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700154
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700155 // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
156 template<class Visitor>
157 void VisitRoots(Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700158 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700159 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700160 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700161
Mathieu Chartiere4275c02015-08-06 15:34:15 -0700162 template<class Visitor>
163 void VisitRoots(const Visitor& visitor)
Mathieu Chartier00310e02015-10-17 12:46:42 -0700164 NO_THREAD_SAFETY_ANALYSIS
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700165 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700166 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700167
Mathieu Chartier1aa8ec22016-02-01 10:34:47 -0800168 // Stops visit if the visitor returns false.
169 template <typename Visitor>
170 bool Visit(Visitor& visitor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700171 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700172 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700173
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800174 // Return the first class that matches the descriptor. Returns null if there are none.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700175 mirror::Class* Lookup(const char* descriptor, 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 Chartierfbc31082016-01-24 11:59:56 -0800179 // Return the first class that matches the descriptor of klass. Returns null if there are none.
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700180 mirror::Class* LookupByDescriptor(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700181 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700182 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800183
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700184 void Insert(ObjPtr<mirror::Class> klass)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700185 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700186 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700187
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700188 void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
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
192 // Returns true if the class was found and removed, false otherwise.
193 bool Remove(const char* descriptor)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700194 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700195 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier00310e02015-10-17 12:46:42 -0700196
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700197 // Return true if we inserted the strong root, false if it already exists.
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700198 bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700199 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700200 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700201
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000202 // Return true if we inserted the oat file, false if it already exists.
203 bool InsertOatFile(const OatFile* oat_file)
204 REQUIRES(!lock_)
205 REQUIRES_SHARED(Locks::mutator_lock_);
206
Mathieu Chartier41dc8ce2015-12-04 15:07:48 -0800207 // Combines all of the tables into one class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800208 size_t WriteToMemory(uint8_t* ptr) const
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
212 // Read a table from ptr and put it at the front of the class set.
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800213 size_t ReadFromMemory(uint8_t* ptr)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700214 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700215 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier208a5cb2015-12-02 15:44:07 -0800216
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800217 // Add a class set to the front of classes.
218 void AddClassSet(ClassSet&& set)
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700219 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700220 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700221
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700222 // Clear strong roots (other than classes themselves).
223 void ClearStrongRoots()
224 REQUIRES(!lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700225 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700226
Mathieu Chartier92091bd2016-05-10 18:13:20 -0700227 ReaderWriterMutex& GetLock() {
228 return lock_;
229 }
230
Mathieu Chartier88027bd2016-03-02 16:08:31 -0800231 private:
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700232 void InsertWithoutLocks(ObjPtr<mirror::Class> klass) NO_THREAD_SAFETY_ANALYSIS;
Mathieu Chartier496577f2016-09-20 15:33:31 -0700233
Vladimir Marko1bc4b172016-10-24 16:53:39 +0000234 // Return true if we inserted the oat file, false if it already exists.
235 bool InsertOatFileLocked(const OatFile* oat_file)
236 REQUIRES(lock_)
237 REQUIRES_SHARED(Locks::mutator_lock_);
238
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700239 // Lock to guard inserting and removing.
240 mutable ReaderWriterMutex lock_;
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700241 // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
Mathieu Chartier1609e3a2016-04-05 14:36:57 -0700242 std::vector<ClassSet> classes_ GUARDED_BY(lock_);
Mathieu Chartierc9dbb1d2016-06-03 17:47:32 -0700243 // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
244 // loader which may not be owned by the class loader must be held strongly live. Also dex caches
245 // are held live to prevent them being unloading once they have classes in them.
246 std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
Vladimir Markoaad75c62016-10-03 08:46:48 +0000247 // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
248 std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);
Mathieu Chartier496577f2016-09-20 15:33:31 -0700249
250 friend class ImageWriter; // for InsertWithoutLocks.
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700251};
252
253} // namespace art
254
255#endif // ART_RUNTIME_CLASS_TABLE_H_