kern: devirtualize several KAutoObject functions

This commit is contained in:
Michael Scire 2021-10-23 21:13:26 -07:00
parent 2490bbf4f9
commit 436613401a
30 changed files with 84 additions and 81 deletions

View file

@ -64,9 +64,8 @@ namespace ams::kern {
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
};
template<typename Derived, typename Base, bool SupportDynamicExpansion = false>
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList>
class KAutoObjectWithSlabHeapAndContainer : public Base {
static_assert(std::is_base_of<KAutoObjectWithList, Base>::value);
private:
static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap;
static constinit inline KAutoObjectWithListContainer s_container;
@ -84,28 +83,44 @@ namespace ams::kern {
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer::ListAccessor(s_container) { /* ... */ }
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
private:
static ALWAYS_INLINE bool IsInitialized(const Derived *obj) {
if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) {
return obj->IsInitialized();
} else {
return true;
}
}
static ALWAYS_INLINE uintptr_t GetPostDestroyArgument(const Derived *obj) {
if constexpr (requires { { obj->GetPostDestroyArgument() } -> std::same_as<uintptr_t>; }) {
return obj->GetPostDestroyArgument();
} else {
return 0;
}
}
public:
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
virtual void Destroy() override {
const bool is_initialized = this->IsInitialized();
uintptr_t arg = 0;
if (is_initialized) {
/* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */
/* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */
/* We also devirtualize KAutoObject::Finalize(), which is only used by this function in Nintendo's kernel. */
virtual void Destroy() override final {
Derived * const derived = static_cast<Derived *>(this);
if (IsInitialized(derived)) {
s_container.Unregister(this);
arg = this->GetPostDestroyArgument();
this->Finalize();
}
Free(static_cast<Derived *>(this));
if (is_initialized) {
const uintptr_t arg = GetPostDestroyArgument(derived);
derived->Finalize();
Free(derived);
Derived::PostDestroy(arg);
} else {
Free(derived);
}
}
virtual bool IsInitialized() const { return true; }
virtual uintptr_t GetPostDestroyArgument() const { return 0; }
size_t GetSlabIndex() const {
return s_slab_heap.GetObjectIndex(static_cast<const Derived *>(this));
}