Adopted rattr.from for simpler appendrattr_ lazy encoding

This breaks down the previously 16-bit rattr.count field into two 8-bit
rattr.from and rattr.count fields. Now, instead of using a mixture of
rattr.tag and sign(rattr.count) to determine rattr encoding, we just
jump based on rattr.from:

  lfs3_rattr_t:
  .---+---+---+---.
  |  tag  |frm|cnt| -+-> 16-bit tag   - on-disk encoding + rbyd flags
  +---+---+---+---+  +->  8-bit from  - in-RAM encoding
  |     weight    |  '->  8-bit count - from-specific count
  +---+---+---+---+
  |      ptr      |
  '---+---+---+---'

The internal appendrattr_ ctx also saw a bit of rework, and now uses a
big union with multiple buffers instead of stacking a ridiculous number
of LFS_MAX calls. Expanding the LFS_MAX stack grows O(n^2), so this is
probably good for compile times.

And all rattr.from branches now generate an lfs3_data_t*. This was
already a side-effect of all the internal lfs3_data_from* functions, and
it simplifies the tail end of appendrattr_. No more relying on
data_count's sign bit.

Also rearranged rattr.from encoders to match source code order.

---

Unfortunately, while this did simplify the source code, it didn't really
lead to much improvement in code size:

           code          stack          ctx
  before: 37024           2416          652
  after:  37016 (-0.0%)   2416 (+0.0%)  652 (+0.0%)

I guess jump tables are more a performance optimization than a code size
one. That and the benefit of cheaper appendrattr_ logic is likely
overshadowed by the extra constants needed to populate rattr.from in
every LFS3_RATTR_* macro.

Also test_attrs_fattr_resync_receive is now failing, but I think that's
just because of an unrelated bug exposed by the shrinking count field.
In theory rattr.count should be limited to internal fixed-size buffers.
This commit is contained in:
Christopher Haster
2025-07-15 00:26:08 -05:00
parent 0bed3867d8
commit 5b0ec8090a
3 changed files with 259 additions and 228 deletions
+22 -14
View File
@@ -2485,15 +2485,17 @@ code = '''
uint8_t buf2[SIZE];
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 0, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_DATA, 0, buf1, SIZE),
LFS3_RATTR_BUF(LFS3_TAG_DATA, +1, buf2, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_DATA, 0,
&LFS3_DATA_BUF(buf1, SIZE)),
LFS3_RATTR_DATA(LFS3_TAG_DATA, +1,
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
// force compaction
btree.eoff = -1;
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 1, LFS3_RATTRS(
LFS3_RATTR_BUF(
LFS3_RATTR_DATA(
LFS3_TAG_MASK8 | LFS3_TAG_DATA, 0,
buf2, SIZE))) => 0;
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
assert(btree.weight == 2);
// now remove one entry, since this brings the rbyd down to zero,
@@ -2554,15 +2556,17 @@ code = '''
uint8_t buf2[SIZE];
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 0, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_DATA, 0, buf1, SIZE),
LFS3_RATTR_BUF(LFS3_TAG_DATA, +1, buf2, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_DATA, 0,
&LFS3_DATA_BUF(buf1, SIZE)),
LFS3_RATTR_DATA(LFS3_TAG_DATA, +1,
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
// force compaction
btree.eoff = -1;
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 1, LFS3_RATTRS(
LFS3_RATTR_BUF(
LFS3_RATTR_DATA(
LFS3_TAG_MASK8 | LFS3_TAG_DATA, 0,
buf2, SIZE))) => 0;
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
assert(btree.weight == 2);
// now remove one entry, since this brings the rbyd down this zero,
@@ -2626,8 +2630,10 @@ code = '''
uint8_t buf2[SIZE];
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 0, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_DATA, 0, buf1, SIZE),
LFS3_RATTR_BUF(LFS3_TAG_DATA, +1, buf2, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_DATA, 0,
&LFS3_DATA_BUF(buf1, SIZE)),
LFS3_RATTR_DATA(LFS3_TAG_DATA, +1,
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
// force compaction, causing a split, but while we're splitting,
// also remove an entry, bringing the split rbyd down to zero mid split
@@ -2691,15 +2697,17 @@ code = '''
uint8_t buf2[SIZE];
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 0, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_DATA, 0, buf1, SIZE),
LFS3_RATTR_BUF(LFS3_TAG_DATA, +1, buf2, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_DATA, 0,
&LFS3_DATA_BUF(buf1, SIZE)),
LFS3_RATTR_DATA(LFS3_TAG_DATA, +1,
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
// force compaction
btree.eoff = -1;
memset(buf2, 'b', SIZE);
lfs3_btree_commit(&lfs3, &btree, 1, LFS3_RATTRS(
LFS3_RATTR_BUF(
LFS3_RATTR_DATA(
LFS3_TAG_MASK8 | LFS3_TAG_DATA, 0,
buf2, SIZE))) => 0;
&LFS3_DATA_BUF(buf2, SIZE)))) => 0;
assert(btree.weight == 2);
// now make both entries small so they should be merged if either compacts
+16 -8
View File
@@ -187,13 +187,15 @@ code = '''
uint8_t buffer[SIZE];
memset(buffer, 'a', SIZE);
lfs3_mdir_commit(&lfs3, &lfs3.mroot, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(1), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(1), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
memset(buffer, 'b', SIZE);
lfs3_mdir_t mdir;
lfs3_mtree_lookup(&lfs3, 0, &mdir) => 0;
lfs3_mdir_commit(&lfs3, &mdir, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(2), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(2), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
// force mroot to compact
lfs3.mroot.r.eoff = -1;
@@ -1287,13 +1289,15 @@ code = '''
uint8_t buffer[SIZE];
memset(buffer, 'a', SIZE);
lfs3_mdir_commit(&lfs3, &lfs3.mroot, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(1), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(1), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
memset(buffer, 'b', SIZE);
lfs3_mdir_t mdir;
lfs3_mtree_lookup(&lfs3, 0, &mdir) => 0;
lfs3_mdir_commit(&lfs3, &mdir, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(2), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(2), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
// force mroot to compact
lfs3.mroot.r.eoff = -1;
@@ -2356,13 +2360,15 @@ code = '''
uint8_t buffer[SIZE];
memset(buffer, 'a', SIZE);
lfs3_mdir_commit(&lfs3, &lfs3.mroot, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(1), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(1), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
memset(buffer, 'b', SIZE);
lfs3_mdir_t mdir;
lfs3_mtree_lookup(&lfs3, 0, &mdir) => 0;
lfs3_mdir_commit(&lfs3, &mdir, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(2), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(2), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
// force mroot to compact, this should both uninline and relocate
lfs3_mdir_t old_mroot = lfs3.mroot;
@@ -3590,13 +3596,15 @@ code = '''
uint8_t buffer[SIZE];
memset(buffer, 'a', SIZE);
lfs3_mdir_commit(&lfs3, &lfs3.mroot, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(1), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(1), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
memset(buffer, 'b', SIZE);
lfs3_mdir_t mdir;
lfs3_mtree_lookup(&lfs3, 0, &mdir) => 0;
lfs3_mdir_commit(&lfs3, &mdir, LFS3_RATTRS(
LFS3_RATTR_BUF(LFS3_TAG_ATTR(1), 0, buffer, SIZE))) => 0;
LFS3_RATTR_DATA(LFS3_TAG_ATTR(1), 0,
&LFS3_DATA_BUF(buffer, SIZE)))) => 0;
// force mroot to compact
lfs3.mroot.r.eoff = -1;