diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index c035f8cc6d7..3c5f76a3c1c 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -55,6 +55,7 @@ protected: unsigned NumTombstones; unsigned ItemSize; protected: + StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { init(16); } StringMapImpl(unsigned InitSize, unsigned ItemSize); void RehashTable(); @@ -87,7 +88,8 @@ protected: /// RemoveKey - Remove the StringMapEntry for the specified key from the /// table, returning it. If the key is not in the table, this returns null. StringMapEntryBase *RemoveKey(const char *KeyStart, const char *KeyEnd); - +private: + void init(unsigned Size); public: static StringMapEntryBase *getTombstoneVal() { return (StringMapEntryBase*)-1; @@ -185,7 +187,8 @@ class StringMap : public StringMapImpl { AllocatorTy Allocator; typedef StringMapEntry MapEntryTy; public: - StringMap(unsigned InitialSize = 0) + StringMap() : StringMapImpl(sizeof(MapEntryTy)) {} + StringMap(unsigned InitialSize) : StringMapImpl(InitialSize, sizeof(MapEntryTy)) {} AllocatorTy &getAllocator() { return Allocator; } @@ -194,11 +197,18 @@ public: typedef StringMapConstIterator const_iterator; typedef StringMapIterator iterator; - iterator begin() { return iterator(TheTable); } - iterator end() { return iterator(TheTable+NumBuckets); } - const_iterator begin() const { return const_iterator(TheTable); } - const_iterator end() const { return const_iterator(TheTable+NumBuckets); } - + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } iterator find(const char *KeyStart, const char *KeyEnd) { int Bucket = FindKey(KeyStart, KeyEnd); @@ -279,8 +289,10 @@ class StringMapConstIterator { protected: StringMapImpl::ItemBucket *Ptr; public: - StringMapConstIterator(StringMapImpl::ItemBucket *Bucket) : Ptr(Bucket) { - AdvancePastEmptyBuckets(); + StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); } const StringMapEntry &operator*() const { @@ -316,8 +328,9 @@ private: template class StringMapIterator : public StringMapConstIterator { public: - StringMapIterator(StringMapImpl::ItemBucket *Bucket) - : StringMapConstIterator(Bucket) { + StringMapIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : StringMapConstIterator(Bucket, NoAdvance) { } StringMapEntry &operator*() const { return *static_cast*>(this->Ptr->Item); diff --git a/lib/Support/StringMap.cpp b/lib/Support/StringMap.cpp index a84cd9dbc64..caf9ba350ef 100644 --- a/lib/Support/StringMap.cpp +++ b/lib/Support/StringMap.cpp @@ -16,10 +16,25 @@ using namespace llvm; StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { + ItemSize = itemSize; + + // If a size is specified, initialize the table with that many buckets. + if (InitSize) { + init(InitSize); + return; + } + + // Otherwise, initialize it with zero buckets to avoid the allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; +} + +void StringMapImpl::init(unsigned InitSize) { assert((InitSize & (InitSize-1)) == 0 && "Init Size must be a power of 2 or zero!"); NumBuckets = InitSize ? InitSize : 16; - ItemSize = itemSize; NumItems = 0; NumTombstones = 0; @@ -52,8 +67,12 @@ static unsigned HashString(const char *Start, const char *End) { /// case, the FullHashValue field of the bucket will be set to the hash value /// of the string. unsigned StringMapImpl::LookupBucketFor(const char *NameStart, - const char *NameEnd) { + const char *NameEnd) { unsigned HTSize = NumBuckets; + if (HTSize == 0) { // Hash table unallocated so far? + init(16); + HTSize = NumBuckets; + } unsigned FullHashValue = HashString(NameStart, NameEnd); unsigned BucketNo = FullHashValue & (HTSize-1); @@ -110,6 +129,7 @@ unsigned StringMapImpl::LookupBucketFor(const char *NameStart, /// This does not modify the map. int StringMapImpl::FindKey(const char *KeyStart, const char *KeyEnd) const { unsigned HTSize = NumBuckets; + if (HTSize == 0) return -1; // Really empty table? unsigned FullHashValue = HashString(KeyStart, KeyEnd); unsigned BucketNo = FullHashValue & (HTSize-1);