aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2026-05-15 22:07:03 +0200
committercrueter <crueter@eden-emu.dev>2026-05-15 22:07:03 +0200
commit413c7543ba25407f79226ba5e3f2f88d0ae63501 (patch)
tree162be7e59c94ebfef73494bc848e4a3ec8819d43 /src
parent975aa4e2f2128b865ec5738c2704c8d37af6a7b9 (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.h13
-rw-r--r--src/core/hle/service/hle_ipc.cpp18
-rw-r--r--src/core/hle/service/hle_ipc.h52
-rw-r--r--src/core/reporter.cpp6
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{