Avoid an unnecessary ComputeModifiedUtf8Hash().

The DescriptorHashPair already has the hash as the member
`second`, so avoid recalculating it in release mode.

Also split "HashEquals" classes into separate "Hash" and
"Equals" classes to disambiguate their operators in traces.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 175869411
Change-Id: I87cbe613778c7d310ba5c2bf437729244780472c
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index 65d9768..fc2640c 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -164,7 +164,7 @@
   return false;
 }
 
-uint32_t ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& slot)
+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
@@ -172,8 +172,12 @@
   return ComputeModifiedUtf8Hash(slot.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
 }
 
-bool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
-                                                       const TableSlot& b) const {
+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()) {
@@ -187,8 +191,8 @@
       b.Read<kWithoutReadBarrier>()->GetDescriptor(&temp));
 }
 
-bool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
-                                                       const DescriptorHashPair& b) const {
+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)) {
@@ -198,10 +202,6 @@
   return a.Read<kWithoutReadBarrier>()->DescriptorEquals(b.first);
 }
 
-uint32_t ClassTable::ClassDescriptorHashEquals::operator()(const DescriptorHashPair& pair) const {
-  return ComputeModifiedUtf8Hash(pair.first);
-}
-
 bool ClassTable::InsertStrongRoot(ObjPtr<mirror::Object> obj) {
   WriterMutexLock mu(Thread::Current(), lock_);
   DCHECK(obj != nullptr);
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 544a26b..375954a 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -103,18 +103,22 @@
 
   using DescriptorHashPair = std::pair<const char*, uint32_t>;
 
-  class ClassDescriptorHashEquals {
+  class ClassDescriptorHash {
    public:
     // uint32_t for cross compilation.
     uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
+    // uint32_t for cross compilation.
+    uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
+  };
+
+  class ClassDescriptorEquals {
+   public:
     // Same class loader and descriptor.
     bool operator()(const TableSlot& a, const TableSlot& b) const
         NO_THREAD_SAFETY_ANALYSIS;
     // Same descriptor.
     bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
         NO_THREAD_SAFETY_ANALYSIS;
-    // uint32_t for cross compilation.
-    uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
   };
 
   class TableSlotEmptyFn {
@@ -132,8 +136,8 @@
   // should be compared for a matching class descriptor and class loader.
   typedef HashSet<TableSlot,
                   TableSlotEmptyFn,
-                  ClassDescriptorHashEquals,
-                  ClassDescriptorHashEquals,
+                  ClassDescriptorHash,
+                  ClassDescriptorEquals,
                   TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
 
   ClassTable();
diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc
index abcc217..b11de51 100644
--- a/runtime/intern_table.cc
+++ b/runtime/intern_table.cc
@@ -307,7 +307,7 @@
   weak_interns_.SweepWeaks(visitor);
 }
 
-std::size_t InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& root) const {
+std::size_t InternTable::StringHash::operator()(const GcRoot<mirror::String>& root) const {
   if (kIsDebugBuild) {
     Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
   }
@@ -316,16 +316,16 @@
       static_cast<uint32_t>(root.Read<kWithoutReadBarrier>()->GetHashCode()));
 }
 
-bool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
-                                               const GcRoot<mirror::String>& b) const {
+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::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
-                                               const Utf8String& b) const {
+bool InternTable::StringEquals::operator()(const GcRoot<mirror::String>& a,
+                                           const Utf8String& b) const {
   if (kIsDebugBuild) {
     Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
   }
diff --git a/runtime/intern_table.h b/runtime/intern_table.h
index 5ed6aac..db6016e 100644
--- a/runtime/intern_table.h
+++ b/runtime/intern_table.h
@@ -72,18 +72,23 @@
     const char* utf8_data_;
   };
 
-  class StringHashEquals {
+  class StringHash {
    public:
     std::size_t operator()(const GcRoot<mirror::String>& root) const NO_THREAD_SAFETY_ANALYSIS;
-    bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
-        NO_THREAD_SAFETY_ANALYSIS;
 
     // Utf8String can be used for lookup.
     std::size_t operator()(const Utf8String& key) const {
       // A cast to prevent undesired sign extension.
       return static_cast<uint32_t>(key.GetHash());
     }
+  };
 
+  class StringEquals {
+   public:
+    bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
+        NO_THREAD_SAFETY_ANALYSIS;
+
+    // Utf8String can be used for lookup.
     bool operator()(const GcRoot<mirror::String>& a, const Utf8String& b) const
         NO_THREAD_SAFETY_ANALYSIS;
   };
@@ -100,8 +105,8 @@
 
   using UnorderedSet = HashSet<GcRoot<mirror::String>,
                                GcRootEmptyFn,
-                               StringHashEquals,
-                               StringHashEquals,
+                               StringHash,
+                               StringEquals,
                                TrackingAllocator<GcRoot<mirror::String>, kAllocatorTagInternTable>>;
 
   InternTable();