<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>