fs: reduce path size 0x28 -> 0x18

This implements two optimizations on fs::Path, which N added in 12.0.0.

The current structure looks like: 

```cpp
struct Path {
    const char *m_str; // Points to the read-only path string
    char *m_write_buffer_buffer; // Part of std::unique_ptr<char[], ams::fs::impl::Deleter>
    ams::fs::impl::Deleter m_write_buffer_deleter; // Parse of std::unique_ptr<char[], ams::fs::impl::Deleter>, stores the size of the buffer.
    size_t m_write_buffer_length; // Copy of the write buffer's size accessible to the Path() structure.
    bool m_is_normalized; // Whether the path buffer is normalized
};
```

This is pretty wasteful. The write buffer size is stored twice, wasting 8 bytes, because one copy of the size isn't accessible to the path.

In addition, due to alignment, the bool wastes 7 padding bytes.

This commit:

* Encodes normalized in the low bit of the write buffer length, saving 8 bytes.
* Use a custom WriteBuffer class rather than generic unique_ptr, to avoid needing to store the WriteBuffer twice.


These each save 8 bytes, for a final size of 0x18 rather than 0x28.
This commit is contained in:
SciresM
2022-03-24 20:22:47 -07:00
committed by GitHub
parent 817ad8f98d
commit 64c6ef2de7
2 changed files with 172 additions and 84 deletions

View File

@@ -26,6 +26,8 @@ namespace ams::fs {
namespace impl {
class Newable;
void *Allocate(size_t size);
void Deallocate(void *ptr, size_t size);
@@ -130,20 +132,27 @@ namespace ams::fs {
};
template<typename T>
std::unique_ptr<T, Deleter> MakeUnique() {
static_assert(util::is_pod<T>::value);
auto MakeUnique() {
/* Check that we're not using MakeUnique unnecessarily. */
static_assert(!std::derived_from<T, ::ams::fs::impl::Newable>);
return std::unique_ptr<T, Deleter>(static_cast<T *>(::ams::fs::impl::Allocate(sizeof(T))), Deleter(sizeof(T)));
}
template<typename ArrayT>
std::unique_ptr<ArrayT, Deleter> MakeUnique(size_t size) {
auto MakeUnique(size_t size) {
using T = typename std::remove_extent<ArrayT>::type;
static_assert(util::is_pod<ArrayT>::value);
static_assert(std::is_array<ArrayT>::value);
/* Check that we're not using MakeUnique unnecessarily. */
static_assert(!std::derived_from<T, ::ams::fs::impl::Newable>);
using ReturnType = std::unique_ptr<ArrayT, Deleter>;
const size_t alloc_size = sizeof(T) * size;
return std::unique_ptr<ArrayT, Deleter>(static_cast<T *>(::ams::fs::impl::Allocate(alloc_size)), Deleter(alloc_size));
return ReturnType(static_cast<T *>(::ams::fs::impl::Allocate(alloc_size)), Deleter(alloc_size));
}
}