Specialize partial key split for newly created Node3

This commit is contained in:
2024-08-06 13:04:19 -07:00
parent a7b3d8fe4c
commit ed5589e4ed

View File

@@ -902,6 +902,8 @@ Node *&getChildExists(Node *self, uint8_t index) {
} }
InternalVersionT maxVersion(Node *n, ConflictSet::Impl *); InternalVersionT maxVersion(Node *n, ConflictSet::Impl *);
InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax,
ConflictSet::Impl *);
void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion); void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion);
@@ -2898,26 +2900,28 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
longestCommonPrefix((*self)->partialKey(), key.data(), commonLen); longestCommonPrefix((*self)->partialKey(), key.data(), commonLen);
if (partialKeyIndex < (*self)->partialKeyLen) { if (partialKeyIndex < (*self)->partialKeyLen) {
auto *old = *self; auto *old = *self;
InternalVersionT oldMaxVersion = maxVersion(old, impl); InternalVersionT oldMaxVersion =
exchangeMaxVersion(old, writeVersion, impl);
// *self will have one child // *self will have one child (old)
*self = tls->allocate<Node3>(partialKeyIndex); auto *newSelf = tls->allocate<Node3>(partialKeyIndex);
memcpy((char *)*self + kNodeCopyBegin, (char *)old + kNodeCopyBegin, newSelf->parent = old->parent;
kNodeCopySize); newSelf->parentsIndex = old->parentsIndex;
(*self)->partialKeyLen = partialKeyIndex; newSelf->partialKeyLen = partialKeyIndex;
newSelf->entryPresent = false;
newSelf->numChildren = 1;
// Not necessary to call removeKey here, since this node is "synthetic" memcpy(newSelf->partialKey(), old->partialKey(),
(*self)->entryPresent = false; newSelf->partialKeyLen);
(*self)->numChildren = 0; uint8_t oldDistinguishingByte = old->partialKey()[partialKeyIndex];
memcpy((*self)->partialKey(), old->partialKey(), old->parent = newSelf;
(*self)->partialKeyLen); old->parentsIndex = oldDistinguishingByte;
newSelf->index[0] = oldDistinguishingByte;
getOrCreateChild(*self, old->partialKey()[partialKeyIndex], tls) = old; newSelf->children[0] = old;
old->parent = *self; newSelf->childMaxVersion[0] = oldMaxVersion;
old->parentsIndex = old->partialKey()[partialKeyIndex]; *self = newSelf;
setMaxVersion(old, impl, oldMaxVersion);
memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1, memmove(old->partialKey(), old->partialKey() + partialKeyIndex + 1,
old->partialKeyLen - (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<Node3 *>(n);
int i = getNodeIndex(n3, index);
return std::exchange(n3->childMaxVersion[i], newMax);
}
case Type_Node16: {
auto *n16 = static_cast<Node16 *>(n);
int i = getNodeIndex(n16, index);
return std::exchange(n16->childMaxVersion[i], newMax);
}
case Type_Node48: {
auto *n48 = static_cast<Node48 *>(n);
assert(n48->bitSet.test(index));
return std::exchange(n48->childMaxVersion[n48->index[index]], newMax);
}
case Type_Node256: {
auto *n256 = static_cast<Node256 *>(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) { void setMaxVersion(Node *n, ConflictSet::Impl *impl, InternalVersionT newMax) {
int index = n->parentsIndex; int index = n->parentsIndex;
n = n->parent; n = n->parent;