From 5cc9bd770284a74fd85cf45a2412b34cf137b212 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 3 Feb 2021 17:05:31 +0300 Subject: [PATCH] typeindices.hpp: upgrade with size and align info This allows contiguous allocation (as in an aggregate). --- rpcs3/util/typeindices.hpp | 168 +++++++++++++++++++++++++++++++++---- 1 file changed, 153 insertions(+), 15 deletions(-) diff --git a/rpcs3/util/typeindices.hpp b/rpcs3/util/typeindices.hpp index eb7210bb5..742310b88 100644 --- a/rpcs3/util/typeindices.hpp +++ b/rpcs3/util/typeindices.hpp @@ -1,5 +1,14 @@ #pragma once +#include "util/types.hpp" +#include "util/shared_ptr.hpp" + +#ifndef _MSC_VER +#define ATTR_PURE __attribute__((pure)) +#else +#define ATTR_PURE /* nothing available */ +#endif + namespace stx { template @@ -10,12 +19,19 @@ namespace stx class type_info final : public Info { // Current type id (starts from 0) - unsigned type = 0u - 1; + u32 type = UINT32_MAX; + + u32 size = 1; + u32 align = 1; + u32 begin = 0; // Next typeinfo in linked list type_info* next = nullptr; - type_info(Info info, decltype(sizeof(int))) noexcept; + // Auxiliary pointer to base type + const type_info* base = nullptr; + + type_info(Info info, u32 size, u32 align, const type_info* base = nullptr) noexcept; friend type_counter; @@ -25,10 +41,20 @@ namespace stx { } - unsigned index() const + ATTR_PURE u32 index() const { return type; } + + ATTR_PURE u32 pos() const + { + return begin; + } + + ATTR_PURE u32 end() const + { + return begin + size; + } }; // Class for automatic type registration for given Info type @@ -46,11 +72,37 @@ namespace stx public: constexpr type_counter() noexcept = default; - unsigned count() const + u32 count() const { return next->index() + 1; } + u32 align() const + { + return first.align; + } + + u32 size() const + { + // Get on first use + static const u32 sz = [&]() + { + u32 result = 0; + + for (auto* ptr = first.next; ptr; ptr = ptr->next) + { + result = ((result + ptr->align - 1) & (u32{0} - ptr->align)); + ptr->begin = result; + + result = result + ptr->size; + } + + return result; + }(); + + return sz; + } + class const_iterator { const type_info* ptr; @@ -107,7 +159,11 @@ namespace stx // Global type info instance template - static inline const type_info type{Info::template make_typeinfo(), sizeof(T)}; + static const type_info type; + + // Helper for dynamic types + template + static const type_info dyn_type; }; // Global typecounter instance @@ -118,28 +174,110 @@ namespace stx return typelist_v; } + // Helper for dynamic types template - type_info::type_info(Info info, decltype(sizeof(int))) noexcept - : Info(info) - , type(typelist().count()) + auto& dyn_typelist() + { + static type_counter typelist_v; + return typelist_v; + } + + template template + const type_info type_counter::type{Info::template make_typeinfo(), sizeof(T), alignof(T)}; + + template template + const type_info type_counter::dyn_type{Info::template make_typeinfo(), sizeof(As), alignof(As), &type_counter::template type}; + + template + type_info::type_info(Info info, u32 _size, u32 _align, const type_info* cbase) noexcept + : Info(info) { - // Update linked list auto& tl = typelist(); + + // Update type info + this->size = _size > this->size ? _size : this->size; + this->align = _align > this->align ? _align : this->align; + this->base = cbase; + + // Update global max alignment + tl.first.align = _align > tl.first.align ? _align : tl.first.align; + + auto& dl = dyn_typelist(); + + if (cbase) + { + dl.next->next = this; + dl.next = this; + + // Update base max size/align for dynamic types + for (auto ptr = tl.first.next; ptr; ptr = ptr->next) + { + if (cbase == ptr) + { + ptr->size = _size > ptr->size ? _size : ptr->size; + ptr->align = _align > ptr->align ? _align : ptr->align; + this->type = ptr->type; + } + } + + return; + } + + // Update type index + this->type = tl.next->type + 1; + + // Update base max size/align for dynamic types + for (auto ptr = dl.first.next; ptr; ptr = ptr->next) + { + if (ptr->base == this) + { + this->size = ptr->size > this->size ? ptr->size : this->size; + this->align = ptr->align > this->align ? ptr->align : this->align; + ptr->type = this->type; + } + } + + // Update linked list tl.next->next = this; tl.next = this; } // Type index accessor - template - inline unsigned typeindex() noexcept + template + ATTR_PURE inline u32 typeindex() noexcept { - return type_counter::template type.index(); + static_assert(sizeof(T) > 0); + + if constexpr (std::is_same_v) + { + return type_counter::template type.index(); + } + else + { + static_assert(sizeof(As) > 0); + static_assert(is_same_ptr()); + return type_counter::template dyn_type.index(); + } + } + + // Type global offset + template + ATTR_PURE inline u32 typeoffset() noexcept + { + static_assert(sizeof(T) > 0); + + return type_counter::template type.pos(); } // Type info accessor - template - inline const Info& typedata() noexcept + template + ATTR_PURE inline const Info& typedata() noexcept { - return type_counter::template type; + static_assert(sizeof(T) > 0 && sizeof(As) > 0); + static_assert(is_same_ptr()); + + return type_counter::template dyn_type; } } + +#undef ATTR_PURE