diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-05-15 22:07:03 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-05-15 22:07:03 +0200 |
| commit | 413c7543ba25407f79226ba5e3f2f88d0ae63501 (patch) | |
| tree | 162be7e59c94ebfef73494bc848e4a3ec8819d43 /src | |
| parent | 975aa4e2f2128b865ec5738c2704c8d37af6a7b9 (diff) | |
[hle] inline HLE cmif request to not allocate on heap stuff (#3605)
so basically each construction of HLEContext and whatever would result in a heap allocation (atleast 1)
so what if instead of that we did a memset() at ctor time and we avoided heap allocations altogether?
reminder that std::vector<> CAN do small object optimisation but it's not guaranteed
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3605
Reviewed-by: crueter <crueter@eden-emu.dev>
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/ipc.h | 13 | ||||
| -rw-r--r-- | src/core/hle/service/hle_ipc.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/service/hle_ipc.h | 52 | ||||
| -rw-r--r-- | src/core/reporter.cpp | 6 |
4 files changed, 48 insertions, 41 deletions
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 416da15ecb..9cd2908823 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,6 +16,16 @@ namespace IPC { /// Size of the command buffer area, in 32-bit words. constexpr std::size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); +/// Must match bitfields +constexpr std::size_t MAX_BUFFER_DESCRIPTORS = 16; +constexpr std::size_t MAX_INCOMING_MOVE_HANDLERS = 16; +constexpr std::size_t MAX_INCOMING_COPY_HANDLERS = 16; + +/// Doesn't need to match bitfields but usually not big enough +constexpr std::size_t MAX_OUTGOING_COPY_OBJECTS = 16; +constexpr std::size_t MAX_OUTGOING_MOVE_OBJECTS = 16; +constexpr std::size_t MAX_OUTGOING_DOMAIN_OBJECTS = 16; + enum class ControlCommand : u32 { ConvertSessionToDomain = 0, ConvertDomainToSession = 1, diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 8569d2bad8..8db8f8538c 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp @@ -128,10 +128,12 @@ Result SessionRequestManager::HandleDomainSyncRequest(Kernel::KServerSession* se return ResultSuccess; } -HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory::Memory& memory_, - Kernel::KServerSession* server_session_, - Kernel::KThread* thread_) - : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { +HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory::Memory& memory_, Kernel::KServerSession* server_session_, Kernel::KThread* thread_) + : server_session(server_session_) + , thread(thread_) + , kernel{kernel_} + , memory{memory_} +{ cmd_buf[0] = 0; } @@ -155,9 +157,6 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { } if (incoming) { // Populate the object lists with the data in the IPC request. - incoming_copy_handles.reserve(handle_descriptor_header->num_handles_to_copy); - incoming_move_handles.reserve(handle_descriptor_header->num_handles_to_move); - for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { incoming_copy_handles.push_back(rp.Pop<Handle>()); } @@ -172,11 +171,6 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { } } - buffer_x_descriptors.reserve(command_header->num_buf_x_descriptors); - buffer_a_descriptors.reserve(command_header->num_buf_a_descriptors); - buffer_b_descriptors.reserve(command_header->num_buf_b_descriptors); - buffer_w_descriptors.reserve(command_header->num_buf_w_descriptors); - for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { buffer_x_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); } diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index c2e0e5e8c4..ec8185a09e 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,6 +14,7 @@ #include <string> #include <type_traits> #include <vector> +#include <boost/container/static_vector.hpp> #include "common/assert.h" #include "common/common_types.h" @@ -181,8 +185,7 @@ private: */ class HLERequestContext { public: - explicit HLERequestContext(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, - Kernel::KServerSession* session, Kernel::KThread* thread); + explicit HLERequestContext(Kernel::KernelCore& kernel, Core::Memory::Memory& memory, Kernel::KServerSession* session, Kernel::KThread* thread); ~HLERequestContext(); /// Returns a pointer to the IPC command buffer for this request. @@ -233,19 +236,19 @@ public: return data_payload_offset; } - [[nodiscard]] const std::vector<IPC::BufferDescriptorX>& BufferDescriptorX() const { + [[nodiscard]] const boost::container::static_vector<IPC::BufferDescriptorX, 16>& BufferDescriptorX() const { return buffer_x_descriptors; } - [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorA() const { + [[nodiscard]] const boost::container::static_vector<IPC::BufferDescriptorABW, 16>& BufferDescriptorA() const { return buffer_a_descriptors; } - [[nodiscard]] const std::vector<IPC::BufferDescriptorABW>& BufferDescriptorB() const { + [[nodiscard]] const boost::container::static_vector<IPC::BufferDescriptorABW, 16>& BufferDescriptorB() const { return buffer_b_descriptors; } - [[nodiscard]] const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { + [[nodiscard]] const boost::container::static_vector<IPC::BufferDescriptorC, 16>& BufferDescriptorC() const { return buffer_c_descriptors; } @@ -399,38 +402,35 @@ private: Kernel::KHandleTable* client_handle_table{}; Kernel::KThread* thread{}; - std::vector<Handle> incoming_move_handles; - std::vector<Handle> incoming_copy_handles; + boost::container::static_vector<IPC::BufferDescriptorX, IPC::MAX_BUFFER_DESCRIPTORS> buffer_x_descriptors; + boost::container::static_vector<IPC::BufferDescriptorABW, IPC::MAX_BUFFER_DESCRIPTORS> buffer_a_descriptors; + boost::container::static_vector<IPC::BufferDescriptorABW, IPC::MAX_BUFFER_DESCRIPTORS> buffer_b_descriptors; + boost::container::static_vector<IPC::BufferDescriptorABW, IPC::MAX_BUFFER_DESCRIPTORS> buffer_w_descriptors; + boost::container::static_vector<IPC::BufferDescriptorC, IPC::MAX_BUFFER_DESCRIPTORS> buffer_c_descriptors; + boost::container::static_vector<Handle, IPC::MAX_INCOMING_MOVE_HANDLERS> incoming_move_handles; + boost::container::static_vector<Handle, IPC::MAX_INCOMING_COPY_HANDLERS> incoming_copy_handles; + boost::container::static_vector<Kernel::KAutoObject*, IPC::MAX_OUTGOING_MOVE_OBJECTS> outgoing_move_objects; + boost::container::static_vector<Kernel::KAutoObject*, IPC::MAX_OUTGOING_COPY_OBJECTS> outgoing_copy_objects; + boost::container::static_vector<SessionRequestHandlerPtr, IPC::MAX_OUTGOING_DOMAIN_OBJECTS> outgoing_domain_objects; - std::vector<Kernel::KAutoObject*> outgoing_move_objects; - std::vector<Kernel::KAutoObject*> outgoing_copy_objects; - std::vector<SessionRequestHandlerPtr> outgoing_domain_objects; + mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_a{}; + mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_x{}; std::optional<IPC::CommandHeader> command_header; std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; std::optional<IPC::DataPayloadHeader> data_payload_header; std::optional<IPC::DomainMessageHeader> domain_message_header; - std::vector<IPC::BufferDescriptorX> buffer_x_descriptors; - std::vector<IPC::BufferDescriptorABW> buffer_a_descriptors; - std::vector<IPC::BufferDescriptorABW> buffer_b_descriptors; - std::vector<IPC::BufferDescriptorABW> buffer_w_descriptors; - std::vector<IPC::BufferDescriptorC> buffer_c_descriptors; + std::weak_ptr<SessionRequestManager> manager{}; + Kernel::KernelCore& kernel; + Core::Memory::Memory& memory; - u32_le command{}; u64 pid{}; + u32_le command{}; u32 write_size{}; u32 data_payload_offset{}; u32 handles_offset{}; u32 domain_offset{}; - - std::weak_ptr<SessionRequestManager> manager{}; - bool is_deferred{false}; - - Kernel::KernelCore& kernel; - Core::Memory::Memory& memory; - - mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_a{}; - mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_x{}; + bool is_deferred = false; }; } // namespace Service diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 1723636811..2a5212fed8 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -20,6 +20,7 @@ #include "common/settings.h" #include "core/arm/arm_interface.h" #include "core/core.h" +#include "core/hle/ipc.h" #include "core/hle/kernel/k_page_table.h" #include "core/hle/kernel/k_process.h" #include "core/hle/result.h" @@ -124,8 +125,7 @@ json GetFullDataAuto(const std::string& timestamp, u64 title_id, Core::System& s } template <bool read_value, typename DescriptorType> -json GetHLEBufferDescriptorData(const std::vector<DescriptorType>& buffer, - Core::Memory::Memory& memory) { +json GetHLEBufferDescriptorData(const boost::container::static_vector<DescriptorType, IPC::MAX_BUFFER_DESCRIPTORS>& buffer, Core::Memory::Memory& memory) { auto buffer_out = json::array(); for (const auto& desc : buffer) { auto entry = json{ |
