Readopted 16-bit crammed size lfsr_attr_ts
Now that compound-literals have been identified as the culprit, we can
actually adopt this smaller lfsr_attr_t representation without a random
code/stack increase.
This limits lfsr_cat_t's size field to 16-bits (15-bit size + 1-bit
for concatenated datas), allowing simple small attrs (the most common)
to save a word of RAM:
lfsr_tag_t lfsr_attr_t
.---+---. .---+---+---+---.
| tag |-----------+--->| tag |c|size |
'---+---' | +---+---+---+---+
.-|--->| delta |
lfsr_srid_t | | +---+---+---+---+
.---+---+---+---. | | .->| ptr |
| delta |-' | | '---+---+---+---'
'---+---+---+---' | |
| |
lfsr_cat_t | |
.---+---+---+---. | |
|c|size |-----------' |
+---+---+---+---+ |
| ptr |-----'
'---+---+---+---'
The non-trivial mapping of lfsr_cat_t to lfsr_attr_t does mean a bit
more complexity on lfsr_cat_t access, but now that we figured out the
compound-literal cost it seems the compiler is able to mostly elide
these.
The end result is some nice stack savings:
code stack
before: 33812 2712
after: 33756 (-0.2%) 2624 (-3.2%)
This commit is contained in:
@@ -1416,19 +1416,19 @@ typedef struct lfsr_cat {
|
||||
// sign(size)=0 => single in-RAM buffer
|
||||
// sign(size)=1 => multiple concatenated datas
|
||||
union {
|
||||
lfs_size_t size;
|
||||
uint16_t size;
|
||||
struct {
|
||||
lfs_size_t size;
|
||||
uint16_t size;
|
||||
const uint8_t *buffer;
|
||||
} buf;
|
||||
struct {
|
||||
lfs_size_t size;
|
||||
uint16_t size;
|
||||
const lfsr_data_t *datas;
|
||||
} cat;
|
||||
} u;
|
||||
} lfsr_cat_t;
|
||||
|
||||
#define LFSR_CAT_ISCAT 0x80000000
|
||||
#define LFSR_CAT_ISCAT 0x8000
|
||||
|
||||
#define LFSR_CAT_NULL() \
|
||||
((lfsr_cat_t){ \
|
||||
@@ -1572,8 +1572,14 @@ static int lfsr_bd_progcat(lfs_t *lfs,
|
||||
|
||||
typedef struct lfsr_attr {
|
||||
lfsr_tag_t tag;
|
||||
uint16_t size;
|
||||
lfsr_srid_t delta;
|
||||
lfsr_cat_t cat;
|
||||
// sign(size)=0 => single in-RAM buffer
|
||||
// sign(size)=1 => multiple concatenated datas
|
||||
union {
|
||||
const uint8_t *buffer;
|
||||
const lfsr_data_t *datas;
|
||||
} u;
|
||||
} lfsr_attr_t;
|
||||
|
||||
#define LFSR_ATTR(_tag, _delta, _cat) \
|
||||
@@ -1584,13 +1590,14 @@ static inline lfsr_attr_t lfsr_attr(
|
||||
// don't use a compound literal here, GCC hates it
|
||||
lfsr_attr_t attr;
|
||||
attr.tag = tag;
|
||||
attr.size = cat.u.cat.size;
|
||||
attr.delta = delta;
|
||||
attr.cat = cat;
|
||||
attr.u.datas = cat.u.cat.datas;
|
||||
return attr;
|
||||
}
|
||||
|
||||
#define LFSR_ATTR_NOOP() \
|
||||
LFSR_ATTR(LFSR_TAG_NULL, 0, LFSR_CAT_NULL())
|
||||
((const lfsr_attr_t){LFSR_TAG_NULL, 0, LFSR_CAT_NULL()})
|
||||
|
||||
// create an attribute list
|
||||
#define LFSR_ATTRS(...) \
|
||||
@@ -1604,7 +1611,7 @@ static inline lfsr_attr_t lfsr_attr(
|
||||
((const lfsr_attr_t){ \
|
||||
.tag=_tag, \
|
||||
.delta=_delta, \
|
||||
.cat.u.buf.buffer=(const void*)(const lfsr_mdir_t*){_mdir}})
|
||||
.u.buffer=(const void*)(const lfsr_mdir_t*){_mdir}})
|
||||
|
||||
// a grm update, note this is mutable! we may update the grm during
|
||||
// mdir commits
|
||||
@@ -1612,7 +1619,7 @@ static inline lfsr_attr_t lfsr_attr(
|
||||
((const lfsr_attr_t){ \
|
||||
.tag=_tag, \
|
||||
.delta=_delta, \
|
||||
.cat.u.buf.buffer=(const void*)(const lfsr_grm_t*){_grm}})
|
||||
.u.buffer=(const void*)(const lfsr_grm_t*){_grm}})
|
||||
|
||||
// writing to an unrelated trunk in the rbyd
|
||||
typedef struct lfsr_shrubcommit lfsr_shrubcommit_t;
|
||||
@@ -1621,7 +1628,7 @@ typedef struct lfsr_shrubcommit lfsr_shrubcommit_t;
|
||||
((const lfsr_attr_t){ \
|
||||
.tag=_tag, \
|
||||
.delta=_delta, \
|
||||
.cat.u.buf.buffer=(const void*)&(const lfsr_shrubcommit_t){ \
|
||||
.u.buffer=(const void*)&(const lfsr_shrubcommit_t){ \
|
||||
.shrub=_shrub, \
|
||||
.rid=_rid, \
|
||||
.attrs=_attrs, \
|
||||
@@ -1631,7 +1638,7 @@ typedef struct lfsr_shrubcommit lfsr_shrubcommit_t;
|
||||
((const lfsr_attr_t){ \
|
||||
.tag=_tag, \
|
||||
.delta=_delta, \
|
||||
.cat.u.buf.buffer=(const void*)(const lfsr_shrub_t*){_shrub}})
|
||||
.u.buffer=(const void*)(const lfsr_shrub_t*){_shrub}})
|
||||
|
||||
// some helpers
|
||||
static inline bool lfsr_attr_isnoop(const lfsr_attr_t *attr) {
|
||||
@@ -1642,22 +1649,33 @@ static inline bool lfsr_attr_isinsert(const lfsr_attr_t *attr) {
|
||||
return !lfsr_tag_isgrow(attr->tag) && attr->delta > 0;
|
||||
}
|
||||
|
||||
static inline lfsr_cat_t lfsr_attr_cat(const lfsr_attr_t *attr) {
|
||||
lfsr_cat_t cat;
|
||||
cat.u.cat.size = attr->size;
|
||||
cat.u.cat.datas = attr->u.datas;
|
||||
return cat;
|
||||
}
|
||||
|
||||
static inline lfs_size_t lfsr_attr_size(const lfsr_attr_t *attr) {
|
||||
return lfsr_cat_size(lfsr_attr_cat(attr));
|
||||
}
|
||||
|
||||
static inline lfsr_grm_t *lfsr_attr_grm(const lfsr_attr_t *attr) {
|
||||
return (lfsr_grm_t*)attr->cat.u.buf.buffer;
|
||||
return (lfsr_grm_t*)attr->u.buffer;
|
||||
}
|
||||
|
||||
static inline const lfsr_mdir_t *lfsr_attr_mdir(const lfsr_attr_t *attr) {
|
||||
return (lfsr_mdir_t*)attr->cat.u.buf.buffer;
|
||||
return (lfsr_mdir_t*)attr->u.buffer;
|
||||
}
|
||||
|
||||
static inline const lfsr_shrubcommit_t *lfsr_attr_shrubcommit(
|
||||
const lfsr_attr_t *attr) {
|
||||
return (const lfsr_shrubcommit_t*)attr->cat.u.buf.buffer;
|
||||
return (const lfsr_shrubcommit_t*)attr->u.buffer;
|
||||
}
|
||||
|
||||
static inline const lfsr_shrub_t *lfsr_attr_shrubtrunk(
|
||||
const lfsr_attr_t *attr) {
|
||||
return (const lfsr_shrub_t*)attr->cat.u.buf.buffer;
|
||||
return (const lfsr_shrub_t*)attr->u.buffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -3612,7 +3630,7 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
&& (lfs_size_t)(rid + 1) <= (lfs_size_t)end_rid) {
|
||||
int err = lfsr_rbyd_appendattr(lfs, rbyd,
|
||||
rid - lfs_smax32(start_rid, 0),
|
||||
attrs[i].tag, attrs[i].delta, attrs[i].cat);
|
||||
attrs[i].tag, attrs[i].delta, lfsr_attr_cat(&attrs[i]));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -6182,7 +6200,9 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
|
||||
|
||||
int err = lfsr_rbyd_appendattr(lfs, &rbyd_,
|
||||
rid - lfs_smax32(start_rid, 0),
|
||||
attrs[i].tag, attrs[i].delta, attrs[i].cat);
|
||||
attrs[i].tag,
|
||||
attrs[i].delta,
|
||||
lfsr_attr_cat(&attrs[i]));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -10233,7 +10253,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
|
||||
&& !lfsr_tag_isrm(attrs[i].tag)) {
|
||||
commit_estimate += lfs->attr_estimate;
|
||||
}
|
||||
commit_estimate += lfsr_cat_size(attrs[i].cat);
|
||||
commit_estimate += lfsr_attr_size(&attrs[i]);
|
||||
}
|
||||
|
||||
// does our estimate exceed our shrub_size? need to recalculate an
|
||||
@@ -11431,7 +11451,10 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
||||
lfsr_attr_t attrs[2];
|
||||
lfs_size_t attr_count = 0;
|
||||
lfsr_data_t name_data;
|
||||
uint8_t buf[LFSR_BTREE_DSIZE];
|
||||
union {
|
||||
lfsr_data_t data;
|
||||
uint8_t buf[LFSR_BTREE_DSIZE];
|
||||
} data;
|
||||
|
||||
// not created yet? need to convert orphan to normal file
|
||||
if (lfsr_f_isorphan(file->m.flags)) {
|
||||
@@ -11457,9 +11480,10 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
||||
LFSR_CAT_NULL());
|
||||
// small file inlined in mdir?
|
||||
} else if (lfsr_f_isunflush(file->m.flags)) {
|
||||
data.data = LFSR_DATA_BUF(file->buffer, file->buffer_size);
|
||||
attrs[attr_count++] = LFSR_ATTR(
|
||||
LFSR_TAG_SUB | LFSR_TAG_DATA, 0,
|
||||
LFSR_CAT_BUF(file->buffer, file->buffer_size));
|
||||
LFSR_CAT_DATA_(&data.data));
|
||||
// bshrub?
|
||||
} else if (lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub)) {
|
||||
attrs[attr_count++] = LFSR_ATTR_SHRUBTRUNK(
|
||||
@@ -11469,7 +11493,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
||||
} else if (lfsr_bshrub_isbtree(&file->m.mdir, &file->bshrub)) {
|
||||
attrs[attr_count++] = LFSR_ATTR(
|
||||
LFSR_TAG_SUB | LFSR_TAG_BTREE, 0,
|
||||
LFSR_CAT_BTREE_(&file->bshrub.u.btree, buf));
|
||||
LFSR_CAT_BTREE_(&file->bshrub.u.btree, data.buf));
|
||||
} else {
|
||||
LFS_UNREACHABLE();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user