Update eraseTree to account for leaves

This commit is contained in:
2024-11-22 18:27:45 -08:00
parent 8b71852495
commit 235938b5aa

View File

@@ -276,6 +276,8 @@ struct TaggedNodePointer {
__builtin_prefetch((void *)withoutType());
}
bool isLeaf() { return getType() > Type_Node256; }
private:
TaggedNodePointer(struct Node *p, Type t) : p((uintptr_t)p) {
assert((this->p & 15) == 0);
@@ -3069,6 +3071,12 @@ void eraseTree(Node *root, WriteContext *writeContext) {
removeKey(n);
auto pushIfNotLeaf = [&toFree](TaggedNodePointer p) {
if (!p.isLeaf()) {
toFree.push_back(p);
}
};
switch (n->getType()) {
case Type_Node0: {
auto *n0 = static_cast<Node0 *>(n);
@@ -3077,31 +3085,33 @@ void eraseTree(Node *root, WriteContext *writeContext) {
case Type_Node3: {
auto *n3 = static_cast<Node3 *>(n);
for (int i = 0; i < n3->numChildren; ++i) {
toFree.push_back(n3->children[i]);
pushIfNotLeaf(n3->children[i]);
}
writeContext->release(n3);
} break;
case Type_Node16: {
auto *n16 = static_cast<Node16 *>(n);
for (int i = 0; i < n16->numChildren; ++i) {
toFree.push_back(n16->children[i]);
pushIfNotLeaf(n16->children[i]);
}
writeContext->release(n16);
} break;
case Type_Node48: {
auto *n48 = static_cast<Node48 *>(n);
for (int i = 0; i < n48->numChildren; ++i) {
toFree.push_back(n48->children[i]);
pushIfNotLeaf(n48->children[i]);
}
writeContext->release(n48);
} break;
case Type_Node256: {
auto *n256 = static_cast<Node256 *>(n);
auto *out = toFree.unsafePrepareAppend(n256->numChildren).data();
n256->bitSet.forEachSet([&](int i) { *out++ = n256->children[i]; });
assert(out == toFree.end());
n256->bitSet.forEachSet([&](int i) { pushIfNotLeaf(n256->children[i]); });
writeContext->release(n256);
} break;
case Type_Leaf3: // GCOVR_EXCL_LINE
case Type_Leaf16: // GCOVR_EXCL_LINE
case Type_Leaf48: // GCOVR_EXCL_LINE
case Type_Leaf256: // GCOVR_EXCL_LINE
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}