summaryrefslogtreecommitdiff
path: root/Libraries/LibJS/Heap
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-19 17:24:56 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-19 17:34:33 +0200
commitf7a1696087d3b2f03e11f07cb28ef4f6cbd9fdb0 (patch)
tree0dfdd8c0b6cfa0e8a2534da52b3f997943bd62cf /Libraries/LibJS/Heap
parentcb3cf589ed8a5df38a801bbc34a21951924e9195 (diff)
downloadserenity-f7a1696087d3b2f03e11f07cb28ef4f6cbd9fdb0.zip
LibJS: Add MarkedValueList and use it for argument passing
A MarkedValueList is basically a Vector<JS::Value> that registers with the Heap and makes sure that the stored values don't get GC'd. Before this change, we were unsafely keeping Vector<JS::Value> in some places, which is out-of-reach for the live reference finding logic since Vector puts its elements on the heap by default. We now pass all the JavaScript tests even when running with "js -g", which does a GC on every heap allocation.
Diffstat (limited to 'Libraries/LibJS/Heap')
-rw-r--r--Libraries/LibJS/Heap/Heap.cpp20
-rw-r--r--Libraries/LibJS/Heap/Heap.h5
2 files changed, 25 insertions, 0 deletions
diff --git a/Libraries/LibJS/Heap/Heap.cpp b/Libraries/LibJS/Heap/Heap.cpp
index 0bb47f0d6b..c36a43e7cf 100644
--- a/Libraries/LibJS/Heap/Heap.cpp
+++ b/Libraries/LibJS/Heap/Heap.cpp
@@ -30,6 +30,7 @@
#include <LibJS/Heap/Heap.h>
#include <LibJS/Heap/HeapBlock.h>
#include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/Object.h>
#include <setjmp.h>
#include <stdio.h>
@@ -104,6 +105,13 @@ void Heap::gather_roots(HashTable<Cell*>& roots)
for (auto* handle : m_handles)
roots.set(handle->cell());
+ for (auto* list : m_marked_value_lists) {
+ for (auto& value : list->values()) {
+ if (value.is_cell())
+ roots.set(value.as_cell());
+ }
+ }
+
#ifdef HEAP_DEBUG
dbg() << "gather_roots:";
for (auto* root : roots) {
@@ -266,6 +274,18 @@ void Heap::did_destroy_handle(Badge<HandleImpl>, HandleImpl& impl)
m_handles.remove(&impl);
}
+void Heap::did_create_marked_value_list(Badge<MarkedValueList>, MarkedValueList& list)
+{
+ ASSERT(!m_marked_value_lists.contains(&list));
+ m_marked_value_lists.set(&list);
+}
+
+void Heap::did_destroy_marked_value_list(Badge<MarkedValueList>, MarkedValueList& list)
+{
+ ASSERT(m_marked_value_lists.contains(&list));
+ m_marked_value_lists.remove(&list);
+}
+
void Heap::defer_gc(Badge<DeferGC>)
{
++m_gc_deferrals;
diff --git a/Libraries/LibJS/Heap/Heap.h b/Libraries/LibJS/Heap/Heap.h
index 5504472107..6544021b5a 100644
--- a/Libraries/LibJS/Heap/Heap.h
+++ b/Libraries/LibJS/Heap/Heap.h
@@ -68,6 +68,9 @@ public:
void did_create_handle(Badge<HandleImpl>, HandleImpl&);
void did_destroy_handle(Badge<HandleImpl>, HandleImpl&);
+ void did_create_marked_value_list(Badge<MarkedValueList>, MarkedValueList&);
+ void did_destroy_marked_value_list(Badge<MarkedValueList>, MarkedValueList&);
+
void defer_gc(Badge<DeferGC>);
void undefer_gc(Badge<DeferGC>);
@@ -90,6 +93,8 @@ private:
Vector<NonnullOwnPtr<HeapBlock>> m_blocks;
HashTable<HandleImpl*> m_handles;
+ HashTable<MarkedValueList*> m_marked_value_lists;
+
size_t m_gc_deferrals { 0 };
bool m_should_gc_when_deferral_ends { false };
};