diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 108616c..61fc5fc 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -100,6 +100,8 @@ struct BitSet { } int firstSetGeq(int i) const { + assert(0 <= i); + assert(i < 256); if (i < 128) { int a = std::countr_zero(lo >> i); if (a < 128) { @@ -126,7 +128,10 @@ struct Node48 : Node { Node *children[48] = {}; int8_t nextFree = 0; int8_t index[256]; - Node48() { this->type = Type::Node48; } + Node48() { + memset(index, -1, 256); + this->type = Type::Node48; + } }; struct Node256 : Node { @@ -443,7 +448,7 @@ void eraseChild(Node *self, uint8_t index) { } else if (self->type == Type::Node48) { auto *self48 = static_cast(self); self48->bitSet.reset(index); - int8_t toRemoveChildrenIndex = self48->index[index]; + int8_t toRemoveChildrenIndex = std::exchange(self48->index[index], -1); int8_t lastChildrenIndex = --self48->nextFree; assert(toRemoveChildrenIndex >= 0); assert(lastChildrenIndex >= 0); @@ -730,18 +735,60 @@ downLeftSpine: } int64_t maxBetweenExclusive(Node *n, int begin, int end) { + assert(-1 <= begin); + assert(begin <= 256); + assert(-1 <= end); + assert(end <= 256); + assert(begin < end); int64_t result = std::numeric_limits::lowest(); - int next = begin; - for (;;) { - next = getChildGeq(n, next + 1); - if (next < 0 || next >= end) { - break; + { + int c = getChildGeq(n, begin + 1); + if (c >= 0 && c < end) { + auto *child = getChildExists(n, c); + if (child->entryPresent) { + result = std::max(result, child->entry.rangeVersion); + } } - auto *child = getChildExists(n, next); - if (child->entryPresent) { - result = std::max(result, child->entry.rangeVersion); + } + switch (n->type) { + case Type::Node4: { + auto *self = static_cast(n); + for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) { + if (begin < self->index[i]) { + result = std::max(result, self->children[i]->maxVersion); + } } - result = std::max(result, child->maxVersion); + break; + } + case Type::Node16: { + auto *self = static_cast(n); + for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) { + if (begin < self->index[i]) { + result = std::max(result, self->children[i]->maxVersion); + } + } + break; + } + case Type::Node48: { + auto *self = static_cast(n); + for (int i = begin + 1; i < end; ++i) { + if (self->index[i] != -1) { + result = std::max(result, self->children[self->index[i]]->maxVersion); + } + } + break; + } + case Type::Node256: { + auto *self = static_cast(n); + for (int i = begin + 1; i < end; ++i) { + if (self->children[i] != nullptr) { + result = std::max(result, self->children[i]->maxVersion); + } + } + break; + } + case Type::Invalid: + __builtin_unreachable(); // GCOVR_EXCL_LINE } #if DEBUG_VERBOSE && !defined(NDEBUG) fprintf(stderr, "At `%s', max version in (%02x, %02x) is %" PRId64 "\n",