Tweaked canonical altn to point to itself

By definition, altns should never be followed, so it doesn't really
matter where they point. But it's not like they can point literally
nowhere, so where should they point?

A couple options:

1. jump=jump - Wherever the old alt pointed
   - Easy, literally a noop
   - Unsafe, bugs could reveal outdated parts of the tree
   - Encoding size eh

2. jump=0 - Point to offset=0
   - Easier, +0 code
   - Safer, branching to 0 should assert
   - Worst possible encoding size

3. jump=itself - Point to itself
   - A bit tricky, +4 code
   - Safe, should assert, even without asserts worst case infinite loop
   - Optimal encoding size

An infinite loop isn't the best failure state, but we can catch this
with an assert, which we would need for jump=0 anyways. And this is only
a concern if there are other fs bugs. jump=0 is actually slightly worse
if asserts are disabled, since we'd end up reading the revision count as
garbage.

Adopting jump=itself gives us the optimal 4-byte encoding:

  altbn w0 = 40 00 00 00
             '-+-'  ^  ^
               '----|--|-- tag = altbn
                    '--|-- weight = 0
                       '-- jump = itself (branch - 0)

This requires tweaking the alt encoder a bit, to avoid relative encoding
jump=0s, but this is pretty cheap:

                code          stack
  jump=jump:   34068           2864
  jump=0:      34068 (+0.0%)   2864 (+0.0%)
  jump=itself: 34072 (+0.0%)   2864 (+0.0%)

I thought we may need to also tweak the decoder, so later trunk copies
don't accidentally point to the old location, but humorously our pruning
kicks in redundantly to reset altbn's jump=itself on every trunk.

Note lfsr_rbyd_lookupnext was also rearranged a bit to make it easier to
assert on infinite loops and this also added some code. Probably just
due to compiler noise:

           code          stack
  before: 34068           2864
  after:  34076 (+0.0%)   2864 (+0.0%)

Also note that we still accept all of the above altbn encoding options.
This only affects encoding and dbg scripts.
This commit is contained in:
Christopher Haster
2024-04-23 15:47:37 -05:00
parent e8f6b0006c
commit 86a8582445
6 changed files with 26 additions and 24 deletions
+15 -12
View File
@@ -2458,6 +2458,9 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
// found an alt?
if (lfsr_tag_isalt(alt)) {
lfs_size_t branch_ = branch + d;
// take alt?
if (lfsr_tag_follow(
alt, weight,
lower_rid, upper_rid,
@@ -2465,19 +2468,16 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
lfsr_tag_flip(
&alt, &weight,
lower_rid, upper_rid);
lfsr_tag_trim(
alt, weight,
&lower_rid, &upper_rid,
NULL, NULL);
branch = branch - jump;
} else {
lfsr_tag_trim(
alt, weight,
&lower_rid, &upper_rid,
NULL, NULL);
branch = branch + d;
branch_ = branch - jump;
}
lfsr_tag_trim(
alt, weight,
&lower_rid, &upper_rid,
NULL, NULL);
LFS_ASSERT(branch_ != branch);
branch = branch_;
// found end of tree?
} else {
// update the tag rid
@@ -2683,7 +2683,9 @@ static int lfsr_p_flush(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// change to a relative jump at the last minute
lfsr_tag_t alt = p[3-1-i].alt;
lfsr_rid_t weight = p[3-1-i].weight;
lfs_size_t jump = rbyd->eoff - p[3-1-i].jump;
lfs_size_t jump = (p[3-1-i].jump)
? rbyd->eoff - p[3-1-i].jump
: 0;
int err = lfsr_rbyd_appendtag(lfs, rbyd, alt, weight, jump);
if (err) {
@@ -3196,6 +3198,7 @@ trunk:;
}
// continue to next alt
LFS_ASSERT(branch_ != branch);
branch = branch_;
continue;
+2 -2
View File
@@ -239,8 +239,8 @@ def tagrepr(tag, w=None, size=None, off=None):
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size is not None and off is not None
else ' -%d' % size if size is not None
if size and off is not None
else ' -%d' % size if size
else '')
else:
return '0x%04x%s%s' % (
+2 -2
View File
@@ -270,8 +270,8 @@ def tagrepr(tag, w=None, size=None, off=None):
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size is not None and off is not None
else ' -%d' % size if size is not None
if size and off is not None
else ' -%d' % size if size
else '')
else:
return '0x%04x%s%s' % (
+2 -2
View File
@@ -254,8 +254,8 @@ def tagrepr(tag, w=None, size=None, off=None):
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size is not None and off is not None
else ' -%d' % size if size is not None
if size and off is not None
else ' -%d' % size if size
else '')
else:
return '0x%04x%s%s' % (
+3 -4
View File
@@ -241,8 +241,8 @@ def tagrepr(tag, w=None, size=None, off=None):
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size is not None and off is not None
else ' -%d' % size if size is not None
if size and off is not None
else ' -%d' % size if size
else '')
else:
return '0x%04x%s%s' % (
@@ -267,8 +267,7 @@ def dbg_log(data, block_size, rev, eoff, weight, *,
if not tag & TAG_ALT:
j_ += size
# skip alt-nevers
if tag & TAG_ALT and tag & ~TAG_R != TAG_ALT:
if tag & TAG_ALT and size:
# figure out which alt color
if tag & TAG_R:
_, ntag, _, _, _ = fromtag(data[j_:])
+2 -2
View File
@@ -199,8 +199,8 @@ def tagrepr(tag, w=None, size=None, off=None):
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size is not None and off is not None
else ' -%d' % size if size is not None
if size and off is not None
else ' -%d' % size if size
else '')
else:
return '0x%04x%s%s' % (