diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 1604f5b..7c5820a 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -829,7 +829,7 @@ void maybeDecreaseCapacity(Node *&self, NodeAllocators *allocators, // TODO fuse into erase child so we don't need to repeat branches on type void maybeDownsize(Node *self, NodeAllocators *allocators, - ConflictSet::Impl *impl) { + ConflictSet::Impl *impl, Node *&dontInvalidate) { switch (self->type) { case Type::Node0: __builtin_unreachable(); // GCOVR_EXCL_LINE @@ -954,7 +954,8 @@ void maybeDownsize(Node *self, NodeAllocators *allocators, } // Precondition: self is not the root. May invalidate nodes along the search -// path to self. +// path to self. May invalidate children of self->parent. Returns a pointer to +// the node after self. Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl) { assert(self->parent != nullptr); @@ -1019,7 +1020,7 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl) { parent->parent != nullptr) { erase(parent, allocators, impl); } else { - maybeDownsize(parent, allocators, impl); + maybeDownsize(parent, allocators, impl, result); } return result; } @@ -2014,8 +2015,14 @@ void addWriteRange(Node *&root, int64_t oldestVersion, assert(beginNode->entryPresent); } - for (beginNode = nextLogical(beginNode); beginNode != endNode; - beginNode = erase(beginNode, allocators, impl)) { + for (beginNode = nextLogical(beginNode); beginNode != endNode;) { + auto *next = nextLogical(beginNode); + bool done = next == endNode; + erase(beginNode, allocators, impl); + if (done) { + break; + } + beginNode = next; } }