<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Fri, Oct 21, 2016 at 1:20 PM Justin Lebar via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jlebar<br class="gmail_msg">
Date: Fri Oct 21 15:10:48 2016<br class="gmail_msg">
New Revision: 284871<br class="gmail_msg">
<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=284871&view=rev" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project?rev=284871&view=rev</a><br class="gmail_msg">
Log:<br class="gmail_msg">
[ADT] Add CachedHashString.<br class="gmail_msg">
<br class="gmail_msg">
Summary:<br class="gmail_msg">
This is like CachedHashStringRef, but owns its data.<br class="gmail_msg">
<br class="gmail_msg">
This lets us use strings inside of DenseMaps.<br class="gmail_msg">
<br class="gmail_msg">
Reviewers: timshen<br class="gmail_msg">
<br class="gmail_msg">
Subscribers: llvm-commits<br class="gmail_msg">
<br class="gmail_msg">
Differential Revision: <a href="https://reviews.llvm.org/D25645" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D25645</a><br class="gmail_msg">
<br class="gmail_msg">
Modified:<br class="gmail_msg">
    llvm/trunk/include/llvm/ADT/CachedHashString.h<br class="gmail_msg">
<br class="gmail_msg">
Modified: llvm/trunk/include/llvm/ADT/CachedHashString.h<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/CachedHashString.h?rev=284871&r1=284870&r2=284871&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/CachedHashString.h?rev=284871&r1=284870&r2=284871&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- llvm/trunk/include/llvm/ADT/CachedHashString.h (original)<br class="gmail_msg">
+++ llvm/trunk/include/llvm/ADT/CachedHashString.h Fri Oct 21 15:10:48 2016<br class="gmail_msg">
@@ -7,16 +7,14 @@<br class="gmail_msg">
 //<br class="gmail_msg">
 //===----------------------------------------------------------------------===//<br class="gmail_msg">
 //<br class="gmail_msg">
-// This file defines CachedHashString and CachedHashStringRef.  These are like<br class="gmail_msg">
-// std::string and StringRef, except they store their hash in addition to their<br class="gmail_msg">
-// string data.<br class="gmail_msg">
+// This file defines CachedHashString and CachedHashStringRef.  These are owning<br class="gmail_msg">
+// and not-owning string types that store their hash in addition to their string<br class="gmail_msg">
+// data.<br class="gmail_msg">
 //<br class="gmail_msg">
 // Unlike std::string, CachedHashString can be used in DenseSet/DenseMap<br class="gmail_msg">
 // (because, unlike std::string, CachedHashString lets us have empty and<br class="gmail_msg">
 // tombstone values).<br class="gmail_msg">
 //<br class="gmail_msg">
-// TODO: Add CachedHashString.<br class="gmail_msg">
-//<br class="gmail_msg">
 //===----------------------------------------------------------------------===//<br class="gmail_msg">
<br class="gmail_msg">
 #ifndef LLVM_ADT_CACHED_HASH_STRING_H<br class="gmail_msg">
@@ -24,6 +22,7 @@<br class="gmail_msg">
<br class="gmail_msg">
 #include "llvm/ADT/DenseMap.h"<br class="gmail_msg">
 #include "llvm/ADT/StringRef.h"<br class="gmail_msg">
+#include "llvm/Support/raw_ostream.h"<br class="gmail_msg">
<br class="gmail_msg">
 namespace llvm {<br class="gmail_msg">
<br class="gmail_msg">
@@ -66,6 +65,114 @@ template <> struct DenseMapInfo<CachedHa<br class="gmail_msg">
   }<br class="gmail_msg">
 };<br class="gmail_msg">
<br class="gmail_msg">
+/// A container which contains a string, which it owns, plus a precomputed hash.<br class="gmail_msg">
+///<br class="gmail_msg">
+/// We do not null-terminate the string.<br class="gmail_msg">
+class CachedHashString {<br class="gmail_msg">
+  friend struct DenseMapInfo<CachedHashString>;<br class="gmail_msg">
+<br class="gmail_msg">
+  char *P;<br class="gmail_msg">
+  uint32_t Size;<br class="gmail_msg">
+  uint32_t Hash;<br class="gmail_msg"></blockquote><div><br>This loses std::string's small string optimization - is that OK?<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br class="gmail_msg">
+  static char *getEmptyKeyPtr() { return DenseMapInfo<char *>::getEmptyKey(); }<br class="gmail_msg">
+  static char *getTombstoneKeyPtr() {<br class="gmail_msg">
+    return DenseMapInfo<char *>::getTombstoneKey();<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  bool isEmptyOrTombstone() const {<br class="gmail_msg">
+    return P == getEmptyKeyPtr() || P == getTombstoneKeyPtr();<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  explicit CachedHashString(char *EmptyOrTombstonePtr)<br class="gmail_msg">
+      : P(EmptyOrTombstonePtr), Size(0), Hash(0) {<br class="gmail_msg">
+    assert(isEmptyOrTombstone());<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  // TODO: Use small-string optimization to avoid allocating.<br class="gmail_msg">
+<br class="gmail_msg">
+public:<br class="gmail_msg">
+  // Explicit because copying and hashing a string isn't free.<br class="gmail_msg">
+  explicit CachedHashString(StringRef S)<br class="gmail_msg">
+      : CachedHashString(S, DenseMapInfo<StringRef>::getHashValue(S)) {}<br class="gmail_msg">
+<br class="gmail_msg">
+  CachedHashString(StringRef S, uint32_t Hash)<br class="gmail_msg">
+      : P(new char[S.size()]), Size(S.size()), Hash(Hash) {<br class="gmail_msg">
+    memcpy(P, S.data(), S.size());<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  // Ideally this class would not be copyable.  But SetVector requires copyable<br class="gmail_msg">
+  // keys, and we want this to be usable there.<br class="gmail_msg">
+  CachedHashString(const CachedHashString &Other)<br class="gmail_msg">
+      : Size(Other.Size), Hash(Other.Hash) {<br class="gmail_msg">
+    if (Other.isEmptyOrTombstone()) {<br class="gmail_msg">
+      P = Other.P;<br class="gmail_msg">
+    } else {<br class="gmail_msg">
+      P = new char[Size];<br class="gmail_msg">
+      memcpy(P, Other.P, Size);<br class="gmail_msg">
+    }<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  CachedHashString &operator=(CachedHashString Other) {<br class="gmail_msg">
+    swap(*this, Other);<br class="gmail_msg">
+    return *this;<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  CachedHashString(CachedHashString &&Other) LLVM_NOEXCEPT : P(Other.P),<br class="gmail_msg">
+                                                             Size(Other.Size),<br class="gmail_msg">
+                                                             Hash(Other.Hash) {<br class="gmail_msg">
+    Other.P = getEmptyKeyPtr();<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  ~CachedHashString() {<br class="gmail_msg">
+    if (!isEmptyOrTombstone())<br class="gmail_msg">
+      delete[] P;<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  StringRef val() const { return StringRef(P, Size); }<br class="gmail_msg">
+  uint32_t size() const { return Size; }<br class="gmail_msg">
+  uint32_t hash() const { return Hash; }<br class="gmail_msg">
+<br class="gmail_msg">
+  operator StringRef() const { return val(); }<br class="gmail_msg">
+  operator CachedHashStringRef() const {<br class="gmail_msg">
+    return CachedHashStringRef(val(), Hash);<br class="gmail_msg">
+  }<br class="gmail_msg">
+<br class="gmail_msg">
+  friend void swap(CachedHashString &LHS, CachedHashString &RHS) {<br class="gmail_msg">
+    using std::swap;<br class="gmail_msg">
+    swap(LHS.P, RHS.P);<br class="gmail_msg">
+    swap(LHS.Size, RHS.Size);<br class="gmail_msg">
+    swap(LHS.Hash, RHS.Hash);<br class="gmail_msg">
+  }<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
+template <> struct DenseMapInfo<CachedHashString> {<br class="gmail_msg">
+  static CachedHashString getEmptyKey() {<br class="gmail_msg">
+    return CachedHashString(CachedHashString::getEmptyKeyPtr());<br class="gmail_msg">
+  }<br class="gmail_msg">
+  static CachedHashString getTombstoneKey() {<br class="gmail_msg">
+    return CachedHashString(CachedHashString::getTombstoneKeyPtr());<br class="gmail_msg">
+  }<br class="gmail_msg">
+  static unsigned getHashValue(const CachedHashString &S) {<br class="gmail_msg">
+    assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!");<br class="gmail_msg">
+    assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!");<br class="gmail_msg">
+    return S.hash();<br class="gmail_msg">
+  }<br class="gmail_msg">
+  static bool isEqual(const CachedHashString &LHS,<br class="gmail_msg">
+                      const CachedHashString &RHS) {<br class="gmail_msg">
+    if (LHS.hash() != RHS.hash())<br class="gmail_msg">
+      return false;<br class="gmail_msg">
+    if (LHS.P == CachedHashString::getEmptyKeyPtr())<br class="gmail_msg">
+      return RHS.P == CachedHashString::getEmptyKeyPtr();<br class="gmail_msg">
+    if (LHS.P == CachedHashString::getTombstoneKeyPtr())<br class="gmail_msg">
+      return RHS.P == CachedHashString::getTombstoneKeyPtr();<br class="gmail_msg">
+<br class="gmail_msg">
+    // This is safe because if RHS.P is the empty or tombstone key, it will have<br class="gmail_msg">
+    // length 0, so we'll never dereference its pointer.<br class="gmail_msg">
+    return LHS.val() == RHS.val();<br class="gmail_msg">
+  }<br class="gmail_msg">
+};<br class="gmail_msg">
+<br class="gmail_msg">
 } // namespace llvm<br class="gmail_msg">
<br class="gmail_msg">
 #endif<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
llvm-commits mailing list<br class="gmail_msg">
<a href="mailto:llvm-commits@lists.llvm.org" class="gmail_msg" target="_blank">llvm-commits@lists.llvm.org</a><br class="gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" class="gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="gmail_msg">
</blockquote></div></div>