diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 5f56f5d..de1be22 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -219,6 +219,8 @@ template struct NodeAllocator; struct TaggedNodePointer { TaggedNodePointer() = default; operator struct Node *() { return (struct Node *)withoutType(); } + // In preparation for when we might store leafs directly in parents + struct Node *asNodeUnsafe() { return (struct Node *)withoutType(); } operator struct Node0 *() { assert(getType() == Type_Node0); return (struct Node0 *)withoutType(); @@ -1470,7 +1472,8 @@ void consumePartialKeyFull(TaggedNodePointer &self, TrivialSpan &key, int partialKeyIndex = longestCommonPrefix(self->partialKey(), key.data(), commonLen); if (partialKeyIndex < self->partialKeyLen) { - Node *old = self; + // Safety: self has a partial key so it can't be a leaf + Node *old = self.asNodeUnsafe(); // Since root cannot have a partial key assert(old->parent != nullptr); InternalVersionT oldMaxVersion = exchangeMaxVersion(old, writeVersion); @@ -1628,7 +1631,8 @@ TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self, TrivialSpan &key, self3->childMaxVersion[i + 1] = newMaxVersion; result = newChild; ++self->numChildren; - newChild->parent = self; + // Safety: self has a child so it can't be a leaf + newChild->parent = self.asNodeUnsafe(); return result; } case Type_Node16: { @@ -1660,7 +1664,8 @@ TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self, TrivialSpan &key, self16->childMaxVersion[i + 1] = newMaxVersion; result = newChild; ++self->numChildren; - newChild->parent = self; + // Safety: self has a child so it can't be a leaf + newChild->parent = self.asNodeUnsafe(); return result; } case Type_Node48: { @@ -1687,7 +1692,8 @@ TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self, TrivialSpan &key, self48->maxOfMax[nextFree >> Node48::kMaxOfMaxShift] = std::max( newMaxVersion, self48->maxOfMax[nextFree >> Node48::kMaxOfMaxShift]); result = newChild; - newChild->parent = self; + // Safety: self has a child so it can't be a leaf + newChild->parent = self.asNodeUnsafe(); return result; } case Type_Node256: { @@ -1701,7 +1707,8 @@ TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self, TrivialSpan &key, self256->maxOfMax[index >> Node256::kMaxOfMaxShift] = std::max( newMaxVersion, self256->maxOfMax[index >> Node256::kMaxOfMaxShift]); result = newChild; - newChild->parent = self; + // Safety: self has a child so it can't be a leaf + newChild->parent = self.asNodeUnsafe(); return result; } default: // GCOVR_EXCL_LINE @@ -1921,7 +1928,7 @@ void mergeWithChild(TaggedNodePointer &self, WriteContext *writeContext, setMaxVersion(child, std::max(childMaxVersion, writeContext->zero)); self = child; - writeContext->deferRelease(self3, self); + writeContext->deferRelease(self3, child); } bool needsDownsize(Node *n) {