Skip to content

Commit f6b3875

Browse files
committed
Reapply "lldb: Cache string hash during ConstString pool queries/insertions"
Reverted due to an internally discovered lld crash due to the underlying StringMap changes, which turned out to be an existing lld bug that got tickled by the StringMap changes. That's addressed in dee8786 so let's have another go with this change. Original commit message: 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. This reverts commit 5bc1adf. Effectively reapplying the original 2e19760.
1 parent 9a4a4c3 commit f6b3875

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
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
}

llvm/lib/Support/StringMap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ int StringMapImpl::FindKey(StringRef Key, uint32_t FullHashValue) const {
148148
if (NumBuckets == 0)
149149
return -1; // Really empty table?
150150
#ifdef EXPENSIVE_CHECKS
151-
assert(FullHashValue == hash(Key);
151+
assert(FullHashValue == hash(Key));
152152
#endif
153153
if (shouldReverseIterate())
154154
FullHashValue = ~FullHashValue;

0 commit comments

Comments
 (0)