mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 21:29:41 +00:00
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
This commit is contained in:
parent
a637691871
commit
633eb95f3e
@ -51,10 +51,8 @@ public:
|
|||||||
|
|
||||||
/// getLeft - Returns a pointer to the left subtree. This value
|
/// getLeft - Returns a pointer to the left subtree. This value
|
||||||
/// is NULL if there is no left subtree.
|
/// is NULL if there is no left subtree.
|
||||||
ImutAVLTree* getLeft() const {
|
ImutAVLTree *getLeft() const {
|
||||||
assert (!isMutable() && "Node is incorrectly marked mutable.");
|
return reinterpret_cast<ImutAVLTree*>(Left & ~LeftFlags);
|
||||||
|
|
||||||
return reinterpret_cast<ImutAVLTree*>(Left);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getRight - Returns a pointer to the right subtree. This value is
|
/// getRight - Returns a pointer to the right subtree. This value is
|
||||||
@ -227,7 +225,7 @@ private:
|
|||||||
ImutAVLTree* Right;
|
ImutAVLTree* Right;
|
||||||
unsigned Height;
|
unsigned Height;
|
||||||
value_type Value;
|
value_type Value;
|
||||||
unsigned Digest;
|
uint32_t Digest;
|
||||||
|
|
||||||
//===----------------------------------------------------===//
|
//===----------------------------------------------------===//
|
||||||
// Internal methods (node manipulation; used by Factory).
|
// Internal methods (node manipulation; used by Factory).
|
||||||
@ -235,12 +233,12 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum { Mutable = 0x1 };
|
enum { Mutable = 0x1, NoCachedDigest = 0x2, LeftFlags = 0x3 };
|
||||||
|
|
||||||
/// ImutAVLTree - Internal constructor that is only called by
|
/// ImutAVLTree - Internal constructor that is only called by
|
||||||
/// ImutAVLFactory.
|
/// ImutAVLFactory.
|
||||||
ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height)
|
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) {}
|
Right(r), Height(height), Value(v), Digest(0) {}
|
||||||
|
|
||||||
|
|
||||||
@ -252,12 +250,9 @@ private:
|
|||||||
/// will also have this method return false. The converse is not true.
|
/// will also have this method return false. The converse is not true.
|
||||||
bool isMutable() const { return Left & Mutable; }
|
bool isMutable() const { return Left & Mutable; }
|
||||||
|
|
||||||
/// getSafeLeft - Returns the pointer to the left tree by always masking
|
/// hasCachedDigest - Returns true if the digest for this tree is cached.
|
||||||
/// out the mutable bit. This is used internally by ImutAVLFactory,
|
/// This can only be true if the tree is immutable.
|
||||||
/// as no trees returned to the client should have the mutable flag set.
|
bool hasCachedDigest() const { return !(Left & NoCachedDigest); }
|
||||||
ImutAVLTree* getSafeLeft() const {
|
|
||||||
return reinterpret_cast<ImutAVLTree*>(Left & ~Mutable);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------===//
|
//===----------------------------------------------------===//
|
||||||
// Mutating operations. A tree root can be manipulated as
|
// Mutating operations. A tree root can be manipulated as
|
||||||
@ -270,22 +265,28 @@ private:
|
|||||||
// immutable.
|
// immutable.
|
||||||
//===----------------------------------------------------===//
|
//===----------------------------------------------------===//
|
||||||
|
|
||||||
|
|
||||||
/// MarkImmutable - Clears the mutable flag for a tree. After this happens,
|
/// MarkImmutable - Clears the mutable flag for a tree. After this happens,
|
||||||
/// it is an error to call setLeft(), setRight(), and setHeight(). It
|
/// it is an error to call setLeft(), setRight(), and setHeight().
|
||||||
/// is also then safe to call getLeft() instead of getSafeLeft().
|
|
||||||
void MarkImmutable() {
|
void MarkImmutable() {
|
||||||
assert (isMutable() && "Mutable flag already removed.");
|
assert(isMutable() && "Mutable flag already removed.");
|
||||||
Left &= ~Mutable;
|
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
|
/// setLeft - Changes the reference of the left subtree. Used internally
|
||||||
/// by ImutAVLFactory.
|
/// by ImutAVLFactory.
|
||||||
void setLeft(ImutAVLTree* NewLeft) {
|
void setLeft(ImutAVLTree* NewLeft) {
|
||||||
assert (isMutable() &&
|
assert(isMutable() &&
|
||||||
"Only a mutable tree can have its left subtree changed.");
|
"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
|
/// setRight - Changes the reference of the right subtree. Used internally
|
||||||
@ -304,29 +305,36 @@ private:
|
|||||||
Height = h;
|
Height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
unsigned ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
|
uint32_t ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) {
|
||||||
unsigned digest = 0;
|
uint32_t digest = 0;
|
||||||
|
|
||||||
if (L) digest += L->ComputeDigest();
|
if (L)
|
||||||
|
digest += L->ComputeDigest();
|
||||||
|
|
||||||
{ // Compute digest of stored data.
|
// Compute digest of stored data.
|
||||||
FoldingSetNodeID ID;
|
FoldingSetNodeID ID;
|
||||||
ImutInfo::Profile(ID,V);
|
ImutInfo::Profile(ID,V);
|
||||||
digest += ID.ComputeHash();
|
digest += ID.ComputeHash();
|
||||||
}
|
|
||||||
|
|
||||||
if (R) digest += R->ComputeDigest();
|
if (R)
|
||||||
|
digest += R->ComputeDigest();
|
||||||
|
|
||||||
return digest;
|
return digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned ComputeDigest() {
|
inline uint32_t ComputeDigest() {
|
||||||
if (Digest) return Digest;
|
// Check the lowest bit to determine if digest has actually been
|
||||||
|
// pre-computed.
|
||||||
|
if (hasCachedDigest())
|
||||||
|
return Digest;
|
||||||
|
|
||||||
unsigned X = ComputeDigest(getSafeLeft(), getRight(), getValue());
|
uint32_t X = ComputeDigest(getLeft(), getRight(), getValue());
|
||||||
if (!isMutable()) Digest = X;
|
|
||||||
|
if (!isMutable()) {
|
||||||
|
Digest = X;
|
||||||
|
MarkedCachedDigest();
|
||||||
|
}
|
||||||
|
|
||||||
return X;
|
return X;
|
||||||
}
|
}
|
||||||
@ -394,7 +402,7 @@ private:
|
|||||||
|
|
||||||
bool isEmpty(TreeTy* T) const { return !T; }
|
bool isEmpty(TreeTy* T) const { return !T; }
|
||||||
unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; }
|
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(); }
|
TreeTy* Right(TreeTy* T) const { return T->getRight(); }
|
||||||
value_type_ref Value(TreeTy* T) const { return T->Value; }
|
value_type_ref Value(TreeTy* T) const { return T->Value; }
|
||||||
|
|
||||||
@ -701,7 +709,7 @@ public:
|
|||||||
|
|
||||||
switch (getVisitState()) {
|
switch (getVisitState()) {
|
||||||
case VisitedNone:
|
case VisitedNone:
|
||||||
if (TreeTy* L = Current->getSafeLeft())
|
if (TreeTy* L = Current->getLeft())
|
||||||
stack.push_back(reinterpret_cast<uintptr_t>(L));
|
stack.push_back(reinterpret_cast<uintptr_t>(L));
|
||||||
else
|
else
|
||||||
stack.back() |= VisitedLeft;
|
stack.back() |= VisitedLeft;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user