Unified attr-list context into little attr arenas
The idea is for cases where we need to incrementally allocate attrs +
context, to allocate from both sides of a statically allocated attr
array. This keeps all of the attr-list state in one place, simplifying
state allocation:
.---+---+---+---.
| attr |
+---+---+---+---+
| attr ----------.
+---+---+---+---+ |
| attr --------. |
+---+---+---+---+ | |
| | | | |
| v | | |
| | | |
| ^ | | |
| | | | |
+---+---+---+---+ | |
| data | <-' |
+---+---+---+---+ |
| encoded bptr | <---'
'---+---+---+---'
This is especially useful for the non-terminating tail-recursive
lfsr_btree_commit_, which needs to pass this state through a function
call.
Unfortunately, to make this work we needed to implement more-or-less a
full arena allocator, complete with annoying alignment handling. alignof
isn't even available in C99, so we needed a few more intrinsics:
- LFS_ALIGNOF(t) - Alignment of type t
- LFS_ALIGNEDSIZEOF(t) - Necessary size to force alignment for t
- LFS_MIN(a, b) - Compile-time min
- LFS_MAX(a, b) - Compile-time max
Technically only LFS_ALIGNOF was required, but the others are nice to
have. LFS_MIN/LFS_MAX is also useful anywhere you need to calculate
complicated compile-time sizes.
At least in C11 we get alignof, so we won't need compiler extensions/
hacks for this in the future...
---
Unfortunately this ended up a net-negative. Pushing up the code/stack
cost to near pre-cat levels:
code stack
before cat: 33856 2824
before scratch: 33812 (-0.1%) 2800 (-0.8%)
after: 33844 (-0.0%) 2824 (+0.0%)
I think the two main culprits are 1. the extra logic needed to calculate
alignment, and 2. wasted stack due to aligning scratch space up to the
nearest lfsr_attr_t.
This commit is contained in:
+22
-8
@@ -142,16 +142,16 @@ extern "C"
|
||||
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||
// expensive basic C implementation for debugging purposes
|
||||
|
||||
// Min/max functions for unsigned 32-bit numbers
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
// Compile time min/max
|
||||
#define LFS_MIN(a, b) ((a < b) ? a : b)
|
||||
#define LFS_MAX(a, b) ((a > b) ? a : b)
|
||||
|
||||
// Min/max functions for unsigned 32-bit numbers
|
||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_max32(uint32_t a, uint32_t b) {
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ static inline uint32_t lfs_min32(uint32_t a, uint32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int32_t lfs_smax32(int32_t a, int32_t b) {
|
||||
static inline uint32_t lfs_max32(uint32_t a, uint32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
@@ -167,15 +167,19 @@ static inline int32_t lfs_smin32(int32_t a, int32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
// TODO other 16-bit ops?
|
||||
static inline uint16_t lfs_max16(uint16_t a, uint16_t b) {
|
||||
static inline int32_t lfs_smax32(int32_t a, int32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
// TODO other 16-bit ops?
|
||||
static inline uint16_t lfs_min16(uint16_t a, uint16_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint16_t lfs_max16(uint16_t a, uint16_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
// Clamp is useful as the logic for min/max when clamping can become confusing
|
||||
static inline uint32_t lfs_clamp32(uint32_t a, uint32_t min, uint32_t max) {
|
||||
return lfs_min32(lfs_max32(a, min), max);
|
||||
@@ -217,6 +221,16 @@ static inline void lfs_sswap32(int32_t *a, int32_t *b) {
|
||||
*b = t;
|
||||
}
|
||||
|
||||
// Find alignment of a type at compile time
|
||||
#if !defined(LFS_NO_INTRINSICS)
|
||||
#define LFS_ALIGNOF(t) __alignof__(t)
|
||||
#else
|
||||
#define LFS_ALIGNOF(t) ((size_t)&((struct {char a; t b;}*)0)->b)
|
||||
#endif
|
||||
|
||||
// Find size necessary to align type at compile time
|
||||
#define LFS_ALIGNEDSIZEOF(t) (sizeof(t) + LFS_ALIGNOF(t)-1)
|
||||
|
||||
// Align to nearest multiple of a size
|
||||
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
|
||||
return a - (a % alignment);
|
||||
|
||||
Reference in New Issue
Block a user