6 Commits

Author SHA1 Message Date
e5452c0f7d Only check against sequential if we interleaved
All checks were successful
Tests / 64 bit versions total: 5794, passed: 5794
Tests / Debug total: 5792, passed: 5792
Tests / SIMD fallback total: 5794, passed: 5794
Tests / Release [clang] total: 5794, passed: 5794
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc] total: 5794, passed: 5794
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [clang,aarch64] total: 3836, passed: 3836
Tests / Coverage total: 3876, passed: 3876
Code Coverage #### Project Overview No changes detected, that affect the code coverage. * Line Coverage: 97.23% (2666/2742) * Branch Coverage: 48.95% (9912/20251) * Complexity Density: 0.00 * Lines of Code: 2742 #### Quality Gates Summary Output truncated.
weaselab/conflict-set/pipeline/head This commit looks good
2024-10-17 16:17:21 -07:00
66fc526a55 Add to corpus 2024-10-17 16:07:15 -07:00
21f08b9f88 Avoid assigning to continuation where unnecessary 2024-10-17 13:16:29 -07:00
10c2f06199 Mix type dispatch and interleaving for down left spine 2024-10-17 13:13:16 -07:00
5cf04e9718 Add to corpus 2024-10-17 10:58:02 -07:00
707b220fbc Improve next{Physical,Logical} codegen more 2024-10-17 09:52:03 -07:00
65 changed files with 189 additions and 127 deletions

View File

@@ -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.