diff --git a/ConflictSet.cpp b/ConflictSet.cpp index f4bfef0..15814af 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1086,7 +1086,7 @@ void maybeDecreaseCapacity(Node *&self, NodeAllocators *allocators, allocators, impl); } -// TODO fuse into erase child so we don't need to repeat branches on type +template void maybeDownsize(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, Node *&dontInvalidate) { @@ -1094,7 +1094,9 @@ void maybeDownsize(Node *self, NodeAllocators *allocators, fprintf(stderr, "maybeDownsize: %s\n", getSearchPathPrintable(self).c_str()); #endif - switch (self->getType()) { + assert(self->getType() == kType); + static_assert(kType != Type_Node0); + switch (kType) { case Type_Node0: __builtin_unreachable(); // GCOVR_EXCL_LINE case Type_Node3: { @@ -1198,7 +1200,24 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, if (self->numChildren != 0) { const bool update = result == dontInvalidate; - maybeDownsize(self, allocators, impl, result); + switch (self->getType()) { + case Type_Node0: + __builtin_unreachable(); // GCOVR_EXCL_LINE + case Type_Node3: + maybeDownsize(self, allocators, impl, result); + break; + case Type_Node16: + maybeDownsize(self, allocators, impl, result); + break; + case Type_Node48: + maybeDownsize(self, allocators, impl, result); + break; + case Type_Node256: + maybeDownsize(self, allocators, impl, result); + break; + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + } if (update) { dontInvalidate = result; } @@ -1238,6 +1257,18 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, memmove(parent3->children + nodeIndex, parent3->children + nodeIndex + 1, sizeof(parent3->children[0]) * (parent->numChildren - (nodeIndex + 1))); + + --parent->numChildren; + if (parent->numChildren == 0 && !parent->entryPresent && + parent->parent != nullptr) { + return erase(parent, allocators, impl, dontInvalidate); + } else { + const bool update = result == dontInvalidate; + maybeDownsize(parent, allocators, impl, result); + if (update) { + dontInvalidate = result; + } + } } break; case Type_Node16: { auto *parent16 = static_cast(parent); @@ -1249,6 +1280,18 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, memmove(parent16->children + nodeIndex, parent16->children + nodeIndex + 1, sizeof(parent16->children[0]) * (parent->numChildren - (nodeIndex + 1))); + + --parent->numChildren; + if (parent->numChildren == 0 && !parent->entryPresent && + parent->parent != nullptr) { + return erase(parent, allocators, impl, dontInvalidate); + } else { + const bool update = result == dontInvalidate; + maybeDownsize(parent, allocators, impl, result); + if (update) { + dontInvalidate = result; + } + } } break; case Type_Node48: { auto *parent48 = static_cast(parent); @@ -1264,27 +1307,40 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl, parent48->index[parent48->children[toRemoveChildrenIndex] .child->parentsIndex] = toRemoveChildrenIndex; } + + --parent->numChildren; + if (parent->numChildren == 0 && !parent->entryPresent && + parent->parent != nullptr) { + return erase(parent, allocators, impl, dontInvalidate); + } else { + const bool update = result == dontInvalidate; + maybeDownsize(parent, allocators, impl, result); + if (update) { + dontInvalidate = result; + } + } } break; case Type_Node256: { auto *parent256 = static_cast(parent); parent256->bitSet.reset(parentsIndex); parent256->children[parentsIndex].child = nullptr; + + --parent->numChildren; + if (parent->numChildren == 0 && !parent->entryPresent && + parent->parent != nullptr) { + return erase(parent, allocators, impl, dontInvalidate); + } else { + const bool update = result == dontInvalidate; + maybeDownsize(parent, allocators, impl, result); + if (update) { + dontInvalidate = result; + } + } } break; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } - --parent->numChildren; - if (parent->numChildren == 0 && !parent->entryPresent && - parent->parent != nullptr) { - return erase(parent, allocators, impl, dontInvalidate); - } else { - const bool update = result == dontInvalidate; - maybeDownsize(parent, allocators, impl, result); - if (update) { - dontInvalidate = result; - } - } return result; }