From 99b372a6c5c6d42e1c2e36e710e191901973f449 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 15 Sep 2020 09:06:43 -0400 Subject: [PATCH 1/2] nca_patch: Make SearchBucketEntry() internally linked This is only used internally and doesn't depend on any class state, so we can make it fully internal. --- src/core/file_sys/nca_patch.cpp | 83 +++++++++++++++++---------------- src/core/file_sys/nca_patch.h | 4 -- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index fe7375e84..fd7b69e11 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp @@ -12,6 +12,49 @@ #include "core/file_sys/nca_patch.h" namespace FileSys { +namespace { +template +std::pair SearchBucketEntry(u64 offset, BlockType block, + BucketType buckets) { + if constexpr (Subsection) { + const auto last_bucket = buckets[block.number_buckets - 1]; + if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) { + return {block.number_buckets - 1, last_bucket.number_entries}; + } + } else { + ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); + } + + std::size_t bucket_id = std::count_if( + block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, + [&offset](u64 base_offset) { return base_offset <= offset; }); + + const auto bucket = buckets[bucket_id]; + + if (bucket.number_entries == 1) { + return {bucket_id, 0}; + } + + std::size_t low = 0; + std::size_t mid = 0; + std::size_t high = bucket.number_entries - 1; + while (low <= high) { + mid = (low + high) / 2; + if (bucket.entries[mid].address_patch > offset) { + high = mid - 1; + } else { + if (mid == bucket.number_entries - 1 || + bucket.entries[mid + 1].address_patch > offset) { + return {bucket_id, mid}; + } + + low = mid + 1; + } + } + + UNREACHABLE_MSG("Offset could not be found in BKTR block."); +} +} // Anonymous namespace BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_, std::vector relocation_buckets_, SubsectionBlock subsection_, @@ -110,46 +153,6 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const { return raw_read; } -template -std::pair BKTR::SearchBucketEntry(u64 offset, BlockType block, - BucketType buckets) const { - if constexpr (Subsection) { - const auto last_bucket = buckets[block.number_buckets - 1]; - if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) - return {block.number_buckets - 1, last_bucket.number_entries}; - } else { - ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block."); - } - - std::size_t bucket_id = std::count_if( - block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, - [&offset](u64 base_offset) { return base_offset <= offset; }); - - const auto bucket = buckets[bucket_id]; - - if (bucket.number_entries == 1) - return {bucket_id, 0}; - - std::size_t low = 0; - std::size_t mid = 0; - std::size_t high = bucket.number_entries - 1; - while (low <= high) { - mid = (low + high) / 2; - if (bucket.entries[mid].address_patch > offset) { - high = mid - 1; - } else { - if (mid == bucket.number_entries - 1 || - bucket.entries[mid + 1].address_patch > offset) { - return {bucket_id, mid}; - } - - low = mid + 1; - } - } - - UNREACHABLE_MSG("Offset could not be found in BKTR block."); -} - RelocationEntry BKTR::GetRelocationEntry(u64 offset) const { const auto res = SearchBucketEntry(offset, relocation, relocation_buckets); return relocation_buckets[res.first].entries[res.second]; diff --git a/src/core/file_sys/nca_patch.h b/src/core/file_sys/nca_patch.h index 8e64e8378..60c544f8e 100644 --- a/src/core/file_sys/nca_patch.h +++ b/src/core/file_sys/nca_patch.h @@ -117,10 +117,6 @@ public: bool Rename(std::string_view name) override; private: - template - std::pair SearchBucketEntry(u64 offset, BlockType block, - BucketType buckets) const; - RelocationEntry GetRelocationEntry(u64 offset) const; RelocationEntry GetNextRelocationEntry(u64 offset) const; From 66fc037ef2181cdddc1588032be18cb368fb3e97 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 15 Sep 2020 09:10:55 -0400 Subject: [PATCH 2/2] nca_patch: Significantly reduce the stack usage size within SearchBucketEntry() Previously this function was using ~16KB of stack (16528 bytes), which was caused by the function arguments being taken by value rather than by reference. We can make this significantly lighter on the stack by taking them by reference. --- src/core/file_sys/nca_patch.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp index fd7b69e11..5990a2fd5 100644 --- a/src/core/file_sys/nca_patch.cpp +++ b/src/core/file_sys/nca_patch.cpp @@ -14,10 +14,10 @@ namespace FileSys { namespace { template -std::pair SearchBucketEntry(u64 offset, BlockType block, - BucketType buckets) { +std::pair SearchBucketEntry(u64 offset, const BlockType& block, + const BucketType& buckets) { if constexpr (Subsection) { - const auto last_bucket = buckets[block.number_buckets - 1]; + const auto& last_bucket = buckets[block.number_buckets - 1]; if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) { return {block.number_buckets - 1, last_bucket.number_entries}; } @@ -29,7 +29,7 @@ std::pair SearchBucketEntry(u64 offset, BlockType bloc block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets, [&offset](u64 base_offset) { return base_offset <= offset; }); - const auto bucket = buckets[bucket_id]; + const auto& bucket = buckets[bucket_id]; if (bucket.number_entries == 1) { return {bucket_id, 0};