Skip to content

Commit

Permalink
[PlayStation] Add libpas implementation which don't map huge vss region.
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=274234

Reviewed by Yusuke Suzuki.

libpas allocate memory region called `compact heap reservation` in its very early stage of
its life cycle. The area is used by libpas's management object to achieve several heaps
managed by libpas system. The point is that they never been deallocated and even more, they
never been decommitted. So only action to the memory region is allocation. This means that
we don't need to patch every mmap usage with vss library but only this usage. Much simpler.

This reservation heap is designed for mmpa's behavior called *demand paging*, that the
kernel never assign physical memory to the page until actual write is happened. So the heap
is as is from the beginning to the end without any further memory calls such as madvise or
munmap. But when some are is allowed to be used for some object, the first write to that
page will be used to assign physical memory to that region.

This is smart but not good for our platform. We need precise reserve / commit management.
So in this PR, we add some code in `pas_compact_heap_reservation_try_allocate()` to switch
current implementation and ours and manage commit when region is actually allocated.

Compact heap reservation is used from lower address to higher address by order or request.
They don't care page boundary when the region is used. Just the requested alignment is
cared. For instance, say the request is coming like following order:

- 84 bytes with 1 byte alignment
- 64 bytes with 16 bytes alignment
- 1M bytes with 1M bytes alignment

then allocation and unused padding is like this:

| request 1   | padding | request 2      | padding   | request 3      | ...
| 84 bytes    | 12      | 64 bytes       | 1,048,416 | 1M bytes       |
| 1 byte alin | bytes   | 16 bytes align | bytes     | 1M bytes align |

See the second padding is pretty huge and sounds very inefficient. But it is okay because
actual region is never touched and no page is consumed for the padding region. And 128MB
of addresses are enough big for the libpas usage.

FYI: The purpose of this reservation is to represent 64 bit address with compact size
(3 bytes in actual configuration). The client of compact heap reservation uses the fact
that the assigned address fits in the range of reservation start and end so it can be
represented as the index from the start.

Testing is done on Speedometer 3.0 using MiniBrowser

* Source/bmalloc/PlatformPlayStation.cmake:
* Source/bmalloc/libpas/src/libpas/pas_compact_heap_reservation.c:
(pas_compact_heap_reservation_try_allocate):

Canonical link: https://commits.webkit.org/278937@main
  • Loading branch information
basuke committed May 17, 2024
1 parent fe3cc47 commit 8e655f8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Source/bmalloc/PlatformPlayStation.cmake
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
WEBKIT_APPEND_GLOBAL_COMPILER_FLAGS(-Wno-typedef-redefinition)

list(APPEND bmalloc_PRIVATE_INCLUDE_DIRECTORIES
${MEMORY_EXTRA_INCLUDE_DIR}
)
42 changes: 42 additions & 0 deletions Source/bmalloc/libpas/src/libpas/pas_compact_heap_reservation.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,21 @@
#include "pas_heap_lock.h"
#include "pas_page_malloc.h"

#if PAS_PLATFORM(PLAYSTATION)
#include <memory-extra.h>
#endif

size_t pas_compact_heap_reservation_size =
(size_t)1 << PAS_COMPACT_PTR_BITS << PAS_INTERNAL_MIN_ALIGN_SHIFT;
size_t pas_compact_heap_reservation_guard_size = 16;
uintptr_t pas_compact_heap_reservation_base = 0;
size_t pas_compact_heap_reservation_available_size = 0;
size_t pas_compact_heap_reservation_bump = 0;

#if PAS_PLATFORM(PLAYSTATION)
uintptr_t pas_compact_heap_reservation_committed = 0;
#endif

pas_aligned_allocation_result pas_compact_heap_reservation_try_allocate(size_t size, size_t alignment)
{
pas_aligned_allocation_result result;
Expand All @@ -56,12 +64,19 @@ pas_aligned_allocation_result pas_compact_heap_reservation_try_allocate(size_t s
if (!pas_compact_heap_reservation_base) {
pas_aligned_allocation_result page_result;

#if PAS_PLATFORM(PLAYSTATION)
pas_zero_memory(&page_result, sizeof(pas_aligned_allocation_result));

page_result.result = memory_extra_vss_reserve(pas_compact_heap_reservation_size, pas_page_malloc_alignment());
PAS_ASSERT(page_result.result);
#else
page_result = pas_page_malloc_try_allocate_without_deallocating_padding(
pas_compact_heap_reservation_size, pas_alignment_create_trivial());
PAS_ASSERT(!page_result.left_padding_size);
PAS_ASSERT(!page_result.right_padding_size);
PAS_ASSERT(page_result.result);
PAS_ASSERT(page_result.result_size == pas_compact_heap_reservation_size);
#endif

pas_compact_heap_reservation_base =
(uintptr_t)page_result.result - pas_compact_heap_reservation_guard_size;
Expand All @@ -83,6 +98,33 @@ pas_aligned_allocation_result pas_compact_heap_reservation_try_allocate(size_t s

pas_compact_heap_reservation_bump = allocation_end - pas_compact_heap_reservation_base;

#if PAS_PLATFORM(PLAYSTATION)
if (pas_compact_heap_reservation_committed < allocation_end && size > 0) {
uintptr_t need_commit_start;
uintptr_t need_commit_end;
bool success;
uintptr_t page_size;

if (!pas_compact_heap_reservation_committed)
pas_compact_heap_reservation_committed = pas_compact_heap_reservation_base + pas_compact_heap_reservation_guard_size;

page_size = pas_page_malloc_alignment();

need_commit_start = pas_round_down_to_power_of_2(allocation_start, page_size);
need_commit_end = pas_round_up_to_power_of_2(allocation_end, page_size);

if (need_commit_start < pas_compact_heap_reservation_committed)
need_commit_start = pas_compact_heap_reservation_committed;

PAS_ASSERT(need_commit_start < need_commit_end);

success = memory_extra_vss_commit((void*)need_commit_start, need_commit_end - need_commit_start, true, -1);
PAS_ASSERT(success);

pas_compact_heap_reservation_committed = need_commit_end;
}
#endif

result.left_padding = (void*)padding_start;
result.left_padding_size = allocation_start - padding_start;
result.result = (void*)allocation_start;
Expand Down

0 comments on commit 8e655f8

Please sign in to comment.