[PATCH] Add standard insert overloads to StringMap
Alp Toker
alp at nuanti.com
Thu Jun 19 12:54:09 PDT 2014
On 19/06/2014 22:37, Agustín Bergé wrote:
> Changes in this iteration:
>
> - Removed hash check.
> - Added comment explaining how brittle the rehash test case is.
>
> David: I don't have commit access, could you take care of that?
>
> http://reviews.llvm.org/D4153
>
> Files:
> include/llvm/ADT/StringMap.h
> lib/Support/StringMap.cpp
> unittests/ADT/StringMapTest.cpp
>
> D4153.10652.patch
>
>
> Index: include/llvm/ADT/StringMap.h
> ===================================================================
> --- include/llvm/ADT/StringMap.h
> +++ include/llvm/ADT/StringMap.h
> @@ -64,7 +64,7 @@
> }
>
> StringMapImpl(unsigned InitSize, unsigned ItemSize);
> - void RehashTable();
> + unsigned RehashTable(unsigned BucketNo = 0);
>
> /// LookupBucketFor - Look up the bucket that the specified string should end
> /// up in. If it already exists as a key in the map, the Item pointer for the
> @@ -323,6 +323,28 @@
> return true;
> }
>
> + /// insert - Inserts the specified key/value pair into the map if the key
> + /// isn't already in the map. The bool component of the returned pair is true
> + /// if and only if the insertion takes places, and the iterator component of
Takes 'place'
Looks okay otherwise.
Thanks!
Alp.
> + /// the pair points to the element with key equivalent to the key of the pair.
> + std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) {
> + unsigned BucketNo = LookupBucketFor(KV.first);
> + StringMapEntryBase *&Bucket = TheTable[BucketNo];
> + if (Bucket && Bucket != getTombstoneVal())
> + return std::make_pair(iterator(TheTable + BucketNo, false),
> + false); // Already exists in map.
> +
> + if (Bucket == getTombstoneVal())
> + --NumTombstones;
> + Bucket =
> + MapEntryTy::Create(KV.first, Allocator, std::move(KV.second));
> + ++NumItems;
> + assert(NumItems + NumTombstones <= NumBuckets);
> +
> + BucketNo = RehashTable(BucketNo);
> + return std::make_pair(iterator(TheTable + BucketNo, false), true);
> + }
> +
> // clear - Empties out the StringMap
> void clear() {
> if (empty()) return;
> @@ -346,24 +368,7 @@
> /// return.
> template <typename InitTy>
> MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
> - unsigned BucketNo = LookupBucketFor(Key);
> - StringMapEntryBase *&Bucket = TheTable[BucketNo];
> - if (Bucket && Bucket != getTombstoneVal())
> - return*static_cast<MapEntryTy*>(Bucket);
> -
> - MapEntryTy *NewItem = MapEntryTy::Create(Key, Allocator, std::move(Val));
> -
> - if (Bucket == getTombstoneVal())
> - --NumTombstones;
> - ++NumItems;
> - assert(NumItems + NumTombstones <= NumBuckets);
> -
> - // Fill in the bucket for the hash table. The FullHashValue was already
> - // filled in by LookupBucketFor.
> - Bucket = NewItem;
> -
> - RehashTable();
> - return *NewItem;
> + return *insert(std::make_pair(Key, std::move(Val))).first;
> }
>
> MapEntryTy &GetOrCreateValue(StringRef Key) {
> Index: lib/Support/StringMap.cpp
> ===================================================================
> --- lib/Support/StringMap.cpp
> +++ lib/Support/StringMap.cpp
> @@ -181,7 +181,7 @@
>
> /// RehashTable - Grow the table, redistributing values into the buckets with
> /// the appropriate mod-of-hashtable-size.
> -void StringMapImpl::RehashTable() {
> +unsigned StringMapImpl::RehashTable(unsigned BucketNo) {
> unsigned NewSize;
> unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
>
> @@ -193,9 +193,10 @@
> } else if (NumBuckets-(NumItems+NumTombstones) <= NumBuckets/8) {
> NewSize = NumBuckets;
> } else {
> - return;
> + return BucketNo;
> }
>
> + unsigned NewBucketNo = BucketNo;
> // Allocate one extra bucket which will always be non-empty. This allows the
> // iterators to stop at end.
> StringMapEntryBase **NewTableArray =
> @@ -215,6 +216,8 @@
> if (!NewTableArray[NewBucket]) {
> NewTableArray[FullHash & (NewSize-1)] = Bucket;
> NewHashArray[FullHash & (NewSize-1)] = FullHash;
> + if (I == BucketNo)
> + NewBucketNo = NewBucket;
> continue;
> }
>
> @@ -227,12 +230,15 @@
> // Finally found a slot. Fill it in.
> NewTableArray[NewBucket] = Bucket;
> NewHashArray[NewBucket] = FullHash;
> + if (I == BucketNo)
> + NewBucketNo = NewBucket;
> }
> }
>
> free(TheTable);
>
> TheTable = NewTableArray;
> NumBuckets = NewSize;
> NumTombstones = 0;
> + return NewBucketNo;
> }
> Index: unittests/ADT/StringMapTest.cpp
> ===================================================================
> --- unittests/ADT/StringMapTest.cpp
> +++ unittests/ADT/StringMapTest.cpp
> @@ -10,6 +10,7 @@
> #include "gtest/gtest.h"
> #include "llvm/ADT/StringMap.h"
> #include "llvm/Support/DataTypes.h"
> +#include <tuple>
> using namespace llvm;
>
> namespace {
> @@ -201,6 +202,43 @@
> StringRef(testKeyFirst, testKeyLength),
> testMap.getAllocator(), 1u));
> assertSingleItemMap();
> +}
> +
> +// Test insert(pair<K, V>) method
> +TEST_F(StringMapTest, InsertPairTest) {
> + bool Inserted;
> + StringMap<uint32_t>::iterator NewIt;
> + std::tie(NewIt, Inserted) =
> + testMap.insert(std::make_pair(testKeyFirst, testValue));
> + EXPECT_EQ(1u, testMap.size());
> + EXPECT_EQ(testValue, testMap[testKeyFirst]);
> + EXPECT_EQ(testKeyFirst, NewIt->first());
> + EXPECT_EQ(testValue, NewIt->second);
> + EXPECT_TRUE(Inserted);
> +
> + StringMap<uint32_t>::iterator ExistingIt;
> + std::tie(ExistingIt, Inserted) =
> + testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
> + EXPECT_EQ(1u, testMap.size());
> + EXPECT_EQ(testValue, testMap[testKeyFirst]);
> + EXPECT_FALSE(Inserted);
> + EXPECT_EQ(NewIt, ExistingIt);
> +}
> +
> +// Test insert(pair<K, V>) method when rehashing occurs
> +TEST_F(StringMapTest, InsertRehashingPairTest) {
> + // Check that the correct iterator is returned when the inserted element is
> + // moved to a different bucket during internal rehashing. This depends on
> + // the particular key, and the implementation of StringMap and HashString.
> + // Changes to those might result in this test not actually checking that.
> + StringMap<uint32_t> t(1);
> + EXPECT_EQ(1, t.getNumBuckets());
> +
> + StringMap<uint32_t>::iterator It =
> + t.insert(std::make_pair("abcdef", 42)).first;
> + EXPECT_EQ(2, t.getNumBuckets());
> + EXPECT_EQ("abcdef", It->first());
> + EXPECT_EQ(42, It->second);
> }
>
> // Create a non-default constructable value
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
--
http://www.nuanti.com
the browser experts
More information about the llvm-commits
mailing list