diff --git a/lfs.c b/lfs.c index 30edc9b2..73617c22 100644 --- a/lfs.c +++ b/lfs.c @@ -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 // : : // 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; } } diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index 2cd66637..ed78de37 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -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 diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index 0ea428c7..00268921 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -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 diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index 1f622a7f..f46330e3 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -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 diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index 4fdb2046..7b14cef4 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -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 diff --git a/scripts/dbgtag.py b/scripts/dbgtag.py index 669e857d..21c856b9 100755 --- a/scripts/dbgtag.py +++ b/scripts/dbgtag.py @@ -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