Update some of the invariant checks to account for leaves
This commit is contained in:
@@ -269,14 +269,22 @@ struct TaggedNodePointer {
|
||||
|
||||
TaggedNodePointer(const TaggedNodePointer &) = default;
|
||||
TaggedNodePointer &operator=(const TaggedNodePointer &) = default;
|
||||
|
||||
/*implicit*/ TaggedNodePointer(Node *n);
|
||||
|
||||
// Leaf constructor
|
||||
TaggedNodePointer(InternalVersionT rangeVersion, struct Node *parent);
|
||||
|
||||
void prefetch() {
|
||||
// __builtin_prefetch is ok even if argument isn't addressable
|
||||
__builtin_prefetch((void *)withoutType());
|
||||
}
|
||||
|
||||
bool isLeaf() { return getType() > Type_Node256; }
|
||||
bool isLeaf() { return (p & uintptr_t(15)) > Type_Node256; }
|
||||
InternalVersionT rangeVersion() {
|
||||
assert(isLeaf());
|
||||
return InternalVersionT(p >> 32);
|
||||
}
|
||||
|
||||
private:
|
||||
TaggedNodePointer(struct Node *p, Type t) : p((uintptr_t)p) {
|
||||
@@ -323,6 +331,12 @@ private:
|
||||
TaggedNodePointer::TaggedNodePointer(Node *n)
|
||||
: TaggedNodePointer(n, n->getType()) {}
|
||||
|
||||
TaggedNodePointer::TaggedNodePointer(InternalVersionT rangeVersion, Node *n) {
|
||||
p = rangeVersion.toInt64();
|
||||
p <<= 32;
|
||||
p |= n->getType();
|
||||
}
|
||||
|
||||
Type TaggedNodePointer::getType() {
|
||||
assert(p != 0);
|
||||
prefetch();
|
||||
@@ -6096,18 +6110,27 @@ void checkVersionsGeqOldestExtant(Node *n,
|
||||
[[maybe_unused]] auto *self = static_cast<Node3 *>(n);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
assert(self->childMaxVersion[i] >= oldestExtantVersion);
|
||||
if (i < self->numChildren && self->children[i].isLeaf()) {
|
||||
assert(self->children[i].rangeVersion() >= oldestExtantVersion);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Type_Node16: {
|
||||
[[maybe_unused]] auto *self = static_cast<Node16 *>(n);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
assert(self->childMaxVersion[i] >= oldestExtantVersion);
|
||||
if (i < self->numChildren && self->children[i].isLeaf()) {
|
||||
assert(self->children[i].rangeVersion() >= oldestExtantVersion);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Type_Node48: {
|
||||
auto *self = static_cast<Node48 *>(n);
|
||||
for (int i = 0; i < 48; ++i) {
|
||||
assert(self->childMaxVersion[i] >= oldestExtantVersion);
|
||||
if (i < self->numChildren && self->children[i].isLeaf()) {
|
||||
assert(self->children[i].rangeVersion() >= oldestExtantVersion);
|
||||
}
|
||||
}
|
||||
for ([[maybe_unused]] auto m : self->maxOfMax) {
|
||||
assert(m >= oldestExtantVersion);
|
||||
@@ -6117,11 +6140,18 @@ void checkVersionsGeqOldestExtant(Node *n,
|
||||
auto *self = static_cast<Node256 *>(n);
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
assert(self->childMaxVersion[i] >= oldestExtantVersion);
|
||||
if (self->children[i].isLeaf()) {
|
||||
assert(self->children[i].rangeVersion() >= oldestExtantVersion);
|
||||
}
|
||||
}
|
||||
for ([[maybe_unused]] auto m : self->maxOfMax) {
|
||||
assert(m >= oldestExtantVersion);
|
||||
}
|
||||
} break;
|
||||
case Type_Leaf3:
|
||||
case Type_Leaf16:
|
||||
case Type_Leaf48:
|
||||
case Type_Leaf256:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -6180,9 +6210,10 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
||||
return total;
|
||||
}
|
||||
|
||||
[[maybe_unused]] void checkMemoryBoundInvariants(Node *node, bool &success) {
|
||||
[[maybe_unused]] void checkMemoryBoundInvariants(TaggedNodePointer node,
|
||||
bool &success) {
|
||||
int minNumChildren;
|
||||
switch (node->getType()) {
|
||||
switch (node.getType()) {
|
||||
case Type_Node0:
|
||||
minNumChildren = kMinChildrenNode0;
|
||||
break;
|
||||
@@ -6198,6 +6229,11 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
||||
case Type_Node256:
|
||||
minNumChildren = kMinChildrenNode256;
|
||||
break;
|
||||
case Type_Leaf3:
|
||||
case Type_Leaf16:
|
||||
case Type_Leaf48:
|
||||
case Type_Leaf256:
|
||||
return;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@@ -6219,8 +6255,9 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion,
|
||||
success = false;
|
||||
}
|
||||
|
||||
for (auto child = getChildGeq(node, 0); child != nullptr;
|
||||
child = getChildGeq(node, child->parentsIndex + 1)) {
|
||||
// Safety: if node were a leaf we would have returned by now
|
||||
for (auto child = getChildGeq(node.asNodeUnsafe(), 0); child != nullptr;
|
||||
child = getChildGeq(node.asNodeUnsafe(), child->parentsIndex + 1)) {
|
||||
checkMemoryBoundInvariants(child, success);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user