summaryrefslogtreecommitdiff
path: root/runtime/class_table-inl.h
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2016-12-01 14:21:11 -0800
committer Mathieu Chartier <mathieuc@google.com> 2016-12-06 11:01:52 -0800
commit58c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77 (patch)
tree18788ed5f6ffb44679acaee8faff9a5caf237f13 /runtime/class_table-inl.h
parente4cdd4dbcbc75e373917d22214cd431643cd3610 (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.h57
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