mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Use outline Function storage if alignment requirements are not met
Instead of ballooning the size of the Function object, simply place the callable on the heap with a properly aligned address. This brings the alignment of Function down from ridiculous sizes like 64 bytes down to a manageable 8 bytes.
This commit is contained in:
parent
5e0a28c947
commit
1b2007cc7f
Notes:
sideshowbarker
2024-07-17 09:56:35 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/1b2007cc7f Pull-request: https://github.com/SerenityOS/serenity/pull/21071 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/BertalanD Reviewed-by: https://github.com/bugaevc Reviewed-by: https://github.com/kleinesfilmroellchen ✅
1 changed files with 19 additions and 2 deletions
|
@ -56,6 +56,14 @@ public:
|
|||
using FunctionType = Out(In...);
|
||||
using ReturnType = Out;
|
||||
|
||||
#ifdef KERNEL
|
||||
constexpr static auto AccommodateExcessiveAlignmentRequirements = false;
|
||||
constexpr static size_t ExcessiveAlignmentThreshold = alignof(void*);
|
||||
#else
|
||||
constexpr static auto AccommodateExcessiveAlignmentRequirements = true;
|
||||
constexpr static size_t ExcessiveAlignmentThreshold = 16;
|
||||
#endif
|
||||
|
||||
Function() = default;
|
||||
Function(nullptr_t)
|
||||
{
|
||||
|
@ -234,10 +242,17 @@ private:
|
|||
template<typename Callable>
|
||||
void init_with_callable(Callable&& callable, CallableKind callable_kind)
|
||||
{
|
||||
if constexpr (alignof(Callable) > ExcessiveAlignmentThreshold && !AccommodateExcessiveAlignmentRequirements) {
|
||||
static_assert(
|
||||
alignof(Callable) <= ExcessiveAlignmentThreshold,
|
||||
"This callable object has a very large alignment requirement, "
|
||||
"check your capture list if it is a lambda expression, "
|
||||
"and make sure your callable object is not excessively aligned.");
|
||||
}
|
||||
VERIFY(m_call_nesting_level == 0);
|
||||
using WrapperType = CallableWrapper<Callable>;
|
||||
#ifndef KERNEL
|
||||
if constexpr (sizeof(WrapperType) > inline_capacity) {
|
||||
if constexpr (alignof(Callable) > inline_alignment || sizeof(WrapperType) > inline_capacity) {
|
||||
*bit_cast<CallableWrapperBase**>(&m_storage) = new WrapperType(forward<Callable>(callable));
|
||||
m_kind = FunctionKind::Outline;
|
||||
} else {
|
||||
|
@ -281,6 +296,7 @@ private:
|
|||
bool m_deferred_clear { false };
|
||||
mutable Atomic<u16> m_call_nesting_level { 0 };
|
||||
|
||||
static constexpr size_t inline_alignment = max(alignof(CallableWrapperBase), alignof(CallableWrapperBase*));
|
||||
#ifndef KERNEL
|
||||
// Empirically determined to fit most lambdas and functions.
|
||||
static constexpr size_t inline_capacity = 4 * sizeof(void*);
|
||||
|
@ -288,7 +304,8 @@ private:
|
|||
// FIXME: Try to decrease this.
|
||||
static constexpr size_t inline_capacity = 6 * sizeof(void*);
|
||||
#endif
|
||||
alignas(max(alignof(CallableWrapperBase), alignof(CallableWrapperBase*))) u8 m_storage[inline_capacity];
|
||||
|
||||
alignas(inline_alignment) u8 m_storage[inline_capacity];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue