diff --git a/ConflictSet.cpp b/ConflictSet.cpp index bef8fb9..a99d920 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1741,109 +1741,69 @@ void addWriteRange(Node *&root, int64_t oldestVersion, } } -struct FirstGeqStepwise { - Node *n; - std::span remaining; - int cmp; - - enum Phase { - Init, - // Being in this phase implies that the key matches the search path exactly - // up to this point - Search, - DownLeftSpine - }; - Phase phase; - - FirstGeqStepwise(Node *n, std::span remaining) - : n(n), remaining(remaining), phase(Init) {} - - // Not being done implies that n is not the firstGeq - bool step() { - switch (phase) { - case Search: { - if (remaining.size() == 0) { - int c = getChildGeq(n, 0); - assert(c >= 0); - n = getChildExists(n, c); - return downLeftSpine(); +Iterator firstGeq(Node *n, const std::span key) { + auto remaining = key; + for (;;) { + if (remaining.size() == 0) { + if (n->entryPresent) { + return {n, 0}; } - - auto *child = getChild(n, remaining[0]); - if (child == nullptr) { - int c = getChildGeq(n, remaining[0]); - if (c >= 0) { - n = getChildExists(n, c); - return downLeftSpine(); - } else { - n = nextSibling(n); - return downLeftSpine(); - } - } - - n = child; - remaining = remaining.subspan(1, remaining.size() - 1); - - if (n->partialKeyLen > 0) { - int commonLen = std::min(n->partialKeyLen, remaining.size()); - int i = longestCommonPrefixPartialKey(n->partialKey, remaining.data(), - commonLen); - if (i < commonLen) { - auto c = n->partialKey[i] <=> remaining[i]; - if (c > 0) { - return downLeftSpine(); - } else { - n = nextSibling(n); - return downLeftSpine(); - } - } - if (commonLen == n->partialKeyLen) { - // partial key matches - remaining = - remaining.subspan(commonLen, remaining.size() - commonLen); - } else if (n->partialKeyLen > int(remaining.size())) { - // n is the first physical node greater than remaining, and there's no - // eq node - return downLeftSpine(); - } - } - } - [[fallthrough]]; - case Init: - phase = Search; - if (remaining.size() == 0 && n->entryPresent) { - cmp = 0; - return true; - } - return false; - case DownLeftSpine: int c = getChildGeq(n, 0); assert(c >= 0); n = getChildExists(n, c); - if (n->entryPresent) { - cmp = 1; - return true; + goto downLeftSpine; + } + + auto *child = getChild(n, remaining[0]); + if (child == nullptr) { + int c = getChildGeq(n, remaining[0]); + if (c >= 0) { + n = getChildExists(n, c); + goto downLeftSpine; + } else { + n = nextSibling(n); + goto downLeftSpine; } - return false; } - __builtin_unreachable(); // GCOVR_EXCL_LINE - } - bool downLeftSpine() { - phase = DownLeftSpine; - if (n == nullptr || n->entryPresent) { - cmp = 1; - return true; + n = child; + remaining = remaining.subspan(1, remaining.size() - 1); + + if (n->partialKeyLen > 0) { + int commonLen = std::min(n->partialKeyLen, remaining.size()); + int i = longestCommonPrefixPartialKey(n->partialKey, remaining.data(), + commonLen); + if (i < commonLen) { + auto c = n->partialKey[i] <=> remaining[i]; + if (c > 0) { + goto downLeftSpine; + } else { + n = nextSibling(n); + goto downLeftSpine; + } + } + if (commonLen == n->partialKeyLen) { + // partial key matches + remaining = remaining.subspan(commonLen, remaining.size() - commonLen); + } else if (n->partialKeyLen > int(remaining.size())) { + // n is the first physical node greater than remaining, and there's no + // eq node + goto downLeftSpine; + } } - return step(); } -}; - -Iterator firstGeq(Node *n, const std::span key) { - FirstGeqStepwise stepwise{n, key}; - while (!stepwise.step()) - ; - return {stepwise.n, stepwise.cmp}; +downLeftSpine: + if (n == nullptr) { + return {nullptr, 1}; + } + for (;;) { + if (n->entryPresent) { + return {n, 1}; + } + int c = getChildGeq(n, 0); + assert(c >= 0); + n = getChildExists(n, c); + } } struct __attribute__((visibility("hidden"))) ConflictSet::Impl {