Compare commits
6
Commits
fd39065498
...
e5452c0f7d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5452c0f7d | ||
|
|
66fc526a55 | ||
|
|
21f08b9f88 | ||
|
|
10c2f06199 | ||
|
|
5cf04e9718 | ||
|
|
707b220fbc |
+189
-127
@@ -1193,9 +1193,9 @@ ChildAndMaxVersion getChildAndMaxVersion(Node *self, uint8_t index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *getChildGeq(Node0 *, int) { return nullptr; }
|
TaggedNodePointer getChildGeq(Node0 *, int) { return nullptr; }
|
||||||
|
|
||||||
Node *getChildGeq(Node3 *n, int child) {
|
TaggedNodePointer getChildGeq(Node3 *n, int child) {
|
||||||
assume(n->numChildren >= 1);
|
assume(n->numChildren >= 1);
|
||||||
assume(n->numChildren <= 3);
|
assume(n->numChildren <= 3);
|
||||||
for (int i = 0; i < n->numChildren; ++i) {
|
for (int i = 0; i < n->numChildren; ++i) {
|
||||||
@@ -1206,7 +1206,7 @@ Node *getChildGeq(Node3 *n, int child) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *getChildGeq(Node16 *self, int child) {
|
TaggedNodePointer getChildGeq(Node16 *self, int child) {
|
||||||
if (child > 255) {
|
if (child > 255) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1249,14 +1249,14 @@ Node *getChildGeq(Node16 *self, int child) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *getChildGeq(Node48 *self, int child) {
|
TaggedNodePointer getChildGeq(Node48 *self, int child) {
|
||||||
int c = self->bitSet.firstSetGeq(child);
|
int c = self->bitSet.firstSetGeq(child);
|
||||||
if (c < 0) {
|
if (c < 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return self->children[self->index[c]];
|
return self->children[self->index[c]];
|
||||||
}
|
}
|
||||||
Node *getChildGeq(Node256 *self, int child) {
|
TaggedNodePointer getChildGeq(Node256 *self, int child) {
|
||||||
int c = self->bitSet.firstSetGeq(child);
|
int c = self->bitSet.firstSetGeq(child);
|
||||||
if (c < 0) {
|
if (c < 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -1264,7 +1264,7 @@ Node *getChildGeq(Node256 *self, int child) {
|
|||||||
return self->children[c];
|
return self->children[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *getChildGeq(Node *self, int child) {
|
TaggedNodePointer getChildGeq(Node *self, int child) {
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
case Type_Node0:
|
case Type_Node0:
|
||||||
return getChildGeq(static_cast<Node0 *>(self), child);
|
return getChildGeq(static_cast<Node0 *>(self), child);
|
||||||
@@ -1281,27 +1281,62 @@ Node *getChildGeq(Node *self, int child) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node *getFirstChild(Node0 *) { return nullptr; }
|
||||||
|
Node *getFirstChild(Node3 *self) {
|
||||||
|
return self->numChildren == 0 ? nullptr : self->children[0];
|
||||||
|
}
|
||||||
|
Node *getFirstChild(Node16 *self) {
|
||||||
|
return self->numChildren == 0 ? nullptr : self->children[0];
|
||||||
|
}
|
||||||
|
Node *getFirstChild(Node48 *self) {
|
||||||
|
int index = self->index[self->bitSet.firstSetGeq(0)];
|
||||||
|
return index < 0 ? nullptr : self->children[index];
|
||||||
|
}
|
||||||
|
Node *getFirstChild(Node256 *self) {
|
||||||
|
return self->children[self->bitSet.firstSetGeq(0)];
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *getFirstChild(Node *self) {
|
||||||
|
// Only require that the node-specific overloads are covered
|
||||||
|
// GCOVR_EXCL_START
|
||||||
|
switch (self->getType()) {
|
||||||
|
case Type_Node0:
|
||||||
|
return getFirstChild(static_cast<Node0 *>(self));
|
||||||
|
case Type_Node3:
|
||||||
|
return getFirstChild(static_cast<Node3 *>(self));
|
||||||
|
case Type_Node16:
|
||||||
|
return getFirstChild(static_cast<Node16 *>(self));
|
||||||
|
case Type_Node48:
|
||||||
|
return getFirstChild(static_cast<Node48 *>(self));
|
||||||
|
case Type_Node256:
|
||||||
|
return getFirstChild(static_cast<Node256 *>(self));
|
||||||
|
default:
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
// GCOVR_EXCL_STOP
|
||||||
|
}
|
||||||
|
|
||||||
// Precondition: self has a child
|
// Precondition: self has a child
|
||||||
Node *getFirstChildExists(Node3 *self) {
|
TaggedNodePointer getFirstChildExists(Node3 *self) {
|
||||||
assert(self->numChildren > 0);
|
assert(self->numChildren > 0);
|
||||||
return self->children[0];
|
return self->children[0];
|
||||||
}
|
}
|
||||||
// Precondition: self has a child
|
// Precondition: self has a child
|
||||||
Node *getFirstChildExists(Node16 *self) {
|
TaggedNodePointer getFirstChildExists(Node16 *self) {
|
||||||
assert(self->numChildren > 0);
|
assert(self->numChildren > 0);
|
||||||
return self->children[0];
|
return self->children[0];
|
||||||
}
|
}
|
||||||
// Precondition: self has a child
|
// Precondition: self has a child
|
||||||
Node *getFirstChildExists(Node48 *self) {
|
TaggedNodePointer getFirstChildExists(Node48 *self) {
|
||||||
return self->children[self->index[self->bitSet.firstSetGeq(0)]];
|
return self->children[self->index[self->bitSet.firstSetGeq(0)]];
|
||||||
}
|
}
|
||||||
// Precondition: self has a child
|
// Precondition: self has a child
|
||||||
Node *getFirstChildExists(Node256 *self) {
|
TaggedNodePointer getFirstChildExists(Node256 *self) {
|
||||||
return self->children[self->bitSet.firstSetGeq(0)];
|
return self->children[self->bitSet.firstSetGeq(0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precondition: self has a child
|
// Precondition: self has a child
|
||||||
Node *getFirstChildExists(Node *self) {
|
TaggedNodePointer getFirstChildExists(Node *self) {
|
||||||
// Only require that the node-specific overloads are covered
|
// Only require that the node-specific overloads are covered
|
||||||
// GCOVR_EXCL_START
|
// GCOVR_EXCL_START
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
@@ -1559,36 +1594,45 @@ TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Node *nextPhysical(Node *node) {
|
Node *nextPhysical(Node *node) {
|
||||||
int index = -1;
|
auto nextChild = getFirstChild(node);
|
||||||
|
if (nextChild != nullptr) {
|
||||||
|
return nextChild;
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto nextChild = getChildGeq(node, index + 1);
|
int index = node->parentsIndex;
|
||||||
if (nextChild != nullptr) {
|
|
||||||
return nextChild;
|
|
||||||
}
|
|
||||||
index = node->parentsIndex;
|
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
auto nextChild = getChildGeq(node, index + 1);
|
||||||
|
if (nextChild != nullptr) {
|
||||||
|
return nextChild;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *nextLogical(Node *node) {
|
Node *nextLogical(Node *node) {
|
||||||
int index = -1;
|
auto nextChild = getFirstChild(node);
|
||||||
|
if (nextChild != nullptr) {
|
||||||
|
node = nextChild;
|
||||||
|
goto downLeftSpine;
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto nextChild = getChildGeq(node, index + 1);
|
int index = node->parentsIndex;
|
||||||
if (nextChild != nullptr) {
|
|
||||||
for (node = nextChild; !node->entryPresent;
|
|
||||||
node = getFirstChildExists(node)) {
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
index = node->parentsIndex;
|
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
auto nextChild = getChildGeq(node, index + 1);
|
||||||
|
if (nextChild != nullptr) {
|
||||||
|
node = nextChild;
|
||||||
|
goto downLeftSpine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
downLeftSpine:
|
||||||
|
for (; !node->entryPresent; node = getFirstChildExists(node)) {
|
||||||
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidates `self`, replacing it with a node of at least capacity.
|
// Invalidates `self`, replacing it with a node of at least capacity.
|
||||||
@@ -1977,7 +2021,7 @@ Node *erase(Node *self, WriteContext *writeContext, ConflictSet::Impl *impl,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *nextSibling(Node *node) {
|
TaggedNodePointer nextSibling(Node *node) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (node->parent == nullptr) {
|
if (node->parent == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -3053,13 +3097,25 @@ PRESERVE_NONE void complete(CheckJob *job, CheckContext *context) {
|
|||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class NodeT>
|
||||||
|
PRESERVE_NONE void down_left_spine(CheckJob *job, CheckContext *context);
|
||||||
|
|
||||||
|
static Continuation downLeftSpineTable[] = {
|
||||||
|
down_left_spine<Node0>, down_left_spine<Node3>, down_left_spine<Node16>,
|
||||||
|
down_left_spine<Node48>, down_left_spine<Node256>};
|
||||||
|
|
||||||
|
template <class NodeT>
|
||||||
PRESERVE_NONE void down_left_spine(CheckJob *job, CheckContext *context) {
|
PRESERVE_NONE void down_left_spine(CheckJob *job, CheckContext *context) {
|
||||||
if (job->n->entryPresent) {
|
assert(job->n->getType() == NodeT::kType);
|
||||||
job->setResult(job->n->entry.rangeVersion <= job->readVersion);
|
NodeT *n = static_cast<NodeT *>(job->n);
|
||||||
|
if (n->entryPresent) {
|
||||||
|
job->setResult(n->entry.rangeVersion <= job->readVersion);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->n = getFirstChildExists(job->n);
|
auto child = getFirstChildExists(n);
|
||||||
|
job->n = child;
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
|
job->continuation = downLeftSpineTable[child.getType()];
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3092,7 +3148,7 @@ void begin(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(job->n, job->begin[0]);
|
auto c = getChildGeq(job->n, job->begin[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
@@ -3119,15 +3175,15 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
if (i < commonLen) [[unlikely]] {
|
if (i < commonLen) [[unlikely]] {
|
||||||
auto c = n->partialKey()[i] <=> job->begin[i];
|
auto c = n->partialKey()[i] <=> job->begin[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return down_left_spine(job, context);
|
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(n);
|
auto s = nextSibling(n);
|
||||||
|
job->n = s;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[s.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3138,8 +3194,7 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
} else if (n->partialKeyLen > int(job->begin.size())) [[unlikely]] {
|
} else if (n->partialKeyLen > int(job->begin.size())) [[unlikely]] {
|
||||||
// n is the first physical node greater than remaining, and there's no
|
// n is the first physical node greater than remaining, and there's no
|
||||||
// eq node
|
// eq node
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return down_left_spine(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3156,8 +3211,9 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->setResult(n->entry.pointVersion <= job->readVersion);
|
job->setResult(n->entry.pointVersion <= job->readVersion);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->n = getFirstChildExists(n);
|
auto c = getFirstChildExists(n);
|
||||||
job->continuation = down_left_spine;
|
job->n = c;
|
||||||
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3169,16 +3225,17 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(n, job->begin[0]);
|
auto c = getChildGeq(n, job->begin[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c->getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3216,7 +3273,7 @@ void begin(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(job->n, job->begin[0]);
|
auto c = getChildGeq(job->n, job->begin[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
@@ -3243,15 +3300,15 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
if (i < commonLen) [[unlikely]] {
|
if (i < commonLen) [[unlikely]] {
|
||||||
auto c = n->partialKey()[i] <=> job->begin[i];
|
auto c = n->partialKey()[i] <=> job->begin[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return down_left_spine(job, context);
|
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(n);
|
auto c = nextSibling(n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3267,8 +3324,7 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return down_left_spine(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3292,16 +3348,17 @@ template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(n, job->begin[0]);
|
auto c = getChildGeq(n, job->begin[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3336,8 +3393,14 @@ static Continuation doneCommonPrefixIterTable[] = {
|
|||||||
template <class NodeT>
|
template <class NodeT>
|
||||||
PRESERVE_NONE void left_side_iter(CheckJob *, CheckContext *);
|
PRESERVE_NONE void left_side_iter(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
|
template <class NodeT>
|
||||||
PRESERVE_NONE void left_side_down_left_spine(CheckJob *, CheckContext *);
|
PRESERVE_NONE void left_side_down_left_spine(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
|
static Continuation leftSideDownLeftSpineTable[] = {
|
||||||
|
left_side_down_left_spine<Node0>, left_side_down_left_spine<Node3>,
|
||||||
|
left_side_down_left_spine<Node16>, left_side_down_left_spine<Node48>,
|
||||||
|
left_side_down_left_spine<Node256>};
|
||||||
|
|
||||||
PRESERVE_NONE void done_left_side_iter(CheckJob *, CheckContext *);
|
PRESERVE_NONE void done_left_side_iter(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
static Continuation leftSideIterTable[] = {
|
static Continuation leftSideIterTable[] = {
|
||||||
@@ -3356,32 +3419,28 @@ PRESERVE_NONE void begin(CheckJob *job, CheckContext *context) {
|
|||||||
std::min(job->begin.size(), job->end.size()));
|
std::min(job->begin.size(), job->end.size()));
|
||||||
if (job->lcp == int(job->begin.size()) &&
|
if (job->lcp == int(job->begin.size()) &&
|
||||||
job->end.size() == job->begin.size() + 1 && job->end.back() == 0) {
|
job->end.size() == job->begin.size() + 1 && job->end.back() == 0) {
|
||||||
job->continuation = check_point_read_state_machine::begin;
|
|
||||||
// Call directly since we have nothing to prefetch
|
// Call directly since we have nothing to prefetch
|
||||||
MUSTTAIL return job->continuation(job, context);
|
MUSTTAIL return check_point_read_state_machine::begin(job, context);
|
||||||
}
|
}
|
||||||
if (job->lcp == int(job->begin.size() - 1) &&
|
if (job->lcp == int(job->begin.size() - 1) &&
|
||||||
job->end.size() == job->begin.size() &&
|
job->end.size() == job->begin.size() &&
|
||||||
int(job->begin.back()) + 1 == int(job->end.back())) {
|
int(job->begin.back()) + 1 == int(job->end.back())) {
|
||||||
job->continuation = check_prefix_read_state_machine::begin;
|
|
||||||
// Call directly since we have nothing to prefetch
|
// Call directly since we have nothing to prefetch
|
||||||
MUSTTAIL return job->continuation(job, context);
|
MUSTTAIL return check_prefix_read_state_machine::begin(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
++context->readContext.range_read_accum;
|
++context->readContext.range_read_accum;
|
||||||
job->remaining = job->begin.subspan(0, job->lcp);
|
job->remaining = job->begin.subspan(0, job->lcp);
|
||||||
|
|
||||||
if (job->remaining.size() == 0) {
|
if (job->remaining.size() == 0) {
|
||||||
job->continuation = doneCommonPrefixIterTable[job->n->getType()];
|
MUSTTAIL return doneCommonPrefixIterTable[job->n->getType()](job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [c, maxV] = getChildAndMaxVersion(job->n, job->remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(job->n, job->remaining[0]);
|
||||||
job->maxV = maxV;
|
job->maxV = maxV;
|
||||||
job->child = c;
|
job->child = c;
|
||||||
if (job->child == nullptr) {
|
if (job->child == nullptr) {
|
||||||
job->continuation = doneCommonPrefixIterTable[job->n->getType()];
|
MUSTTAIL return doneCommonPrefixIterTable[job->n->getType()](job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job->continuation = commonPrefixIterTable[c.getType()];
|
job->continuation = commonPrefixIterTable[c.getType()];
|
||||||
@@ -3401,8 +3460,8 @@ void common_prefix_iter(CheckJob *job, CheckContext *context) {
|
|||||||
int i =
|
int i =
|
||||||
longestCommonPrefix(child->partialKey(), job->remaining.data() + 1, cl);
|
longestCommonPrefix(child->partialKey(), job->remaining.data() + 1, cl);
|
||||||
if (i != child->partialKeyLen) {
|
if (i != child->partialKeyLen) {
|
||||||
job->continuation = doneCommonPrefixIterTable[job->n->getType()];
|
MUSTTAIL return doneCommonPrefixIterTable[job->n->getType()](job,
|
||||||
MUSTTAIL return job->continuation(job, context);
|
context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
job->n = child;
|
job->n = child;
|
||||||
@@ -3419,16 +3478,14 @@ void common_prefix_iter(CheckJob *job, CheckContext *context) {
|
|||||||
++context->readContext.range_read_iterations_accum;
|
++context->readContext.range_read_iterations_accum;
|
||||||
|
|
||||||
if (job->remaining.size() == 0) {
|
if (job->remaining.size() == 0) {
|
||||||
job->continuation = done_common_prefix_iter<NodeT>;
|
MUSTTAIL return done_common_prefix_iter<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [c, maxV] = getChildAndMaxVersion(child, job->remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(child, job->remaining[0]);
|
||||||
job->maxV = maxV;
|
job->maxV = maxV;
|
||||||
job->child = c;
|
job->child = c;
|
||||||
if (job->child == nullptr) {
|
if (job->child == nullptr) {
|
||||||
job->continuation = done_common_prefix_iter<NodeT>;
|
MUSTTAIL return done_common_prefix_iter<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
job->continuation = commonPrefixIterTable[c.getType()];
|
job->continuation = commonPrefixIterTable[c.getType()];
|
||||||
@@ -3481,16 +3538,17 @@ PRESERVE_NONE void done_common_prefix_iter(CheckJob *job,
|
|||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return downLeftSpineTable[c.getType()](job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3519,16 +3577,16 @@ PRESERVE_NONE void done_common_prefix_iter(CheckJob *job,
|
|||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = left_side_down_left_spine;
|
job->continuation = leftSideDownLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
job->continuation = left_side_down_left_spine;
|
job->continuation = leftSideDownLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3558,8 +3616,7 @@ PRESERVE_NONE void left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
if (n->parent == job->commonPrefixNode) {
|
if (n->parent == job->commonPrefixNode) {
|
||||||
if (i < job->lcp) {
|
if (i < job->lcp) {
|
||||||
job->continuation = left_side_down_left_spine;
|
MUSTTAIL return left_side_down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (n->entryPresent && n->entry.rangeVersion > job->readVersion) {
|
if (n->entryPresent && n->entry.rangeVersion > job->readVersion) {
|
||||||
@@ -3570,16 +3627,16 @@ PRESERVE_NONE void left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(n);
|
auto c = nextSibling(n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
job->continuation = left_side_down_left_spine;
|
job->continuation = leftSideDownLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == n->partialKeyLen) {
|
||||||
@@ -3595,14 +3652,12 @@ PRESERVE_NONE void left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job->maxV <= job->readVersion) {
|
if (job->maxV <= job->readVersion) {
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++context->readContext.range_read_iterations_accum;
|
++context->readContext.range_read_iterations_accum;
|
||||||
@@ -3626,15 +3681,14 @@ PRESERVE_NONE void left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
job->continuation = left_side_down_left_spine;
|
job->continuation = leftSideDownLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3657,16 +3711,17 @@ PRESERVE_NONE void done_left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(job->n, job->remaining[0]);
|
auto c = getChildGeq(job->n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3676,16 +3731,21 @@ PRESERVE_NONE void done_left_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class NodeT>
|
||||||
void left_side_down_left_spine(CheckJob *job, CheckContext *context) {
|
void left_side_down_left_spine(CheckJob *job, CheckContext *context) {
|
||||||
if (job->n->entryPresent) {
|
assert(job->n->getType() == NodeT::kType);
|
||||||
if (job->n->entry.rangeVersion > job->readVersion) {
|
NodeT *n = static_cast<NodeT *>(job->n);
|
||||||
|
|
||||||
|
if (n->entryPresent) {
|
||||||
|
if (n->entry.rangeVersion > job->readVersion) {
|
||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = done_left_side_iter;
|
MUSTTAIL return done_left_side_iter(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
job->n = getFirstChildExists(job->n);
|
auto c = getFirstChildExists(n);
|
||||||
|
job->n = c;
|
||||||
|
job->continuation = leftSideDownLeftSpineTable[c.getType()];
|
||||||
__builtin_prefetch(job->n);
|
__builtin_prefetch(job->n);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
@@ -3706,8 +3766,7 @@ PRESERVE_NONE void right_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
if (i < commonLen) {
|
if (i < commonLen) {
|
||||||
auto c = n->partialKey()[i] <=> job->remaining[i];
|
auto c = n->partialKey()[i] <=> job->remaining[i];
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
} else {
|
} else {
|
||||||
if ((n->parent != job->commonPrefixNode || i >= job->lcp) &&
|
if ((n->parent != job->commonPrefixNode || i >= job->lcp) &&
|
||||||
n->entryPresent && n->entry.rangeVersion > job->readVersion) {
|
n->entryPresent && n->entry.rangeVersion > job->readVersion) {
|
||||||
@@ -3719,13 +3778,15 @@ PRESERVE_NONE void right_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->setResult(false);
|
job->setResult(false);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (commonLen == n->partialKeyLen) {
|
if (commonLen == n->partialKeyLen) {
|
||||||
@@ -3733,16 +3794,14 @@ PRESERVE_NONE void right_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
job->remaining =
|
job->remaining =
|
||||||
job->remaining.subspan(commonLen, job->remaining.size() - commonLen);
|
job->remaining.subspan(commonLen, job->remaining.size() - commonLen);
|
||||||
} else if (n->partialKeyLen > int(job->remaining.size())) {
|
} else if (n->partialKeyLen > int(job->remaining.size())) {
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++context->readContext.range_read_iterations_accum;
|
++context->readContext.range_read_iterations_accum;
|
||||||
|
|
||||||
if (job->remaining.size() == 0) {
|
if (job->remaining.size() == 0) {
|
||||||
job->continuation = down_left_spine;
|
MUSTTAIL return down_left_spine<NodeT>(job, context);
|
||||||
MUSTTAIL return job->continuation(job, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->entryPresent && n->entry.pointVersion > job->readVersion) {
|
if (n->entryPresent && n->entry.pointVersion > job->readVersion) {
|
||||||
@@ -3767,16 +3826,19 @@ PRESERVE_NONE void right_side_iter(CheckJob *job, CheckContext *context) {
|
|||||||
auto c = getChildGeq(n, job->remaining[0]);
|
auto c = getChildGeq(n, job->remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
job->n = c;
|
job->n = c;
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
} else {
|
} else {
|
||||||
job->n = nextSibling(job->n);
|
auto c = nextSibling(job->n);
|
||||||
|
job->n = c;
|
||||||
if (job->n == nullptr) {
|
if (job->n == nullptr) {
|
||||||
job->setResult(true);
|
job->setResult(true);
|
||||||
MUSTTAIL return complete(job, context);
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
job->continuation = down_left_spine;
|
job->continuation = downLeftSpineTable[c.getType()];
|
||||||
MUSTTAIL return job->continuation(job, context);
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4289,17 +4351,17 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
// Kick off the sequence of tail calls that finally returns once all jobs
|
// Kick off the sequence of tail calls that finally returns once all jobs
|
||||||
// are done
|
// are done
|
||||||
inProgress->continuation(inProgress, &context);
|
inProgress->continuation(inProgress, &context);
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Arena arena;
|
Arena arena;
|
||||||
auto *results2 = new (arena) Result[count];
|
auto *results2 = new (arena) Result[count];
|
||||||
CheckContext context2;
|
CheckContext context2;
|
||||||
context2.readContext.impl = this;
|
context2.readContext.impl = this;
|
||||||
useSequential(reads, results2, count, context2);
|
useSequential(reads, results2, count, context2);
|
||||||
assert(memcmp(result, results2, count) == 0);
|
assert(memcmp(result, results2, count) == 0);
|
||||||
assert(context.readContext == context2.readContext);
|
assert(context.readContext == context2.readContext);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
useSequential(reads, result, count, context);
|
useSequential(reads, result, count, context);
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user