Browse Source

LibJS: Use IntrusiveList for Allocator's block lists

This way we don't need to deal with shifting vector storage, and most
operations are upgraded from O(n) to O(1) :^)
Andreas Kling 4 years ago
parent
commit
c541310e19

+ 7 - 14
Libraries/LibJS/Heap/Allocator.cpp

@@ -42,35 +42,28 @@ Allocator::~Allocator()
 Cell* Allocator::allocate_cell(Heap& heap)
 Cell* Allocator::allocate_cell(Heap& heap)
 {
 {
     if (m_usable_blocks.is_empty()) {
     if (m_usable_blocks.is_empty()) {
-        m_usable_blocks.append(HeapBlock::create_with_cell_size(heap, m_cell_size));
+        auto block = HeapBlock::create_with_cell_size(heap, m_cell_size);
+        m_usable_blocks.append(*block.leak_ptr());
     }
     }
 
 
     auto& block = *m_usable_blocks.last();
     auto& block = *m_usable_blocks.last();
     auto* cell = block.allocate();
     auto* cell = block.allocate();
     ASSERT(cell);
     ASSERT(cell);
-    if (block.is_full()) {
-        m_full_blocks.append(m_usable_blocks.take_last());
-    }
+    if (block.is_full())
+        m_full_blocks.append(*m_usable_blocks.last());
     return cell;
     return cell;
 }
 }
 
 
 void Allocator::block_did_become_empty(Badge<Heap>, HeapBlock& block)
 void Allocator::block_did_become_empty(Badge<Heap>, HeapBlock& block)
 {
 {
-    bool removed_something = false;
-    removed_something |= m_full_blocks.remove_first_matching([&block](auto& entry) { return entry == &block; });
-    removed_something |= m_usable_blocks.remove_first_matching([&block](auto& entry) { return entry == &block; });
-    ASSERT(removed_something);
+    block.m_list_node.remove();
+    delete &block;
 }
 }
 
 
 void Allocator::block_did_become_usable(Badge<Heap>, HeapBlock& block)
 void Allocator::block_did_become_usable(Badge<Heap>, HeapBlock& block)
 {
 {
     ASSERT(!block.is_full());
     ASSERT(!block.is_full());
-    auto it = m_full_blocks.find([&](auto& entry) {
-        return entry == &block;
-    });
-    ASSERT(it != m_full_blocks.end());
-    auto owned_block = m_full_blocks.take(it.index());
-    m_usable_blocks.append(move(owned_block));
+    m_usable_blocks.append(block);
 }
 }
 
 
 }
 }

+ 7 - 4
Libraries/LibJS/Heap/Allocator.h

@@ -26,9 +26,11 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <AK/IntrusiveList.h>
 #include <AK/NonnullOwnPtr.h>
 #include <AK/NonnullOwnPtr.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Forward.h>
+#include <LibJS/Heap/HeapBlock.h>
 
 
 namespace JS {
 namespace JS {
 
 
@@ -45,11 +47,11 @@ public:
     IterationDecision for_each_block(Callback callback)
     IterationDecision for_each_block(Callback callback)
     {
     {
         for (auto& block : m_full_blocks) {
         for (auto& block : m_full_blocks) {
-            if (callback(*block) == IterationDecision::Break)
+            if (callback(block) == IterationDecision::Break)
                 return IterationDecision::Break;
                 return IterationDecision::Break;
         }
         }
         for (auto& block : m_usable_blocks) {
         for (auto& block : m_usable_blocks) {
-            if (callback(*block) == IterationDecision::Break)
+            if (callback(block) == IterationDecision::Break)
                 return IterationDecision::Break;
                 return IterationDecision::Break;
         }
         }
         return IterationDecision::Continue;
         return IterationDecision::Continue;
@@ -61,8 +63,9 @@ public:
 private:
 private:
     const size_t m_cell_size;
     const size_t m_cell_size;
 
 
-    Vector<NonnullOwnPtr<HeapBlock>> m_full_blocks;
-    Vector<NonnullOwnPtr<HeapBlock>> m_usable_blocks;
+    typedef IntrusiveList<HeapBlock, &HeapBlock::m_list_node> BlockList;
+    BlockList m_full_blocks;
+    BlockList m_usable_blocks;
 };
 };
 
 
 }
 }

+ 3 - 0
Libraries/LibJS/Heap/HeapBlock.h

@@ -26,6 +26,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include <AK/IntrusiveList.h>
 #include <AK/Types.h>
 #include <AK/Types.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Runtime/Cell.h>
 #include <LibJS/Runtime/Cell.h>
@@ -79,6 +80,8 @@ public:
         return cell(cell_index);
         return cell(cell_index);
     }
     }
 
 
+    IntrusiveListNode m_list_node;
+
 private:
 private:
     HeapBlock(Heap&, size_t cell_size);
     HeapBlock(Heap&, size_t cell_size);