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