[llvm] 617b08f - Refactor StringMap.h, splitting StringMapEntry out to its own header.
Chris Lattner via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 12 08:25:26 PDT 2020
Author: Chris Lattner
Date: 2020-04-12T08:25:17-07:00
New Revision: 617b08ff9bef7b17957781682f78155351b0d2e9
URL: https://github.com/llvm/llvm-project/commit/617b08ff9bef7b17957781682f78155351b0d2e9
DIFF: https://github.com/llvm/llvm-project/commit/617b08ff9bef7b17957781682f78155351b0d2e9.diff
LOG: Refactor StringMap.h, splitting StringMapEntry out to its own header.
Summary:
StringMapEntry.h can have lower dependencies, than StringMap.h, which
is useful for public headers that want to expose inline methods on
StringMapEntry<> but don't need to expose all of StringMap.h. One
example of this is mlir's Identifier.h, another example is the existing
LLVM StringPool.h.
StringPool also could use a cleanup, I'll deal with that in a follow-on
patch.
Reviewers: rriddle
Subscribers: hiraditya, dexonsmith, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D77963
Added:
llvm/include/llvm/ADT/StringMapEntry.h
Modified:
llvm/include/llvm/ADT/StringMap.h
llvm/lib/Support/StringMap.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h
index fb15c00576c3..d6cad5feb0e3 100644
--- a/llvm/include/llvm/ADT/StringMap.h
+++ b/llvm/include/llvm/ADT/StringMap.h
@@ -13,8 +13,7 @@
#ifndef LLVM_ADT_STRINGMAP_H
#define LLVM_ADT_STRINGMAP_H
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/AllocatorBase.h"
+#include "llvm/ADT/StringMapEntry.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <initializer_list>
#include <iterator>
@@ -25,16 +24,6 @@ template <typename ValueTy> class StringMapConstIterator;
template <typename ValueTy> class StringMapIterator;
template <typename ValueTy> class StringMapKeyIterator;
-/// StringMapEntryBase - Shared base class of StringMapEntry instances.
-class StringMapEntryBase {
- size_t StrLen;
-
-public:
- explicit StringMapEntryBase(size_t Len) : StrLen(Len) {}
-
- size_t getKeyLength() const { return StrLen; }
-};
-
/// StringMapImpl - This is the base class of StringMap that is shared among
/// all of its instantiations.
class StringMapImpl {
@@ -108,122 +97,6 @@ class StringMapImpl {
}
};
-/// StringMapEntryStorage - Holds the value in a StringMapEntry.
-///
-/// Factored out into a separate base class to make it easier to specialize.
-/// This is primarily intended to support StringSet, which doesn't need a value
-/// stored at all.
-template <typename ValueTy>
-class StringMapEntryStorage : public StringMapEntryBase {
-public:
- ValueTy second;
-
- explicit StringMapEntryStorage(size_t strLen)
- : StringMapEntryBase(strLen), second() {}
- template <typename... InitTy>
- StringMapEntryStorage(size_t strLen, InitTy &&... InitVals)
- : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
- StringMapEntryStorage(StringMapEntryStorage &E) = delete;
-
- const ValueTy &getValue() const { return second; }
- ValueTy &getValue() { return second; }
-
- void setValue(const ValueTy &V) { second = V; }
-};
-
-template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
-public:
- explicit StringMapEntryStorage(size_t strLen, NoneType none = None)
- : StringMapEntryBase(strLen) {}
- StringMapEntryStorage(StringMapEntryStorage &E) = delete;
-
- NoneType getValue() const { return None; }
-};
-
-/// StringMapEntry - This is used to represent one value that is inserted into
-/// a StringMap. It contains the Value itself and the key: the string length
-/// and data.
-template <typename ValueTy>
-class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
-public:
- using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
-
- StringRef getKey() const {
- return StringRef(getKeyData(), this->getKeyLength());
- }
-
- /// getKeyData - Return the start of the string data that is the key for this
- /// value. The string data is always stored immediately after the
- /// StringMapEntry object.
- const char *getKeyData() const {
- return reinterpret_cast<const char *>(this + 1);
- }
-
- StringRef first() const {
- return StringRef(getKeyData(), this->getKeyLength());
- }
-
- /// Create a StringMapEntry for the specified key construct the value using
- /// \p InitiVals.
- template <typename AllocatorTy, typename... InitTy>
- static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator,
- InitTy &&... InitVals) {
- size_t KeyLength = Key.size();
-
- // Allocate a new item with space for the string at the end and a null
- // terminator.
- size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1;
- size_t Alignment = alignof(StringMapEntry);
-
- StringMapEntry *NewItem =
- static_cast<StringMapEntry *>(Allocator.Allocate(AllocSize, Alignment));
- assert(NewItem && "Unhandled out-of-memory");
-
- // Construct the value.
- new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
-
- // Copy the string information.
- char *StrBuffer = const_cast<char *>(NewItem->getKeyData());
- if (KeyLength > 0)
- memcpy(StrBuffer, Key.data(), KeyLength);
- StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients.
- return NewItem;
- }
-
- /// Create - Create a StringMapEntry with normal malloc/free.
- template <typename... InitType>
- static StringMapEntry *Create(StringRef Key, InitType &&... InitVal) {
- MallocAllocator A;
- return Create(Key, A, std::forward<InitType>(InitVal)...);
- }
-
- static StringMapEntry *Create(StringRef Key) {
- return Create(Key, ValueTy());
- }
-
- /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
- /// into a StringMapEntry, return the StringMapEntry itself.
- static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
- char *Ptr = const_cast<char *>(KeyData) - sizeof(StringMapEntry<ValueTy>);
- return *reinterpret_cast<StringMapEntry *>(Ptr);
- }
-
- /// Destroy - Destroy this StringMapEntry, releasing memory back to the
- /// specified allocator.
- template <typename AllocatorTy> void Destroy(AllocatorTy &Allocator) {
- // Free memory referenced by the item.
- size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
- this->~StringMapEntry();
- Allocator.Deallocate(static_cast<void *>(this), AllocSize);
- }
-
- /// Destroy this object, releasing memory back to the malloc allocator.
- void Destroy() {
- MallocAllocator A;
- Destroy(A);
- }
-};
-
/// StringMap - This is an unconventional map that is specialized for handling
/// keys that are "strings", which are basically ranges of bytes. This does some
/// funky memory allocation and hashing things to make it extremely efficient,
diff --git a/llvm/include/llvm/ADT/StringMapEntry.h b/llvm/include/llvm/ADT/StringMapEntry.h
new file mode 100644
index 000000000000..76a8e1f018d2
--- /dev/null
+++ b/llvm/include/llvm/ADT/StringMapEntry.h
@@ -0,0 +1,152 @@
+//===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StringMapEntry class - it is intended to be a low
+// dependency implementation detail of StringMap that is more suitable for
+// inclusion in public headers than StringMap.h itself is.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_STRINGMAPENTRY_H
+#define LLVM_ADT_STRINGMAPENTRY_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AllocatorBase.h"
+
+namespace llvm {
+
+/// StringMapEntryBase - Shared base class of StringMapEntry instances.
+class StringMapEntryBase {
+ size_t keyLength;
+
+public:
+ explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {}
+
+ size_t getKeyLength() const { return keyLength; }
+};
+
+/// StringMapEntryStorage - Holds the value in a StringMapEntry.
+///
+/// Factored out into a separate base class to make it easier to specialize.
+/// This is primarily intended to support StringSet, which doesn't need a value
+/// stored at all.
+template <typename ValueTy>
+class StringMapEntryStorage : public StringMapEntryBase {
+public:
+ ValueTy second;
+
+ explicit StringMapEntryStorage(size_t keyLength)
+ : StringMapEntryBase(keyLength), second() {}
+ template <typename... InitTy>
+ StringMapEntryStorage(size_t keyLength, InitTy &&... initVals)
+ : StringMapEntryBase(keyLength),
+ second(std::forward<InitTy>(initVals)...) {}
+ StringMapEntryStorage(StringMapEntryStorage &e) = delete;
+
+ const ValueTy &getValue() const { return second; }
+ ValueTy &getValue() { return second; }
+
+ void setValue(const ValueTy &V) { second = V; }
+};
+
+template <> class StringMapEntryStorage<NoneType> : public StringMapEntryBase {
+public:
+ explicit StringMapEntryStorage(size_t keyLength, NoneType none = None)
+ : StringMapEntryBase(keyLength) {}
+ StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
+
+ NoneType getValue() const { return None; }
+};
+
+/// StringMapEntry - This is used to represent one value that is inserted into
+/// a StringMap. It contains the Value itself and the key: the string length
+/// and data.
+template <typename ValueTy>
+class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
+public:
+ using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
+
+ StringRef getKey() const {
+ return StringRef(getKeyData(), this->getKeyLength());
+ }
+
+ /// getKeyData - Return the start of the string data that is the key for this
+ /// value. The string data is always stored immediately after the
+ /// StringMapEntry object.
+ const char *getKeyData() const {
+ return reinterpret_cast<const char *>(this + 1);
+ }
+
+ StringRef first() const {
+ return StringRef(getKeyData(), this->getKeyLength());
+ }
+
+ /// Create a StringMapEntry for the specified key construct the value using
+ /// \p InitiVals.
+ template <typename AllocatorTy, typename... InitTy>
+ static StringMapEntry *Create(StringRef key, AllocatorTy &allocator,
+ InitTy &&... initVals) {
+ size_t keyLength = key.size();
+
+ // Allocate a new item with space for the string at the end and a null
+ // terminator.
+ size_t allocSize = sizeof(StringMapEntry) + keyLength + 1;
+ size_t alignment = alignof(StringMapEntry);
+
+ StringMapEntry *newItem =
+ static_cast<StringMapEntry *>(allocator.Allocate(allocSize, alignment));
+ assert(newItem && "Unhandled out-of-memory");
+
+ // Construct the value.
+ new (newItem) StringMapEntry(keyLength, std::forward<InitTy>(initVals)...);
+
+ // Copy the string information.
+ char *strBuffer = const_cast<char *>(newItem->getKeyData());
+ if (keyLength > 0)
+ memcpy(strBuffer, key.data(), keyLength);
+ strBuffer[keyLength] = 0; // Null terminate for convenience of clients.
+ return newItem;
+ }
+
+ /// Create - Create a StringMapEntry with normal malloc/free.
+ template <typename... InitType>
+ static StringMapEntry *Create(StringRef key, InitType &&... initVal) {
+ MallocAllocator allocator;
+ return Create(key, allocator, std::forward<InitType>(initVal)...);
+ }
+
+ static StringMapEntry *Create(StringRef key) {
+ return Create(key, ValueTy());
+ }
+
+ /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
+ /// into a StringMapEntry, return the StringMapEntry itself.
+ static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) {
+ char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>);
+ return *reinterpret_cast<StringMapEntry *>(ptr);
+ }
+
+ /// Destroy - Destroy this StringMapEntry, releasing memory back to the
+ /// specified allocator.
+ template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) {
+ // Free memory referenced by the item.
+ size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
+ this->~StringMapEntry();
+ allocator.Deallocate(static_cast<void *>(this), AllocSize);
+ }
+
+ /// Destroy this object, releasing memory back to the malloc allocator.
+ void Destroy() {
+ MallocAllocator allocator;
+ Destroy(allocator);
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_STRINGMAPENTRY_H
diff --git a/llvm/lib/Support/StringMap.cpp b/llvm/lib/Support/StringMap.cpp
index 6b5ea020dd46..f65d3846623c 100644
--- a/llvm/lib/Support/StringMap.cpp
+++ b/llvm/lib/Support/StringMap.cpp
@@ -12,10 +12,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/MathExtras.h"
-#include <cassert>
using namespace llvm;
@@ -50,23 +48,22 @@ StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) {
}
void StringMapImpl::init(unsigned InitSize) {
- assert((InitSize & (InitSize-1)) == 0 &&
+ assert((InitSize & (InitSize - 1)) == 0 &&
"Init Size must be a power of 2 or zero!");
unsigned NewNumBuckets = InitSize ? InitSize : 16;
NumItems = 0;
NumTombstones = 0;
- TheTable = static_cast<StringMapEntryBase **>(
- safe_calloc(NewNumBuckets+1,
- sizeof(StringMapEntryBase **) + sizeof(unsigned)));
+ TheTable = static_cast<StringMapEntryBase **>(safe_calloc(
+ NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned)));
// Set the member only if TheTable was successfully allocated
NumBuckets = NewNumBuckets;
// Allocate one extra bucket, set it to look filled so the iterators stop at
// end.
- TheTable[NumBuckets] = (StringMapEntryBase*)2;
+ TheTable[NumBuckets] = (StringMapEntryBase *)2;
}
/// LookupBucketFor - Look up the bucket that the specified string should end
@@ -76,12 +73,12 @@ void StringMapImpl::init(unsigned InitSize) {
/// of the string.
unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
unsigned HTSize = NumBuckets;
- if (HTSize == 0) { // Hash table unallocated so far?
+ if (HTSize == 0) { // Hash table unallocated so far?
init(16);
HTSize = NumBuckets;
}
unsigned FullHashValue = djbHash(Name, 0);
- unsigned BucketNo = FullHashValue & (HTSize-1);
+ unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned ProbeAmt = 1;
@@ -103,7 +100,8 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
if (BucketItem == getTombstoneVal()) {
// Skip over tombstones. However, remember the first one we see.
- if (FirstTombstone == -1) FirstTombstone = BucketNo;
+ if (FirstTombstone == -1)
+ FirstTombstone = BucketNo;
} else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
// If the full hash value matches, check deeply for a match. The common
// case here is that we are only looking at the buckets (for item info
@@ -112,7 +110,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
// Do the comparison like this because Name isn't necessarily
// null-terminated!
- char *ItemStr = (char*)BucketItem+ItemSize;
+ char *ItemStr = (char *)BucketItem + ItemSize;
if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) {
// We found a match!
return BucketNo;
@@ -120,7 +118,7 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
}
// Okay, we didn't find the item. Probe to the next bucket.
- BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+ BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -133,9 +131,10 @@ unsigned StringMapImpl::LookupBucketFor(StringRef Name) {
/// This does not modify the map.
int StringMapImpl::FindKey(StringRef Key) const {
unsigned HTSize = NumBuckets;
- if (HTSize == 0) return -1; // Really empty table?
+ if (HTSize == 0)
+ return -1; // Really empty table?
unsigned FullHashValue = djbHash(Key, 0);
- unsigned BucketNo = FullHashValue & (HTSize-1);
+ unsigned BucketNo = FullHashValue & (HTSize - 1);
unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
unsigned ProbeAmt = 1;
@@ -155,7 +154,7 @@ int StringMapImpl::FindKey(StringRef Key) const {
// Do the comparison like this because NameStart isn't necessarily
// null-terminated!
- char *ItemStr = (char*)BucketItem+ItemSize;
+ char *ItemStr = (char *)BucketItem + ItemSize;
if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) {
// We found a match!
return BucketNo;
@@ -163,7 +162,7 @@ int StringMapImpl::FindKey(StringRef Key) const {
}
// Okay, we didn't find the item. Probe to the next bucket.
- BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+ BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
// Use quadratic probing, it has fewer clumping artifacts than linear
// probing and has good cache behavior in the common case.
@@ -174,7 +173,7 @@ int StringMapImpl::FindKey(StringRef Key) const {
/// RemoveKey - Remove the specified StringMapEntry from the table, but do not
/// delete it. This aborts if the value isn't in the table.
void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
- const char *VStr = (char*)V + ItemSize;
+ const char *VStr = (char *)V + ItemSize;
StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength()));
(void)V2;
assert(V == V2 && "Didn't find key?");
@@ -184,7 +183,8 @@ void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
/// table, returning it. If the key is not in the table, this returns null.
StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) {
int Bucket = FindKey(Key);
- if (Bucket == -1) return nullptr;
+ if (Bucket == -1)
+ return nullptr;
StringMapEntryBase *Result = TheTable[Bucket];
TheTable[Bucket] = getTombstoneVal();
@@ -205,7 +205,7 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
// the buckets are empty (meaning that many are filled with tombstones),
// grow/rehash the table.
if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
- NewSize = NumBuckets*2;
+ NewSize = NumBuckets * 2;
} else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
NumBuckets / 8)) {
NewSize = NumBuckets;
@@ -216,11 +216,11 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
unsigned NewBucketNo = BucketNo;
// Allocate one extra bucket which will always be non-empty. This allows the
// iterators to stop at end.
- auto NewTableArray = static_cast<StringMapEntryBase **>(
- safe_calloc(NewSize+1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
+ auto NewTableArray = static_cast<StringMapEntryBase **>(safe_calloc(
+ NewSize + 1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
- NewTableArray[NewSize] = (StringMapEntryBase*)2;
+ NewTableArray[NewSize] = (StringMapEntryBase *)2;
// Rehash all the items into their new buckets. Luckily :) we already have
// the hash values available, so we don't have to rehash any strings.
@@ -229,10 +229,10 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
if (Bucket && Bucket != getTombstoneVal()) {
// Fast case, bucket available.
unsigned FullHash = HashTable[I];
- unsigned NewBucket = FullHash & (NewSize-1);
+ unsigned NewBucket = FullHash & (NewSize - 1);
if (!NewTableArray[NewBucket]) {
- NewTableArray[FullHash & (NewSize-1)] = Bucket;
- NewHashArray[FullHash & (NewSize-1)] = FullHash;
+ NewTableArray[FullHash & (NewSize - 1)] = Bucket;
+ NewHashArray[FullHash & (NewSize - 1)] = FullHash;
if (I == BucketNo)
NewBucketNo = NewBucket;
continue;
@@ -241,7 +241,7 @@ unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
// Otherwise probe for a spot.
unsigned ProbeSize = 1;
do {
- NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
+ NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1);
} while (NewTableArray[NewBucket]);
// Finally found a slot. Fill it in.
More information about the llvm-commits
mailing list