From e99a14862841841d74be8d0ea9426c2d23546b5e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 7 Mar 2019 16:32:10 -0500 Subject: [PATCH 1/3] common/bit_field: Make BitField trivially copyable This makes the class much more flexible and doesn't make performing copies with classes that contain a bitfield member a pain. Given BitField instances are only intended to be used within unions, the fact the full storage value would be copied isn't a big concern (only sizeof(union_type) would be copied anyways). While we're at it, provide defaulted move constructors for consistency. --- src/common/bit_field.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 21e07925d..7433c39ba 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -111,12 +111,6 @@ template struct BitField { private: - // We hide the copy assigment operator here, because the default copy - // assignment would copy the full storage value, rather than just the bits - // relevant to this particular bit field. - // We don't delete it because we want BitField to be trivially copyable. - constexpr BitField& operator=(const BitField&) = default; - // UnderlyingType is T for non-enum types and the underlying type of T if // T is an enumeration. Note that T is wrapped within an enable_if in the // former case to workaround compile errors which arise when using @@ -163,9 +157,13 @@ public: BitField(T val) = delete; BitField& operator=(T val) = delete; - // Force default constructor to be created - // so that we can use this within unions - constexpr BitField() = default; + constexpr BitField() noexcept = default; + + constexpr BitField(const BitField&) noexcept = default; + constexpr BitField& operator=(const BitField&) noexcept = default; + + constexpr BitField(BitField&&) noexcept = default; + constexpr BitField& operator=(BitField&&) noexcept = default; constexpr FORCE_INLINE operator T() const { return Value(); From 69749a88cd9c22c28f4f6053647e9eeb8b997927 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 7 Mar 2019 23:32:23 -0500 Subject: [PATCH 2/3] travis: Bump macOS version to 10.14 For whatever bizarre reason, Apple only made a few of std::optional's member functions available on newer SDK versions. Given we can't even run yuzu on macOS, and we keep the builder around to ensure that it always at least compiles on macOS, we can bump this up a version. --- .travis.yml | 2 +- .travis/macos/build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0fbe3c5f..9512f7843 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ matrix: - os: osx env: NAME="macos build" sudo: false - osx_image: xcode10 + osx_image: xcode10.1 install: "./.travis/macos/deps.sh" script: "./.travis/macos/build.sh" after_success: "./.travis/macos/upload.sh" diff --git a/.travis/macos/build.sh b/.travis/macos/build.sh index 4a14837fc..b7b4c6f8c 100755 --- a/.travis/macos/build.sh +++ b/.travis/macos/build.sh @@ -2,7 +2,7 @@ set -o pipefail -export MACOSX_DEPLOYMENT_TARGET=10.13 +export MACOSX_DEPLOYMENT_TARGET=10.14 export Qt5_DIR=$(brew --prefix)/opt/qt5 export UNICORNDIR=$(pwd)/externals/unicorn export PATH="/usr/local/opt/ccache/libexec:$PATH" From fbb82e61e35a4e40154ad9a9fcb1ecc46f6622b8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 7 Mar 2019 16:44:28 -0500 Subject: [PATCH 3/3] kernel/hle_ipc: Convert std::shared_ptr IPC header instances to std::optional There's no real need to use a shared lifetime here, since we don't actually expose them to anything else. This is also kind of an unnecessary use of the heap given the objects themselves are so small; small enough, in fact that changing over to optionals actually reduces the overall size of the HLERequestContext struct (818 bytes to 808 bytes). --- src/core/hle/ipc_helpers.h | 2 +- src/core/hle/kernel/hle_ipc.cpp | 14 +++--- src/core/hle/kernel/hle_ipc.h | 15 +++--- src/core/hle/kernel/server_session.cpp | 67 +++++++++++++------------- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 90f276ee8..079283830 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -350,7 +350,7 @@ public: template std::shared_ptr PopIpcInterface() { ASSERT(context->Session()->IsDomain()); - ASSERT(context->GetDomainMessageHeader()->input_object_count > 0); + ASSERT(context->GetDomainMessageHeader().input_object_count > 0); return context->GetDomainRequestHandler(Pop() - 1); } }; diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index cbffff017..fe710eb6e 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -86,7 +86,7 @@ HLERequestContext::~HLERequestContext() = default; void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming) { IPC::RequestParser rp(src_cmdbuf); - command_header = std::make_shared(rp.PopRaw()); + command_header = rp.PopRaw(); if (command_header->type == IPC::CommandType::Close) { // Close does not populate the rest of the IPC header @@ -95,8 +95,7 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ // If handle descriptor is present, add size of it if (command_header->enable_handle_descriptor) { - handle_descriptor_header = - std::make_shared(rp.PopRaw()); + handle_descriptor_header = rp.PopRaw(); if (handle_descriptor_header->send_current_pid) { rp.Skip(2, false); } @@ -140,16 +139,15 @@ void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_ // If this is an incoming message, only CommandType "Request" has a domain header // All outgoing domain messages have the domain header, if only incoming has it if (incoming || domain_message_header) { - domain_message_header = - std::make_shared(rp.PopRaw()); + domain_message_header = rp.PopRaw(); } else { - if (Session()->IsDomain()) + if (Session()->IsDomain()) { LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); + } } } - data_payload_header = - std::make_shared(rp.PopRaw()); + data_payload_header = rp.PopRaw(); data_payload_offset = rp.GetCurrentOffset(); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 0107acea4..2bdd9f02c 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -168,12 +169,12 @@ public: return buffer_c_desciptors; } - const IPC::DomainMessageHeader* GetDomainMessageHeader() const { - return domain_message_header.get(); + const IPC::DomainMessageHeader& GetDomainMessageHeader() const { + return domain_message_header.value(); } bool HasDomainMessageHeader() const { - return domain_message_header != nullptr; + return domain_message_header.has_value(); } /// Helper function to read a buffer using the appropriate buffer descriptor @@ -272,10 +273,10 @@ private: boost::container::small_vector, 8> copy_objects; boost::container::small_vector, 8> domain_objects; - std::shared_ptr command_header; - std::shared_ptr handle_descriptor_header; - std::shared_ptr data_payload_header; - std::shared_ptr domain_message_header; + std::optional command_header; + std::optional handle_descriptor_header; + std::optional data_payload_header; + std::optional domain_message_header; std::vector buffer_x_desciptors; std::vector buffer_a_desciptors; std::vector buffer_b_desciptors; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 3452a9c0c..4d8a337a7 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -92,41 +92,42 @@ std::size_t ServerSession::NumDomainRequestHandlers() const { } ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { - auto* const domain_message_header = context.GetDomainMessageHeader(); - if (domain_message_header) { - // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs - context.SetDomainRequestHandlers(domain_request_handlers); - - // If there is a DomainMessageHeader, then this is CommandType "Request" - const u32 object_id{context.GetDomainMessageHeader()->object_id}; - switch (domain_message_header->command) { - case IPC::DomainMessageHeader::CommandType::SendMessage: - if (object_id > domain_request_handlers.size()) { - LOG_CRITICAL(IPC, - "object_id {} is too big! This probably means a recent service call " - "to {} needed to return a new interface!", - object_id, name); - UNREACHABLE(); - return RESULT_SUCCESS; // Ignore error if asserts are off - } - return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); - - case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { - LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); - - domain_request_handlers[object_id - 1] = nullptr; - - IPC::ResponseBuilder rb{context, 2}; - rb.Push(RESULT_SUCCESS); - return RESULT_SUCCESS; - } - } - - LOG_CRITICAL(IPC, "Unknown domain command={}", - static_cast(domain_message_header->command.Value())); - ASSERT(false); + if (!context.HasDomainMessageHeader()) { + return RESULT_SUCCESS; } + // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs + context.SetDomainRequestHandlers(domain_request_handlers); + + // If there is a DomainMessageHeader, then this is CommandType "Request" + const auto& domain_message_header = context.GetDomainMessageHeader(); + const u32 object_id{domain_message_header.object_id}; + switch (domain_message_header.command) { + case IPC::DomainMessageHeader::CommandType::SendMessage: + if (object_id > domain_request_handlers.size()) { + LOG_CRITICAL(IPC, + "object_id {} is too big! This probably means a recent service call " + "to {} needed to return a new interface!", + object_id, name); + UNREACHABLE(); + return RESULT_SUCCESS; // Ignore error if asserts are off + } + return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); + + case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { + LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); + + domain_request_handlers[object_id - 1] = nullptr; + + IPC::ResponseBuilder rb{context, 2}; + rb.Push(RESULT_SUCCESS); + return RESULT_SUCCESS; + } + } + + LOG_CRITICAL(IPC, "Unknown domain command={}", + static_cast(domain_message_header.command.Value())); + ASSERT(false); return RESULT_SUCCESS; }