Ver Fonte

LibJS: Add fast ExecutionContext allocator

...that maintains a list of allocated execution contexts so malloc()
does not have to be called every time we need to get a new one.

20% improvement in Octane/typescript.js
16% improvement in Kraken/imaging-darkroom.js
Aliaksandr Kalenik há 1 ano atrás
pai
commit
63a56a77a2

+ 26 - 1
Userland/Libraries/LibJS/Runtime/ExecutionContext.cpp

@@ -13,9 +13,34 @@
 
 namespace JS {
 
+class ExecutionContextAllocator {
+public:
+    NonnullOwnPtr<ExecutionContext> allocate(Heap& heap)
+    {
+        if (m_execution_contexts.is_empty())
+            return adopt_own(*new ExecutionContext(heap));
+        void* slot = m_execution_contexts.take_last();
+        return adopt_own(*new (slot) ExecutionContext(heap));
+    }
+    void deallocate(void* ptr)
+    {
+        m_execution_contexts.append(ptr);
+    }
+
+private:
+    Vector<void*> m_execution_contexts;
+};
+
+static NeverDestroyed<ExecutionContextAllocator> s_execution_context_allocator;
+
 NonnullOwnPtr<ExecutionContext> ExecutionContext::create(Heap& heap)
 {
-    return adopt_own(*new ExecutionContext(heap));
+    return s_execution_context_allocator->allocate(heap);
+}
+
+void ExecutionContext::operator delete(void* ptr)
+{
+    s_execution_context_allocator->deallocate(ptr);
 }
 
 ExecutionContext::ExecutionContext(Heap& heap)

+ 4 - 0
Userland/Libraries/LibJS/Runtime/ExecutionContext.h

@@ -31,11 +31,15 @@ struct ExecutionContext {
     void visit_edges(Cell::Visitor&);
 
 private:
+    friend class ExecutionContextAllocator;
+
     ExecutionContext(Heap&);
 
     IntrusiveListNode<ExecutionContext> m_list_node;
 
 public:
+    void operator delete(void* ptr);
+
     Heap& m_heap;
 
     using List = IntrusiveList<&ExecutionContext::m_list_node>;