t: Changed lfsr_mtree_traverse to operate on mdir+mtraversal

Separated out omdir/mdir and mtraversal. You still need to allocate an
mdir for mtraversal to work, but this avoids the extra cost of omdir's
linked-list.

To avoid _too_ many pointers, I duplicated the flags field into both
lfsr_traversal_t and lfsr_mtraversal_t. This is basically free since we
end up with a bunch of padding for mtraversal's state field, but comes
with the risk of getting confused when the two flag fields don't match
in the future.

I also merged the intermediary btype field into flags to avoid yet
another single-byte field, where it fits comfortably in 3-bits.

Note that the mdir can be uninitialized in cases where we don't need to
worry about traversal clobbering.

---

This has the same problems as separating out mdirs/bshrubs in bshrub
functions: more stack/code to move the multiple pointers around, but is
necessary to avoid strict aliasing issues. There's no way to represent
overlapping omdir/mdir/mtraversal struct in standard C99 otherwise.

The end result saves a bit of code, but adds a bit of stack:

           code          stack
  before: 34576           2632
  after:  34524 (-0.2%)   2640 (+0.3%)

Though these numbers may be close enough to the compiler noise floor to
not really care about...
This commit is contained in:
Christopher Haster
2024-06-23 23:21:34 -05:00
parent b383821a22
commit 2f1d711902
4 changed files with 151 additions and 149 deletions
+6 -3
View File
@@ -163,6 +163,7 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
(CKMETA) ? LFS_T_CKMETA : 0);
for (lfs_block_t i = 0;; i++) {
@@ -170,7 +171,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -331,6 +332,7 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
((CKMETA) ? LFS_T_CKMETA : 0));
for (lfs_block_t i = 0;; i++) {
@@ -338,7 +340,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -485,6 +487,7 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
((CKMETA) ? LFS_T_CKMETA : 0));
for (lfs_block_t i = 0;; i++) {
@@ -492,7 +495,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
+11 -10
View File
@@ -3370,7 +3370,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -3485,7 +3485,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -3622,7 +3622,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -3780,7 +3780,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -3922,7 +3922,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -4031,6 +4031,7 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
LFS_T_MTREEONLY
| ((CKMETA) ? LFS_T_CKMETA : 0));
@@ -4039,7 +4040,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -4087,7 +4088,6 @@ code = '''
// and the tree should still work
// try looking up each entry
lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
lfsr_data_t data;
uint8_t buffer[256];
@@ -4190,6 +4190,7 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
LFS_T_MTREEONLY
| ((CKMETA) ? LFS_T_CKMETA : 0));
@@ -4198,7 +4199,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) {
break;
@@ -4246,7 +4247,6 @@ code = '''
// and the tree should still work
// try looking up each entry
lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
lfsr_data_t data;
uint8_t buffer[256];
@@ -4313,6 +4313,7 @@ code = '''
LFSR_DATA_MPTR(&LFSR_MPTR_MROOTANCHOR())))) => 0;
// technically, cycle detection only needs to work when we're validating
lfsr_mdir_t mdir;
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
LFS_T_MTREEONLY | LFS_T_CKMETA);
for (lfs_block_t i = 0;; i++) {
@@ -4320,7 +4321,7 @@ code = '''
assert(i < 2*BLOCK_COUNT);
lfsr_mtinfo_t mtinfo;
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
assert(!err || err == LFS_ERR_CORRUPT);
if (err == LFS_ERR_CORRUPT) {
break;