diff --git a/AK/Bitmap.h b/AK/Bitmap.h index b7fb6ba79af..85098ef597b 100644 --- a/AK/Bitmap.h +++ b/AK/Bitmap.h @@ -50,7 +50,7 @@ public: Bitmap& operator=(Bitmap&& other) { if (this != &other) { - kfree_sized(m_data, size_in_bytes()); + kfree(m_data); m_data = exchange(other.m_data, nullptr); m_size = exchange(other.m_size, 0); } @@ -60,7 +60,7 @@ public: ~Bitmap() { if (m_is_owning) { - kfree_sized(m_data, size_in_bytes()); + kfree(m_data); } m_data = nullptr; } @@ -96,7 +96,7 @@ public: __builtin_memcpy(m_data, previous_data, previous_size_bytes); if ((previous_size % 8) != 0) set_range(previous_size, 8 - previous_size % 8, default_value); - kfree_sized(previous_data, previous_size_bytes); + kfree(previous_data); } } diff --git a/AK/BumpAllocator.h b/AK/BumpAllocator.h index 26f543d9940..3dd28793b20 100644 --- a/AK/BumpAllocator.h +++ b/AK/BumpAllocator.h @@ -87,7 +87,7 @@ public: munmap((void*)chunk, m_chunk_size); #endif } else { - kfree_sized((void*)chunk, m_chunk_size); + kfree((void*)chunk); } }); } diff --git a/AK/ByteBuffer.h b/AK/ByteBuffer.h index 9e8a14e87f8..4da3360c2eb 100644 --- a/AK/ByteBuffer.h +++ b/AK/ByteBuffer.h @@ -43,7 +43,7 @@ public: { if (this != &other) { if (!m_inline) - kfree_sized(m_outline_buffer, m_outline_capacity); + kfree(m_outline_buffer); move_from(move(other)); } return *this; @@ -176,7 +176,7 @@ public: void clear() { if (!m_inline) { - kfree_sized(m_outline_buffer, m_outline_capacity); + kfree(m_outline_buffer); m_inline = true; } m_size = 0; @@ -353,10 +353,9 @@ private: { // m_inline_buffer and m_outline_buffer are part of a union, so save the pointer auto* outline_buffer = m_outline_buffer; - auto outline_capacity = m_outline_capacity; if (!may_discard_existing_data) __builtin_memcpy(m_inline_buffer, outline_buffer, size); - kfree_sized(outline_buffer, outline_capacity); + kfree(outline_buffer); m_inline = true; } @@ -377,7 +376,7 @@ private: __builtin_memcpy(new_buffer, data(), m_size); } else if (m_outline_buffer) { __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; diff --git a/AK/ByteStringImpl.h b/AK/ByteStringImpl.h index cc3d5ff8d59..40061fbb1d4 100644 --- a/AK/ByteStringImpl.h +++ b/AK/ByteStringImpl.h @@ -30,7 +30,7 @@ public: void operator delete(void* ptr) { - kfree_sized(ptr, allocation_size_for_stringimpl(static_cast(ptr)->m_length)); + kfree(ptr); } static ByteStringImpl& the_empty_stringimpl(); diff --git a/AK/CMakeLists.txt b/AK/CMakeLists.txt index 481032944cd..65fd99ee54e 100644 --- a/AK/CMakeLists.txt +++ b/AK/CMakeLists.txt @@ -77,12 +77,22 @@ target_link_libraries(AK PRIVATE FastFloat::fast_float) find_package(fmt CONFIG REQUIRED) 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 if (BUILD_SHARED_LIBS AND NOT CMAKE_SKIP_INSTALL_RULES AND NOT "${VCPKG_INSTALLED_DIR}" STREQUAL "") install(IMPORTED_RUNTIME_ARTIFACTS simdutf::simdutf LIBRARY COMPONENT Lagom_Runtime NAMELINK_COMPONENT Lagom_Development FRAMEWORK COMPONENT Lagom_Runtime ) + install(IMPORTED_RUNTIME_ARTIFACTS mimalloc + LIBRARY COMPONENT Lagom_Runtime NAMELINK_COMPONENT Lagom_Development + FRAMEWORK COMPONENT Lagom_Runtime + ) endif() if (WIN32) @@ -108,6 +118,14 @@ elseif (APPLE) set(ASSERTION_HANDLER_VISIBILITY INTERFACE) endif() 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() # Manually install AK headers diff --git a/AK/FixedArray.h b/AK/FixedArray.h index aa840997e5e..32fdf5c8553 100644 --- a/AK/FixedArray.h +++ b/AK/FixedArray.h @@ -99,7 +99,7 @@ public: return; for (size_t i = 0; i < m_size; ++i) m_elements[i].~T(); - kfree_sized(m_elements, storage_allocation_size(m_size)); + kfree(m_elements); m_elements = nullptr; } diff --git a/AK/HashTable.h b/AK/HashTable.h index 2d51d4f711f..72365b5f518 100644 --- a/AK/HashTable.h +++ b/AK/HashTable.h @@ -190,7 +190,7 @@ public: } } - kfree_sized(m_buckets, size_in_bytes(capacity())); + kfree(m_buckets); } HashTable(HashTable const& other) @@ -622,7 +622,6 @@ private: VERIFY(new_capacity >= size()); auto* old_buckets = m_buckets; - auto old_buckets_size = size_in_bytes(capacity()); Iterator old_iter = begin(); auto* new_buckets = kcalloc(1, size_in_bytes(new_capacity)); @@ -644,7 +643,7 @@ private: it->~T(); } - kfree_sized(old_buckets, old_buckets_size); + kfree(old_buckets); return {}; } void rehash(size_t new_capacity) diff --git a/AK/StringData.h b/AK/StringData.h index 51ea994815d..df80fbda3ef 100644 --- a/AK/StringData.h +++ b/AK/StringData.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace AK::Detail { @@ -26,7 +27,7 @@ public: VERIFY(byte_count); auto capacity = allocation_size_for_string_data(byte_count); - void* slot = malloc(capacity); + void* slot = kmalloc(capacity); if (!slot) return Error::from_errno(ENOMEM); @@ -52,7 +53,7 @@ public: VERIFY(byte_count > MAX_SHORT_STRING_BYTE_COUNT); auto capacity = sizeof(StringData) + sizeof(StringData::SubstringData); - void* slot = malloc(capacity); + void* slot = kmalloc(capacity); if (!slot) return Error::from_errno(ENOMEM); @@ -66,7 +67,7 @@ public: void operator delete(void* ptr) { - free(ptr); + kfree(ptr); } ~StringData() diff --git a/AK/Utf16StringData.cpp b/AK/Utf16StringData.cpp index 8a1b711429c..bad2855ac76 100644 --- a/AK/Utf16StringData.cpp +++ b/AK/Utf16StringData.cpp @@ -20,11 +20,9 @@ namespace AK::Detail { NonnullRefPtr Utf16StringData::create_uninitialized(StorageType storage_type, size_t code_unit_length) { - auto allocation_size = storage_type == Utf16StringData::StorageType::ASCII - ? sizeof(Utf16StringData) + (sizeof(char) * code_unit_length) - : sizeof(Utf16StringData) + (sizeof(char16_t) * code_unit_length); + auto allocation_size = allocation_size_for_string_data(storage_type == Utf16StringData::StorageType::ASCII, code_unit_length); - void* slot = malloc(allocation_size); + void* slot = kmalloc(allocation_size); VERIFY(slot); return adopt_ref(*new (slot) Utf16StringData(storage_type, code_unit_length)); diff --git a/AK/Utf16StringData.h b/AK/Utf16StringData.h index 8d85ae5358b..47a389643ec 100644 --- a/AK/Utf16StringData.h +++ b/AK/Utf16StringData.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace AK::Detail { @@ -52,7 +53,7 @@ public: void operator delete(void* ptr) { - free(ptr); + kfree(ptr); } [[nodiscard]] ALWAYS_INLINE bool operator==(Utf16StringData const& other) const @@ -130,6 +131,13 @@ private: template static NonnullRefPtr 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; // We store whether this string has ASCII or UTF-16 storage by setting the most significant bit of m_length_in_code_units diff --git a/AK/Vector.h b/AK/Vector.h index a1a296a1a84..c5791d320c6 100644 --- a/AK/Vector.h +++ b/AK/Vector.h @@ -481,7 +481,7 @@ public: { clear_with_capacity(); 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; } reset_capacity(); @@ -862,7 +862,7 @@ public: } } 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_capacity = new_capacity; update_metadata(); // We have *some* space, we just allocated it. diff --git a/AK/kmalloc.cpp b/AK/kmalloc.cpp index 181634fbbd1..f4a0702fc89 100644 --- a/AK/kmalloc.cpp +++ b/AK/kmalloc.cpp @@ -68,4 +68,162 @@ nothrow_t const nothrow; } +#else + +# include +# include + +# 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 +# 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(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 diff --git a/AK/kmalloc.h b/AK/kmalloc.h index 11d93033309..7b20e413001 100644 --- a/AK/kmalloc.h +++ b/AK/kmalloc.h @@ -12,25 +12,43 @@ #include #include -#define kcalloc calloc -#define kmalloc malloc -#define kmalloc_good_size malloc_good_size +#if defined(AK_OS_SERENITY) +# define kcalloc calloc +# 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 -# include - -# ifndef AK_OS_MACOS -extern "C" { -inline size_t malloc_good_size(size_t size) { return size; } +inline void kfree(void* ptr) +{ + ak_kfree(ptr); +} + +[[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 -# endif #endif using std::nothrow; diff --git a/CMakeLists.txt b/CMakeLists.txt index aa359f237c2..803ba0f1b59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,8 @@ if (WIN32) find_package(mman REQUIRED) endif() +find_package(mimalloc CONFIG REQUIRED) + include(rust_crate) include(targets) diff --git a/Cargo.toml b/Cargo.toml index 0b4668c86e8..69f2fad9d41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,4 +32,4 @@ ref_option = "deny" elidable_lifetime_names = "deny" unnested_or_patterns = "deny" borrow_as_ptr = "deny" -explicit_iter_loop = "deny" \ No newline at end of file +explicit_iter_loop = "deny" diff --git a/Libraries/LibGfx/Bitmap.cpp b/Libraries/LibGfx/Bitmap.cpp index a692d1cb584..ece27e795cc 100644 --- a/Libraries/LibGfx/Bitmap.cpp +++ b/Libraries/LibGfx/Bitmap.cpp @@ -108,8 +108,8 @@ Bitmap::Bitmap(BitmapFormat format, AlphaType alpha_type, IntSize size, BackingS VERIFY(!size_would_overflow(format, size)); VERIFY(m_data); VERIFY(backing_store.size_in_bytes == size_in_bytes()); - m_destruction_callback = [data = m_data, size_in_bytes = this->size_in_bytes()] { - kfree_sized(data, size_in_bytes); + m_destruction_callback = [data = m_data] { + kfree(data); }; } diff --git a/Libraries/LibJS/CMakeLists.txt b/Libraries/LibJS/CMakeLists.txt index 4987d2adcd1..0a7a7c479c6 100644 --- a/Libraries/LibJS/CMakeLists.txt +++ b/Libraries/LibJS/CMakeLists.txt @@ -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) 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 # entry points, Rust calls C++ callbacks). For static builds, merge the diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index b9966684aca..274b9d9fd66 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,8 @@ static constexpr u32 HEAP_STORAGE_HEADER_SIZE = sizeof(Value); static Value* allocate_heap_named_storage(u32 capacity) { VERIFY(capacity > Object::INLINE_NAMED_PROPERTY_CAPACITY); - auto* raw = static_cast(malloc(HEAP_STORAGE_HEADER_SIZE + capacity * sizeof(Value))); + auto allocation_size = HEAP_STORAGE_HEADER_SIZE + capacity * sizeof(Value); + auto* raw = static_cast(kmalloc(allocation_size)); VERIFY(raw); *reinterpret_cast(raw) = capacity; return reinterpret_cast(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) { - free(reinterpret_cast(storage) - HEAP_STORAGE_HEADER_SIZE); + auto* raw = reinterpret_cast(storage) - HEAP_STORAGE_HEADER_SIZE; + kfree(raw); } static u32 heap_named_storage_capacity(Value* storage) @@ -73,7 +76,7 @@ void Object::ensure_named_storage_capacity(u32 needed) new_storage[i] = Value(); m_named_properties = new_storage; } else { - auto* raw = static_cast(realloc( + auto* raw = static_cast(krealloc( reinterpret_cast(m_named_properties) - HEAP_STORAGE_HEADER_SIZE, HEAP_STORAGE_HEADER_SIZE + new_capacity * sizeof(Value))); VERIFY(raw); @@ -1703,7 +1706,9 @@ u32 Object::indexed_elements_capacity() const static Value* allocate_indexed_elements(u32 capacity) { // Layout: [u32 capacity] [u32 padding] [Value 0] [Value 1] ... - auto* raw = static_cast(malloc(sizeof(u64) + capacity * sizeof(Value))); + auto allocation_size = sizeof(u64) + capacity * sizeof(Value); + auto* raw = static_cast(kmalloc(allocation_size)); + VERIFY(raw); *reinterpret_cast(raw) = capacity; *reinterpret_cast(raw + sizeof(u32)) = 0; // padding auto* elements = reinterpret_cast(raw + sizeof(u64)); @@ -1717,7 +1722,7 @@ static void deallocate_indexed_elements(Value* elements) if (!elements) return; auto* raw = reinterpret_cast(elements) - sizeof(u64); - free(raw); + kfree(raw); } void Object::free_indexed_elements() diff --git a/Libraries/LibJS/Rust/src/lib.rs b/Libraries/LibJS/Rust/src/lib.rs index 75d5724794e..24b9d6ca6bd 100644 --- a/Libraries/LibJS/Rust/src/lib.rs +++ b/Libraries/LibJS/Rust/src/lib.rs @@ -52,6 +52,9 @@ //! - `bytecode/` — Bytecode generator, instruction types, and FFI //! - `scope_collector.rs` — Scope analysis +#[path = "../../../RustAllocator.rs"] +mod rust_allocator; + /// Compile-time conversion of an ASCII string literal to `&'static [u16]`. /// /// Produces a static `[u16; N]` array, so comparisons like diff --git a/Libraries/LibJS/RustIntegration.cpp b/Libraries/LibJS/RustIntegration.cpp index f1c36bfa06e..cf66d0152e9 100644 --- a/Libraries/LibJS/RustIntegration.cpp +++ b/Libraries/LibJS/RustIntegration.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -1005,7 +1006,7 @@ extern "C" void* rust_compile_regex( auto parsed_pattern = JS::parse_regex_pattern(pattern, is_unicode, is_unicode_sets); if (parsed_pattern.is_error()) { auto msg = MUST(String::formatted("RegExp compile error: {}", parsed_pattern.release_error().error)); - auto* buf = static_cast(malloc(msg.byte_count() + 1)); + auto* buf = static_cast(kmalloc(msg.byte_count() + 1)); memcpy(buf, msg.bytes().data(), msg.byte_count()); buf[msg.byte_count()] = '\0'; *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); if (compiled.is_error()) { auto msg = MUST(String::formatted("RegExp compile error: {}", compiled.release_error())); - auto* buf = static_cast(malloc(msg.byte_count() + 1)); + auto* buf = static_cast(kmalloc(msg.byte_count() + 1)); memcpy(buf, msg.bytes().data(), msg.byte_count()); buf[msg.byte_count()] = '\0'; *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) { - free(const_cast(str)); + kfree(const_cast(str)); } extern "C" size_t rust_number_to_utf16(double value, uint16_t* buffer, size_t buffer_len) diff --git a/Libraries/LibMedia/Audio/PlaybackStreamAudioUnit.cpp b/Libraries/LibMedia/Audio/PlaybackStreamAudioUnit.cpp index a8466b7561b..d566b719386 100644 --- a/Libraries/LibMedia/Audio/PlaybackStreamAudioUnit.cpp +++ b/Libraries/LibMedia/Audio/PlaybackStreamAudioUnit.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -78,7 +79,7 @@ class CoreAudioPropertyValue { public: static ErrorOr> create(u32 size) { - auto ptr = reinterpret_cast(malloc(size)); + auto ptr = reinterpret_cast(kmalloc(size)); if (ptr == nullptr) return Error::from_errno(ENOMEM); return CoreAudioPropertyValue(ptr, size); @@ -96,7 +97,7 @@ public: } ~CoreAudioPropertyValue() { - free(m_ptr); + kfree(m_ptr); } u32 size() const { return m_size; } @@ -471,8 +472,8 @@ ErrorOr audio_channel_layout_to_channel_map(AudioChannelLayout const &explicit_layout_size)); VERIFY(explicit_layout_size >= sizeof(AudioChannelLayout)); - auto* explicit_layout = reinterpret_cast(malloc(explicit_layout_size)); - ScopeGuard free_explicit_layout { [&] { free(explicit_layout); } }; + auto* explicit_layout = reinterpret_cast(kmalloc(explicit_layout_size)); + ScopeGuard free_explicit_layout { [&] { kfree(explicit_layout); } }; AU_TRY(AudioFormatGetProperty( kAudioFormatProperty_ChannelLayoutForTag, diff --git a/Libraries/LibRegex/CMakeLists.txt b/Libraries/LibRegex/CMakeLists.txt index a3d4023a6fa..7e0206edb7a 100644 --- a/Libraries/LibRegex/CMakeLists.txt +++ b/Libraries/LibRegex/CMakeLists.txt @@ -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) 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() diff --git a/Libraries/LibRegex/Rust/src/lib.rs b/Libraries/LibRegex/Rust/src/lib.rs index c0aec919878..4da383bbb95 100644 --- a/Libraries/LibRegex/Rust/src/lib.rs +++ b/Libraries/LibRegex/Rust/src/lib.rs @@ -4,6 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#[path = "../../../RustAllocator.rs"] +mod rust_allocator; + pub mod ast; pub mod bytecode; pub mod compiler; diff --git a/Libraries/LibUnicode/Rust/src/lib.rs b/Libraries/LibUnicode/Rust/src/lib.rs index 762936799d6..a23360a6d55 100644 --- a/Libraries/LibUnicode/Rust/src/lib.rs +++ b/Libraries/LibUnicode/Rust/src/lib.rs @@ -4,4 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#[path = "../../../RustAllocator.rs"] +mod rust_allocator; + pub mod calendar; diff --git a/Libraries/RustAllocator.rs b/Libraries/RustAllocator.rs new file mode 100644 index 00000000000..26464b76a7f --- /dev/null +++ b/Libraries/RustAllocator.rs @@ -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()) } + } +} diff --git a/Meta/CMake/flatpak/org.ladybird.Ladybird.json b/Meta/CMake/flatpak/org.ladybird.Ladybird.json index 58a0b8fdc07..64ce3e93a61 100644 --- a/Meta/CMake/flatpak/org.ladybird.Ladybird.json +++ b/Meta/CMake/flatpak/org.ladybird.Ladybird.json @@ -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", "buildsystem": "cmake-ninja", diff --git a/vcpkg.json b/vcpkg.json index 6402f7608ad..3114da131b9 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -113,6 +113,7 @@ "name": "mman", "platform": "windows" }, + "mimalloc", "openssl", { "name": "pthread", @@ -309,6 +310,10 @@ "name": "libxml2", "version": "2.13.8#1" }, + { + "name": "mimalloc", + "version": "2.2.7" + }, { "name": "mman", "version": "git-f5ff813#5"