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 23namespace art { 24 25template<class Visitor> 26void 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 43template<class Visitor> 44void 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 61template <typename Visitor> 62bool 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 74template <typename Visitor> 75bool 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 87template<ReadBarrierOption kReadBarrierOption> 88inline 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 101template<typename Visitor> 102inline 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 115inline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) { 116 return reinterpret_cast<mirror::Class*>(data & ~kHashMask); 117} 118 119inline 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 124inline 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