diff --git a/ConflictSet.cpp b/ConflictSet.cpp index ca2558a..c4074aa 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1675,53 +1675,67 @@ void mergeWithChild(Node *&self, WriteContext *tls, ConflictSet::Impl *impl, tls->release(self3); } -void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl, - Node *&dontInvalidate) { +bool needsDownsize(Node *n) { + static int minTable[] = {0, kMinChildrenNode3, kMinChildrenNode16, + kMinChildrenNode48, kMinChildrenNode256}; + return n->numChildren + n->entryPresent < minTable[n->getType()]; +} -#if DEBUG_VERBOSE && !defined(NDEBUG) - fprintf(stderr, "maybeDownsize: %s\n", getSearchPathPrintable(self).c_str()); -#endif +void downsize(Node3 *self, WriteContext *tls, ConflictSet::Impl *impl, + Node *&dontInvalidate) { + if (self->numChildren == 0) { + auto *newSelf = tls->allocate(self->partialKeyLen); + newSelf->copyChildrenAndKeyFrom(*self); + getInTree(self, impl) = newSelf; + tls->release(self); + } else { + assert(self->numChildren == 1 && !self->entryPresent); + mergeWithChild(getInTree(self, impl), tls, impl, dontInvalidate, self); + } +} + +void downsize(Node16 *self, WriteContext *tls, ConflictSet::Impl *impl) { + assert(self->numChildren + int(self->entryPresent) < kMinChildrenNode16); + auto *newSelf = tls->allocate(self->partialKeyLen); + newSelf->copyChildrenAndKeyFrom(*self); + getInTree(self, impl) = newSelf; + tls->release(self); +} + +void downsize(Node48 *self, WriteContext *tls, ConflictSet::Impl *impl) { + assert(self->numChildren + int(self->entryPresent) < kMinChildrenNode48); + auto *newSelf = tls->allocate(self->partialKeyLen); + newSelf->copyChildrenAndKeyFrom(*self); + getInTree(self, impl) = newSelf; + tls->release(self); +} + +void downsize(Node256 *self, WriteContext *tls, ConflictSet::Impl *impl) { + assert(self->numChildren + int(self->entryPresent) < kMinChildrenNode256); + auto *self256 = (Node256 *)self; + auto *newSelf = tls->allocate(self->partialKeyLen); + newSelf->copyChildrenAndKeyFrom(*self256); + getInTree(self, impl) = newSelf; + tls->release(self256); +} + +void downsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl, + Node *&dontInvalidate) { switch (self->getType()) { case Type_Node0: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE - case Type_Node3: { - auto *self3 = (Node3 *)self; - if (self->numChildren == 0) { - auto *newSelf = tls->allocate(self->partialKeyLen); - newSelf->copyChildrenAndKeyFrom(*self3); - getInTree(self, impl) = newSelf; - tls->release(self3); - } else if (self->numChildren == 1 && !self->entryPresent) { - mergeWithChild(getInTree(self, impl), tls, impl, dontInvalidate, self3); - } - } break; + case Type_Node3: + downsize(static_cast(self), tls, impl, dontInvalidate); + break; case Type_Node16: - if (self->numChildren + int(self->entryPresent) < kMinChildrenNode16) { - auto *self16 = (Node16 *)self; - auto *newSelf = tls->allocate(self->partialKeyLen); - newSelf->copyChildrenAndKeyFrom(*self16); - getInTree(self, impl) = newSelf; - tls->release(self16); - } + downsize(static_cast(self), tls, impl); break; case Type_Node48: - if (self->numChildren + int(self->entryPresent) < kMinChildrenNode48) { - auto *self48 = (Node48 *)self; - auto *newSelf = tls->allocate(self->partialKeyLen); - newSelf->copyChildrenAndKeyFrom(*self48); - getInTree(self, impl) = newSelf; - tls->release(self48); - } + downsize(static_cast(self), tls, impl); break; case Type_Node256: - if (self->numChildren + int(self->entryPresent) < kMinChildrenNode256) { - auto *self256 = (Node256 *)self; - auto *newSelf = tls->allocate(self->partialKeyLen); - newSelf->copyChildrenAndKeyFrom(*self256); - getInTree(self, impl) = newSelf; - tls->release(self256); - } + downsize(static_cast(self), tls, impl); break; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE @@ -1751,7 +1765,9 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, self->entryPresent = false; if (self->numChildren != 0) { - maybeDownsize(self, tls, impl, result); + if (needsDownsize(self)) { + downsize(self, tls, impl, result); + } return result; } @@ -1771,7 +1787,10 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, parent3->children[i] = parent3->children[i + 1]; parent3->childMaxVersion[i] = parent3->childMaxVersion[i + 1]; } - assert(parent->numChildren > 0 || parent->entryPresent); + + if (needsDownsize(parent3)) { + downsize(parent3, tls, impl, result); + } } break; case Type_Node16: { auto *parent16 = static_cast(parent); @@ -1784,8 +1803,9 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, parent16->childMaxVersion[i] = parent16->childMaxVersion[i + 1]; } - // By kMinChildrenNode16 - assert(parent->numChildren > 0); + if (needsDownsize(parent16)) { + downsize(parent16, tls, impl, result); + } } break; case Type_Node48: { auto *parent48 = static_cast(parent); @@ -1813,8 +1833,9 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, --parent->numChildren; - // By kMinChildrenNode48 - assert(parent->numChildren > 0); + if (needsDownsize(parent48)) { + downsize(parent48, tls, impl, result); + } } break; case Type_Node256: { auto *parent256 = static_cast(parent); @@ -1823,16 +1844,14 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, --parent->numChildren; - // By kMinChildrenNode256 - assert(parent->numChildren > 0); - + if (needsDownsize(parent256)) { + downsize(parent256, tls, impl, result); + } } break; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } - maybeDownsize(parent, tls, impl, result); - return result; }