diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 2ed53bb..26b50c0 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -902,6 +902,8 @@ Node *&getChildExists(Node *self, uint8_t index) { } InternalVersionT maxVersion(Node *n, ConflictSet::Impl *); +InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax, + ConflictSet::Impl *); void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion); @@ -2898,26 +2900,28 @@ checkMaxBetweenExclusiveImpl(Node *n, int begin, int end, longestCommonPrefix((*self)->partialKey(), key.data(), commonLen); if (partialKeyIndex < (*self)->partialKeyLen) { auto *old = *self; - InternalVersionT oldMaxVersion = maxVersion(old, impl); + InternalVersionT oldMaxVersion = + exchangeMaxVersion(old, writeVersion, impl); - // *self will have one child - *self = tls->allocate(partialKeyIndex); + // *self will have one child (old) + auto *newSelf = tls->allocate(partialKeyIndex); - memcpy((char *)*self + kNodeCopyBegin, (char *)old + kNodeCopyBegin, - kNodeCopySize); - (*self)->partialKeyLen = partialKeyIndex; + newSelf->parent = old->parent; + newSelf->parentsIndex = old->parentsIndex; + newSelf->partialKeyLen = partialKeyIndex; + newSelf->entryPresent = false; + newSelf->numChildren = 1; - // Not necessary to call removeKey here, since this node is "synthetic" - (*self)->entryPresent = false; + memcpy(newSelf->partialKey(), old->partialKey(), + newSelf->partialKeyLen); - (*self)->numChildren = 0; - memcpy((*self)->partialKey(), old->partialKey(), - (*self)->partialKeyLen); - - getOrCreateChild(*self, old->partialKey()[partialKeyIndex], tls) = old; - old->parent = *self; - old->parentsIndex = old->partialKey()[partialKeyIndex]; - setMaxVersion(old, impl, oldMaxVersion); + uint8_t oldDistinguishingByte = old->partialKey()[partialKeyIndex]; + old->parent = newSelf; + old->parentsIndex = oldDistinguishingByte; + newSelf->index[0] = oldDistinguishingByte; + newSelf->children[0] = old; + newSelf->childMaxVersion[0] = oldMaxVersion; + *self = newSelf; memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1, old->partialKeyLen - (partialKeyIndex + 1)); @@ -3548,6 +3552,41 @@ InternalVersionT maxVersion(Node *n, ConflictSet::Impl *impl) { } } +InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax, + ConflictSet::Impl *impl) { + int index = n->parentsIndex; + n = n->parent; + if (n == nullptr) { + return std::exchange(impl->rootMaxVersion, newMax); + } + switch (n->getType()) { + case Type_Node0: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + case Type_Node3: { + auto *n3 = static_cast(n); + int i = getNodeIndex(n3, index); + return std::exchange(n3->childMaxVersion[i], newMax); + } + case Type_Node16: { + auto *n16 = static_cast(n); + int i = getNodeIndex(n16, index); + return std::exchange(n16->childMaxVersion[i], newMax); + } + case Type_Node48: { + auto *n48 = static_cast(n); + assert(n48->bitSet.test(index)); + return std::exchange(n48->childMaxVersion[n48->index[index]], newMax); + } + case Type_Node256: { + auto *n256 = static_cast(n); + assert(n256->bitSet.test(index)); + return std::exchange(n256->childMaxVersion[index], newMax); + } + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + } +} + void setMaxVersion(Node *n, ConflictSet::Impl *impl, InternalVersionT newMax) { int index = n->parentsIndex; n = n->parent;