From 1398e888c1fef871768c1cfc2b8ad17b5d64b590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 May 2024 15:14:39 +0200 Subject: [PATCH] StackSpace: use std::aligned_alloc() (#907) Use `std::aligned_alloc()` (and `_aligned_malloc()` on MSVC) to allocate the memory for EVM stack. This removes unnecessary initialization of the memory to zero (closes https://github.com/ethereum/evmone/issues/403). The memory alignment is set to 32 bytes (as previously) but allows transitioning to "over-aligned" allocation for additional optimization (see https://github.com/ethereum/evmone/issues/781). --- lib/evmone/execution_state.hpp | 41 +++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/evmone/execution_state.hpp b/lib/evmone/execution_state.hpp index 27be8163b9..7fc56c6ae5 100644 --- a/lib/evmone/execution_state.hpp +++ b/lib/evmone/execution_state.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -27,20 +28,48 @@ using intx::uint256; /// Provides memory for EVM stack. class StackSpace { + static uint256* allocate() noexcept + { + static constexpr auto alignment = sizeof(uint256); + static constexpr auto size = limit * sizeof(uint256); +#ifdef _MSC_VER + // MSVC doesn't support aligned_alloc() but _aligned_malloc() can be used instead. + const auto p = _aligned_malloc(size, alignment); +#else + const auto p = std::aligned_alloc(alignment, size); +#endif + return static_cast(p); + } + + struct Deleter + { + // TODO(C++23): static + void operator()(void* p) noexcept + { +#ifdef _MSC_VER + // For MSVC the _aligned_malloc() must be paired with _aligned_free(). + _aligned_free(p); +#else + std::free(p); +#endif + } + }; + + /// The storage allocated for maximum possible number of items. + /// Items are aligned to 256 bits for better packing in cache lines. + std::unique_ptr m_stack_space; + public: /// The maximum number of EVM stack items. static constexpr auto limit = 1024; + StackSpace() noexcept : m_stack_space{allocate()} {} + /// Returns the pointer to the "bottom", i.e. below the stack space. [[nodiscard, clang::no_sanitize("bounds")]] uint256* bottom() noexcept { - return m_stack_space - 1; + return m_stack_space.get() - 1; } - -private: - /// The storage allocated for maximum possible number of items. - /// Items are aligned to 256 bits for better packing in cache lines. - alignas(sizeof(uint256)) uint256 m_stack_space[limit]; };