aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/ADT
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-07-09 18:34:41 +0000
committerTed Kremenek <kremenek@apple.com>2009-07-09 18:34:41 +0000
commitb302952e21533f08b6fd4883398848b5adb5bb47 (patch)
treee3c050e522b1d44e438b86072d11037d6ce227da /include/llvm/ADT
parent426fee3741fbd612479f927aeaa4e042a53175f2 (diff)
downloadexternal_llvm-b302952e21533f08b6fd4883398848b5adb5bb47.zip
external_llvm-b302952e21533f08b6fd4883398848b5adb5bb47.tar.gz
external_llvm-b302952e21533f08b6fd4883398848b5adb5bb47.tar.bz2
ImmutableSet/ImmutableMap: Allow caching of null digests by properly using a flag to record if the digest of an ImutAVLTree has been cached.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75157 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT')
-rw-r--r--include/llvm/ADT/ImmutableSet.h82
1 files changed, 45 insertions, 37 deletions
diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h
index be274db..38816c7 100644
--- a/include/llvm/ADT/ImmutableSet.h
+++ b/include/llvm/ADT/ImmutableSet.h
@@ -51,10 +51,8 @@ public:
/// getLeft - Returns a pointer to the left subtree. This value
/// is NULL if there is no left subtree.
- ImutAVLTree* getLeft() const {
- assert (!isMutable() && "Node is incorrectly marked mutable.");
-
- return reinterpret_cast<ImutAVLTree*>(Left);
+ ImutAVLTree *getLeft() const {
+ return reinterpret_cast<ImutAVLTree*>(Left & ~LeftFlags);
}
/// getRight - Returns a pointer to the right subtree. This value is
@@ -227,7 +225,7 @@ private:
ImutAVLTree* Right;
unsigned Height;
value_type Value;
- unsigned Digest;
+ uint32_t Digest;
//===----------------------------------------------------===//
// Internal methods (node manipulation; used by Factory).
@@ -235,12 +233,12 @@ private:
private:
- enum { Mutable = 0x1 };
+ enum { Mutable = 0x1, NoCachedDigest = 0x2, LeftFlags = 0x3 };
/// ImutAVLTree - Internal constructor that is only called by
/// ImutAVLFactory.
ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height)
- : Left(reinterpret_cast<uintptr_t>(l) | Mutable),
+ : Left(reinterpret_cast<uintptr_t>(l) | (Mutable | NoCachedDigest)),
Right(r), Height(height), Value(v), Digest(0) {}
@@ -251,13 +249,10 @@ private:
/// method returns false for an instance of ImutAVLTree, all subtrees
/// will also have this method return false. The converse is not true.
bool isMutable() const { return Left & Mutable; }
-
- /// getSafeLeft - Returns the pointer to the left tree by always masking
- /// out the mutable bit. This is used internally by ImutAVLFactory,
- /// as no trees returned to the client should have the mutable flag set.
- ImutAVLTree* getSafeLeft() const {
- return reinterpret_cast<ImutAVLTree*>(Left & ~Mutable);
- }
+
+ /// hasCachedDigest - Returns true if the digest for this tree is cached.
+ /// This can only be true if the tree is immutable.
+ bool hasCachedDigest() const { return !(Left & NoCachedDigest); }
//===----------------------------------------------------===//
// Mutating operations. A tree root can be manipulated as
@@ -270,22 +265,28 @@ private:
// immutable.
//===----------------------------------------------------===//
-
/// MarkImmutable - Clears the mutable flag for a tree. After this happens,
- /// it is an error to call setLeft(), setRight(), and setHeight(). It
- /// is also then safe to call getLeft() instead of getSafeLeft().
+ /// it is an error to call setLeft(), setRight(), and setHeight().
void MarkImmutable() {
- assert (isMutable() && "Mutable flag already removed.");
+ assert(isMutable() && "Mutable flag already removed.");
Left &= ~Mutable;
}
+
+ /// MarkedCachedDigest - Clears the NoCachedDigest flag for a tree.
+ void MarkedCachedDigest() {
+ assert(!hasCachedDigest() && "NoCachedDigest flag already removed.");
+ Left &= ~NoCachedDigest;
+ }
/// setLeft - Changes the reference of the left subtree. Used internally
/// by ImutAVLFactory.
void setLeft(ImutAVLTree* NewLeft) {
- assert (isMutable() &&
- "Only a mutable tree can have its left subtree changed.");
+ assert(isMutable() &&
+ "Only a mutable tree can have its left subtree changed.");
+ assert(!hasCachedDigest() &&
+ "A mutable tree cannot have a cached digest.");
- Left = reinterpret_cast<uintptr_t>(NewLeft) | Mutable;
+ Left = reinterpret_cast<uintptr_t>(NewLeft) | LeftFlags;
}
/// setRight - Changes the reference of the right subtree. Used internally
@@ -304,29 +305,36 @@ private:
Height = h;
}
-
static inline
- unsigned ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
- unsigned digest = 0;
+ uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
+ uint32_t digest = 0;
- if (L) digest += L->ComputeDigest();
+ if (L)
+ digest += L->ComputeDigest();
- { // Compute digest of stored data.
- FoldingSetNodeID ID;
- ImutInfo::Profile(ID,V);
- digest += ID.ComputeHash();
- }
+ // Compute digest of stored data.
+ FoldingSetNodeID ID;
+ ImutInfo::Profile(ID,V);
+ digest += ID.ComputeHash();
- if (R) digest += R->ComputeDigest();
+ if (R)
+ digest += R->ComputeDigest();
return digest;
}
- inline unsigned ComputeDigest() {
- if (Digest) return Digest;
+ inline uint32_t ComputeDigest() {
+ // Check the lowest bit to determine if digest has actually been
+ // pre-computed.
+ if (hasCachedDigest())
+ return Digest;
- unsigned X = ComputeDigest(getSafeLeft(), getRight(), getValue());
- if (!isMutable()) Digest = X;
+ uint32_t X = ComputeDigest(getLeft(), getRight(), getValue());
+
+ if (!isMutable()) {
+ Digest = X;
+ MarkedCachedDigest();
+ }
return X;
}
@@ -394,7 +402,7 @@ private:
bool isEmpty(TreeTy* T) const { return !T; }
unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; }
- TreeTy* Left(TreeTy* T) const { return T->getSafeLeft(); }
+ TreeTy* Left(TreeTy* T) const { return T->getLeft(); }
TreeTy* Right(TreeTy* T) const { return T->getRight(); }
value_type_ref Value(TreeTy* T) const { return T->Value; }
@@ -701,7 +709,7 @@ public:
switch (getVisitState()) {
case VisitedNone:
- if (TreeTy* L = Current->getSafeLeft())
+ if (TreeTy* L = Current->getLeft())
stack.push_back(reinterpret_cast<uintptr_t>(L));
else
stack.back() |= VisitedLeft;