Adopted lfsr_rbyd_lookupwide, dropped wide bit in lookups

This trades a runtime check for a different function call. Enforcing
some minor semantics in the function's type/asserts.

This also makes it so there are no special tag bits used during rbyds
lookup, only rbyd commits.

In theory this saves a bit of code, we don't have a runtime check, but
in practice the extra function apparently outweighs the cost of the
runtime check:

            code          stack
  before:  31956           2880
  after:   32024 (+0.2%)   2880 (+0.0%)
This commit is contained in:
Christopher Haster
2023-12-14 12:24:32 -06:00
parent 3e45fc739d
commit 02d2919130
3 changed files with 86 additions and 61 deletions
+72 -47
View File
@@ -2232,12 +2232,11 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
lfsr_srid_t *rid_, lfsr_tag_t *tag_, lfsr_rid_t *weight_,
lfsr_data_t *data_) {
// these bits should be clear at this point
LFS_ASSERT(!lfsr_tag_isrm(tag));
LFS_ASSERT(!lfsr_tag_isgrow(tag));
LFS_ASSERT(lfsr_tag_mode(tag) == 0);
// make sure we never look up zero tags, the way we create
// unreachable tags has a hole here
tag = lfs_max16(lfsr_tag_key(tag), 0x1);
tag = lfs_max16(tag, 0x1);
// keep track of bounds as we descend down the tree
lfs_size_t branch = rbyd->trunk;
@@ -2306,8 +2305,31 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
}
static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
lfsr_srid_t rid, lfsr_tag_t tag,
lfsr_data_t *data_) {
lfsr_srid_t rid_;
lfsr_tag_t tag_;
int err = lfsr_rbyd_lookupnext(lfs, rbyd, rid, tag,
&rid_, &tag_, NULL, data_);
if (err) {
return err;
}
// lookup finds the next-smallest tag, all we need to do is fail if it
// picks up the wrong tag
if (rid_ != rid || tag_ != tag) {
return LFS_ERR_NOENT;
}
return 0;
}
static int lfsr_rbyd_lookupwide(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
lfsr_srid_t rid, lfsr_tag_t tag,
lfsr_tag_t *tag_, lfsr_data_t *data_) {
// looking up a wide tag with subtype is probably a mistake
LFS_ASSERT(lfsr_tag_subtype(tag) == 0);
lfsr_srid_t rid_;
lfsr_tag_t tag__;
int err = lfsr_rbyd_lookupnext(lfs, rbyd, rid, tag,
@@ -2316,15 +2338,9 @@ static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
return err;
}
// lookup finds the next-smallest tag, all we need to do is fail if it
// picks up the wrong tag
//
// we accept either exact matches or suptype matches depending on the
// wide bit
if (rid_ != rid
|| (lfsr_tag_iswide(tag)
? lfsr_tag_suptype(tag__) != (tag & ~LFSR_TAG_WIDE)
: tag__ != tag)) {
// the difference between lookup and lookupwide is we accept any
// subtype of the requested tag
if (rid_ != rid || lfsr_tag_suptype(tag__) != tag) {
return LFS_ERR_NOENT;
}
@@ -3402,7 +3418,7 @@ static int lfsr_rbyd_appendgdelta(lfs_t *lfs, lfsr_rbyd_t *rbyd) {
lfsr_data_t data;
int err = lfsr_rbyd_lookup(lfs, rbyd, -1, LFSR_TAG_GRMDELTA,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -3817,7 +3833,7 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
}
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
err = lfsr_rbyd_lookup(lfs, &branch, rid__, LFSR_TAG_WIDE(STRUCT),
err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
&tag__, &data__);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -3914,7 +3930,7 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
}
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
err = lfsr_rbyd_lookup(lfs, &branch, rid__, LFSR_TAG_WIDE(STRUCT),
err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
&tag__, &data__);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -4101,8 +4117,8 @@ static lfs_ssize_t lfsr_btree_commit_(lfs_t *lfs,
}
if (sibling_tag == LFSR_TAG_NAME) {
err = lfsr_rbyd_lookup(lfs, &parent,
sibling_rid, LFSR_TAG_WIDE(STRUCT),
err = lfsr_rbyd_lookupwide(lfs, &parent,
sibling_rid, LFSR_TAG_STRUCT,
&sibling_tag, &sibling_data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -4149,8 +4165,8 @@ static lfs_ssize_t lfsr_btree_commit_(lfs_t *lfs,
}
if (sibling_tag == LFSR_TAG_NAME) {
err = lfsr_rbyd_lookup(lfs, &parent,
sibling_rid, LFSR_TAG_WIDE(STRUCT),
err = lfsr_rbyd_lookupwide(lfs, &parent,
sibling_rid, LFSR_TAG_STRUCT,
&sibling_tag, &sibling_data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -4542,7 +4558,7 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
// the name may not match exactly, but indicates which branch to follow
lfsr_tag_t tag__;
lfsr_data_t data__;
int err = lfsr_rbyd_lookup(lfs, &branch, rid__, LFSR_TAG_WIDE(STRUCT),
int err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
&tag__, &data__);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -4653,8 +4669,8 @@ static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree,
}
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
err = lfsr_rbyd_lookup(lfs, &btraversal->branch,
rid__, LFSR_TAG_WIDE(STRUCT),
err = lfsr_rbyd_lookupwide(lfs, &btraversal->branch,
rid__, LFSR_TAG_STRUCT,
&tag__, &data__);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -5130,8 +5146,16 @@ static int lfsr_mdir_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir,
static int lfsr_mdir_lookup(lfs_t *lfs, const lfsr_mdir_t *mdir,
lfsr_smid_t mid, lfsr_tag_t tag,
lfsr_tag_t *tag_, lfsr_data_t *data_) {
lfsr_data_t *data_) {
return lfsr_rbyd_lookup(lfs, &mdir->rbyd,
lfsr_mid_rid(lfs, mid), tag,
data_);
}
static int lfsr_mdir_lookupwide(lfs_t *lfs, const lfsr_mdir_t *mdir,
lfsr_smid_t mid, lfsr_tag_t tag,
lfsr_tag_t *tag_, lfsr_data_t *data_) {
return lfsr_rbyd_lookupwide(lfs, &mdir->rbyd,
lfsr_mid_rid(lfs, mid), tag,
tag_, data_);
}
@@ -5404,7 +5428,7 @@ static void lfsr_fs_flushgdelta(lfs_t *lfs) {
static int lfsr_fs_consumegdelta(lfs_t *lfs, const lfsr_mdir_t *mdir) {
lfsr_data_t data;
int err = lfsr_mdir_lookup(lfs, mdir, -1, LFSR_TAG_GRMDELTA,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -6040,7 +6064,8 @@ static int lfsr_mroot_parent(lfs_t *lfs, const lfsr_mptr_t *mptr,
// lookup next mroot
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, &mdir, -1, LFSR_TAG_MROOT, NULL, &data);
err = lfsr_mdir_lookup(lfs, &mdir, -1, LFSR_TAG_MROOT,
&data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
@@ -6594,7 +6619,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// note we need to do this after playing out pending attrs in
// case they introduce a new name!
lfsr_data_t split_data;
err = lfsr_rbyd_lookup(lfs, &msibling_.rbyd, 0, LFSR_TAG_WIDE(NAME),
err = lfsr_rbyd_lookupwide(lfs, &msibling_.rbyd, 0, LFSR_TAG_NAME,
NULL, &split_data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -7034,7 +7059,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path,
if (!lfsr_mid_isroot(mdir.mid)) {
lfsr_data_t data;
int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID,
NULL, &data);
&data);
if (err) {
return err;
}
@@ -7183,8 +7208,8 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
// lookup mroot, if we find one this is a fake mroot
lfsr_tag_t tag;
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, &traversal->mdir,
-1, LFSR_TAG_WIDE(STRUCT),
err = lfsr_mdir_lookupwide(lfs, &traversal->mdir,
-1, LFSR_TAG_STRUCT,
&tag, &data);
if (err) {
// if we have no mtree/mdir (inlined mdir), we need to traverse
@@ -7663,7 +7688,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// has magic string?
lfsr_data_t data;
int err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_MAGIC,
NULL, &data);
&data);
if (err) {
if (err == LFS_ERR_NOENT) {
LFS_ERROR("No littlefs magic found");
@@ -7685,7 +7710,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// check the disk version
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_VERSION,
NULL, &data);
&data);
if (err) {
if (err == LFS_ERR_NOENT) {
LFS_ERROR("No littlefs version found");
@@ -7726,7 +7751,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// check for any rcompatflags, we must understand these to read
// the filesystem
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_RCOMPATFLAGS,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -7761,7 +7786,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// check for any wcompatflags, we must understand these to write
// the filesystem
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_WCOMPATFLAGS,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -7778,7 +7803,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// check block size
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_BLOCKSIZE,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -7803,7 +7828,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// check block count
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_BLOCKCOUNT,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -7829,7 +7854,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// read the name limit
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_NAMELIMIT,
NULL, &data);
&data);
if (err) {
if (err == LFS_ERR_NOENT) {
LFS_ERROR("No name limit found");
@@ -7858,7 +7883,7 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
// read the size limit
err = lfsr_mdir_lookup(lfs, mroot, -1, LFSR_TAG_SIZELIMIT,
NULL, &data);
&data);
if (err) {
if (err == LFS_ERR_NOENT) {
LFS_ERROR("No size limit found");
@@ -8557,7 +8582,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
// first lets figure out the did
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID,
NULL, &data);
&data);
if (err) {
return err;
}
@@ -8588,8 +8613,8 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
if (err != LFS_ERR_NOENT) {
lfsr_tag_t bookmark_tag;
err = lfsr_mdir_lookup(lfs, &bookmark_mdir,
bookmark_mdir.mid, LFSR_TAG_WIDE(NAME),
err = lfsr_mdir_lookupwide(lfs, &bookmark_mdir,
bookmark_mdir.mid, LFSR_TAG_NAME,
&bookmark_tag, NULL);
if (err) {
return err;
@@ -8695,7 +8720,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, &new_mdir,
new_mdir.mid, LFSR_TAG_DID,
NULL, &data);
&data);
if (err) {
return err;
}
@@ -8726,8 +8751,8 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
if (err != LFS_ERR_NOENT) {
lfsr_tag_t bookmark_tag;
err = lfsr_mdir_lookup(lfs, &bookmark_mdir,
bookmark_mdir.mid, LFSR_TAG_WIDE(NAME),
err = lfsr_mdir_lookupwide(lfs, &bookmark_mdir,
bookmark_mdir.mid, LFSR_TAG_NAME,
&bookmark_tag, NULL);
if (err) {
return err;
@@ -8767,7 +8792,7 @@ static int lfsr_mdir_stat(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_mid_t mid,
// lookup our name tag
lfsr_tag_t tag;
lfsr_data_t data;
int err = lfsr_mdir_lookup(lfs, mdir, mid, LFSR_TAG_WIDE(NAME),
int err = lfsr_mdir_lookupwide(lfs, mdir, mid, LFSR_TAG_NAME,
&tag, &data);
if (err) {
return err;
@@ -8875,7 +8900,7 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) {
} else {
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID,
NULL, &data);
&data);
if (err) {
return err;
}
@@ -9379,7 +9404,7 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs,
if (becksum_) {
// need an extra lookup to find becksums
err = lfsr_rbyd_lookup(lfs, &rbyd, rid, LFSR_TAG_BECKSUM,
NULL, &data);
&data);
if (err && err != LFS_ERR_NOENT) {
return err;
}
@@ -10421,7 +10446,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
// TODO deduplicate?
err = lfsr_mdir_lookup(lfs, &file->mdir,
file->mdir.mid, LFSR_TAG_DATA,
NULL, &file->ftree.u.bsprout.data);
&file->ftree.u.bsprout.data);
if (err) {
return err;
}
+1 -1
View File
@@ -11,7 +11,7 @@ code = '''
static lfs_ssize_t lfsr_mdir_get(lfs_t *lfs, const lfsr_mdir_t *mdir,
lfs_ssize_t rid, lfsr_tag_t tag, void *buffer, lfs_size_t size) {
lfsr_data_t data;
int err = lfsr_mdir_lookup(lfs, mdir, rid, tag, NULL, &data);
int err = lfsr_mdir_lookup(lfs, mdir, rid, tag, &data);
if (err) {
return err;
}
+13 -13
View File
@@ -20,7 +20,7 @@ code = '''
static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
lfs_ssize_t rid, lfsr_tag_t tag, void *buffer, lfs_size_t size) {
lfsr_data_t data;
int err = lfsr_rbyd_lookup(lfs, rbyd, rid, tag, NULL, &data);
int err = lfsr_rbyd_lookup(lfs, rbyd, rid, tag, &data);
if (err) {
return err;
}
@@ -11618,7 +11618,7 @@ code = '''
for (unsigned j = 0; j < N; j++) {
lfsr_tag_t tag_;
lfsr_data_t data_;
lfsr_rbyd_lookup(&lfs, &rbyd, j, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
@@ -11748,10 +11748,10 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
if (k == j) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => LFS_ERR_NOENT;
} else {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
assert(lfsr_data_size(&data_) == 2);
@@ -11890,7 +11890,7 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
if (k == j) {
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
@@ -11983,7 +11983,7 @@ code = '''
for (unsigned j = 0; j < N; j++) {
lfsr_tag_t tag_;
lfsr_data_t data_;
lfsr_rbyd_lookup(&lfs, &rbyd, j, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
@@ -12122,10 +12122,10 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
if (k == j) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => LFS_ERR_NOENT;
} else {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
assert(lfsr_data_size(&data_) == 2);
@@ -12273,7 +12273,7 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
if (k == j) {
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
@@ -12363,7 +12363,7 @@ code = '''
for (unsigned j = 0; j < N; j++) {
lfsr_tag_t tag_;
lfsr_data_t data_;
lfsr_rbyd_lookup(&lfs, &rbyd, j, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
@@ -12495,10 +12495,10 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
if (k == j) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => LFS_ERR_NOENT;
} else {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
assert(lfsr_data_size(&data_) == 4);
@@ -12629,7 +12629,7 @@ code = '''
// also test that we can lookup each tag with a wide lookup
for (unsigned k = 0; k < N; k++) {
lfsr_rbyd_lookup(&lfs, &rbyd, k, LFSR_TAG_WIDE(UATTR),
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
&tag_, &data_) => 0;
if (k == j) {
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));