mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
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.
This commit is contained in:
parent
26c02e2019
commit
bfffe6b119
3 changed files with 40 additions and 4 deletions
|
@ -32,3 +32,10 @@
|
||||||
//#define MESOSPHERE_BUILD_FOR_TRACING
|
//#define MESOSPHERE_BUILD_FOR_TRACING
|
||||||
#define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP
|
#define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP
|
||||||
#define MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP
|
#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
|
|
@ -63,7 +63,11 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) {
|
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:
|
private:
|
||||||
|
@ -71,11 +75,23 @@ namespace ams::kern {
|
||||||
private:
|
private:
|
||||||
KAutoObject *m_next_closed_object;
|
KAutoObject *m_next_closed_object;
|
||||||
std::atomic<u32> m_ref_count;
|
std::atomic<u32> m_ref_count;
|
||||||
|
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||||
|
ClassTokenType m_class_token;
|
||||||
|
#else
|
||||||
u32 m_reserved;
|
u32 m_reserved;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
static KAutoObject *Create(KAutoObject *ptr);
|
static KAutoObject *Create(KAutoObject *ptr);
|
||||||
public:
|
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. */
|
/* Destroy is responsible for destroying the auto object's resources when ref_count hits zero. */
|
||||||
virtual void Destroy() { MESOSPHERE_ASSERT_THIS(); }
|
virtual void Destroy() { MESOSPHERE_ASSERT_THIS(); }
|
||||||
|
@ -90,11 +106,19 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE bool IsDerivedFrom(const TypeObj &rhs) const {
|
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 {
|
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<typename Derived>
|
template<typename Derived>
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace ams::kern {
|
||||||
|
|
||||||
KAutoObject *KAutoObject::Create(KAutoObject *obj) {
|
KAutoObject *KAutoObject::Create(KAutoObject *obj) {
|
||||||
obj->m_ref_count = 1;
|
obj->m_ref_count = 1;
|
||||||
|
|
||||||
|
#if defined(MESOSPHERE_ENABLE_DEVIRTUALIZED_DYNAMIC_CAST)
|
||||||
|
obj->m_class_token = obj->GetTypeObj().GetClassToken();
|
||||||
|
#endif
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue