mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:27:43 +00:00
LibJS: Use a work queue instead of the C++ stack for the GC mark phase
This fixes an issue where we'd run out of C++ stack while traversing large GC heap graphs.
This commit is contained in:
parent
5dcc58d54a
commit
7826cb2556
2 changed files with 30 additions and 5 deletions
|
@ -208,7 +208,12 @@ __attribute__((no_sanitize("address"))) void Heap::gather_conservative_roots(Has
|
||||||
|
|
||||||
class MarkingVisitor final : public Cell::Visitor {
|
class MarkingVisitor final : public Cell::Visitor {
|
||||||
public:
|
public:
|
||||||
MarkingVisitor() = default;
|
explicit MarkingVisitor(HashTable<Cell*> const& roots)
|
||||||
|
{
|
||||||
|
for (auto* root : roots) {
|
||||||
|
visit(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit_impl(Cell& cell) override
|
virtual void visit_impl(Cell& cell) override
|
||||||
{
|
{
|
||||||
|
@ -217,17 +222,26 @@ public:
|
||||||
dbgln_if(HEAP_DEBUG, " ! {}", &cell);
|
dbgln_if(HEAP_DEBUG, " ! {}", &cell);
|
||||||
|
|
||||||
cell.set_marked(true);
|
cell.set_marked(true);
|
||||||
cell.visit_edges(*this);
|
m_work_queue.append(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mark_all_live_cells()
|
||||||
|
{
|
||||||
|
while (!m_work_queue.is_empty()) {
|
||||||
|
m_work_queue.take_last().visit_edges(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<Cell&> m_work_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Heap::mark_live_cells(HashTable<Cell*> const& roots)
|
void Heap::mark_live_cells(HashTable<Cell*> const& roots)
|
||||||
{
|
{
|
||||||
dbgln_if(HEAP_DEBUG, "mark_live_cells:");
|
dbgln_if(HEAP_DEBUG, "mark_live_cells:");
|
||||||
|
|
||||||
MarkingVisitor visitor;
|
MarkingVisitor visitor(roots);
|
||||||
for (auto* root : roots)
|
visitor.mark_all_live_cells();
|
||||||
visitor.visit(root);
|
|
||||||
|
|
||||||
for (auto& inverse_root : m_uprooted_cells)
|
for (auto& inverse_root : m_uprooted_cells)
|
||||||
inverse_root->set_marked(false);
|
inverse_root->set_marked(false);
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
test("garbage collection of a deeply-nested object graph", () => {
|
||||||
|
let root = {};
|
||||||
|
let o = root;
|
||||||
|
|
||||||
|
for (let i = 0; i < 200_000; ++i) {
|
||||||
|
o.next = {};
|
||||||
|
o = o.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc();
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue