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_INL_H_
18 #define ART_RUNTIME_CLASS_TABLE_INL_H_
19 
20 #include "class_table.h"
21 #include "oat_file.h"
22 
23 namespace art {
24 
25 template<class Visitor>
VisitRoots(Visitor & visitor)26 void ClassTable::VisitRoots(Visitor& visitor) {
27   ReaderMutexLock mu(Thread::Current(), lock_);
28   for (ClassSet& class_set : classes_) {
29     for (TableSlot& table_slot : class_set) {
30       table_slot.VisitRoot(visitor);
31     }
32   }
33   for (GcRoot<mirror::Object>& root : strong_roots_) {
34     visitor.VisitRoot(root.AddressWithoutBarrier());
35   }
36   for (const OatFile* oat_file : oat_files_) {
37     for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
38       visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
39     }
40   }
41 }
42 
43 template<class Visitor>
VisitRoots(const Visitor & visitor)44 void ClassTable::VisitRoots(const Visitor& visitor) {
45   ReaderMutexLock mu(Thread::Current(), lock_);
46   for (ClassSet& class_set : classes_) {
47     for (TableSlot& table_slot : class_set) {
48       table_slot.VisitRoot(visitor);
49     }
50   }
51   for (GcRoot<mirror::Object>& root : strong_roots_) {
52     visitor.VisitRoot(root.AddressWithoutBarrier());
53   }
54   for (const OatFile* oat_file : oat_files_) {
55     for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
56       visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
57     }
58   }
59 }
60 
61 template <typename Visitor>
Visit(Visitor & visitor)62 bool ClassTable::Visit(Visitor& visitor) {
63   ReaderMutexLock mu(Thread::Current(), lock_);
64   for (ClassSet& class_set : classes_) {
65     for (TableSlot& table_slot : class_set) {
66       if (!visitor(table_slot.Read())) {
67         return false;
68       }
69     }
70   }
71   return true;
72 }
73 
74 template <typename Visitor>
Visit(const Visitor & visitor)75 bool ClassTable::Visit(const Visitor& visitor) {
76   ReaderMutexLock mu(Thread::Current(), lock_);
77   for (ClassSet& class_set : classes_) {
78     for (TableSlot& table_slot : class_set) {
79       if (!visitor(table_slot.Read())) {
80         return false;
81       }
82     }
83   }
84   return true;
85 }
86 
87 template<ReadBarrierOption kReadBarrierOption>
Read()88 inline mirror::Class* ClassTable::TableSlot::Read() const {
89   const uint32_t before = data_.LoadRelaxed();
90   ObjPtr<mirror::Class> const before_ptr(ExtractPtr(before));
91   ObjPtr<mirror::Class> const after_ptr(
92       GcRoot<mirror::Class>(before_ptr).Read<kReadBarrierOption>());
93   if (kReadBarrierOption != kWithoutReadBarrier && before_ptr != after_ptr) {
94     // If another thread raced and updated the reference, do not store the read barrier updated
95     // one.
96     data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before)));
97   }
98   return after_ptr.Ptr();
99 }
100 
101 template<typename Visitor>
VisitRoot(const Visitor & visitor)102 inline void ClassTable::TableSlot::VisitRoot(const Visitor& visitor) const {
103   const uint32_t before = data_.LoadRelaxed();
104   ObjPtr<mirror::Class> before_ptr(ExtractPtr(before));
105   GcRoot<mirror::Class> root(before_ptr);
106   visitor.VisitRoot(root.AddressWithoutBarrier());
107   ObjPtr<mirror::Class> after_ptr(root.Read<kWithoutReadBarrier>());
108   if (before_ptr != after_ptr) {
109     // If another thread raced and updated the reference, do not store the read barrier updated
110     // one.
111     data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before)));
112   }
113 }
114 
ExtractPtr(uint32_t data)115 inline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) {
116   return reinterpret_cast<mirror::Class*>(data & ~kHashMask);
117 }
118 
Encode(ObjPtr<mirror::Class> klass,uint32_t hash_bits)119 inline uint32_t ClassTable::TableSlot::Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits) {
120   DCHECK_LE(hash_bits, kHashMask);
121   return reinterpret_cast<uintptr_t>(klass.Ptr()) | hash_bits;
122 }
123 
TableSlot(ObjPtr<mirror::Class> klass,uint32_t descriptor_hash)124 inline ClassTable::TableSlot::TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash)
125     : data_(Encode(klass, MaskHash(descriptor_hash))) {
126   if (kIsDebugBuild) {
127     std::string temp;
128     const uint32_t hash = ComputeModifiedUtf8Hash(klass->GetDescriptor(&temp));
129     CHECK_EQ(descriptor_hash, hash);
130   }
131 }
132 
133 }  // namespace art
134 
135 #endif  // ART_RUNTIME_CLASS_TABLE_INL_H_
136