diff options
author | 2021-02-23 18:13:47 +0000 | |
---|---|---|
committer | 2021-03-04 11:30:53 +0000 | |
commit | 4e7b3c78854d9639758e2519ae29f86a6799857b (patch) | |
tree | 287f5211900b53e22f64f3364bd3cc44ce78e87a | |
parent | 18839fe532ceae55e5cb6ae98b5aecb4217623fa (diff) |
Make some hash/equals operators inline.
Namely class descriptor hash/equals in ClassTable and
string hash/equals in InternTable.
This should reduce reliance on ThinLTO for performance.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 179799979
Bug: 179837605
Change-Id: Ie513b2312d30e1b52efefd705a26d13035789e4a
-rw-r--r-- | runtime/class_table-inl.h | 39 | ||||
-rw-r--r-- | runtime/class_table.cc | 38 | ||||
-rw-r--r-- | runtime/gc/space/image_space_test.cc | 2 | ||||
-rw-r--r-- | runtime/intern_table-inl.h | 51 | ||||
-rw-r--r-- | runtime/intern_table.cc | 52 | ||||
-rw-r--r-- | runtime/intern_table_test.cc | 2 |
6 files changed, 94 insertions, 90 deletions
diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h index d043af36fe..3645b647c4 100644 --- a/runtime/class_table-inl.h +++ b/runtime/class_table-inl.h @@ -20,6 +20,7 @@ #include "class_table.h" #include "base/mutex-inl.h" +#include "dex/utf.h" #include "gc_root-inl.h" #include "mirror/class.h" #include "oat_file.h" @@ -27,6 +28,44 @@ namespace art { +inline uint32_t ClassTable::ClassDescriptorHash::operator()(const TableSlot& slot) const { + std::string temp; + // No read barrier needed, we're reading a chain of constant references for comparison + // with null and retrieval of constant primitive data. See ReadBarrierOption. + return ComputeModifiedUtf8Hash(slot.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)); +} + +inline uint32_t ClassTable::ClassDescriptorHash::operator()(const DescriptorHashPair& pair) const { + DCHECK_EQ(ComputeModifiedUtf8Hash(pair.first), pair.second); + return pair.second; +} + +inline bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a, + const TableSlot& b) const { + // No read barrier needed, we're reading a chain of constant references for comparison + // with null and retrieval of constant primitive data. See ReadBarrierOption. + if (a.Hash() != b.Hash()) { + std::string temp; + DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals( + b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp))); + return false; + } + std::string temp; + return a.Read<kWithoutReadBarrier>()->DescriptorEquals( + b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)); +} + +inline bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a, + const DescriptorHashPair& b) const { + // No read barrier needed, we're reading a chain of constant references for comparison + // with null and retrieval of constant primitive data. See ReadBarrierOption. + if (!a.MaskedHashEquals(b.second)) { + DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first)); + return false; + } + return a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first); +} + template<class Visitor> void ClassTable::VisitRoots(Visitor& visitor) { ReaderMutexLock mu(Thread::Current(), lock_); diff --git a/runtime/class_table.cc b/runtime/class_table.cc index fc2640c2cc..288e312bb1 100644 --- a/runtime/class_table.cc +++ b/runtime/class_table.cc @@ -164,44 +164,6 @@ bool ClassTable::Remove(const char* descriptor) { return false; } -uint32_t ClassTable::ClassDescriptorHash::operator()(const TableSlot& slot) - const { - std::string temp; - // No read barrier needed, we're reading a chain of constant references for comparison - // with null and retrieval of constant primitive data. See ReadBarrierOption. - return ComputeModifiedUtf8Hash(slot.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)); -} - -uint32_t ClassTable::ClassDescriptorHash::operator()(const DescriptorHashPair& pair) const { - DCHECK_EQ(ComputeModifiedUtf8Hash(pair.first), pair.second); - return pair.second; -} - -bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a, const TableSlot& b) const { - // No read barrier needed, we're reading a chain of constant references for comparison - // with null and retrieval of constant primitive data. See ReadBarrierOption. - if (a.Hash() != b.Hash()) { - std::string temp; - DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals( - b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp))); - return false; - } - std::string temp; - return a.Read<kWithoutReadBarrier>()->DescriptorEquals( - b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp)); -} - -bool ClassTable::ClassDescriptorEquals::operator()(const TableSlot& a, - const DescriptorHashPair& b) const { - // No read barrier needed, we're reading a chain of constant references for comparison - // with null and retrieval of constant primitive data. See ReadBarrierOption. - if (!a.MaskedHashEquals(b.second)) { - DCHECK(!a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first)); - return false; - } - return a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first); -} - bool ClassTable::InsertStrongRoot(ObjPtr<mirror::Object> obj) { WriterMutexLock mu(Thread::Current(), lock_); DCHECK(obj != nullptr); diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc index 6208a73357..0b22a6f83f 100644 --- a/runtime/gc/space/image_space_test.cc +++ b/runtime/gc/space/image_space_test.cc @@ -24,7 +24,7 @@ #include "class_linker.h" #include "dexopt_test.h" #include "dex/utf.h" -#include "intern_table.h" +#include "intern_table-inl.h" #include "noop_compiler_callbacks.h" #include "oat_file.h" diff --git a/runtime/intern_table-inl.h b/runtime/intern_table-inl.h index 687f5ee6ba..44bdb1fe19 100644 --- a/runtime/intern_table-inl.h +++ b/runtime/intern_table-inl.h @@ -19,12 +19,61 @@ #include "intern_table.h" +#include "dex/utf.h" #include "gc/space/image_space.h" +#include "gc_root-inl.h" #include "image.h" -#include "mirror/string-inl.h" // Required for ToModifiedUtf8 below. +#include "mirror/string-inl.h" +#include "thread-current-inl.h" namespace art { +inline std::size_t InternTable::StringHash::operator()(const GcRoot<mirror::String>& root) const { + if (kIsDebugBuild) { + Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + } + // An additional cast to prevent undesired sign extension. + return static_cast<size_t>( + static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode())); +} + +inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a, + const GcRoot<mirror::String>& b) const { + if (kIsDebugBuild) { + Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + } + return a.Read<kWithoutReadBarrier>()->Equals(b.Read<kWithoutReadBarrier>()); +} + +inline bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a, + const Utf8String& b) const { + if (kIsDebugBuild) { + Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); + } + ObjPtr<mirror::String> a_string = a.Read<kWithoutReadBarrier>(); + uint32_t a_length = static_cast<uint32_t>(a_string->GetLength()); + if (a_length != b.GetUtf16Length()) { + return false; + } + if (a_string->IsCompressed()) { + size_t b_byte_count = strlen(b.GetUtf8Data()); + size_t b_utf8_length = CountModifiedUtf8Chars(b.GetUtf8Data(), b_byte_count); + // Modified UTF-8 single byte character range is 0x01 .. 0x7f + // The string compression occurs on regular ASCII with same exact range, + // not on extended ASCII which up to 0xff + const bool is_b_regular_ascii = (b_byte_count == b_utf8_length); + if (is_b_regular_ascii) { + return memcmp(b.GetUtf8Data(), + a_string->GetValueCompressed(), a_length * sizeof(uint8_t)) == 0; + } else { + return false; + } + } else { + const uint16_t* a_value = a_string->GetValue(); + return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0; + } +} + template <typename Visitor> inline void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space, const Visitor& visitor) { diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index b11de51eb4..6af04550a4 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "intern_table.h" +#include "intern_table-inl.h" #include <memory> @@ -100,8 +100,8 @@ ObjPtr<mirror::String> InternTable::LookupStrong(Thread* self, ObjPtr<mirror::St } ObjPtr<mirror::String> InternTable::LookupStrong(Thread* self, - uint32_t utf16_length, - const char* utf8_data) { + uint32_t utf16_length, + const char* utf8_data) { DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data)); Utf8String string(utf16_length, utf8_data, @@ -307,52 +307,6 @@ void InternTable::SweepInternTableWeaks(IsMarkedVisitor* visitor) { weak_interns_.SweepWeaks(visitor); } -std::size_t InternTable::StringHash::operator()(const GcRoot<mirror::String>& root) const { - if (kIsDebugBuild) { - Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); - } - // An additional cast to prevent undesired sign extension. - return static_cast<size_t>( - static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode())); -} - -bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a, - const GcRoot<mirror::String>& b) const { - if (kIsDebugBuild) { - Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); - } - return a.Read<kWithoutReadBarrier>()->Equals(b.Read<kWithoutReadBarrier>()); -} - -bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a, - const Utf8String& b) const { - if (kIsDebugBuild) { - Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); - } - ObjPtr<mirror::String> a_string = a.Read<kWithoutReadBarrier>(); - uint32_t a_length = static_cast<uint32_t>(a_string->GetLength()); - if (a_length != b.GetUtf16Length()) { - return false; - } - if (a_string->IsCompressed()) { - size_t b_byte_count = strlen(b.GetUtf8Data()); - size_t b_utf8_length = CountModifiedUtf8Chars(b.GetUtf8Data(), b_byte_count); - // Modified UTF-8 single byte character range is 0x01 .. 0x7f - // The string compression occurs on regular ASCII with same exact range, - // not on extended ASCII which up to 0xff - const bool is_b_regular_ascii = (b_byte_count == b_utf8_length); - if (is_b_regular_ascii) { - return memcmp(b.GetUtf8Data(), - a_string->GetValueCompressed(), a_length * sizeof(uint8_t)) == 0; - } else { - return false; - } - } else { - const uint16_t* a_value = a_string->GetValue(); - return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0; - } -} - void InternTable::Table::Remove(ObjPtr<mirror::String> s) { for (InternalTable& table : tables_) { auto it = table.set_.find(GcRoot<mirror::String>(s)); diff --git a/runtime/intern_table_test.cc b/runtime/intern_table_test.cc index b64ca7dafb..e4eed55c09 100644 --- a/runtime/intern_table_test.cc +++ b/runtime/intern_table_test.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "intern_table.h" +#include "intern_table-inl.h" #include "base/hash_set.h" #include "common_runtime_test.h" |