From bfffe6b119dbc3300b7fb3f0bd1e310e72856f13 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 16 Oct 2021 16:24:06 -0700 Subject: [PATCH] kern: devirtualize KAutoObject::DynamicCast<>() This is an optimization that saves the most common type of virtual call in the kernel (DynamicCast) by storing class token as a member, rather than getting it via virtual call every time. This does not currently cost any memory space on 64-bit targets, due to pre-existing padding space. This optimization can be turned off via a compile-time flag for accuracy. --- .../include/mesosphere/kern_build_config.hpp | 7 ++++ .../include/mesosphere/kern_k_auto_object.hpp | 32 ++++++++++++++++--- .../source/kern_k_auto_object.cpp | 5 +++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_build_config.hpp b/libraries/libmesosphere/include/mesosphere/kern_build_config.hpp index ade122a96..8216bab0c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_build_config.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_build_config.hpp @@ -32,3 +32,10 @@ //#define MESOSPHERE_BUILD_FOR_TRACING #define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP #define MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP + +/* NOTE: This enables fast class token storage using a class member. */ +/* This saves a virtual call when doing KAutoObject->DynCast<>(), */ +/* at the cost of storing class tokens inside the class object. */ +/* However, as of (10/16/2021) KAutoObject has an unused class member */ +/* of the right side, and so this does not actually cost any space. */ +#define MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST \ No newline at end of file diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp index 07075ecc4..d4c0ca600 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp @@ -63,7 +63,11 @@ namespace ams::kern { } constexpr ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) { - return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken(); + return IsClassTokenDerivedFrom(this->GetClassToken(), rhs.GetClassToken()); + } + + static constexpr ALWAYS_INLINE bool IsClassTokenDerivedFrom(ClassTokenType derived, ClassTokenType base) { + return (derived | base) == derived; } }; private: @@ -71,11 +75,23 @@ namespace ams::kern { private: KAutoObject *m_next_closed_object; std::atomic m_ref_count; + #if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST) + ClassTokenType m_class_token; + #else u32 m_reserved; + #endif public: static KAutoObject *Create(KAutoObject *ptr); public: - constexpr ALWAYS_INLINE explicit KAutoObject() : m_next_closed_object(nullptr), m_ref_count(0), m_reserved(0) { MESOSPHERE_ASSERT_THIS(); } + constexpr ALWAYS_INLINE explicit KAutoObject() : m_next_closed_object(nullptr), m_ref_count(0), + #if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST) + m_class_token(0) + #else + m_reserved(0) + #endif + { + MESOSPHERE_ASSERT_THIS(); + } /* Destroy is responsible for destroying the auto object's resources when ref_count hits zero. */ virtual void Destroy() { MESOSPHERE_ASSERT_THIS(); } @@ -90,11 +106,19 @@ namespace ams::kern { } ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) const { - return this->GetTypeObj().IsDerivedFrom(rhs); + #if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST) + return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken()); + #else + return this->GetTypeObj().IsDerivedFrom(rhs); + #endif } ALWAYS_INLINE bool IsDerivedFrom(const KAutoObject &rhs) const { - return this->IsDerivedFrom(rhs.GetTypeObj()); + #if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST) + return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token); + #else + return this->IsDerivedFrom(rhs.GetTypeObj()); + #endif } template diff --git a/libraries/libmesosphere/source/kern_k_auto_object.cpp b/libraries/libmesosphere/source/kern_k_auto_object.cpp index f8126a95c..e50616a04 100644 --- a/libraries/libmesosphere/source/kern_k_auto_object.cpp +++ b/libraries/libmesosphere/source/kern_k_auto_object.cpp @@ -19,6 +19,11 @@ namespace ams::kern { KAutoObject *KAutoObject::Create(KAutoObject *obj) { obj->m_ref_count = 1; + + #if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST) + obj->m_class_token = obj->GetTypeObj().GetClassToken(); + #endif + return obj; }