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;
|
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) {
|
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);
|
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_tag_t alt, lfsr_rid_t weight,
|
||||||
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
|
||||||
lfsr_srid_t rid, lfsr_tag_t tag) {
|
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);
|
LFS_ASSERT(lfsr_tag_key(tag) != 0);
|
||||||
|
|
||||||
if (lfsr_tag_isgt(alt)) {
|
if (lfsr_tag_isgt(alt)) {
|
||||||
@@ -1332,12 +1324,12 @@ static inline void lfsr_tag_trim(
|
|||||||
LFS_ASSERT((lfsr_srid_t)weight >= 0);
|
LFS_ASSERT((lfsr_srid_t)weight >= 0);
|
||||||
if (lfsr_tag_isgt(alt)) {
|
if (lfsr_tag_isgt(alt)) {
|
||||||
*upper_rid -= weight;
|
*upper_rid -= weight;
|
||||||
if (upper_tag && !lfsr_tag_isa(alt)) {
|
if (upper_tag) {
|
||||||
*upper_tag = alt + 1;
|
*upper_tag = alt + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*lower_rid += weight;
|
*lower_rid += weight;
|
||||||
if (lower_tag && !lfsr_tag_isn(alt)) {
|
if (lower_tag) {
|
||||||
*lower_tag = alt;
|
*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
|
// write out some number of alt pointers in our queue
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (p[3-1-i].alt) {
|
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_tag_t alt = p[3-1-i].alt;
|
||||||
lfsr_rid_t weight = p[3-1-i].weight;
|
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)
|
lfs_size_t jump = (p[3-1-i].jump)
|
||||||
? lfsr_rbyd_eoff(rbyd) - p[3-1-i].jump
|
? lfsr_rbyd_eoff(rbyd) - p[3-1-i].jump
|
||||||
: 0;
|
: 0;
|
||||||
@@ -3335,8 +3331,8 @@ static void lfsr_rbyd_p_recolor(
|
|||||||
if (p[1].alt) {
|
if (p[1].alt) {
|
||||||
p[1].alt |= LFSR_TAG_R;
|
p[1].alt |= LFSR_TAG_R;
|
||||||
|
|
||||||
// alt-never? we can prune this now
|
// unreachable alt? we can prune this now
|
||||||
if (lfsr_tag_isn(p[1].alt)) {
|
if (!p[1].jump) {
|
||||||
p[1] = p[2];
|
p[1] = p[2];
|
||||||
p[2].alt = 0;
|
p[2].alt = 0;
|
||||||
|
|
||||||
@@ -3708,16 +3704,25 @@ trunk:;
|
|||||||
branch = branch_;
|
branch = branch_;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// convert unreachable non-root black alts into alt-nevers,
|
// mark unreachable non-root black alts as unreachable,
|
||||||
// if we prune these it would break the color balance of
|
// we can't prune these or we risk breaking the color
|
||||||
// our tree
|
// balance of our tree, but if we push a red up later we
|
||||||
|
// can get rid of them
|
||||||
// : :
|
// : :
|
||||||
// <b => nb
|
// <b => nb
|
||||||
// .-'| .--'
|
// .-'| .--'
|
||||||
// 3 4 3 4 x
|
// 3 4 3 4 x
|
||||||
} else {
|
} else {
|
||||||
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, 0);
|
alt = LFSR_TAG_ALT(
|
||||||
weight = 0;
|
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;
|
jump = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -226,13 +226,10 @@ def tagrepr(tag, w=None, size=None, off=None):
|
|||||||
' w%d' % w if w else '',
|
' w%d' % w if w else '',
|
||||||
' %s' % size if size is not None else '')
|
' %s' % size if size is not None else '')
|
||||||
elif tag & TAG_ALT:
|
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',
|
'r' if tag & TAG_R else 'b',
|
||||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
'gt' if tag & TAG_GT else 'le',
|
||||||
else 'n' if tag & 0x0fff == 0
|
tag & 0x0fff,
|
||||||
else 'gt' if tag & TAG_GT
|
|
||||||
else 'le',
|
|
||||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
|
||||||
' w%d' % w if w is not None else '',
|
' w%d' % w if w is not None else '',
|
||||||
' 0x%x' % (0xffffffff & (off-size))
|
' 0x%x' % (0xffffffff & (off-size))
|
||||||
if size and off is not None
|
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 '',
|
' w%d' % w if w else '',
|
||||||
' %s' % size if size is not None else '')
|
' %s' % size if size is not None else '')
|
||||||
elif tag & TAG_ALT:
|
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',
|
'r' if tag & TAG_R else 'b',
|
||||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
'gt' if tag & TAG_GT else 'le',
|
||||||
else 'n' if tag & 0x0fff == 0
|
tag & 0x0fff,
|
||||||
else 'gt' if tag & TAG_GT
|
|
||||||
else 'le',
|
|
||||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
|
||||||
' w%d' % w if w is not None else '',
|
' w%d' % w if w is not None else '',
|
||||||
' 0x%x' % (0xffffffff & (off-size))
|
' 0x%x' % (0xffffffff & (off-size))
|
||||||
if size and off is not None
|
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 '',
|
' w%d' % w if w else '',
|
||||||
' %s' % size if size is not None else '')
|
' %s' % size if size is not None else '')
|
||||||
elif tag & TAG_ALT:
|
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',
|
'r' if tag & TAG_R else 'b',
|
||||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
'gt' if tag & TAG_GT else 'le',
|
||||||
else 'n' if tag & 0x0fff == 0
|
tag & 0x0fff,
|
||||||
else 'gt' if tag & TAG_GT
|
|
||||||
else 'le',
|
|
||||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
|
||||||
' w%d' % w if w is not None else '',
|
' w%d' % w if w is not None else '',
|
||||||
' 0x%x' % (0xffffffff & (off-size))
|
' 0x%x' % (0xffffffff & (off-size))
|
||||||
if size and off is not None
|
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 '',
|
' w%d' % w if w else '',
|
||||||
' %s' % size if size is not None else '')
|
' %s' % size if size is not None else '')
|
||||||
elif tag & TAG_ALT:
|
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',
|
'r' if tag & TAG_R else 'b',
|
||||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
'gt' if tag & TAG_GT else 'le',
|
||||||
else 'n' if tag & 0x0fff == 0
|
tag & 0x0fff,
|
||||||
else 'gt' if tag & TAG_GT
|
|
||||||
else 'le',
|
|
||||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
|
||||||
' w%d' % w if w is not None else '',
|
' w%d' % w if w is not None else '',
|
||||||
' 0x%x' % (0xffffffff & (off-size))
|
' 0x%x' % (0xffffffff & (off-size))
|
||||||
if size and off is not None
|
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 '',
|
' w%d' % w if w else '',
|
||||||
' %s' % size if size is not None else '')
|
' %s' % size if size is not None else '')
|
||||||
elif tag & TAG_ALT:
|
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',
|
'r' if tag & TAG_R else 'b',
|
||||||
'a' if tag & 0x0fff == 0 and tag & TAG_GT
|
'gt' if tag & TAG_GT else 'le',
|
||||||
else 'n' if tag & 0x0fff == 0
|
tag & 0x0fff,
|
||||||
else 'gt' if tag & TAG_GT
|
|
||||||
else 'le',
|
|
||||||
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
|
|
||||||
' w%d' % w if w is not None else '',
|
' w%d' % w if w is not None else '',
|
||||||
' 0x%x' % (0xffffffff & (off-size))
|
' 0x%x' % (0xffffffff & (off-size))
|
||||||
if size and off is not None
|
if size and off is not None
|
||||||
|
|||||||
Reference in New Issue
Block a user