diff --git a/Libraries/LibJS/Cell.cpp b/Libraries/LibJS/Cell.cpp index d07f877e16..c781a943bf 100644 --- a/Libraries/LibJS/Cell.cpp +++ b/Libraries/LibJS/Cell.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -38,6 +39,11 @@ void Cell::Visitor::visit(Value value) visit(value.as_cell()); } +Heap& Cell::heap() +{ + return HeapBlock::from_cell(this)->heap(); +} + const LogStream& operator<<(const LogStream& stream, const Cell* cell) { if (!cell) diff --git a/Libraries/LibJS/Cell.h b/Libraries/LibJS/Cell.h index 274e41cb4f..973150c2d0 100644 --- a/Libraries/LibJS/Cell.h +++ b/Libraries/LibJS/Cell.h @@ -51,6 +51,8 @@ public: virtual void visit_children(Visitor&) {} + Heap& heap(); + private: bool m_mark { false }; bool m_live { true }; diff --git a/Libraries/LibJS/Heap.cpp b/Libraries/LibJS/Heap.cpp index d6cd2fedb0..c7419f4d0d 100644 --- a/Libraries/LibJS/Heap.cpp +++ b/Libraries/LibJS/Heap.cpp @@ -53,10 +53,10 @@ Cell* Heap::allocate_cell(size_t size) return cell; } - auto* block = (HeapBlock*)malloc(HeapBlock::block_size); - new (block) HeapBlock(size); - m_blocks.append(NonnullOwnPtr(NonnullOwnPtr::Adopt, *block)); - return block->allocate(); + auto block = HeapBlock::create_with_cell_size(*this, size); + auto* cell = block->allocate(); + m_blocks.append(move(block)); + return cell; } void Heap::collect_garbage() diff --git a/Libraries/LibJS/HeapBlock.cpp b/Libraries/LibJS/HeapBlock.cpp index 016726e90b..01fb20b00f 100644 --- a/Libraries/LibJS/HeapBlock.cpp +++ b/Libraries/LibJS/HeapBlock.cpp @@ -25,12 +25,30 @@ */ #include +#include +#include #include +#include namespace JS { -HeapBlock::HeapBlock(size_t cell_size) - : m_cell_size(cell_size) +NonnullOwnPtr HeapBlock::create_with_cell_size(Heap& heap, size_t cell_size) +{ + auto* block = (HeapBlock*)serenity_mmap(nullptr, block_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, block_size, "HeapBlock"); + ASSERT(block != MAP_FAILED); + new (block) HeapBlock(heap, cell_size); + return NonnullOwnPtr(NonnullOwnPtr::Adopt, *block); +} + +void HeapBlock::operator delete(void* ptr) +{ + int rc = munmap(ptr, block_size); + ASSERT(rc == 0); +} + +HeapBlock::HeapBlock(Heap& heap, size_t cell_size) + : m_heap(heap) + , m_cell_size(cell_size) { for (size_t i = 0; i < cell_count(); ++i) { auto* freelist_entry = static_cast(cell(i)); diff --git a/Libraries/LibJS/HeapBlock.h b/Libraries/LibJS/HeapBlock.h index d2bd5c42de..fbc4ed67ff 100644 --- a/Libraries/LibJS/HeapBlock.h +++ b/Libraries/LibJS/HeapBlock.h @@ -35,8 +35,9 @@ namespace JS { class HeapBlock { public: static constexpr size_t block_size = 16 * KB; + static NonnullOwnPtr create_with_cell_size(Heap&, size_t); - explicit HeapBlock(size_t cell_size); + void operator delete(void*); size_t cell_size() const { return m_cell_size; } size_t cell_count() const { return (block_size - sizeof(HeapBlock)) / m_cell_size; } @@ -53,11 +54,21 @@ public: callback(cell(i)); } + Heap& heap() { return m_heap; } + + static HeapBlock* from_cell(Cell* cell) + { + return reinterpret_cast((FlatPtr)cell & ~(block_size - 1)); + } + private: + HeapBlock(Heap&, size_t cell_size); + struct FreelistEntry : public Cell { FreelistEntry* next; }; + Heap& m_heap; size_t m_cell_size { 0 }; FreelistEntry* m_freelist { nullptr }; u8 m_storage[];