diff options
author | 2016-12-01 14:21:11 -0800 | |
---|---|---|
committer | 2016-12-06 11:01:52 -0800 | |
commit | 58c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77 (patch) | |
tree | 18788ed5f6ffb44679acaee8faff9a5caf237f13 /runtime/class_table-inl.h | |
parent | e4cdd4dbcbc75e373917d22214cd431643cd3610 (diff) |
Reduce calls to DescriptorEquals
Store the low 3 bits of the descriptor hash inside of class set
entries. Compare these bits before comparing descriptors.
Simpleperf interpret-only compile of facebook:
mirror::Class::DescriptorEquals(char const*): 3.66% -> 1.03%
Bug: 32641252
Test: test-art-host
Change-Id: I8d898d4ac7c95383c49401fbcd85bfde226e026c
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 |