diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7755c1d..2f9c120 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,3 +8,11 @@ repos: rev: e2c2116d86a80e72e7146a06e68b7c228afc6319 hooks: - id: cmake-format + - repo: local + hooks: + - id: debug verbose check + name: disallow checking in DEBUG_VERBOSE=1 + description: disallow checking in DEBUG_VERBOSE=1 + entry: '^#define DEBUG_VERBOSE 1$' + language: pygrep + types: [c++] \ No newline at end of file diff --git a/ConflictSet.cpp b/ConflictSet.cpp index d50033b..8c52643 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -543,6 +543,27 @@ Node *&getOrCreateChild(Node *&self, uint8_t index) { } } +void fixMaxVersion(Node *self) { + for (;;) { + int64_t result = std::numeric_limits::lowest(); + if (self->entryPresent) { + result = std::max(result, self->entry.pointVersion); + result = std::max(result, self->entry.rangeVersion); + } + for (int i = getChildGeq(self, 0); i >= 0; i = getChildGeq(self, i + 1)) { + result = std::max(result, getChildExists(self, i)->maxVersion); + } + if (self->maxVersion == result) { + break; + } + self->maxVersion = result; + if (self->parent == nullptr) { + break; + } + self = self->parent; + } +} + // Precondition - an entry for index must exist in the node void eraseChild(Node *self, uint8_t index) { free(getChildExists(self, index)); @@ -814,21 +835,6 @@ void destroyTree(Node *root) { } } -void invalidateMax(Node *self) { - int64_t expectedMax = std::numeric_limits::lowest(); - if (self->entryPresent) { - expectedMax = std::max(expectedMax, self->entry.pointVersion); - expectedMax = std::max(expectedMax, self->entry.rangeVersion); - } - for (int i = getChildGeq(self, 0); i >= 0; i = getChildGeq(self, i + 1)) { - expectedMax = std::max(expectedMax, getChildExists(self, i)->maxVersion); - } - self->maxVersion = expectedMax; - if (self->parent != nullptr) { - invalidateMax(self->parent); - } -} - struct __attribute__((visibility("hidden"))) ConflictSet::Impl { void check(const ReadRange *reads, Result *result, int count) const { for (int i = 0; i < count; ++i) { @@ -858,33 +864,54 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { for (int i = 0; i < count; ++i) { const auto &w = writes[i]; if (w.end.len > 0) { - auto *n = insert(&root, std::span(w.end.p, w.end.len), - std::numeric_limits::lowest()); - if (!n->entryPresent) { - auto *p = prevLogical(n); - assert(p != nullptr); - n->entryPresent = true; - n->entry.pointVersion = p->entry.rangeVersion; - n->entry.rangeVersion = p->entry.rangeVersion; + auto *begin = + insert(&root, std::span(w.begin.p, w.begin.len), + w.writeVersion); + + const bool insertedBegin = !std::exchange(begin->entryPresent, true); + begin->entry.pointVersion = w.writeVersion; + + auto *end = insert(&root, std::span(w.end.p, w.end.len), + std::numeric_limits::lowest()); + + const bool insertedEnd = !std::exchange(end->entryPresent, true); + if (insertedEnd) { + // begin may have been invalidated + auto iter = + lastLeq(root, std::span(w.begin.p, w.begin.len)); + assert(iter.cmp == 0); + begin = iter.n; } - auto *end = n; - n = insert(&root, std::span(w.begin.p, w.begin.len), - std::numeric_limits::lowest()); - auto *begin = n; - n->entryPresent = true; - n->entry.pointVersion = w.writeVersion; - n->entry.rangeVersion = w.writeVersion; - for (n = nextLogical(n); n != end;) { - auto *old = n; - n = nextLogical(n); + if (insertedBegin) { + auto *p = prevLogical(begin); + assert(p != nullptr); + begin->entry.rangeVersion = p->entry.rangeVersion; + } + + if (insertedEnd) { + auto *p = prevLogical(end); + assert(p != nullptr); + end->entryPresent = true; + end->entry.pointVersion = p->entry.rangeVersion; + end->entry.rangeVersion = p->entry.rangeVersion; + } + + begin->entry.rangeVersion = w.writeVersion; + + for (begin = nextLogical(begin); begin != end;) { + auto *old = begin; + begin = nextLogical(begin); old->entryPresent = false; + fixMaxVersion(old); if (old->numChildren == 0 && old->parent != nullptr) { eraseChild(old->parent, old->parentsIndex); } } - invalidateMax(begin); - invalidateMax(end); + + if (insertedEnd) { + fixMaxVersion(end); + } } else { auto *n = insert(&root, std::span(w.begin.p, w.begin.len), @@ -1175,6 +1202,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fflush(stdout); abort(); } +#if DEBUG_VERBOSE && !defined(NDEBUG) + fprintf(stderr, "Check correctness\n"); +#endif bool success = checkCorrectness(driver.cs.root, driver.refImpl); if (!success) { debugPrintDot(stdout, driver.cs.root);