Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Unified Diff: src/IceStringPool.h

Issue 1838753002: Subzero: Remove IceString. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceRegistersARM32.h ('k') | src/IceSwitchLowering.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceStringPool.h
diff --git a/src/IceStringPool.h b/src/IceStringPool.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6b3d1117b10107fd276d048aad71f9580bf7d37
--- /dev/null
+++ b/src/IceStringPool.h
@@ -0,0 +1,174 @@
+//===- subzero/src/IceStringPool.h - String pooling -------------*- C++ -*-===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines unique pooled strings with short unique IDs. This makes
+/// hashing, equality testing, and ordered comparison faster, and avoids a lot
+/// of memory allocation compared to directly using std::string.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICESTRINGPOOL_H
+#define SUBZERO_SRC_ICESTRINGPOOL_H
+
+#include <cstdint> // uintptr_t
+#include <string>
+
+namespace Ice {
+
+class StringPool {
+ StringPool(const StringPool &) = delete;
+ StringPool &operator=(const StringPool &) = delete;
+
+public:
+ using IDType = uintptr_t;
+
+ StringPool() = default;
+ ~StringPool() = default;
+ IDType getNewID() {
+ // TODO(stichnot): Make it so that the GlobalString ctor doesn't have to
+ // grab the lock, and instead does an atomic increment of NextID.
+ auto NewID = NextID;
+ NextID += IDIncrement;
+ return NewID;
+ }
+ IDType getOrAddString(const std::string &Value) {
+ auto Iter = StringToId.find(Value);
+ if (Iter == StringToId.end()) {
+ auto *NewStr = new std::string(Value);
+ auto ID = reinterpret_cast<IDType>(NewStr);
+ StringToId[Value].reset(NewStr);
+ return ID;
+ }
+ return reinterpret_cast<IDType>(Iter->second.get());
+ }
+ void dump(Ostream &Str) const {
+ if (StringToId.empty())
+ return;
+ Str << "String pool (NumStrings=" << StringToId.size()
+ << " NumIDs=" << ((NextID - FirstID) / IDIncrement) << "):";
+ for (const auto &Tuple : StringToId) {
+ Str << " " << Tuple.first;
+ }
+ Str << "\n";
+ }
+
+private:
+ static constexpr IDType FirstID = 1;
+ static constexpr IDType IDIncrement = 2;
+ IDType NextID = FirstID;
+ std::unordered_map<std::string, std::unique_ptr<std::string>> StringToId;
+};
+
+template <typename Traits> class StringID {
+public:
+ using IDType = StringPool::IDType;
+
+ StringID() = default; // Create a default, invalid StringID.
+ StringID(const StringID &) = default;
+ StringID &operator=(const StringID &) = default;
+
+ /// Create a unique StringID without an actual string, by grabbing the next
+ /// unique integral ID from the Owner.
+ static StringID createWithoutString(const typename Traits::OwnerType *Owner) {
+ return StringID(Owner);
+ }
+ /// Create a unique StringID that holds an actual string, by fetching or
+ /// adding the string from the Owner's pool.
+ static StringID createWithString(const typename Traits::OwnerType *Owner,
+ const std::string &Value) {
+ return StringID(Owner, Value);
+ }
+
+ /// Tests whether the StringID was initialized with respect to an actual
+ /// std::string value, i.e. via StringID::createWithString().
+ bool hasStdString() const { return isValid() && ((ID & 0x1) == 0); }
+
+ IDType getID() const {
+ assert(isValid());
+ return ID;
+ }
+ const std::string &toString() const {
+ if (!hasStdString())
+ llvm::report_fatal_error(
+ "toString() called when hasStdString() is false");
+ return *reinterpret_cast<std::string *>(ID);
+ }
+ std::string toStringOrEmpty() const {
+ if (hasStdString())
+ return toString();
+ return "";
+ }
+
+ bool operator==(const StringID &Other) const { return ID == Other.ID; }
+ bool operator!=(const StringID &Other) const { return !(*this == Other); }
+ bool operator<(const StringID &Other) const {
+ const bool ThisHasString = hasStdString();
+ const bool OtherHasString = Other.hasStdString();
+ // Do a normal string comparison if both have strings.
+ if (ThisHasString && OtherHasString)
+ return this->toString() < Other.toString();
+ // Use the ID as a tiebreaker if neither has a string.
+ if (!ThisHasString && !OtherHasString)
+ return ID < Other.ID;
+ // If exactly one has a string, then that one comes first.
+ assert(!OtherHasString);
+ return ThisHasString;
+ }
+
+private:
+ static constexpr IDType InvalidID = 0;
+ IDType ID = InvalidID;
+
+ explicit StringID(const typename Traits::OwnerType *Owner)
+ : ID(Traits::getStrings(Owner)->getNewID()) {}
+ StringID(const typename Traits::OwnerType *Owner, const std::string &Value)
+ : ID(Traits::getStrings(Owner)->getOrAddString(Value)) {
+ assert(hasStdString());
+ }
+ bool isValid() const { return ID != InvalidID; }
+};
+
+// TODO(stichnot, jpp): Move GlobalStringPoolTraits definition into
+// IceGlobalContext.h, once the include order issues are solved.
+struct GlobalStringPoolTraits {
+ using OwnerType = GlobalContext;
+ static LockedPtr<StringPool> getStrings(const OwnerType *Owner);
+};
+
+using GlobalString = StringID<struct GlobalStringPoolTraits>;
+
+template <typename T>
+Ostream &operator<<(Ostream &Str, const StringID<T> &Name) {
+ return Str << Name.toString();
+}
+
+template <typename T>
+std::string operator+(const std::string &A, const StringID<T> &B) {
+ return A + B.toString();
+}
+
+template <typename T>
+std::string operator+(const StringID<T> &A, const std::string &B) {
+ return A.toString() + B;
+}
+
+} // end of namespace Ice
+
+namespace std {
+template <typename T> struct hash<Ice::StringID<T>> {
+ size_t operator()(const Ice::StringID<T> &Key) const {
+ if (Key.hasStdString())
+ return hash<std::string>()(Key.toString());
+ return hash<Ice::StringPool::IDType>()(Key.getID());
+ }
+};
+} // end of namespace std
+
+#endif // SUBZERO_SRC_ICESTRINGPOOL_H
« no previous file with comments | « src/IceRegistersARM32.h ('k') | src/IceSwitchLowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698