From 4e685bbc3b1cacc8a1b728855fe314bd9a3308c6 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Wed, 30 Oct 2024 14:16:36 -0700 Subject: [PATCH] Use deferred release instead of hacky dontInvalidate logic --- ConflictSet.cpp | 60 ++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index cf5badf..51e1d67 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1849,7 +1849,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity, newSelf->copyChildrenAndKeyFrom(*self0); getInTree(self, impl) = newSelf; if (kUseFreeList) { - writeContext->release(self0); + writeContext->deferRelease(self0, newSelf); } else { removeNode(self0); safe_free(self0, self0->size()); @@ -1862,7 +1862,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity, newSelf->copyChildrenAndKeyFrom(*self3); getInTree(self, impl) = newSelf; if (kUseFreeList) { - writeContext->release(self3); + writeContext->deferRelease(self3, newSelf); } else { removeNode(self3); safe_free(self3, self3->size()); @@ -1875,7 +1875,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity, newSelf->copyChildrenAndKeyFrom(*self16); getInTree(self, impl) = newSelf; if (kUseFreeList) { - writeContext->release(self16); + writeContext->deferRelease(self16, newSelf); } else { removeNode(self16); safe_free(self16, self16->size()); @@ -1888,7 +1888,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity, newSelf->copyChildrenAndKeyFrom(*self48); getInTree(self, impl) = newSelf; if (kUseFreeList) { - writeContext->release(self48); + writeContext->deferRelease(self48, newSelf); } else { removeNode(self48); safe_free(self48, self48->size()); @@ -1901,7 +1901,7 @@ void freeAndMakeCapacityAtLeast(Node *&self, int capacity, newSelf->copyChildrenAndKeyFrom(*self256); getInTree(self, impl) = newSelf; if (kUseFreeList) { - writeContext->release(self256); + writeContext->deferRelease(self256, newSelf); } else { removeNode(self256); safe_free(self256, self256->size()); @@ -1999,18 +1999,13 @@ void rezero(Node *n, InternalVersionT z) { #endif void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext, - ConflictSet::Impl *impl, Node *&dontInvalidate, - Node3 *self3) { + ConflictSet::Impl *impl, Node3 *self3) { assert(!self3->entryPresent); Node *child = self3->children[0]; int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen; if (minCapacity > child->getCapacity()) { - const bool update = child == dontInvalidate; freeAndMakeCapacityAtLeast(child, minCapacity, writeContext, impl, true); - if (update) { - dontInvalidate = child; - } } // Merge partial key with child @@ -2037,7 +2032,7 @@ void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext, setMaxVersion(child, std::max(childMaxVersion, writeContext->zero)); self = child; - writeContext->release(self3); + writeContext->deferRelease(self3, self); } bool needsDownsize(Node *n) { @@ -2046,17 +2041,16 @@ bool needsDownsize(Node *n) { return n->numChildren + n->entryPresent < minTable[n->getType()]; } -void downsize(Node3 *self, WriteContext *writeContext, ConflictSet::Impl *impl, - Node *&dontInvalidate) { +void downsize(Node3 *self, WriteContext *writeContext, + ConflictSet::Impl *impl) { if (self->numChildren == 0) { auto *newSelf = writeContext->allocate(self->partialKeyLen); newSelf->copyChildrenAndKeyFrom(*self); getInTree(self, impl) = newSelf; - writeContext->release(self); + writeContext->deferRelease(self, newSelf); } else { assert(self->numChildren == 1 && !self->entryPresent); - mergeWithChild(getInTree(self, impl), writeContext, impl, dontInvalidate, - self); + mergeWithChild(getInTree(self, impl), writeContext, impl, self); } } @@ -2066,7 +2060,7 @@ void downsize(Node16 *self, WriteContext *writeContext, auto *newSelf = writeContext->allocate(self->partialKeyLen); newSelf->copyChildrenAndKeyFrom(*self); getInTree(self, impl) = newSelf; - writeContext->release(self); + writeContext->deferRelease(self, newSelf); } void downsize(Node48 *self, WriteContext *writeContext, @@ -2075,7 +2069,7 @@ void downsize(Node48 *self, WriteContext *writeContext, auto *newSelf = writeContext->allocate(self->partialKeyLen); newSelf->copyChildrenAndKeyFrom(*self); getInTree(self, impl) = newSelf; - writeContext->release(self); + writeContext->deferRelease(self, newSelf); } void downsize(Node256 *self, WriteContext *writeContext, @@ -2085,17 +2079,16 @@ void downsize(Node256 *self, WriteContext *writeContext, auto *newSelf = writeContext->allocate(self->partialKeyLen); newSelf->copyChildrenAndKeyFrom(*self256); getInTree(self, impl) = newSelf; - writeContext->release(self256); + writeContext->deferRelease(self256, newSelf); } -void downsize(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, - Node *&dontInvalidate) { +void downsize(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl) { switch (self->getType()) { case Type_Node0: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE case Type_Node3: - downsize(static_cast(self), writeContext, impl, dontInvalidate); + downsize(static_cast(self), writeContext, impl); break; case Type_Node16: downsize(static_cast(self), writeContext, impl); @@ -2135,7 +2128,12 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, if (self->numChildren != 0) { if (needsDownsize(self)) { - downsize(self, writeContext, impl, result); + downsize(self, writeContext, impl); + } + if (result != nullptr) { + while (result->releaseDeferred) { + result = result->forwardTo; + } } return result; } @@ -2158,7 +2156,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, } if (needsDownsize(parent3)) { - downsize(parent3, writeContext, impl, result); + downsize(parent3, writeContext, impl); } } break; case Type_Node16: { @@ -2173,7 +2171,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, } if (needsDownsize(parent16)) { - downsize(parent16, writeContext, impl, result); + downsize(parent16, writeContext, impl); } } break; case Type_Node48: { @@ -2201,7 +2199,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, parent48->childMaxVersion[lastChildrenIndex] = writeContext->zero; if (needsDownsize(parent48)) { - downsize(parent48, writeContext, impl, result); + downsize(parent48, writeContext, impl); } } break; case Type_Node256: { @@ -2212,13 +2210,18 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl, --parent->numChildren; if (needsDownsize(parent256)) { - downsize(parent256, writeContext, impl, result); + downsize(parent256, writeContext, impl); } } break; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } + if (result != nullptr) { + while (result->releaseDeferred) { + result = result->forwardTo; + } + } return result; } @@ -5102,6 +5105,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { n = nextPhysical(n); } } + writeContext.releaseDeferred(); gc_iterations_total.add(set_oldest_iterations_accum); if (n == nullptr) { removalKey = {};