diff --git a/Userland/Applications/Assistant/main.cpp b/Userland/Applications/Assistant/main.cpp index a3cd79c394..fc5da293c4 100644 --- a/Userland/Applications/Assistant/main.cpp +++ b/Userland/Applications/Assistant/main.cpp @@ -146,7 +146,7 @@ private: ErrorOr serenity_main(Main::Arguments arguments) { - TRY(Core::System::pledge("stdio recvfd sendfd rpath cpath unix proc exec thread")); + TRY(Core::System::pledge("stdio recvfd sendfd rpath cpath unix proc exec thread map_fixed")); Core::LockFile lockfile("/tmp/lock/assistant.lock"); diff --git a/Userland/Applications/Spreadsheet/main.cpp b/Userland/Applications/Spreadsheet/main.cpp index 841388292f..9f69f9426f 100644 --- a/Userland/Applications/Spreadsheet/main.cpp +++ b/Userland/Applications/Spreadsheet/main.cpp @@ -23,7 +23,7 @@ ErrorOr serenity_main(Main::Arguments arguments) { - TRY(Core::System::pledge("stdio recvfd sendfd rpath fattr unix cpath wpath thread")); + TRY(Core::System::pledge("stdio recvfd sendfd rpath fattr unix cpath wpath thread map_fixed")); auto app = TRY(GUI::Application::create(arguments)); diff --git a/Userland/Libraries/LibJS/Heap/BlockAllocator.cpp b/Userland/Libraries/LibJS/Heap/BlockAllocator.cpp index a351bfa45c..bc04bdda5e 100644 --- a/Userland/Libraries/LibJS/Heap/BlockAllocator.cpp +++ b/Userland/Libraries/LibJS/Heap/BlockAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021-2023, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -15,20 +15,24 @@ # include #endif +// FIXME: Implement MADV_FREE and/or MADV_DONTNEED on SerenityOS. +#if defined(AK_OS_SERENITY) || (!defined(MADV_FREE) && !defined(MADV_DONTNEED)) +# define USE_FALLBACK_BLOCK_DEALLOCATION +#endif + namespace JS { +// NOTE: If this changes, we need to update the mmap() code to ensure correct alignment. +static_assert(HeapBlock::block_size == 4096); + BlockAllocator::~BlockAllocator() { for (auto* block : m_blocks) { ASAN_UNPOISON_MEMORY_REGION(block, HeapBlock::block_size); -#ifdef AK_OS_SERENITY if (munmap(block, HeapBlock::block_size) < 0) { perror("munmap"); VERIFY_NOT_REACHED(); } -#else - free(block); -#endif } } @@ -50,28 +54,38 @@ void* BlockAllocator::allocate_block([[maybe_unused]] char const* name) #ifdef AK_OS_SERENITY auto* block = (HeapBlock*)serenity_mmap(nullptr, HeapBlock::block_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_RANDOMIZED | MAP_PRIVATE, 0, 0, HeapBlock::block_size, name); - VERIFY(block != MAP_FAILED); #else - auto* block = (HeapBlock*)aligned_alloc(HeapBlock::block_size, HeapBlock::block_size); - VERIFY(block); + auto* block = (HeapBlock*)mmap(nullptr, HeapBlock::block_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); #endif + VERIFY(block != MAP_FAILED); return block; } void BlockAllocator::deallocate_block(void* block) { VERIFY(block); - if (m_blocks.size() >= max_cached_blocks) { -#ifdef AK_OS_SERENITY - if (munmap(block, HeapBlock::block_size) < 0) { - perror("munmap"); - VERIFY_NOT_REACHED(); - } -#else - free(block); -#endif - return; + +#if defined(USE_FALLBACK_BLOCK_DEALLOCATION) + // If we can't use any of the nicer techniques, unmap and remap the block to return the physical pages while keeping the VM. + if (munmap(block, HeapBlock::block_size) < 0) { + perror("munmap"); + VERIFY_NOT_REACHED(); } + if (mmap(block, HeapBlock::block_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, 0, 0) != block) { + perror("mmap"); + VERIFY_NOT_REACHED(); + } +#elif defined(MADV_FREE) + if (madvise(block, HeapBlock::block_size, MADV_FREE) < 0) { + perror("madvise(MADV_FREE)"); + VERIFY_NOT_REACHED(); + } +#elif defined(MADV_DONTNEED) + if (madvise(block, HeapBlock::block_size, MADV_DONTNEED) < 0) { + perror("madvise(MADV_DONTNEED)"); + VERIFY_NOT_REACHED(); + } +#endif ASAN_POISON_MEMORY_REGION(block, HeapBlock::block_size); m_blocks.append(block); diff --git a/Userland/Libraries/LibJS/Heap/BlockAllocator.h b/Userland/Libraries/LibJS/Heap/BlockAllocator.h index 0dc614825a..9e99d29768 100644 --- a/Userland/Libraries/LibJS/Heap/BlockAllocator.h +++ b/Userland/Libraries/LibJS/Heap/BlockAllocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021-2023, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -20,9 +20,7 @@ public: void deallocate_block(void*); private: - static constexpr size_t max_cached_blocks = 512; - - Vector m_blocks; + Vector m_blocks; }; } diff --git a/Userland/Libraries/LibJS/Heap/CellAllocator.cpp b/Userland/Libraries/LibJS/Heap/CellAllocator.cpp index b4cf5fa41a..6289c73801 100644 --- a/Userland/Libraries/LibJS/Heap/CellAllocator.cpp +++ b/Userland/Libraries/LibJS/Heap/CellAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling + * Copyright (c) 2020-2023, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -37,11 +37,10 @@ Cell* CellAllocator::allocate_cell(Heap& heap) void CellAllocator::block_did_become_empty(Badge, HeapBlock& block) { - auto& heap = block.heap(); block.m_list_node.remove(); // NOTE: HeapBlocks are managed by the BlockAllocator, so we don't want to `delete` the block here. block.~HeapBlock(); - heap.block_allocator().deallocate_block(&block); + m_block_allocator.deallocate_block(&block); } void CellAllocator::block_did_become_usable(Badge, HeapBlock& block) diff --git a/Userland/Libraries/LibJS/Heap/CellAllocator.h b/Userland/Libraries/LibJS/Heap/CellAllocator.h index 592f54cc10..cd835cc4b7 100644 --- a/Userland/Libraries/LibJS/Heap/CellAllocator.h +++ b/Userland/Libraries/LibJS/Heap/CellAllocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling + * Copyright (c) 2020-2023, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,6 +10,7 @@ #include #include #include +#include #include #define JS_DECLARE_ALLOCATOR(ClassName) \ @@ -49,9 +50,13 @@ public: IntrusiveListNode m_list_node; using List = IntrusiveList<&CellAllocator::m_list_node>; + BlockAllocator& block_allocator() { return m_block_allocator; } + private: size_t const m_cell_size; + BlockAllocator m_block_allocator; + using BlockList = IntrusiveList<&HeapBlock::m_list_node>; BlockList m_full_blocks; BlockList m_usable_blocks; diff --git a/Userland/Libraries/LibJS/Heap/Heap.h b/Userland/Libraries/LibJS/Heap/Heap.h index fda95d9266..4002ca229f 100644 --- a/Userland/Libraries/LibJS/Heap/Heap.h +++ b/Userland/Libraries/LibJS/Heap/Heap.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +82,6 @@ public: void register_cell_allocator(Badge, CellAllocator&); - BlockAllocator& block_allocator() { return m_block_allocator; } - void uproot_cell(Cell* cell); private: @@ -154,8 +151,6 @@ private: Vector> m_uprooted_cells; - BlockAllocator m_block_allocator; - size_t m_gc_deferrals { 0 }; bool m_should_gc_when_deferral_ends { false }; diff --git a/Userland/Libraries/LibJS/Heap/HeapBlock.cpp b/Userland/Libraries/LibJS/Heap/HeapBlock.cpp index bedeb4747c..8f5637be6c 100644 --- a/Userland/Libraries/LibJS/Heap/HeapBlock.cpp +++ b/Userland/Libraries/LibJS/Heap/HeapBlock.cpp @@ -26,7 +26,7 @@ NonnullOwnPtr HeapBlock::create_with_cell_size(Heap& heap, CellAlloca #else char const* name = nullptr; #endif - auto* block = static_cast(heap.block_allocator().allocate_block(name)); + auto* block = static_cast(cell_allocator.block_allocator().allocate_block(name)); new (block) HeapBlock(heap, cell_allocator, cell_size); return NonnullOwnPtr(NonnullOwnPtr::Adopt, *block); } diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp index bb531380e5..4c42e971ed 100644 --- a/Userland/Services/WebContent/main.cpp +++ b/Userland/Services/WebContent/main.cpp @@ -27,7 +27,7 @@ ErrorOr serenity_main(Main::Arguments) { Core::EventLoop event_loop; - TRY(Core::System::pledge("stdio recvfd sendfd accept unix rpath thread proc")); + TRY(Core::System::pledge("stdio recvfd sendfd accept unix rpath thread proc map_fixed")); // This must be first; we can't check if /tmp/webdriver exists once we've unveiled other paths. auto webdriver_socket_path = ByteString::formatted("{}/webdriver", TRY(Core::StandardPaths::runtime_directory())); diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index 87d704c6c4..2aa475b1b6 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -531,7 +531,7 @@ private: ErrorOr serenity_main(Main::Arguments arguments) { - TRY(Core::System::pledge("stdio rpath wpath cpath tty sigaction")); + TRY(Core::System::pledge("stdio rpath wpath cpath tty sigaction map_fixed")); bool gc_on_every_allocation = false; bool disable_syntax_highlight = false;