Reduce Save access indirections

Most Save access are to modify the refcount. Now that the freelist
is index based it is not necessary to keep Save objects at fixed
memory locations.
This commit is contained in:
Maxime Coste 2024-03-07 20:40:24 +11:00
parent c81266d4f6
commit a1c52e08a4

View File

@ -233,12 +233,11 @@ public:
~ThreadedRegexVM() ~ThreadedRegexVM()
{ {
for (auto* saves : m_saves) for (auto& saves : m_saves)
{ {
for (size_t i = m_program.save_count-1; i > 0; --i) for (int i = m_program.save_count-1; i >= 0; --i)
saves->pos[i].~Iterator(); saves.pos[i].~Iterator();
saves->~Saves(); operator delete(saves.pos, m_program.save_count * sizeof(Iterator));
operator delete(saves);
} }
} }
@ -289,16 +288,16 @@ public:
ArrayView<const Iterator> captures() const ArrayView<const Iterator> captures() const
{ {
if (m_captures >= 0) if (m_captures >= 0)
return { m_saves[m_captures]->pos, m_program.save_count }; return { m_saves[m_captures].pos, m_program.save_count };
return {}; return {};
} }
private: private:
struct Saves struct Saves
{ {
int16_t refcount; int32_t refcount;
int16_t next_free; int32_t next_free;
Iterator pos[1]; Iterator* pos;
}; };
template<bool copy> template<bool copy>
@ -309,7 +308,7 @@ private:
if (m_first_free >= 0) if (m_first_free >= 0)
{ {
const int16_t res = m_first_free; const int16_t res = m_first_free;
Saves& saves = *m_saves[res]; Saves& saves = m_saves[res];
m_first_free = saves.next_free; m_first_free = saves.next_free;
kak_assert(saves.refcount == 1); kak_assert(saves.refcount == 1);
if (copy) if (copy)
@ -320,11 +319,10 @@ private:
return res; return res;
} }
void* ptr = operator new (sizeof(Saves) + (count-1) * sizeof(Iterator)); auto* new_pos = reinterpret_cast<Iterator*>(operator new (count * sizeof(Iterator)));
Saves* saves = new (ptr) Saves{1, 0, {copy ? pos[0] : Iterator{}}}; for (size_t i = 0; i < count; ++i)
for (size_t i = 1; i < count; ++i) new (new_pos+i) Iterator{copy ? pos[i] : Iterator{}};
new (&saves->pos[i]) Iterator{copy ? pos[i] : Iterator{}}; m_saves.push_back({1, 0, new_pos});
m_saves.push_back(saves);
return static_cast<int16_t>(m_saves.size() - 1); return static_cast<int16_t>(m_saves.size() - 1);
} }
@ -332,7 +330,7 @@ private:
{ {
if (index < 0) if (index < 0)
return; return;
auto& saves = *m_saves[index]; auto& saves = m_saves[index];
if (saves.refcount == 1) if (saves.refcount == 1)
{ {
saves.next_free = m_first_free; saves.next_free = m_first_free;
@ -414,7 +412,7 @@ private:
break; break;
if (thread.saves >= 0) if (thread.saves >= 0)
++m_saves[thread.saves]->refcount; ++m_saves[thread.saves].refcount;
if (inst.param.split.prioritize_parent) if (inst.param.split.prioritize_parent)
m_threads.push_current({inst.param.split.target, thread.saves}); m_threads.push_current({inst.param.split.target, thread.saves});
@ -429,12 +427,12 @@ private:
break; break;
if (thread.saves < 0) if (thread.saves < 0)
thread.saves = new_saves<false>(nullptr); thread.saves = new_saves<false>(nullptr);
else if (m_saves[thread.saves]->refcount > 1) else if (m_saves[thread.saves].refcount > 1)
{ {
--m_saves[thread.saves]->refcount; --m_saves[thread.saves].refcount;
thread.saves = new_saves<true>(m_saves[thread.saves]->pos); thread.saves = new_saves<true>(m_saves[thread.saves].pos);
} }
m_saves[thread.saves]->pos[inst.param.save_index] = pos; m_saves[thread.saves].pos[inst.param.save_index] = pos;
break; break;
case CompiledRegex::CharClass: case CompiledRegex::CharClass:
if (pos == config.end) if (pos == config.end)
@ -709,7 +707,7 @@ private:
static constexpr bool forward = mode & RegexMode::Forward; static constexpr bool forward = mode & RegexMode::Forward;
DualThreadStack m_threads; DualThreadStack m_threads;
Vector<Saves*, MemoryDomain::Regex> m_saves; Vector<Saves, MemoryDomain::Regex> m_saves;
int16_t m_first_free = -1; int16_t m_first_free = -1;
int16_t m_captures = -1; int16_t m_captures = -1;
bool m_found_match = false; bool m_found_match = false;