Optimize NvDevice Function Lookup

This essentially optimizes NvDevice in the same way services were, refer to the last commit for details
This commit is contained in:
PixelyIon 2021-03-20 14:49:14 +05:30 committed by ◱ Mark
parent 33f1a3e1b3
commit 6eea38cca9
3 changed files with 32 additions and 12 deletions

View File

@ -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

View File

@ -30,18 +30,18 @@ namespace skyline::service::nvdrv::device {
}
}()};
std::pair<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, 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);
}
}
}

View File

@ -6,13 +6,18 @@
#include <kernel/ipc.h>
#include <kernel/types/KEvent.h>
#define NVFUNC(id, Class, Function) std::pair<u32, std::pair<std::function<NvStatus(Class*, IoctlType, span<u8>, span<u8>)>, std::string_view>>{id, {&Class::Function, #Function}}
#define NV_STRINGIFY(string) #string
#define NVFUNC(id, Class, Function) std::pair<u32, std::pair<NvStatus(Class::*)(IoctlType, span<u8>, span<u8>), 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<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, std::string_view> GetIoctlFunction(u32 id) override { \
NvDeviceFunctionDescriptor 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); \
return NvDeviceFunctionDescriptor{ \
reinterpret_cast<DerivedDevice*>(this), \
reinterpret_cast<decltype(NvDeviceFunctionDescriptor::function)>(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<u8>, span<u8>); //!< 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<u8> buffer, span<u8> inlineBuffer) {
return (clazz->*function)(type, buffer, inlineBuffer);
}
};
public:
NvDevice(const DeviceState &state) : state(state) {}
virtual ~NvDevice() = default;
virtual std::pair<std::function<NvStatus(IoctlType, span<u8>, span<u8>)>, std::string_view> GetIoctlFunction(u32 id) = 0;
virtual NvDeviceFunctionDescriptor GetIoctlFunction(u32 id) = 0;
/**
* @return The name of the class