summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-07-31 18:50:51 +0430
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-08-02 17:22:50 +0430
commita7653e6a0511e82544e9bc092a7f782f40a3c000 (patch)
tree752987dd37576f00d1573c9e5faf4960915a4882
parentb034fa9f1fdaf922c5224cc92f7fa527ea94658f (diff)
downloadserenity-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.cpp61
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;