Preallocate `CodeInfoTableDeduper::dedupe_set_`.

Preallocate large buffer except for multi-image compilation
which requires multiple dedupe sets, so we let them grow as
needed without wasting too much memory. We do not expect to
use multi-image compilation on user devices.

Also remove the hash from the dedupe set entry. With the
large pre-allocated buffer, we have very few hash conflicts
and comparing the hash just slows down finding identical
entries. If we exceed the pre-allocated buffer, this shall
trade some performance for lower memory use.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Change-Id: Ibbb98b6d3ebbc35ffa75165baad54f4df7c62ad9
diff --git a/compiler/utils/dedupe_set-inl.h b/compiler/utils/dedupe_set-inl.h
index 4e892f2..d4a9cc8 100644
--- a/compiler/utils/dedupe_set-inl.h
+++ b/compiler/utils/dedupe_set-inl.h
@@ -81,6 +81,11 @@
     return store_key;
   }
 
+  size_t Size(Thread* self) {
+    MutexLock lock(self, lock_);
+    return keys_.size();
+  }
+
   void UpdateStats(Thread* self, Stats* global_stats) REQUIRES(!lock_) {
     // HashSet<> doesn't keep entries ordered by hash, so we actually allocate memory
     // for bookkeeping while collecting the stats.
@@ -234,6 +239,20 @@
           typename HashType,
           typename HashFunc,
           HashType kShard>
+size_t DedupeSet<InKey, StoreKey, Alloc, HashType, HashFunc, kShard>::Size(Thread* self) const {
+  size_t result = 0u;
+  for (const auto& shard : shards_) {
+    result += shard->Size(self);
+  }
+  return result;
+}
+
+template <typename InKey,
+          typename StoreKey,
+          typename Alloc,
+          typename HashType,
+          typename HashFunc,
+          HashType kShard>
 std::string DedupeSet<InKey, StoreKey, Alloc, HashType, HashFunc, kShard>::DumpStats(
     Thread* self) const {
   Stats stats;