From 6eea38cca954924b66f54079c7f5b9b55d77977c Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Sat, 20 Mar 2021 14:49:14 +0530 Subject: [PATCH] Optimize NvDevice Function Lookup This essentially optimizes NvDevice in the same way services were, refer to the last commit for details --- .../main/cpp/skyline/services/base_service.h | 2 +- .../services/nvdrv/devices/nvdevice.cpp | 8 ++--- .../skyline/services/nvdrv/devices/nvdevice.h | 34 +++++++++++++++---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/app/src/main/cpp/skyline/services/base_service.h b/app/src/main/cpp/skyline/services/base_service.h index bb3c094a..d727933d 100644 --- a/app/src/main/cpp/skyline/services/base_service.h +++ b/app/src/main/cpp/skyline/services/base_service.h @@ -51,7 +51,7 @@ namespace skyline::service { class DerivedService; //!< A placeholder derived class which is used for class function semantics /** - * @brief A per-service-function descriptor with it's name and a function pointer to it + * @brief A per-function descriptor for HLE service functions */ struct ServiceFunctionDescriptor { DerivedService *clazz; //!< A pointer to the class that this was derived from, it's used as the 'this' pointer for the function diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp index f59225d6..ffce3e71 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp @@ -30,18 +30,18 @@ namespace skyline::service::nvdrv::device { } }()}; - std::pair, span)>, std::string_view> function; + NvDeviceFunctionDescriptor function; try { function = GetIoctlFunction(cmd); - state.logger->DebugNoPrefix("{}: {} @ {}", typeString, GetName(), function.second); + state.logger->DebugNoPrefix("{}: {}", typeString, function.name); } catch (std::out_of_range &) { state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd); return NvStatus::NotImplemented; } try { - return function.first(type, buffer, inlineBuffer); + return function(type, buffer, inlineBuffer); } catch (const std::exception &e) { - throw exception("{} ({} @ {}: {})", e.what(), typeString, GetName(), function.second); + throw exception("{} ({}: {})", e.what(), typeString, function.name); } } } diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h index 58d6e554..6ba45172 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.h @@ -6,13 +6,18 @@ #include #include -#define NVFUNC(id, Class, Function) std::pair, span)>, std::string_view>>{id, {&Class::Function, #Function}} +#define NV_STRINGIFY(string) #string +#define NVFUNC(id, Class, Function) std::pair, span), const char*>>{id, {&Class::Function, NV_STRINGIFY(Class::Function)}} #define NVDEVICE_DECL_AUTO(name, value) decltype(value) name = value -#define NVDEVICE_DECL(...) \ -NVDEVICE_DECL_AUTO(functions, frz::make_unordered_map({__VA_ARGS__})); \ -std::pair, span)>, std::string_view> GetIoctlFunction(u32 id) override { \ - auto& function{functions.at(id)}; \ - return std::make_pair(std::bind(function.first, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), function.second); \ +#define NVDEVICE_DECL(...) \ +NVDEVICE_DECL_AUTO(functions, frz::make_unordered_map({__VA_ARGS__})); \ +NvDeviceFunctionDescriptor GetIoctlFunction(u32 id) override { \ + auto& function{functions.at(id)}; \ + return NvDeviceFunctionDescriptor{ \ + reinterpret_cast(this), \ + reinterpret_cast(function.first), \ + function.second \ + }; \ } namespace skyline::service::nvdrv::device { @@ -67,12 +72,27 @@ namespace skyline::service::nvdrv::device { protected: const DeviceState &state; + class DerivedDevice; //!< A placeholder derived class which is used for class function semantics + + /** + * @brief A per-function descriptor for NvDevice functions + */ + struct NvDeviceFunctionDescriptor { + DerivedDevice *clazz; //!< A pointer to the class that this was derived from, it's used as the 'this' pointer for the function + NvStatus (DerivedDevice::*function)(IoctlType, span, span); //!< A function pointer to the implementation of the function + const char *name; //!< A pointer to a static string in the format "Class::Function" for the specific device class/function + + constexpr NvStatus operator()(IoctlType type, span buffer, span inlineBuffer) { + return (clazz->*function)(type, buffer, inlineBuffer); + } + }; + public: NvDevice(const DeviceState &state) : state(state) {} virtual ~NvDevice() = default; - virtual std::pair, span)>, std::string_view> GetIoctlFunction(u32 id) = 0; + virtual NvDeviceFunctionDescriptor GetIoctlFunction(u32 id) = 0; /** * @return The name of the class