summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2018-12-20 23:07:50 +1100
committerMaxime Coste <mawww@kakoune.org>2019-01-20 22:59:28 +1100
commit8c2603ab3ca58e24ca227bd42e0550adb74fa95f (patch)
tree11c870a9a08bae944a1495965f87e25336013ef5
parent30897fd820df7bb572b7599abeb84715128e4117 (diff)
Support re-using the same ThreadedRegexVM for multiple iterations
This should reduce the number of allocations as the memory allocated for the thread stack and the saves can be re-used between runs instead of being cleared every time.
-rw-r--r--src/highlighters.cc33
-rw-r--r--src/regex.hh24
-rw-r--r--src/selectors.cc6
3 files changed, 34 insertions, 29 deletions
diff --git a/src/highlighters.cc b/src/highlighters.cc
index 1d2624c3..c8b537ba 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -1641,29 +1641,28 @@ struct RegexMatch
};
using RegexMatchList = Vector<RegexMatch, MemoryDomain::Regions>;
-void append_matches(const Buffer& buffer, LineCount line, RegexMatchList& matches, const Regex& regex, bool capture)
-{
- auto l = buffer[line];
- for (auto&& m : RegexIterator{l.begin(), l.end(), regex})
- {
- const bool with_capture = capture and m[1].matched and
- m[0].second - m[0].first < std::numeric_limits<uint16_t>::max();
- matches.push_back({
- line,
- (int)(m[0].first - l.begin()),
- (int)(m[0].second - l.begin()),
- (uint16_t)(with_capture ? m[1].first - m[0].first : 0),
- (uint16_t)(with_capture ? m[1].second - m[1].first : 0)
- });
- }
-}
void insert_matches(const Buffer& buffer, RegexMatchList& matches, const Regex& regex, bool capture, LineRange range)
{
size_t pivot = matches.size();
capture = capture and regex.mark_count() > 0;
+ ThreadedRegexVM<const char*, MatchDirection::Forward> vm{*regex.impl()};
for (auto line = range.begin; line < range.end; ++line)
- append_matches(buffer, line, matches, regex, capture);
+ {
+ const StringView l = buffer[line];
+ for (auto&& m : RegexIterator{l.begin(), l.end(), vm})
+ {
+ const bool with_capture = capture and m[1].matched and
+ m[0].second - m[0].first < std::numeric_limits<uint16_t>::max();
+ matches.push_back({
+ line,
+ (int)(m[0].first - l.begin()),
+ (int)(m[0].second - l.begin()),
+ (uint16_t)(with_capture ? m[1].first - m[0].first : 0),
+ (uint16_t)(with_capture ? m[1].second - m[1].first : 0)
+ });
+ }
+ }
auto pos = std::lower_bound(matches.begin(), matches.begin() + pivot, range.begin,
[](const RegexMatch& m, LineCount l) { return m.line < l; });
diff --git a/src/regex.hh b/src/regex.hh
index 4aa916c9..c0a1fea0 100644
--- a/src/regex.hh
+++ b/src/regex.hh
@@ -164,7 +164,8 @@ bool backward_regex_search(It begin, It end, It subject_begin, It subject_end,
String option_to_string(const Regex& re);
Regex option_from_string(Meta::Type<Regex>, StringView str);
-template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
+template<typename Iterator, MatchDirection direction = MatchDirection::Forward,
+ typename VmArg = const Regex>
struct RegexIterator
{
using ValueType = MatchResults<Iterator>;
@@ -177,25 +178,24 @@ struct RegexIterator
const ValueType* operator->() const { kak_assert(m_valid); return &m_base.m_results; }
It& operator++() { m_valid = m_base.next(); return *this; }
+ bool operator==(Sentinel) const { return not m_valid; }
+ bool operator!=(Sentinel) const { return m_valid; }
RegexIterator& m_base;
bool m_valid;
};
- friend bool operator==(const It& lhs, Sentinel) { return not lhs.m_valid; }
- friend bool operator!=(const It& lhs, Sentinel) { return lhs.m_valid; }
-
RegexIterator(Iterator begin, Iterator end,
Iterator subject_begin, Iterator subject_end,
- const Regex& re, RegexExecFlags flags = RegexExecFlags::None)
- : m_vm{*re.impl()}, m_next_pos{direction == MatchDirection::Forward ? begin : end},
+ VmArg& vm_arg, RegexExecFlags flags = RegexExecFlags::None)
+ : m_vm{make_vm(vm_arg)}, m_next_pos{direction == MatchDirection::Forward ? begin : end},
m_begin{std::move(begin)}, m_end{std::move(end)},
m_subject_begin{std::move(subject_begin)}, m_subject_end{std::move(subject_end)},
m_flags{flags} {}
- RegexIterator(const Iterator& begin, const Iterator& end, const Regex& re,
- RegexExecFlags flags = RegexExecFlags::None)
- : RegexIterator{begin, end, begin, end, re, flags} {}
+ RegexIterator(const Iterator& begin, const Iterator& end,
+ VmArg& vm_arg, RegexExecFlags flags = RegexExecFlags::None)
+ : RegexIterator{begin, end, begin, end, vm_arg, flags} {}
It begin() { return {*this}; }
Sentinel end() const { return {}; }
@@ -219,7 +219,11 @@ private:
return true;
}
- ThreadedRegexVM<Iterator, direction> m_vm;
+ using RegexVM = ThreadedRegexVM<Iterator, direction>;
+ static RegexVM& make_vm(RegexVM& vm) { return vm; }
+ static RegexVM make_vm(const Regex& regex) { return {*regex.impl()}; }
+
+ decltype(make_vm(std::declval<VmArg&>())) m_vm;
MatchResults<Iterator> m_results;
Iterator m_next_pos{};
const Iterator m_begin{};
diff --git a/src/selectors.cc b/src/selectors.cc
index fc661c08..06c64546 100644
--- a/src/selectors.cc
+++ b/src/selectors.cc
@@ -931,12 +931,13 @@ void select_all_matches(SelectionList& selections, const Regex& regex, int captu
Vector<Selection> result;
auto& buffer = selections.buffer();
+ ThreadedRegexVM<BufferIterator, MatchDirection::Forward> vm{*regex.impl()};
for (auto& sel : selections)
{
auto sel_beg = buffer.iterator_at(sel.min());
auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end());
- for (auto&& match : RegexIterator{sel_beg, sel_end, regex, match_flags(buffer, sel_beg, sel_end)})
+ for (auto&& match : RegexIterator{sel_beg, sel_end, vm, match_flags(buffer, sel_beg, sel_end)})
{
auto begin = match[capture].first;
if (begin == sel_end)
@@ -972,12 +973,13 @@ void split_selections(SelectionList& selections, const Regex& regex, int capture
auto& buffer = selections.buffer();
auto buf_end = buffer.end();
auto buf_begin = buffer.begin();
+ ThreadedRegexVM<BufferIterator, MatchDirection::Forward> vm{*regex.impl()};
for (auto& sel : selections)
{
auto begin = buffer.iterator_at(sel.min());
auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end());
- for (auto&& match : RegexIterator{begin, sel_end, regex, match_flags(buffer, begin, sel_end)})
+ for (auto&& match : RegexIterator{begin, sel_end, vm, match_flags(buffer, begin, sel_end)})
{
BufferIterator end = match[capture].first;
if (end == buf_end)