diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-07-31 18:50:51 +0430 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-08-02 17:22:50 +0430 |
commit | a7653e6a0511e82544e9bc092a7f782f40a3c000 (patch) | |
tree | 752987dd37576f00d1573c9e5faf4960915a4882 | |
parent | b034fa9f1fdaf922c5224cc92f7fa527ea94658f (diff) | |
download | serenity-a7653e6a0511e82544e9bc092a7f782f40a3c000.zip |
LibRegex: Use a bump-allocated linked list for fork save states
This makes it avoid the excessively high malloc() traffic.
-rw-r--r-- | Userland/Libraries/LibRegex/RegexMatcher.cpp | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/Userland/Libraries/LibRegex/RegexMatcher.cpp b/Userland/Libraries/LibRegex/RegexMatcher.cpp index b24ecf6b96..3603df182e 100644 --- a/Userland/Libraries/LibRegex/RegexMatcher.cpp +++ b/Userland/Libraries/LibRegex/RegexMatcher.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/BumpAllocator.h> #include <AK/Debug.h> #include <AK/String.h> #include <AK/StringBuilder.h> @@ -334,12 +335,70 @@ RegexResult Matcher<Parser>::match(Vector<RegexStringView> const views, Optional }; } +template<typename T> +class BumpAllocatedLinkedList { +public: + BumpAllocatedLinkedList() = default; + + ALWAYS_INLINE void append(T value) + { + auto new_node = m_allocator.allocate(); + VERIFY(new_node); + auto node_ptr = new (new_node) Node { move(value), nullptr, nullptr }; + + if (!m_first) { + m_first = new_node; + m_last = new_node; + return; + } + + node_ptr->previous = m_last; + m_last->next = node_ptr; + m_last = node_ptr; + } + + ALWAYS_INLINE T take_last() + { + VERIFY(m_last); + T value = move(m_last->value); + if (m_last == m_first) { + m_last = nullptr; + m_first = nullptr; + } else { + m_last = m_last->previous; + m_last->next = nullptr; + } + return value; + } + + ALWAYS_INLINE T& last() + { + return m_last->value; + } + + ALWAYS_INLINE bool is_empty() const + { + return m_first == nullptr; + } + +private: + struct Node { + T value; + Node* next { nullptr }; + Node* previous { nullptr }; + }; + + UniformBumpAllocator<Node, true> m_allocator; + Node* m_first { nullptr }; + Node* m_last { nullptr }; +}; + template<class Parser> Optional<bool> Matcher<Parser>::execute(MatchInput const& input, MatchState& state, MatchOutput& output) const { state.recursion_level = 0; - Vector<MatchState, 64> states_to_try_next; + BumpAllocatedLinkedList<MatchState> states_to_try_next; auto& bytecode = m_pattern->parser_result.bytecode; |