Skip to content

Commit

Permalink
Fix memory error on Yarr
Browse files Browse the repository at this point in the history
If we want to store WTF::String with Vector or HashSet,
we would use another type of allocator

Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed Jul 25, 2024
1 parent 96d165f commit 0f6ea46
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 5 deletions.
33 changes: 33 additions & 0 deletions third_party/yarr/HashSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,39 @@ class HashSet : public std::unordered_set<Key, std::hash<Key>, std::equal_to<Key
}
};

template <typename Key, typename Allocator = GCUtil::gc_malloc_allocator<Key>>
class GCHashSet : public Escargot::HashSet<Key, std::hash<Key>, std::equal_to<Key>, Allocator> {
public:
struct AddResult {
bool isNewEntry;
};
AddResult add(const Key& k)
{
AddResult r;
r.isNewEntry = Escargot::HashSet<Key, std::hash<Key>, std::equal_to<Key>, Allocator>::insert(k).second;
return r;
}

template<typename Other>
void formUnion(const Other& other)
{
for (const auto& value: other) {
add(value);
}
}

bool contains(const Key& k)
{
return Escargot::HashSet<Key, std::hash<Key>, std::equal_to<Key>, Allocator>::find(k) != Escargot::HashSet<Key, std::hash<Key>, std::equal_to<Key>, Allocator>::end();
}

bool isEmpty()
{
return Escargot::HashSet<Key, std::hash<Key>, std::equal_to<Key>, Allocator>::empty();
}
};

} // namespace WTF

using WTF::HashSet;
using WTF::GCHashSet;
185 changes: 183 additions & 2 deletions third_party/yarr/Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ class Vector {
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
std::vector<T> impl;

public:
Vector() {}
Vector(const Vector& v)
{
Expand Down Expand Up @@ -208,8 +206,191 @@ class Vector {
std::fill(begin(), end(), val);
}

private:
std::vector<T> impl;
};

template <typename T>
class GCVector {
public:
using iterator = T*;
using const_iterator = const T*;

GCVector() {}
GCVector(const GCVector& v)
{
append(v);
}

GCVector(const T* v, size_t len)
{
impl.reserve(len);
for (size_t i = 0; i < len; i ++) {
impl.push_back(v[i]);
}
}

GCVector(std::initializer_list<T> list)
{
impl.reserve(list.size());
for (auto& i : list) {
impl.push_back(i);
}
}

size_t size() const
{
return impl.size();
}

T& operator[](size_t i)
{
return impl[i];
}

const T& operator[](size_t i) const
{
return impl[i];
}

T& at(size_t i)
{
return impl[i];
}

T* data()
{
return impl.data();
}

iterator begin()
{
return impl.begin();
}

iterator end()
{
return impl.end();
}

const_iterator begin() const
{
return impl.begin();
}

const_iterator end() const
{
return impl.end();
}

T& last()
{
return impl.back();
}

bool isEmpty() const
{
return impl.empty();
}

template <typename U>
void append(const U& u)
{
impl.push_back(static_cast<T>(u));
}

void append(T&& u)
{
impl.push_back(std::move(u));
}

template <size_t M>
void append(const Vector<T, M>& v)
{
impl.insert(impl.end(), v.impl.begin(), v.impl.end());
}

void insert(size_t i, const T& t)
{
impl.insert(impl.begin() + i, t);
}

void remove(size_t i)
{
impl.erase(impl.begin() + i);
}

void removeLast()
{
impl.pop_back();
}

void clear()
{
impl.clear();
}

void grow(size_t s)
{
impl.resize(s);
}

void shrink(size_t newLength)
{
ASSERT(newLength <= impl.size());
while (impl.size() != newLength) {
impl.pop_back();
}
}

void shrinkToFit()
{
impl.shrink_to_fit();
}

size_t capacity() const
{
return impl.capacity();
}

void reserveInitialCapacity(size_t siz)
{
impl.reserve(siz);
}

void deleteAllValues()
{
clear();
}

void reserve(size_t capacity)
{
impl.reserve(capacity);
}

T takeLast()
{
T last(*impl.rbegin());
impl.pop_back();
return last;
}

void fill(const T& val, size_t newSize)
{
if (size() > newSize)
shrink(newSize);
else if (newSize > capacity()) {
clear();
grow(newSize);
}
std::fill(begin(), end(), val);
}

private:
Escargot::Vector<T, GCUtil::gc_malloc_allocator<T>> impl;
};

} // namespace WTF

using WTF::Vector;
using WTF::GCVector;
6 changes: 3 additions & 3 deletions third_party/yarr/YarrParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Parser {
};

class NamedCaptureGroups {
typedef HashSet<String> GroupNameHashSet;
typedef GCHashSet<String> GroupNameHashSet;

public:
NamedCaptureGroups()
Expand Down Expand Up @@ -117,7 +117,7 @@ class Parser {

private:
GroupNameHashSet m_captureGroupNames;
Vector<GroupNameHashSet, 1> m_activeCaptureGroupNames;
GCVector<GroupNameHashSet> m_activeCaptureGroupNames;
};

/*
Expand Down Expand Up @@ -2076,7 +2076,7 @@ class Parser {
bool m_kIdentityEscapeSeen { false };
Vector<ParenthesesType, 16> m_parenthesesStack;
NamedCaptureGroups m_namedCaptureGroups;
HashSet<String> m_forwardReferenceNames;
GCHashSet<String> m_forwardReferenceNames;

// Derived by empirical testing of compile time in PCRE and WREC.
static constexpr unsigned MAX_PATTERN_SIZE = 1024 * 1024;
Expand Down

0 comments on commit 0f6ea46

Please sign in to comment.