AK: Adopt mimalloc v2 as main allocator
Use mimalloc for Ladybird-owned allocations without overriding malloc(). Route kmalloc(), kcalloc(), krealloc(), and kfree() through mimalloc, and put the embedded Rust crates on the same allocator via a shared shim in AK/kmalloc.cpp. This also lets us drop kfree_sized(), since it no longer used its size argument. StringData, Utf16StringData, JS object storage, Rust error strings, and the CoreAudio playback helpers can all free their AK-backed storage with plain kfree(). Sanitizer builds still use the system allocator. LeakSanitizer does not reliably trace references stored in mimalloc-managed AK containers, so static caches and other long-lived roots can look leaked. Pass the old size into the Rust realloc shim so aligned fallback reallocations can move posix_memalign-backed blocks safely. Static builds still need a little linker help. macOS app binaries need the Rust allocator entry points forced in from liblagom-ak.a, while static ELF links can pull in identical allocator shim definitions from multiple Rust staticlibs. Keep the Apple -u flags and allow those duplicate shim symbols for LibJS and LibRegex links on Linux and BSD.
This commit is contained in:
parent
648ececa62
commit
b23aa38546
27 changed files with 349 additions and 53 deletions
|
|
@ -50,7 +50,7 @@ public:
|
||||||
Bitmap& operator=(Bitmap&& other)
|
Bitmap& operator=(Bitmap&& other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
kfree_sized(m_data, size_in_bytes());
|
kfree(m_data);
|
||||||
m_data = exchange(other.m_data, nullptr);
|
m_data = exchange(other.m_data, nullptr);
|
||||||
m_size = exchange(other.m_size, 0);
|
m_size = exchange(other.m_size, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +60,7 @@ public:
|
||||||
~Bitmap()
|
~Bitmap()
|
||||||
{
|
{
|
||||||
if (m_is_owning) {
|
if (m_is_owning) {
|
||||||
kfree_sized(m_data, size_in_bytes());
|
kfree(m_data);
|
||||||
}
|
}
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,7 @@ public:
|
||||||
__builtin_memcpy(m_data, previous_data, previous_size_bytes);
|
__builtin_memcpy(m_data, previous_data, previous_size_bytes);
|
||||||
if ((previous_size % 8) != 0)
|
if ((previous_size % 8) != 0)
|
||||||
set_range(previous_size, 8 - previous_size % 8, default_value);
|
set_range(previous_size, 8 - previous_size % 8, default_value);
|
||||||
kfree_sized(previous_data, previous_size_bytes);
|
kfree(previous_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ public:
|
||||||
munmap((void*)chunk, m_chunk_size);
|
munmap((void*)chunk, m_chunk_size);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
kfree_sized((void*)chunk, m_chunk_size);
|
kfree((void*)chunk);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public:
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
if (!m_inline)
|
if (!m_inline)
|
||||||
kfree_sized(m_outline_buffer, m_outline_capacity);
|
kfree(m_outline_buffer);
|
||||||
move_from(move(other));
|
move_from(move(other));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -176,7 +176,7 @@ public:
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
if (!m_inline) {
|
if (!m_inline) {
|
||||||
kfree_sized(m_outline_buffer, m_outline_capacity);
|
kfree(m_outline_buffer);
|
||||||
m_inline = true;
|
m_inline = true;
|
||||||
}
|
}
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
|
|
@ -353,10 +353,9 @@ private:
|
||||||
{
|
{
|
||||||
// m_inline_buffer and m_outline_buffer are part of a union, so save the pointer
|
// m_inline_buffer and m_outline_buffer are part of a union, so save the pointer
|
||||||
auto* outline_buffer = m_outline_buffer;
|
auto* outline_buffer = m_outline_buffer;
|
||||||
auto outline_capacity = m_outline_capacity;
|
|
||||||
if (!may_discard_existing_data)
|
if (!may_discard_existing_data)
|
||||||
__builtin_memcpy(m_inline_buffer, outline_buffer, size);
|
__builtin_memcpy(m_inline_buffer, outline_buffer, size);
|
||||||
kfree_sized(outline_buffer, outline_capacity);
|
kfree(outline_buffer);
|
||||||
m_inline = true;
|
m_inline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,7 +376,7 @@ private:
|
||||||
__builtin_memcpy(new_buffer, data(), m_size);
|
__builtin_memcpy(new_buffer, data(), m_size);
|
||||||
} else if (m_outline_buffer) {
|
} else if (m_outline_buffer) {
|
||||||
__builtin_memcpy(new_buffer, m_outline_buffer, min(new_capacity, m_outline_capacity));
|
__builtin_memcpy(new_buffer, m_outline_buffer, min(new_capacity, m_outline_capacity));
|
||||||
kfree_sized(m_outline_buffer, m_outline_capacity);
|
kfree(m_outline_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_outline_buffer = new_buffer;
|
m_outline_buffer = new_buffer;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
void operator delete(void* ptr)
|
void operator delete(void* ptr)
|
||||||
{
|
{
|
||||||
kfree_sized(ptr, allocation_size_for_stringimpl(static_cast<ByteStringImpl*>(ptr)->m_length));
|
kfree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ByteStringImpl& the_empty_stringimpl();
|
static ByteStringImpl& the_empty_stringimpl();
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,22 @@ target_link_libraries(AK PRIVATE FastFloat::fast_float)
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
target_link_libraries(AK PRIVATE fmt::fmt)
|
target_link_libraries(AK PRIVATE fmt::fmt)
|
||||||
|
|
||||||
|
set(MIMALLOC_VISIBILITY PRIVATE)
|
||||||
|
if (NOT BUILD_SHARED_LIBS)
|
||||||
|
set(MIMALLOC_VISIBILITY PUBLIC)
|
||||||
|
endif()
|
||||||
|
target_link_libraries(AK ${MIMALLOC_VISIBILITY} mimalloc)
|
||||||
|
|
||||||
# FIXME: Make this generic for all imported shared library dependencies and apply globally
|
# FIXME: Make this generic for all imported shared library dependencies and apply globally
|
||||||
if (BUILD_SHARED_LIBS AND NOT CMAKE_SKIP_INSTALL_RULES AND NOT "${VCPKG_INSTALLED_DIR}" STREQUAL "")
|
if (BUILD_SHARED_LIBS AND NOT CMAKE_SKIP_INSTALL_RULES AND NOT "${VCPKG_INSTALLED_DIR}" STREQUAL "")
|
||||||
install(IMPORTED_RUNTIME_ARTIFACTS simdutf::simdutf
|
install(IMPORTED_RUNTIME_ARTIFACTS simdutf::simdutf
|
||||||
LIBRARY COMPONENT Lagom_Runtime NAMELINK_COMPONENT Lagom_Development
|
LIBRARY COMPONENT Lagom_Runtime NAMELINK_COMPONENT Lagom_Development
|
||||||
FRAMEWORK COMPONENT Lagom_Runtime
|
FRAMEWORK COMPONENT Lagom_Runtime
|
||||||
)
|
)
|
||||||
|
install(IMPORTED_RUNTIME_ARTIFACTS mimalloc
|
||||||
|
LIBRARY COMPONENT Lagom_Runtime NAMELINK_COMPONENT Lagom_Development
|
||||||
|
FRAMEWORK COMPONENT Lagom_Runtime
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
@ -108,6 +118,14 @@ elseif (APPLE)
|
||||||
set(ASSERTION_HANDLER_VISIBILITY INTERFACE)
|
set(ASSERTION_HANDLER_VISIBILITY INTERFACE)
|
||||||
endif()
|
endif()
|
||||||
target_link_options(AK ${ASSERTION_HANDLER_VISIBILITY} LINKER:-U,_ak_assertion_handler)
|
target_link_options(AK ${ASSERTION_HANDLER_VISIBILITY} LINKER:-U,_ak_assertion_handler)
|
||||||
|
if (NOT BUILD_SHARED_LIBS)
|
||||||
|
target_link_options(AK INTERFACE
|
||||||
|
LINKER:-u,_ladybird_rust_alloc
|
||||||
|
LINKER:-u,_ladybird_rust_alloc_zeroed
|
||||||
|
LINKER:-u,_ladybird_rust_dealloc
|
||||||
|
LINKER:-u,_ladybird_rust_realloc
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Manually install AK headers
|
# Manually install AK headers
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ public:
|
||||||
return;
|
return;
|
||||||
for (size_t i = 0; i < m_size; ++i)
|
for (size_t i = 0; i < m_size; ++i)
|
||||||
m_elements[i].~T();
|
m_elements[i].~T();
|
||||||
kfree_sized(m_elements, storage_allocation_size(m_size));
|
kfree(m_elements);
|
||||||
m_elements = nullptr;
|
m_elements = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree_sized(m_buckets, size_in_bytes(capacity()));
|
kfree(m_buckets);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashTable(HashTable const& other)
|
HashTable(HashTable const& other)
|
||||||
|
|
@ -622,7 +622,6 @@ private:
|
||||||
VERIFY(new_capacity >= size());
|
VERIFY(new_capacity >= size());
|
||||||
|
|
||||||
auto* old_buckets = m_buckets;
|
auto* old_buckets = m_buckets;
|
||||||
auto old_buckets_size = size_in_bytes(capacity());
|
|
||||||
Iterator old_iter = begin();
|
Iterator old_iter = begin();
|
||||||
|
|
||||||
auto* new_buckets = kcalloc(1, size_in_bytes(new_capacity));
|
auto* new_buckets = kcalloc(1, size_in_bytes(new_capacity));
|
||||||
|
|
@ -644,7 +643,7 @@ private:
|
||||||
it->~T();
|
it->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree_sized(old_buckets, old_buckets_size);
|
kfree(old_buckets);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
void rehash(size_t new_capacity)
|
void rehash(size_t new_capacity)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/NonnullRefPtr.h>
|
#include <AK/NonnullRefPtr.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
|
|
||||||
namespace AK::Detail {
|
namespace AK::Detail {
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ public:
|
||||||
VERIFY(byte_count);
|
VERIFY(byte_count);
|
||||||
|
|
||||||
auto capacity = allocation_size_for_string_data(byte_count);
|
auto capacity = allocation_size_for_string_data(byte_count);
|
||||||
void* slot = malloc(capacity);
|
void* slot = kmalloc(capacity);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return Error::from_errno(ENOMEM);
|
return Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
|
|
@ -52,7 +53,7 @@ public:
|
||||||
VERIFY(byte_count > MAX_SHORT_STRING_BYTE_COUNT);
|
VERIFY(byte_count > MAX_SHORT_STRING_BYTE_COUNT);
|
||||||
|
|
||||||
auto capacity = sizeof(StringData) + sizeof(StringData::SubstringData);
|
auto capacity = sizeof(StringData) + sizeof(StringData::SubstringData);
|
||||||
void* slot = malloc(capacity);
|
void* slot = kmalloc(capacity);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return Error::from_errno(ENOMEM);
|
return Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
|
|
@ -66,7 +67,7 @@ public:
|
||||||
|
|
||||||
void operator delete(void* ptr)
|
void operator delete(void* ptr)
|
||||||
{
|
{
|
||||||
free(ptr);
|
kfree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
~StringData()
|
~StringData()
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,9 @@ namespace AK::Detail {
|
||||||
|
|
||||||
NonnullRefPtr<Utf16StringData> Utf16StringData::create_uninitialized(StorageType storage_type, size_t code_unit_length)
|
NonnullRefPtr<Utf16StringData> Utf16StringData::create_uninitialized(StorageType storage_type, size_t code_unit_length)
|
||||||
{
|
{
|
||||||
auto allocation_size = storage_type == Utf16StringData::StorageType::ASCII
|
auto allocation_size = allocation_size_for_string_data(storage_type == Utf16StringData::StorageType::ASCII, code_unit_length);
|
||||||
? sizeof(Utf16StringData) + (sizeof(char) * code_unit_length)
|
|
||||||
: sizeof(Utf16StringData) + (sizeof(char16_t) * code_unit_length);
|
|
||||||
|
|
||||||
void* slot = malloc(allocation_size);
|
void* slot = kmalloc(allocation_size);
|
||||||
VERIFY(slot);
|
VERIFY(slot);
|
||||||
|
|
||||||
return adopt_ref(*new (slot) Utf16StringData(storage_type, code_unit_length));
|
return adopt_ref(*new (slot) Utf16StringData(storage_type, code_unit_length));
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Utf16View.h>
|
#include <AK/Utf16View.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
|
|
||||||
namespace AK::Detail {
|
namespace AK::Detail {
|
||||||
|
|
||||||
|
|
@ -52,7 +53,7 @@ public:
|
||||||
|
|
||||||
void operator delete(void* ptr)
|
void operator delete(void* ptr)
|
||||||
{
|
{
|
||||||
free(ptr);
|
kfree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ALWAYS_INLINE bool operator==(Utf16StringData const& other) const
|
[[nodiscard]] ALWAYS_INLINE bool operator==(Utf16StringData const& other) const
|
||||||
|
|
@ -130,6 +131,13 @@ private:
|
||||||
template<typename ViewType>
|
template<typename ViewType>
|
||||||
static NonnullRefPtr<Utf16StringData> create_from_code_point_iterable(ViewType const&);
|
static NonnullRefPtr<Utf16StringData> create_from_code_point_iterable(ViewType const&);
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr size_t allocation_size_for_string_data(bool has_ascii_storage, size_t code_unit_length)
|
||||||
|
{
|
||||||
|
return has_ascii_storage
|
||||||
|
? sizeof(Utf16StringData) + (sizeof(char) * code_unit_length)
|
||||||
|
: sizeof(Utf16StringData) + (sizeof(char16_t) * code_unit_length);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] size_t calculate_code_point_length() const;
|
[[nodiscard]] size_t calculate_code_point_length() const;
|
||||||
|
|
||||||
// We store whether this string has ASCII or UTF-16 storage by setting the most significant bit of m_length_in_code_units
|
// We store whether this string has ASCII or UTF-16 storage by setting the most significant bit of m_length_in_code_units
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,7 @@ public:
|
||||||
{
|
{
|
||||||
clear_with_capacity();
|
clear_with_capacity();
|
||||||
if (m_metadata.outline_buffer) {
|
if (m_metadata.outline_buffer) {
|
||||||
kfree_sized(m_metadata.outline_buffer, m_capacity * sizeof(StorageType));
|
kfree(m_metadata.outline_buffer);
|
||||||
m_metadata.outline_buffer = nullptr;
|
m_metadata.outline_buffer = nullptr;
|
||||||
}
|
}
|
||||||
reset_capacity();
|
reset_capacity();
|
||||||
|
|
@ -862,7 +862,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_metadata.outline_buffer)
|
if (m_metadata.outline_buffer)
|
||||||
kfree_sized(m_metadata.outline_buffer, m_capacity * sizeof(StorageType));
|
kfree(m_metadata.outline_buffer);
|
||||||
m_metadata.outline_buffer = new_buffer;
|
m_metadata.outline_buffer = new_buffer;
|
||||||
m_capacity = new_capacity;
|
m_capacity = new_capacity;
|
||||||
update_metadata(); // We have *some* space, we just allocated it.
|
update_metadata(); // We have *some* space, we just allocated it.
|
||||||
|
|
|
||||||
158
AK/kmalloc.cpp
158
AK/kmalloc.cpp
|
|
@ -68,4 +68,162 @@ nothrow_t const nothrow;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# include <cstddef>
|
||||||
|
# include <cstring>
|
||||||
|
|
||||||
|
# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||||
|
// LeakSanitizer does not reliably trace references stored in mimalloc-managed
|
||||||
|
// AK containers, so sanitizer builds fall back to the system allocator.
|
||||||
|
# define AK_USE_SYSTEM_ALLOCATOR_INSTRUMENTED 1
|
||||||
|
# else
|
||||||
|
# include <mimalloc.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static bool allocation_needs_explicit_alignment(size_t alignment)
|
||||||
|
{
|
||||||
|
return alignment > alignof(std::max_align_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef AK_USE_SYSTEM_ALLOCATOR_INSTRUMENTED
|
||||||
|
|
||||||
|
static void* aligned_alloc_with_system_allocator(size_t size, size_t alignment, bool zeroed)
|
||||||
|
{
|
||||||
|
void* ptr = nullptr;
|
||||||
|
auto actual_size = size == 0 ? static_cast<size_t>(1) : size;
|
||||||
|
if (auto result = posix_memalign(&ptr, alignment, actual_size); result != 0)
|
||||||
|
return nullptr;
|
||||||
|
if (zeroed)
|
||||||
|
__builtin_memset(ptr, 0, actual_size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ak_kcalloc(size_t count, size_t size)
|
||||||
|
{
|
||||||
|
return calloc(count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ak_kmalloc(size_t size)
|
||||||
|
{
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ak_krealloc(void* ptr, size_t size)
|
||||||
|
{
|
||||||
|
return realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ak_kmalloc_good_size(size_t size)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ak_kfree(void* ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void* ladybird_rust_alloc(size_t size, size_t alignment);
|
||||||
|
void* ladybird_rust_alloc_zeroed(size_t size, size_t alignment);
|
||||||
|
void ladybird_rust_dealloc(void* ptr, size_t alignment);
|
||||||
|
void* ladybird_rust_realloc(void* ptr, size_t old_size, size_t new_size, size_t alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_alloc(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (allocation_needs_explicit_alignment(alignment))
|
||||||
|
return aligned_alloc_with_system_allocator(size, alignment, false);
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_alloc_zeroed(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (allocation_needs_explicit_alignment(alignment))
|
||||||
|
return aligned_alloc_with_system_allocator(size, alignment, true);
|
||||||
|
return calloc(1, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void ladybird_rust_dealloc(void* ptr, size_t)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_realloc(void* ptr, size_t old_size, size_t new_size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (!allocation_needs_explicit_alignment(alignment))
|
||||||
|
return realloc(ptr, new_size);
|
||||||
|
|
||||||
|
auto* new_ptr = aligned_alloc_with_system_allocator(new_size, alignment, false);
|
||||||
|
if (!new_ptr)
|
||||||
|
return nullptr;
|
||||||
|
if (ptr)
|
||||||
|
__builtin_memcpy(new_ptr, ptr, old_size < new_size ? old_size : new_size);
|
||||||
|
free(ptr);
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
void* ak_kcalloc(size_t count, size_t size)
|
||||||
|
{
|
||||||
|
return mi_calloc(count, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ak_kmalloc(size_t size)
|
||||||
|
{
|
||||||
|
return mi_malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ak_krealloc(void* ptr, size_t size)
|
||||||
|
{
|
||||||
|
return mi_realloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ak_kmalloc_good_size(size_t size)
|
||||||
|
{
|
||||||
|
return mi_good_size(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ak_kfree(void* ptr)
|
||||||
|
{
|
||||||
|
mi_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void* ladybird_rust_alloc(size_t size, size_t alignment);
|
||||||
|
void* ladybird_rust_alloc_zeroed(size_t size, size_t alignment);
|
||||||
|
void ladybird_rust_dealloc(void* ptr, size_t alignment);
|
||||||
|
void* ladybird_rust_realloc(void* ptr, size_t old_size, size_t new_size, size_t alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_alloc(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (allocation_needs_explicit_alignment(alignment))
|
||||||
|
return mi_malloc_aligned(size, alignment);
|
||||||
|
return mi_malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_alloc_zeroed(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (allocation_needs_explicit_alignment(alignment))
|
||||||
|
return mi_zalloc_aligned(size, alignment);
|
||||||
|
return mi_zalloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void ladybird_rust_dealloc(void* ptr, size_t)
|
||||||
|
{
|
||||||
|
mi_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void* ladybird_rust_realloc(void* ptr, size_t, size_t new_size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (allocation_needs_explicit_alignment(alignment))
|
||||||
|
return mi_realloc_aligned(ptr, new_size, alignment);
|
||||||
|
return mi_realloc(ptr, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
46
AK/kmalloc.h
46
AK/kmalloc.h
|
|
@ -12,25 +12,43 @@
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define kcalloc calloc
|
#if defined(AK_OS_SERENITY)
|
||||||
#define kmalloc malloc
|
# define kcalloc calloc
|
||||||
#define kmalloc_good_size malloc_good_size
|
# define kfree free
|
||||||
|
# define kmalloc malloc
|
||||||
|
# define krealloc realloc
|
||||||
|
# define kmalloc_good_size malloc_good_size
|
||||||
|
#else
|
||||||
|
[[nodiscard]] void* ak_kcalloc(size_t count, size_t size);
|
||||||
|
void ak_kfree(void* ptr);
|
||||||
|
[[nodiscard]] void* ak_kmalloc(size_t size);
|
||||||
|
[[nodiscard]] void* ak_krealloc(void* ptr, size_t size);
|
||||||
|
[[nodiscard]] size_t ak_kmalloc_good_size(size_t size);
|
||||||
|
|
||||||
inline void kfree_sized(void* ptr, size_t)
|
[[nodiscard]] inline void* kcalloc(size_t count, size_t size)
|
||||||
{
|
{
|
||||||
free(ptr);
|
return ak_kcalloc(count, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef AK_OS_SERENITY
|
inline void kfree(void* ptr)
|
||||||
# include <AK/Types.h>
|
{
|
||||||
|
ak_kfree(ptr);
|
||||||
# ifndef AK_OS_MACOS
|
}
|
||||||
extern "C" {
|
|
||||||
inline size_t malloc_good_size(size_t size) { return size; }
|
[[nodiscard]] inline void* kmalloc(size_t size)
|
||||||
|
{
|
||||||
|
return ak_kmalloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline void* krealloc(void* ptr, size_t size)
|
||||||
|
{
|
||||||
|
return ak_krealloc(ptr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline size_t kmalloc_good_size(size_t size)
|
||||||
|
{
|
||||||
|
return ak_kmalloc_good_size(size);
|
||||||
}
|
}
|
||||||
# else
|
|
||||||
# include <malloc/malloc.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,8 @@ if (WIN32)
|
||||||
find_package(mman REQUIRED)
|
find_package(mman REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(mimalloc CONFIG REQUIRED)
|
||||||
|
|
||||||
include(rust_crate)
|
include(rust_crate)
|
||||||
include(targets)
|
include(targets)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,4 @@ ref_option = "deny"
|
||||||
elidable_lifetime_names = "deny"
|
elidable_lifetime_names = "deny"
|
||||||
unnested_or_patterns = "deny"
|
unnested_or_patterns = "deny"
|
||||||
borrow_as_ptr = "deny"
|
borrow_as_ptr = "deny"
|
||||||
explicit_iter_loop = "deny"
|
explicit_iter_loop = "deny"
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,8 @@ Bitmap::Bitmap(BitmapFormat format, AlphaType alpha_type, IntSize size, BackingS
|
||||||
VERIFY(!size_would_overflow(format, size));
|
VERIFY(!size_would_overflow(format, size));
|
||||||
VERIFY(m_data);
|
VERIFY(m_data);
|
||||||
VERIFY(backing_store.size_in_bytes == size_in_bytes());
|
VERIFY(backing_store.size_in_bytes == size_in_bytes());
|
||||||
m_destruction_callback = [data = m_data, size_in_bytes = this->size_in_bytes()] {
|
m_destruction_callback = [data = m_data] {
|
||||||
kfree_sized(data, size_in_bytes);
|
kfree(data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,12 @@ target_link_libraries(LibJS PUBLIC JSClangPlugin)
|
||||||
|
|
||||||
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libjs_rust FFI_HEADER RustFFI.h)
|
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libjs_rust FFI_HEADER RustFFI.h)
|
||||||
target_link_libraries(LibJS PRIVATE libjs_rust)
|
target_link_libraries(LibJS PRIVATE libjs_rust)
|
||||||
|
if ((LINUX OR BSD) AND NOT BUILD_SHARED_LIBS)
|
||||||
|
# Rust staticlibs each carry the same allocator shim symbols. LibJS can
|
||||||
|
# pull in multiple crates' copies in static ELF links, but they all
|
||||||
|
# forward to the same ladybird_rust_* entry points in AK/kmalloc.cpp.
|
||||||
|
target_link_options(LibJS INTERFACE LINKER:--allow-multiple-definition)
|
||||||
|
endif()
|
||||||
|
|
||||||
# The Rust library and LibJS have a circular dependency (C++ calls Rust
|
# The Rust library and LibJS have a circular dependency (C++ calls Rust
|
||||||
# entry points, Rust calls C++ callbacks). For static builds, merge the
|
# entry points, Rust calls C++ callbacks). For static builds, merge the
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <AK/ByteString.h>
|
#include <AK/ByteString.h>
|
||||||
#include <AK/QuickSort.h>
|
#include <AK/QuickSort.h>
|
||||||
#include <AK/TypeCasts.h>
|
#include <AK/TypeCasts.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
#include <LibJS/Bytecode/PropertyAccess.h>
|
#include <LibJS/Bytecode/PropertyAccess.h>
|
||||||
#include <LibJS/Runtime/AbstractOperations.h>
|
#include <LibJS/Runtime/AbstractOperations.h>
|
||||||
#include <LibJS/Runtime/Accessor.h>
|
#include <LibJS/Runtime/Accessor.h>
|
||||||
|
|
@ -43,7 +44,8 @@ static constexpr u32 HEAP_STORAGE_HEADER_SIZE = sizeof(Value);
|
||||||
static Value* allocate_heap_named_storage(u32 capacity)
|
static Value* allocate_heap_named_storage(u32 capacity)
|
||||||
{
|
{
|
||||||
VERIFY(capacity > Object::INLINE_NAMED_PROPERTY_CAPACITY);
|
VERIFY(capacity > Object::INLINE_NAMED_PROPERTY_CAPACITY);
|
||||||
auto* raw = static_cast<u8*>(malloc(HEAP_STORAGE_HEADER_SIZE + capacity * sizeof(Value)));
|
auto allocation_size = HEAP_STORAGE_HEADER_SIZE + capacity * sizeof(Value);
|
||||||
|
auto* raw = static_cast<u8*>(kmalloc(allocation_size));
|
||||||
VERIFY(raw);
|
VERIFY(raw);
|
||||||
*reinterpret_cast<u32*>(raw) = capacity;
|
*reinterpret_cast<u32*>(raw) = capacity;
|
||||||
return reinterpret_cast<Value*>(raw + HEAP_STORAGE_HEADER_SIZE);
|
return reinterpret_cast<Value*>(raw + HEAP_STORAGE_HEADER_SIZE);
|
||||||
|
|
@ -51,7 +53,8 @@ static Value* allocate_heap_named_storage(u32 capacity)
|
||||||
|
|
||||||
static void free_heap_named_storage(Value* storage)
|
static void free_heap_named_storage(Value* storage)
|
||||||
{
|
{
|
||||||
free(reinterpret_cast<u8*>(storage) - HEAP_STORAGE_HEADER_SIZE);
|
auto* raw = reinterpret_cast<u8*>(storage) - HEAP_STORAGE_HEADER_SIZE;
|
||||||
|
kfree(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 heap_named_storage_capacity(Value* storage)
|
static u32 heap_named_storage_capacity(Value* storage)
|
||||||
|
|
@ -73,7 +76,7 @@ void Object::ensure_named_storage_capacity(u32 needed)
|
||||||
new_storage[i] = Value();
|
new_storage[i] = Value();
|
||||||
m_named_properties = new_storage;
|
m_named_properties = new_storage;
|
||||||
} else {
|
} else {
|
||||||
auto* raw = static_cast<u8*>(realloc(
|
auto* raw = static_cast<u8*>(krealloc(
|
||||||
reinterpret_cast<u8*>(m_named_properties) - HEAP_STORAGE_HEADER_SIZE,
|
reinterpret_cast<u8*>(m_named_properties) - HEAP_STORAGE_HEADER_SIZE,
|
||||||
HEAP_STORAGE_HEADER_SIZE + new_capacity * sizeof(Value)));
|
HEAP_STORAGE_HEADER_SIZE + new_capacity * sizeof(Value)));
|
||||||
VERIFY(raw);
|
VERIFY(raw);
|
||||||
|
|
@ -1703,7 +1706,9 @@ u32 Object::indexed_elements_capacity() const
|
||||||
static Value* allocate_indexed_elements(u32 capacity)
|
static Value* allocate_indexed_elements(u32 capacity)
|
||||||
{
|
{
|
||||||
// Layout: [u32 capacity] [u32 padding] [Value 0] [Value 1] ...
|
// Layout: [u32 capacity] [u32 padding] [Value 0] [Value 1] ...
|
||||||
auto* raw = static_cast<u8*>(malloc(sizeof(u64) + capacity * sizeof(Value)));
|
auto allocation_size = sizeof(u64) + capacity * sizeof(Value);
|
||||||
|
auto* raw = static_cast<u8*>(kmalloc(allocation_size));
|
||||||
|
VERIFY(raw);
|
||||||
*reinterpret_cast<u32*>(raw) = capacity;
|
*reinterpret_cast<u32*>(raw) = capacity;
|
||||||
*reinterpret_cast<u32*>(raw + sizeof(u32)) = 0; // padding
|
*reinterpret_cast<u32*>(raw + sizeof(u32)) = 0; // padding
|
||||||
auto* elements = reinterpret_cast<Value*>(raw + sizeof(u64));
|
auto* elements = reinterpret_cast<Value*>(raw + sizeof(u64));
|
||||||
|
|
@ -1717,7 +1722,7 @@ static void deallocate_indexed_elements(Value* elements)
|
||||||
if (!elements)
|
if (!elements)
|
||||||
return;
|
return;
|
||||||
auto* raw = reinterpret_cast<u8*>(elements) - sizeof(u64);
|
auto* raw = reinterpret_cast<u8*>(elements) - sizeof(u64);
|
||||||
free(raw);
|
kfree(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::free_indexed_elements()
|
void Object::free_indexed_elements()
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@
|
||||||
//! - `bytecode/` — Bytecode generator, instruction types, and FFI
|
//! - `bytecode/` — Bytecode generator, instruction types, and FFI
|
||||||
//! - `scope_collector.rs` — Scope analysis
|
//! - `scope_collector.rs` — Scope analysis
|
||||||
|
|
||||||
|
#[path = "../../../RustAllocator.rs"]
|
||||||
|
mod rust_allocator;
|
||||||
|
|
||||||
/// Compile-time conversion of an ASCII string literal to `&'static [u16]`.
|
/// Compile-time conversion of an ASCII string literal to `&'static [u16]`.
|
||||||
///
|
///
|
||||||
/// Produces a static `[u16; N]` array, so comparisons like
|
/// Produces a static `[u16; N]` array, so comparisons like
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/Utf16String.h>
|
#include <AK/Utf16String.h>
|
||||||
#include <AK/Utf16View.h>
|
#include <AK/Utf16View.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
#include <LibGC/DeferGC.h>
|
#include <LibGC/DeferGC.h>
|
||||||
#include <LibJS/Bytecode/ClassBlueprint.h>
|
#include <LibJS/Bytecode/ClassBlueprint.h>
|
||||||
#include <LibJS/Bytecode/Executable.h>
|
#include <LibJS/Bytecode/Executable.h>
|
||||||
|
|
@ -1005,7 +1006,7 @@ extern "C" void* rust_compile_regex(
|
||||||
auto parsed_pattern = JS::parse_regex_pattern(pattern, is_unicode, is_unicode_sets);
|
auto parsed_pattern = JS::parse_regex_pattern(pattern, is_unicode, is_unicode_sets);
|
||||||
if (parsed_pattern.is_error()) {
|
if (parsed_pattern.is_error()) {
|
||||||
auto msg = MUST(String::formatted("RegExp compile error: {}", parsed_pattern.release_error().error));
|
auto msg = MUST(String::formatted("RegExp compile error: {}", parsed_pattern.release_error().error));
|
||||||
auto* buf = static_cast<char*>(malloc(msg.byte_count() + 1));
|
auto* buf = static_cast<char*>(kmalloc(msg.byte_count() + 1));
|
||||||
memcpy(buf, msg.bytes().data(), msg.byte_count());
|
memcpy(buf, msg.bytes().data(), msg.byte_count());
|
||||||
buf[msg.byte_count()] = '\0';
|
buf[msg.byte_count()] = '\0';
|
||||||
*error_out = buf;
|
*error_out = buf;
|
||||||
|
|
@ -1050,7 +1051,7 @@ extern "C" void* rust_compile_regex(
|
||||||
auto compiled = regex::ECMAScriptRegex::compile(pattern_str.bytes_as_string_view(), compile_flags);
|
auto compiled = regex::ECMAScriptRegex::compile(pattern_str.bytes_as_string_view(), compile_flags);
|
||||||
if (compiled.is_error()) {
|
if (compiled.is_error()) {
|
||||||
auto msg = MUST(String::formatted("RegExp compile error: {}", compiled.release_error()));
|
auto msg = MUST(String::formatted("RegExp compile error: {}", compiled.release_error()));
|
||||||
auto* buf = static_cast<char*>(malloc(msg.byte_count() + 1));
|
auto* buf = static_cast<char*>(kmalloc(msg.byte_count() + 1));
|
||||||
memcpy(buf, msg.bytes().data(), msg.byte_count());
|
memcpy(buf, msg.bytes().data(), msg.byte_count());
|
||||||
buf[msg.byte_count()] = '\0';
|
buf[msg.byte_count()] = '\0';
|
||||||
*error_out = buf;
|
*error_out = buf;
|
||||||
|
|
@ -1067,7 +1068,7 @@ extern "C" void rust_free_compiled_regex(void* ptr)
|
||||||
|
|
||||||
extern "C" void rust_free_error_string(char const* str)
|
extern "C" void rust_free_error_string(char const* str)
|
||||||
{
|
{
|
||||||
free(const_cast<char*>(str));
|
kfree(const_cast<char*>(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" size_t rust_number_to_utf16(double value, uint16_t* buffer, size_t buffer_len)
|
extern "C" size_t rust_number_to_utf16(double value, uint16_t* buffer, size_t buffer_len)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AK/ScopeGuard.h>
|
#include <AK/ScopeGuard.h>
|
||||||
#include <AK/SourceLocation.h>
|
#include <AK/SourceLocation.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
#include <LibCore/ThreadedPromise.h>
|
#include <LibCore/ThreadedPromise.h>
|
||||||
#include <LibMedia/Audio/PlaybackStreamAudioUnit.h>
|
#include <LibMedia/Audio/PlaybackStreamAudioUnit.h>
|
||||||
#include <LibThreading/Mutex.h>
|
#include <LibThreading/Mutex.h>
|
||||||
|
|
@ -78,7 +79,7 @@ class CoreAudioPropertyValue {
|
||||||
public:
|
public:
|
||||||
static ErrorOr<CoreAudioPropertyValue<T>> create(u32 size)
|
static ErrorOr<CoreAudioPropertyValue<T>> create(u32 size)
|
||||||
{
|
{
|
||||||
auto ptr = reinterpret_cast<T*>(malloc(size));
|
auto ptr = reinterpret_cast<T*>(kmalloc(size));
|
||||||
if (ptr == nullptr)
|
if (ptr == nullptr)
|
||||||
return Error::from_errno(ENOMEM);
|
return Error::from_errno(ENOMEM);
|
||||||
return CoreAudioPropertyValue<T>(ptr, size);
|
return CoreAudioPropertyValue<T>(ptr, size);
|
||||||
|
|
@ -96,7 +97,7 @@ public:
|
||||||
}
|
}
|
||||||
~CoreAudioPropertyValue()
|
~CoreAudioPropertyValue()
|
||||||
{
|
{
|
||||||
free(m_ptr);
|
kfree(m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 size() const { return m_size; }
|
u32 size() const { return m_size; }
|
||||||
|
|
@ -471,8 +472,8 @@ ErrorOr<ChannelMap> audio_channel_layout_to_channel_map(AudioChannelLayout const
|
||||||
&explicit_layout_size));
|
&explicit_layout_size));
|
||||||
VERIFY(explicit_layout_size >= sizeof(AudioChannelLayout));
|
VERIFY(explicit_layout_size >= sizeof(AudioChannelLayout));
|
||||||
|
|
||||||
auto* explicit_layout = reinterpret_cast<AudioChannelLayout*>(malloc(explicit_layout_size));
|
auto* explicit_layout = reinterpret_cast<AudioChannelLayout*>(kmalloc(explicit_layout_size));
|
||||||
ScopeGuard free_explicit_layout { [&] { free(explicit_layout); } };
|
ScopeGuard free_explicit_layout { [&] { kfree(explicit_layout); } };
|
||||||
|
|
||||||
AU_TRY(AudioFormatGetProperty(
|
AU_TRY(AudioFormatGetProperty(
|
||||||
kAudioFormatProperty_ChannelLayoutForTag,
|
kAudioFormatProperty_ChannelLayoutForTag,
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,6 @@ target_link_libraries(LibRegex PRIVATE LibUnicode)
|
||||||
|
|
||||||
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libregex_rust FFI_HEADER RustFFI.h)
|
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libregex_rust FFI_HEADER RustFFI.h)
|
||||||
target_link_libraries(LibRegex PRIVATE libregex_rust)
|
target_link_libraries(LibRegex PRIVATE libregex_rust)
|
||||||
|
if ((LINUX OR BSD) AND NOT BUILD_SHARED_LIBS)
|
||||||
|
target_link_options(LibRegex INTERFACE LINKER:--allow-multiple-definition)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#[path = "../../../RustAllocator.rs"]
|
||||||
|
mod rust_allocator;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod bytecode;
|
pub mod bytecode;
|
||||||
pub mod compiler;
|
pub mod compiler;
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#[path = "../../../RustAllocator.rs"]
|
||||||
|
mod rust_allocator;
|
||||||
|
|
||||||
pub mod calendar;
|
pub mod calendar;
|
||||||
|
|
|
||||||
42
Libraries/RustAllocator.rs
Normal file
42
Libraries/RustAllocator.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2026-present, the Ladybird developers.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::alloc::{GlobalAlloc, Layout};
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn ladybird_rust_alloc(size: usize, alignment: usize) -> *mut u8;
|
||||||
|
fn ladybird_rust_alloc_zeroed(size: usize, alignment: usize) -> *mut u8;
|
||||||
|
fn ladybird_rust_dealloc(ptr: *mut u8, alignment: usize);
|
||||||
|
fn ladybird_rust_realloc(
|
||||||
|
ptr: *mut u8,
|
||||||
|
old_size: usize,
|
||||||
|
new_size: usize,
|
||||||
|
alignment: usize,
|
||||||
|
) -> *mut u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LadybirdAllocator;
|
||||||
|
|
||||||
|
#[global_allocator]
|
||||||
|
static LADYBIRD_ALLOCATOR: LadybirdAllocator = LadybirdAllocator;
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for LadybirdAllocator {
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
unsafe { ladybird_rust_alloc(layout.size(), layout.align()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||||
|
unsafe { ladybird_rust_alloc_zeroed(layout.size(), layout.align()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
unsafe { ladybird_rust_dealloc(ptr, layout.align()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
unsafe { ladybird_rust_realloc(ptr, layout.size(), new_size, layout.align()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -653,6 +653,29 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mimalloc",
|
||||||
|
"buildsystem": "cmake-ninja",
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/microsoft/mimalloc.git",
|
||||||
|
"tag": "v2.2.7"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"config-opts": [
|
||||||
|
"-DCMAKE_BUILD_TYPE=Release",
|
||||||
|
"-DCMAKE_PREFIX_PATH=/app",
|
||||||
|
"-DCMAKE_INSTALL_LIBDIR=lib",
|
||||||
|
"-DMI_BUILD_OBJECT=OFF",
|
||||||
|
"-DMI_BUILD_TESTS=OFF",
|
||||||
|
"-DMI_BUILD_STATIC=OFF",
|
||||||
|
"-DMI_BUILD_SHARED=ON",
|
||||||
|
"-DMI_INSTALL_TOPLEVEL=ON",
|
||||||
|
"-DMI_OVERRIDE=OFF",
|
||||||
|
"-DMI_USE_CXX=ON"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Ladybird",
|
"name": "Ladybird",
|
||||||
"buildsystem": "cmake-ninja",
|
"buildsystem": "cmake-ninja",
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@
|
||||||
"name": "mman",
|
"name": "mman",
|
||||||
"platform": "windows"
|
"platform": "windows"
|
||||||
},
|
},
|
||||||
|
"mimalloc",
|
||||||
"openssl",
|
"openssl",
|
||||||
{
|
{
|
||||||
"name": "pthread",
|
"name": "pthread",
|
||||||
|
|
@ -309,6 +310,10 @@
|
||||||
"name": "libxml2",
|
"name": "libxml2",
|
||||||
"version": "2.13.8#1"
|
"version": "2.13.8#1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mimalloc",
|
||||||
|
"version": "2.2.7"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mman",
|
"name": "mman",
|
||||||
"version": "git-f5ff813#5"
|
"version": "git-f5ff813#5"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue