Dispatch on type pairs for common prefix iter
This commit is contained in:
108
ConflictSet.cpp
108
ConflictSet.cpp
@@ -4283,14 +4283,11 @@ void pointIter(Job *job, Context *context) {
|
|||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class NodeT> PRESERVE_NONE void commonPrefixIter(Job *, Context *);
|
template <class NodeTFrom, class NodeTTo>
|
||||||
|
PRESERVE_NONE void prefixIter(Job *, Context *);
|
||||||
template <class NodeT> PRESERVE_NONE void beginIter(Job *, Context *);
|
template <class NodeT> PRESERVE_NONE void beginIter(Job *, Context *);
|
||||||
template <class NodeT> PRESERVE_NONE void endIter(Job *, Context *);
|
template <class NodeT> PRESERVE_NONE void endIter(Job *, Context *);
|
||||||
|
|
||||||
static Continuation commonPrefixIterTable[] = {
|
|
||||||
commonPrefixIter<Node0>, commonPrefixIter<Node3>, commonPrefixIter<Node16>,
|
|
||||||
commonPrefixIter<Node48>, commonPrefixIter<Node256>};
|
|
||||||
|
|
||||||
static Continuation beginIterTable[] = {beginIter<Node0>, beginIter<Node3>,
|
static Continuation beginIterTable[] = {beginIter<Node0>, beginIter<Node3>,
|
||||||
beginIter<Node16>, beginIter<Node48>,
|
beginIter<Node16>, beginIter<Node48>,
|
||||||
beginIter<Node256>};
|
beginIter<Node256>};
|
||||||
@@ -4299,26 +4296,51 @@ static Continuation endIterTable[] = {endIter<Node0>, endIter<Node3>,
|
|||||||
endIter<Node16>, endIter<Node48>,
|
endIter<Node16>, endIter<Node48>,
|
||||||
endIter<Node256>};
|
endIter<Node256>};
|
||||||
|
|
||||||
template <class NodeT> void commonPrefixIter(Job *job, Context *context) {
|
template <class NodeTFrom> struct PrefixIterTable {
|
||||||
assert(NodeT::kType == job->n->getType());
|
static constexpr Continuation table[] = {
|
||||||
NodeT *n = static_cast<NodeT *>(job->n);
|
prefixIter<NodeTFrom, Node0>, prefixIter<NodeTFrom, Node3>,
|
||||||
|
prefixIter<NodeTFrom, Node16>, prefixIter<NodeTFrom, Node48>,
|
||||||
|
prefixIter<NodeTFrom, Node256>};
|
||||||
|
};
|
||||||
|
|
||||||
TaggedNodePointer *child =
|
static constexpr Continuation const *prefixIterTable[] = {
|
||||||
getChildUpdatingMaxVersion(n, job->remaining, context->writeVersion);
|
PrefixIterTable<Node0>::table, PrefixIterTable<Node3>::table,
|
||||||
if (child == nullptr) [[unlikely]] {
|
PrefixIterTable<Node16>::table, PrefixIterTable<Node48>::table,
|
||||||
int prefixLen = job->commonPrefixLen - job->remaining.size();
|
PrefixIterTable<Node256>::table,
|
||||||
assert(prefixLen >= 0);
|
};
|
||||||
assert(job->n != nullptr);
|
|
||||||
*job->result = {
|
template <class NodeTFrom, class NodeTTo>
|
||||||
job->n,
|
void prefixIter(Job *job, Context *context) {
|
||||||
job->begin.subspan(prefixLen, job->begin.size() - prefixLen),
|
assert(NodeTFrom::kType == job->n->getType());
|
||||||
job->n,
|
NodeTFrom *n = static_cast<NodeTFrom *>(job->n);
|
||||||
job->end.subspan(prefixLen, job->end.size() - prefixLen),
|
assert(NodeTTo::kType == job->child->getType());
|
||||||
};
|
NodeTTo *child = static_cast<NodeTTo *>(job->child);
|
||||||
MUSTTAIL return complete(job, context);
|
|
||||||
|
auto key = job->remaining.subspan(1, job->remaining.size() - 1);
|
||||||
|
if (child->partialKeyLen > 0) {
|
||||||
|
int commonLen = std::min<int>(child->partialKeyLen, key.size());
|
||||||
|
int partialKeyIndex =
|
||||||
|
longestCommonPrefix(child->partialKey(), key.data(), commonLen);
|
||||||
|
if (partialKeyIndex < child->partialKeyLen) {
|
||||||
|
goto noNodeOnSearchPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
job->n = *child;
|
|
||||||
++context->iterations;
|
// child is on the search path. Commit to advancing and updating max version
|
||||||
|
job->n = child;
|
||||||
|
job->remaining =
|
||||||
|
key.subspan(child->partialKeyLen, key.size() - child->partialKeyLen);
|
||||||
|
if constexpr (std::is_same_v<NodeTFrom, Node3> ||
|
||||||
|
std::is_same_v<NodeTFrom, Node16>) {
|
||||||
|
n->childMaxVersion[job->childIndex] = context->writeVersion;
|
||||||
|
} else if constexpr (std::is_same_v<NodeTFrom, Node48> ||
|
||||||
|
std::is_same_v<NodeTFrom, Node256>) {
|
||||||
|
n->maxOfMax[job->childIndex >> NodeTFrom::kMaxOfMaxShift] =
|
||||||
|
std::max(n->maxOfMax[job->childIndex >> NodeTFrom::kMaxOfMaxShift],
|
||||||
|
context->writeVersion);
|
||||||
|
n->childMaxVersion[job->childIndex] = context->writeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
if (job->remaining.size() == 0) [[unlikely]] {
|
if (job->remaining.size() == 0) [[unlikely]] {
|
||||||
job->endNode = job->n;
|
job->endNode = job->n;
|
||||||
job->begin = job->begin.subspan(job->commonPrefixLen,
|
job->begin = job->begin.subspan(job->commonPrefixLen,
|
||||||
@@ -4330,11 +4352,29 @@ template <class NodeT> void commonPrefixIter(Job *job, Context *context) {
|
|||||||
} else {
|
} else {
|
||||||
job->continuation = beginIterTable[child->getType()];
|
job->continuation = beginIterTable[child->getType()];
|
||||||
}
|
}
|
||||||
} else {
|
MUSTTAIL return keepGoing(job, context);
|
||||||
job->continuation = commonPrefixIterTable[child->getType()];
|
|
||||||
}
|
}
|
||||||
__builtin_prefetch(job->n);
|
|
||||||
|
if (!job->getChildAndIndex(child, job->remaining.front())) [[unlikely]] {
|
||||||
|
goto noNodeOnSearchPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
++context->iterations;
|
||||||
|
job->continuation = PrefixIterTable<NodeTTo>::table[job->child.getType()];
|
||||||
|
__builtin_prefetch(job->child);
|
||||||
MUSTTAIL return keepGoing(job, context);
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
|
||||||
|
noNodeOnSearchPath:
|
||||||
|
int prefixLen = job->commonPrefixLen - job->remaining.size();
|
||||||
|
assert(prefixLen >= 0);
|
||||||
|
assert(job->n != nullptr);
|
||||||
|
*job->result = {
|
||||||
|
job->n,
|
||||||
|
job->begin.subspan(prefixLen, job->begin.size() - prefixLen),
|
||||||
|
job->n,
|
||||||
|
job->end.subspan(prefixLen, job->end.size() - prefixLen),
|
||||||
|
};
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class NodeT> void beginIter(Job *job, Context *context) {
|
template <class NodeT> void beginIter(Job *job, Context *context) {
|
||||||
@@ -4403,7 +4443,17 @@ void Job::init(Context *context, int index) {
|
|||||||
|
|
||||||
if (commonPrefixLen > 0) {
|
if (commonPrefixLen > 0) {
|
||||||
// common prefix iter will set endNode
|
// common prefix iter will set endNode
|
||||||
continuation = commonPrefixIterTable[n->getType()];
|
if (!getChildAndIndex(n, remaining.front())) [[unlikely]] {
|
||||||
|
*result = {
|
||||||
|
n,
|
||||||
|
begin,
|
||||||
|
n,
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
continuation = complete;
|
||||||
|
} else {
|
||||||
|
continuation = prefixIterTable[n->getType()][child.getType()];
|
||||||
|
}
|
||||||
} else if (begin.size() > 0) {
|
} else if (begin.size() > 0) {
|
||||||
endNode = n;
|
endNode = n;
|
||||||
continuation = beginIterTable[n->getType()];
|
continuation = beginIterTable[n->getType()];
|
||||||
@@ -4417,11 +4467,11 @@ pointWrite:
|
|||||||
remaining = TrivialSpan(context->writes[index].begin.p,
|
remaining = TrivialSpan(context->writes[index].begin.p,
|
||||||
context->writes[index].begin.len);
|
context->writes[index].begin.len);
|
||||||
if (remaining.size() == 0) [[unlikely]] {
|
if (remaining.size() == 0) [[unlikely]] {
|
||||||
context->results[index] = {n, remaining};
|
*result = {n, remaining};
|
||||||
continuation = complete;
|
continuation = complete;
|
||||||
} else {
|
} else {
|
||||||
if (!getChildAndIndex(n, remaining.front())) [[unlikely]] {
|
if (!getChildAndIndex(n, remaining.front())) [[unlikely]] {
|
||||||
context->results[index] = {n, remaining};
|
*result = {n, remaining};
|
||||||
continuation = complete;
|
continuation = complete;
|
||||||
} else {
|
} else {
|
||||||
continuation = pointIterTable[n->getType()][child.getType()];
|
continuation = pointIterTable[n->getType()][child.getType()];
|
||||||
|
Reference in New Issue
Block a user