From b808b97940a77f6d1c42a4e42ec1732226ecae0b Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Thu, 15 Aug 2024 17:15:37 -0700 Subject: [PATCH] Remove a bunch of impl plumbing By making it a precondition that nodes aren't the root for certain functions --- ConflictSet.cpp | 268 +++++++++++++++++++++++------------------------- 1 file changed, 128 insertions(+), 140 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 01d1967..4e4ba60 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -905,10 +905,115 @@ Node *&getChildExists(Node *self, uint8_t index) { } } -InternalVersionT maxVersion(Node *n, ConflictSet::Impl *); -InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax); +// Precondition `n` is not the root +InternalVersionT maxVersion(Node *n) { + int index = n->parentsIndex; + n = n->parent; + assert(n != nullptr); + 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 n3->childMaxVersion[i]; + } + case Type_Node16: { + auto *n16 = static_cast(n); + int i = getNodeIndex(n16, index); + return n16->childMaxVersion[i]; + } + case Type_Node48: { + auto *n48 = static_cast(n); + assert(n48->bitSet.test(index)); + return n48->childMaxVersion[n48->index[index]]; + } + case Type_Node256: { + auto *n256 = static_cast(n); + assert(n256->bitSet.test(index)); + return n256->childMaxVersion[index]; + } + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + } +} -void setMaxVersion(Node *n, ConflictSet::Impl *, InternalVersionT maxVersion); +// Precondition `n` is not the root +InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) { + int index = n->parentsIndex; + n = n->parent; + assert(n != nullptr); + 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 + } +} + +// Precondition `n` is not the root +void setMaxVersion(Node *n, InternalVersionT newMax) { + assert(newMax >= InternalVersionT::zero); + int index = n->parentsIndex; + n = n->parent; + assert(n != nullptr); + 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); + n3->childMaxVersion[i] = newMax; + return; + } + case Type_Node16: { + auto *n16 = static_cast(n); + int i = getNodeIndex(n16, index); + n16->childMaxVersion[i] = newMax; + return; + } + case Type_Node48: { + auto *n48 = static_cast(n); + assert(n48->bitSet.test(index)); + int i = n48->index[index]; + n48->childMaxVersion[i] = newMax; + n48->maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max( + n48->maxOfMax[i >> Node48::kMaxOfMaxShift], newMax); + return; + } + case Type_Node256: { + auto *n256 = static_cast(n); + assert(n256->bitSet.test(index)); + n256->childMaxVersion[index] = newMax; + n256->maxOfMax[index >> Node256::kMaxOfMaxShift] = + std::max( + n256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMax); + return; + } + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + } +} Node *&getInTree(Node *n, ConflictSet::Impl *); @@ -1578,7 +1683,7 @@ void mergeWithChild(Node *&self, WriteContext *tls, ConflictSet::Impl *impl, // Max versions are stored in the parent, so we need to update it now // that we have a new parent. - setMaxVersion(child, impl, std::max(childMaxVersion, tls->zero)); + setMaxVersion(child, std::max(childMaxVersion, tls->zero)); self = child; tls->release(self3); @@ -1850,10 +1955,9 @@ bool checkPrefixRead(Node *n, const std::span key, fprintf(stderr, "Check prefix read: %s\n", printable(key).c_str()); #endif auto remaining = key; - auto *impl = tls->impl; for (;; ++tls->prefix_read_iterations_accum) { if (remaining.size() == 0) { - return maxVersion(n, impl) <= readVersion; + return maxVersion(n) <= readVersion; } auto [child, maxV] = getChildAndMaxVersion(n, remaining[0]); @@ -1896,7 +2000,7 @@ bool checkPrefixRead(Node *n, const std::span key, // n is the first physical node greater than remaining, and there's no // eq node. All physical nodes that start with prefix are reachable from // n. - if (maxVersion(n, impl) > readVersion) { + if (maxVersion(n) > readVersion) { return false; } goto downLeftSpine; @@ -2375,7 +2479,6 @@ bool checkRangeStartsWith(Node *n, std::span key, int begin, fprintf(stderr, "%s(%02x,%02x)*\n", printable(key).c_str(), begin, end); #endif auto remaining = key; - auto *impl = tls->impl; if (remaining.size() == 0) { return checkMaxBetweenExclusive(n, begin, end, readVersion, tls); } @@ -2420,7 +2523,7 @@ bool checkRangeStartsWith(Node *n, std::span key, int begin, if (n->entryPresent && n->entry.rangeVersion > readVersion) { return false; } - return maxVersion(n, impl) <= readVersion; + return maxVersion(n) <= readVersion; } return true; } @@ -2460,7 +2563,7 @@ struct CheckRangeLeftSide { bool step() { if (remaining.size() == 0) { assert(searchPathLen >= prefixLen); - ok = maxVersion(n, impl) <= readVersion; + ok = maxVersion(n) <= readVersion; return true; } @@ -2480,7 +2583,7 @@ struct CheckRangeLeftSide { return downLeftSpine(); } n = c; - ok = maxVersion(n, impl) <= readVersion; + ok = maxVersion(n) <= readVersion; return true; } else { n = nextSibling(n); @@ -2510,7 +2613,7 @@ struct CheckRangeLeftSide { ok = false; return true; } - ok = maxVersion(n, impl) <= readVersion; + ok = maxVersion(n) <= readVersion; return true; } else { n = nextSibling(n); @@ -2530,7 +2633,7 @@ struct CheckRangeLeftSide { ok = false; return true; } - ok = maxVersion(n, impl) <= readVersion; + ok = maxVersion(n) <= readVersion; return true; } } @@ -2651,7 +2754,7 @@ struct CheckRangeRightSide { bool backtrack() { for (;;) { - if (searchPathLen > prefixLen && maxVersion(n, impl) > readVersion) { + if (searchPathLen > prefixLen && maxVersion(n) > readVersion) { ok = false; return true; } @@ -2878,8 +2981,9 @@ void addPointWrite(Node *&root, std::span key, } } -// Precondition: `node->entryPresent` -void fixupMaxVersion(Node *node, ConflictSet::Impl *impl, WriteContext *tls) { +// Precondition: `node->entryPresent`, and node is not the root +void fixupMaxVersion(Node *node, WriteContext *tls) { + assert(node->parent); InternalVersionT max; assert(node->entryPresent); max = std::max(node->entry.pointVersion, tls->zero); @@ -2913,7 +3017,7 @@ void fixupMaxVersion(Node *node, ConflictSet::Impl *impl, WriteContext *tls) { default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } - setMaxVersion(node, impl, max); + setMaxVersion(node, max); } void addWriteRange(Node *&root, std::span begin, @@ -2966,7 +3070,7 @@ void addWriteRange(Node *&root, std::span begin, } // Inserting end trashed endNode's maxVersion. Fix that - fixupMaxVersion(endNode, impl, tls); + fixupMaxVersion(endNode, tls); } Node *firstGeqPhysical(Node *n, const std::span key) { @@ -3134,7 +3238,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { // Don't erase the root if (n == root) { rezero(n, oldestVersion); - rootMaxVersion = std::max(rootMaxVersion, oldestVersion); n = nextPhysical(n); } int64_t set_oldest_iterations_accum = 0; @@ -3225,7 +3328,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { root = tls.allocate(0); root->numChildren = 0; root->parent = nullptr; - rootMaxVersion = this->oldestVersion; root->entryPresent = false; root->partialKeyLen = 0; @@ -3256,7 +3358,6 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { int64_t keyUpdates; Node *root; - InternalVersionT rootMaxVersion; InternalVersionT oldestVersion; int64_t oldestVersionFullPrecision; int64_t oldestExtantVersion; @@ -3355,119 +3456,6 @@ Metric::Metric(ConflictSet::Impl *impl, const char *name, const char *help, ++impl->metricsCount; } -InternalVersionT maxVersion(Node *n, ConflictSet::Impl *impl) { - int index = n->parentsIndex; - n = n->parent; - if (n == nullptr) { - return impl->rootMaxVersion; - } - 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 n3->childMaxVersion[i]; - } - case Type_Node16: { - auto *n16 = static_cast(n); - int i = getNodeIndex(n16, index); - return n16->childMaxVersion[i]; - } - case Type_Node48: { - auto *n48 = static_cast(n); - assert(n48->bitSet.test(index)); - return n48->childMaxVersion[n48->index[index]]; - } - case Type_Node256: { - auto *n256 = static_cast(n); - assert(n256->bitSet.test(index)); - return n256->childMaxVersion[index]; - } - default: // GCOVR_EXCL_LINE - __builtin_unreachable(); // GCOVR_EXCL_LINE - } -} - -// Precondition `n` is not the root -InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) { - int index = n->parentsIndex; - n = n->parent; - assert(n != nullptr); - 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) { - assert(newMax >= InternalVersionT::zero); - int index = n->parentsIndex; - n = n->parent; - if (n == nullptr) { - impl->rootMaxVersion = newMax; - return; - } - 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); - n3->childMaxVersion[i] = newMax; - return; - } - case Type_Node16: { - auto *n16 = static_cast(n); - int i = getNodeIndex(n16, index); - n16->childMaxVersion[i] = newMax; - return; - } - case Type_Node48: { - auto *n48 = static_cast(n); - assert(n48->bitSet.test(index)); - int i = n48->index[index]; - n48->childMaxVersion[i] = newMax; - n48->maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max( - n48->maxOfMax[i >> Node48::kMaxOfMaxShift], newMax); - return; - } - case Type_Node256: { - auto *n256 = static_cast(n); - assert(n256->bitSet.test(index)); - n256->childMaxVersion[index] = newMax; - n256->maxOfMax[index >> Node256::kMaxOfMaxShift] = - std::max( - n256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMax); - return; - } - default: // GCOVR_EXCL_LINE - __builtin_unreachable(); // GCOVR_EXCL_LINE - } -} - Node *&getInTree(Node *n, ConflictSet::Impl *impl) { return n->parent == nullptr ? impl->root : getChildExists(n->parent, n->parentsIndex); @@ -3749,13 +3737,13 @@ std::string getSearchPath(Node *n) { fprintf(file, " k_%p [label=\"m=%" PRId64 " p=%" PRId64 " r=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n", - (void *)n, maxVersion(n, impl).toInt64(), + (void *)n, maxVersion(n).toInt64(), n->entry.pointVersion.toInt64(), n->entry.rangeVersion.toInt64(), getPartialKeyPrintable(n).c_str(), x, y); } else { fprintf(file, " k_%p [label=\"m=%" PRId64 "\n%s\", pos=\"%d,%d!\"];\n", - (void *)n, maxVersion(n, impl).toInt64(), + (void *)n, maxVersion(n).toInt64(), getPartialKeyPrintable(n).c_str(), x, y); } x += kSeparation; @@ -3866,11 +3854,11 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion, expected = std::max(expected, borrowed->entry.rangeVersion); } } - if (maxVersion(node, impl) > oldestVersion && - maxVersion(node, impl) != expected) { + if (node->parent && maxVersion(node) > oldestVersion && + maxVersion(node) != expected) { fprintf(stderr, "%s has max version %" PRId64 " . Expected %" PRId64 "\n", - getSearchPathPrintable(node).c_str(), - maxVersion(node, impl).toInt64(), expected.toInt64()); + getSearchPathPrintable(node).c_str(), maxVersion(node).toInt64(), + expected.toInt64()); success = false; } return expected;