class_table-inl.h revision ab2ce84d4995f05c38c5ebfefc6683b244a36260
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 25namespace art { 26 27template<class Visitor> 28void 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 45template<class Visitor> 46void 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 63template <typename Visitor, ReadBarrierOption kReadBarrierOption> 64bool 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 76template <typename Visitor, ReadBarrierOption kReadBarrierOption> 77bool 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 89template<ReadBarrierOption kReadBarrierOption> 90inline 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 103template<typename Visitor> 104inline 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 117inline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) { 118 return reinterpret_cast<mirror::Class*>(data & ~kHashMask); 119} 120 121inline 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 126inline 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 135template <typename Filter> 136inline 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