Skip to content

Commit 2e19760

Browse files
committed
lldb: Cache string hash during ConstString pool queries/insertions
lldb was rehashing the string 3 times (once to determine which StringMap to use, once to query the StringMap, once to insert) on insertion (twice on successful lookup). This patch allows the lldb to benefit from hash improvements in LLVM (from djbHash to xxh3). Though further changes would be needed to cache this value to disk - we shouldn't rely on the StringMap::hash remaining the same in the future/this value should not be serialized to disk. If we want cache this value StringMap should take a hashing template parameter to allow for a fixed hash to be requested.
1 parent 67c631d commit 2e19760

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

lldb/source/Utility/ConstString.cpp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ class Pool {
7777
return 0;
7878
}
7979

80-
StringPoolValueType GetMangledCounterpart(const char *ccstr) const {
80+
StringPoolValueType GetMangledCounterpart(const char *ccstr) {
8181
if (ccstr != nullptr) {
82-
const uint8_t h = hash(llvm::StringRef(ccstr));
83-
llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
82+
const PoolEntry &pool = selectPool(llvm::StringRef(ccstr));
83+
llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex);
8484
return GetStringMapEntryFromKeyData(ccstr).getValue();
8585
}
8686
return nullptr;
@@ -100,19 +100,20 @@ class Pool {
100100

101101
const char *GetConstCStringWithStringRef(llvm::StringRef string_ref) {
102102
if (string_ref.data()) {
103-
const uint8_t h = hash(string_ref);
103+
const uint32_t string_hash = StringPool::hash(string_ref);
104+
PoolEntry &pool = selectPool(string_hash);
104105

105106
{
106-
llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
107-
auto it = m_string_pools[h].m_string_map.find(string_ref);
108-
if (it != m_string_pools[h].m_string_map.end())
107+
llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex);
108+
auto it = pool.m_string_map.find(string_ref, string_hash);
109+
if (it != pool.m_string_map.end())
109110
return it->getKeyData();
110111
}
111112

112-
llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
113+
llvm::sys::SmartScopedWriter<false> wlock(pool.m_mutex);
113114
StringPoolEntryType &entry =
114-
*m_string_pools[h]
115-
.m_string_map.insert(std::make_pair(string_ref, nullptr))
115+
*pool.m_string_map
116+
.insert(std::make_pair(string_ref, nullptr), string_hash)
116117
.first;
117118
return entry.getKeyData();
118119
}
@@ -125,12 +126,14 @@ class Pool {
125126
const char *demangled_ccstr = nullptr;
126127

127128
{
128-
const uint8_t h = hash(demangled);
129-
llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
129+
const uint32_t demangled_hash = StringPool::hash(demangled);
130+
PoolEntry &pool = selectPool(demangled_hash);
131+
llvm::sys::SmartScopedWriter<false> wlock(pool.m_mutex);
130132

131133
// Make or update string pool entry with the mangled counterpart
132-
StringPool &map = m_string_pools[h].m_string_map;
133-
StringPoolEntryType &entry = *map.try_emplace(demangled).first;
134+
StringPool &map = pool.m_string_map;
135+
StringPoolEntryType &entry =
136+
*map.try_emplace_with_hash(demangled, demangled_hash).first;
134137

135138
entry.second = mangled_ccstr;
136139

@@ -141,8 +144,8 @@ class Pool {
141144
{
142145
// Now assign the demangled const string as the counterpart of the
143146
// mangled const string...
144-
const uint8_t h = hash(llvm::StringRef(mangled_ccstr));
145-
llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
147+
PoolEntry &pool = selectPool(llvm::StringRef(mangled_ccstr));
148+
llvm::sys::SmartScopedWriter<false> wlock(pool.m_mutex);
146149
GetStringMapEntryFromKeyData(mangled_ccstr).setValue(demangled_ccstr);
147150
}
148151

@@ -171,17 +174,20 @@ class Pool {
171174
}
172175

173176
protected:
174-
uint8_t hash(llvm::StringRef s) const {
175-
uint32_t h = llvm::djbHash(s);
176-
return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
177-
}
178-
179177
struct PoolEntry {
180178
mutable llvm::sys::SmartRWMutex<false> m_mutex;
181179
StringPool m_string_map;
182180
};
183181

184182
std::array<PoolEntry, 256> m_string_pools;
183+
184+
PoolEntry &selectPool(const llvm::StringRef &s) {
185+
return selectPool(StringPool::hash(s));
186+
}
187+
188+
PoolEntry &selectPool(uint32_t h) {
189+
return m_string_pools[((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff];
190+
}
185191
};
186192

187193
// Frameworks and dylibs aren't supposed to have global C++ initializers so we
@@ -197,7 +203,7 @@ static Pool &StringPool() {
197203
static Pool *g_string_pool = nullptr;
198204

199205
llvm::call_once(g_pool_initialization_flag,
200-
[]() { g_string_pool = new Pool(); });
206+
[]() { g_string_pool = new Pool(); });
201207

202208
return *g_string_pool;
203209
}

0 commit comments

Comments
 (0)