diff options
Diffstat (limited to 'runtime/class_table-inl.h')
-rw-r--r-- | runtime/class_table-inl.h | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h index 3e54a647dc..229cd477dd 100644 --- a/runtime/class_table-inl.h +++ b/runtime/class_table-inl.h @@ -26,8 +26,8 @@ template<class Visitor> void ClassTable::VisitRoots(Visitor& visitor) { ReaderMutexLock mu(Thread::Current(), lock_); for (ClassSet& class_set : classes_) { - for (GcRoot<mirror::Class>& root : class_set) { - visitor.VisitRoot(root.AddressWithoutBarrier()); + for (TableSlot& table_slot : class_set) { + table_slot.VisitRoot(visitor); } } for (GcRoot<mirror::Object>& root : strong_roots_) { @@ -44,8 +44,8 @@ template<class Visitor> void ClassTable::VisitRoots(const Visitor& visitor) { ReaderMutexLock mu(Thread::Current(), lock_); for (ClassSet& class_set : classes_) { - for (GcRoot<mirror::Class>& root : class_set) { - visitor.VisitRoot(root.AddressWithoutBarrier()); + for (TableSlot& table_slot : class_set) { + table_slot.VisitRoot(visitor); } } for (GcRoot<mirror::Object>& root : strong_roots_) { @@ -62,8 +62,8 @@ template <typename Visitor> bool ClassTable::Visit(Visitor& visitor) { ReaderMutexLock mu(Thread::Current(), lock_); for (ClassSet& class_set : classes_) { - for (GcRoot<mirror::Class>& root : class_set) { - if (!visitor(root.Read())) { + for (TableSlot& table_slot : class_set) { + if (!visitor(table_slot.Read())) { return false; } } @@ -71,6 +71,51 @@ bool ClassTable::Visit(Visitor& visitor) { return true; } +template<ReadBarrierOption kReadBarrierOption> +inline mirror::Class* ClassTable::TableSlot::Read() const { + const uint32_t before = data_.LoadRelaxed(); + ObjPtr<mirror::Class> const before_ptr(ExtractPtr(before)); + ObjPtr<mirror::Class> const after_ptr( + GcRoot<mirror::Class>(before_ptr).Read<kReadBarrierOption>()); + if (kReadBarrierOption != kWithoutReadBarrier && before_ptr != after_ptr) { + // If another thread raced and updated the reference, do not store the read barrier updated + // one. + data_.CompareExchangeStrongRelaxed(before, Encode(after_ptr, MaskHash(before))); + } + return after_ptr.Ptr(); +} + +template<typename Visitor> +inline void ClassTable::TableSlot::VisitRoot(const Visitor& visitor) const { + const uint32_t before = data_.LoadRelaxed(); + ObjPtr<mirror::Class> before_ptr(ExtractPtr(before)); + GcRoot<mirror::Class> root(before_ptr); + visitor.VisitRoot(root.AddressWithoutBarrier()); + ObjPtr<mirror::Class> after_ptr(root.Read<kWithoutReadBarrier>()); + if (before_ptr != after_ptr) { + // If another thread raced and updated the reference, do not store the read barrier updated + // one. + data_.CompareExchangeStrongRelaxed(before, Encode(after_ptr, MaskHash(before))); + } +} + +inline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) { + return reinterpret_cast<mirror::Class*>(data & ~kHashMask); +} + +inline uint32_t ClassTable::TableSlot::Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits) { + DCHECK_LE(hash_bits, kHashMask); + return reinterpret_cast<uintptr_t>(klass.Ptr()) | hash_bits; +} + +inline ClassTable::TableSlot::TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash) + : data_(Encode(klass, MaskHash(descriptor_hash))) { + if (kIsDebugBuild) { + std::string temp; + const uint32_t hash = ComputeModifiedUtf8Hash(klass->GetDescriptor(&temp)); + CHECK_EQ(descriptor_hash, hash); + } +} } // namespace art |