rbyd: Dropped special altn/alta encoding
altas, and to a lesser extend altns, are just too problematic for our
rbyd-append algorithm.
Main issue is these break our "narrowing" invariant, where each alt only
ever decreases the bounds.
I wanted to use altas to simplify lfsr_rbyd_appendcompaction, but
decided it wasn't worth it. Handling them correctly would require adding
a number of special cases to lfsr_rbyd_appendrat, adding complexity to
an already incredibly complex function.
---
Fortunately, we don't really need altns/altas on-disk, but we _do_ need
a way to mark alts as unreachable internally in order to know when we
can collapse alts when recoloring (at this point bounds information is
lost).
I was originally going to use the alt's sign bit for this, but it turns
out we already have this information thanks to setting jump=0 to assert
that an alt is unreachable. So no explicit flag needed!
This ends up saving a surprising amount of code for what is only a
couple lines of changes:
code stack ctx
before: 38512 2624 640
after: 38440 (-0.2%) 2624 (+0.0%) 640 (+0.0%)
This commit is contained in:
@@ -1265,14 +1265,6 @@ static inline bool lfsr_tag_isgt(lfsr_tag_t tag) {
|
||||
return tag & LFSR_TAG_GT;
|
||||
}
|
||||
|
||||
static inline bool lfsr_tag_isa(lfsr_tag_t tag) {
|
||||
return (tag & 0x1fff) == (LFSR_TAG_GT | 0);
|
||||
}
|
||||
|
||||
static inline bool lfsr_tag_isn(lfsr_tag_t tag) {
|
||||
return (tag & 0x1fff) == (LFSR_TAG_LE | 0);
|
||||
}
|
||||
|
||||
static inline lfsr_tag_t lfsr_tag_isparallel(lfsr_tag_t a, lfsr_tag_t b) {
|
||||
return (a & LFSR_TAG_GT) == (b & LFSR_TAG_GT);
|
||||
}
|
||||
@@ -1281,7 +1273,7 @@ static inline bool lfsr_tag_follow(
|
||||
lfsr_tag_t alt, lfsr_rid_t weight,
|
||||
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
||||
lfsr_srid_t rid, lfsr_tag_t tag) {
|
||||
// null tags break the following logic for altns/altas
|
||||
// null tags break the following logic for unreachable alts
|
||||
LFS_ASSERT(lfsr_tag_key(tag) != 0);
|
||||
|
||||
if (lfsr_tag_isgt(alt)) {
|
||||
@@ -1332,12 +1324,12 @@ static inline void lfsr_tag_trim(
|
||||
LFS_ASSERT((lfsr_srid_t)weight >= 0);
|
||||
if (lfsr_tag_isgt(alt)) {
|
||||
*upper_rid -= weight;
|
||||
if (upper_tag && !lfsr_tag_isa(alt)) {
|
||||
if (upper_tag) {
|
||||
*upper_tag = alt + 1;
|
||||
}
|
||||
} else {
|
||||
*lower_rid += weight;
|
||||
if (lower_tag && !lfsr_tag_isn(alt)) {
|
||||
if (lower_tag) {
|
||||
*lower_tag = alt;
|
||||
}
|
||||
}
|
||||
@@ -3289,9 +3281,13 @@ static int lfsr_rbyd_p_flush(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
// write out some number of alt pointers in our queue
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (p[3-1-i].alt) {
|
||||
// change to a relative jump at the last minute
|
||||
// jump=0 represents an unreachable alt, we do write out
|
||||
// unreachable alts sometimes in order to maintain the
|
||||
// balance of the tree
|
||||
LFS_ASSERT(p[3-1-i].jump || lfsr_tag_isblack(p[3-1-i].alt));
|
||||
lfsr_tag_t alt = p[3-1-i].alt;
|
||||
lfsr_rid_t weight = p[3-1-i].weight;
|
||||
// change to a relative jump at the last minute
|
||||
lfs_size_t jump = (p[3-1-i].jump)
|
||||
? lfsr_rbyd_eoff(rbyd) - p[3-1-i].jump
|
||||
: 0;
|
||||
@@ -3335,8 +3331,8 @@ static void lfsr_rbyd_p_recolor(
|
||||
if (p[1].alt) {
|
||||
p[1].alt |= LFSR_TAG_R;
|
||||
|
||||
// alt-never? we can prune this now
|
||||
if (lfsr_tag_isn(p[1].alt)) {
|
||||
// unreachable alt? we can prune this now
|
||||
if (!p[1].jump) {
|
||||
p[1] = p[2];
|
||||
p[2].alt = 0;
|
||||
|
||||
@@ -3708,16 +3704,25 @@ trunk:;
|
||||
branch = branch_;
|
||||
continue;
|
||||
|
||||
// convert unreachable non-root black alts into alt-nevers,
|
||||
// if we prune these it would break the color balance of
|
||||
// our tree
|
||||
// mark unreachable non-root black alts as unreachable,
|
||||
// we can't prune these or we risk breaking the color
|
||||
// balance of our tree, but if we push a red up later we
|
||||
// can get rid of them
|
||||
// : :
|
||||
// <b => nb
|
||||
// .-'| .--'
|
||||
// 3 4 3 4 x
|
||||
} else {
|
||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, 0);
|
||||
weight = 0;
|
||||
alt = LFSR_TAG_ALT(
|
||||
LFSR_TAG_B,
|
||||
LFSR_TAG_LE,
|
||||
(diverged && !(a_rid < b_rid || a_tag < b_tag))
|
||||
? d_tag
|
||||
: lower_tag);
|
||||
LFS_ASSERT(weight == 0);
|
||||
// we don't need to, but setting jump=0 asserts this
|
||||
// alt is unreachable while also minimizing the the
|
||||
// encoding
|
||||
jump = 0;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -226,13 +226,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
|
||||
+3
-6
@@ -272,13 +272,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
|
||||
+3
-6
@@ -241,13 +241,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
|
||||
+3
-6
@@ -229,13 +229,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
|
||||
+3
-6
@@ -183,13 +183,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
||||
' w%d' % w if w else '',
|
||||
' %s' % size if size is not None else '')
|
||||
elif tag & TAG_ALT:
|
||||
return 'alt%s%s%s%s%s' % (
|
||||
return 'alt%s%s 0x%03x%s%s' % (
|
||||
'r' if tag & TAG_R else 'b',
|
||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
||||
else 'n' if tag & 0x0fff == 0
|
||||
else 'gt' if tag & TAG_GT
|
||||
else 'le',
|
||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
||||
'gt' if tag & TAG_GT else 'le',
|
||||
tag & 0x0fff,
|
||||
' w%d' % w if w is not None else '',
|
||||
' 0x%x' % (0xffffffff & (off-size))
|
||||
if size and off is not None
|
||||
|
||||
Reference in New Issue
Block a user