4131 Commits

Author SHA1 Message Date
Andreas Kling
c66cab7e6b AK: Hide tentative HashTable bucket from iterators across ensure()
HashMap<_, GC::Ref<_>>::ensure() crashed under UBSan whenever the
initialization callback triggered a GC: lookup_for_writing() stamped
the target bucket as used and added it to the ordered list before the
callback ran, so the marking visitor walked the map, read the
uninitialized slot, and failed the returns_nonnull check in GC::Ref.

Split bucket reservation into two phases. lookup_for_writing() now
hands back the target in the Free state (not in the ordered list,
m_size unchanged); callers placement-new the value and then commit via
commit_inserted_bucket(). The Robin Hood displacement loop still
stamps the slot internally and un-stamps before returning, so probing
is unchanged and the whole operation remains a single hash and a
single probe.
2026-04-25 06:21:36 +02:00
Aliaksandr Kalenik
eb4038fa83 AK: Fix Utf16View::operator<=> code-unit ordering on little-endian
The !has_ascii_storage() && !other.has_ascii_storage() branch did a
byte-wise __builtin_memcmp over a char16_t array, which on little-endian
does not give code-unit order: the low byte is compared first, so
0xD83D (bytes [0x3D, 0xD8]) spuriously compared less than 0x2764
(bytes [0x64, 0x27]) even though the code unit 0xD83D is greater.

No in-tree caller currently uses operator<=> for Utf16View ordering,
so this bug is dormant; the follow-up LibJS change exposes it.

Replace the memcmp branch with a per-code-unit loop, which the compiler
can auto-vectorize and which mirrors what is_code_unit_less_than already
does.
2026-04-22 19:12:54 +02:00
Andreas Kling
a6b9548b93 AK: Switch AllocatingMemoryStream to a singly-linked chunk list
The old implementation stored chunks in a Vector, which meant every
discard() had to call Vector::remove(0, N) to drop the consumed chunks
from the front, shifting every remaining chunk down. For a stream used
as a back-pressure queue, draining it by discarding one chunk at a time
was quadratic in the queued chunk count: in RequestServer that cost
about a second of CPU per large response.

Replace it with a singly-linked list of chunks (head, tail, head read
offset, tail write offset) so push-back and pop-front are both O(1)
and no shifting ever happens. Each chunk now holds its CHUNK_SIZE byte
array inline rather than a separately-allocated ByteBuffer, which also
halves the per-chunk allocations. Teardown unlinks iteratively to avoid
recursive OwnPtr destructors on very long chains.
2026-04-22 13:32:07 +02:00
Andreas Kling
612c61cc16 AK: Add AllocatingMemoryStream::peek_some_contiguous()
Expose the next contiguous range of readable bytes at the current read
offset without copying. This lets callers hand the underlying chunk
straight to write/send without round-tripping through a user-space
buffer, which is important when the stream is used as a back-pressure
queue and the total queued size can grow to many megabytes.
2026-04-22 13:32:07 +02:00
Tim Ledbetter
df34c626d8 AK: Avoid UAF for consecutive SinglyLinkedList removals
The iterator returned by SinglyLinkedList::remove() left `m_prev`
default-initialized to `nullptr`. If the caller removed another element
without first advancing, the previous node's next pointer was left
dangling to the freed node.

This caused a UAF in FinalizationRegistry's `remove_by_token()` when
two consecutive records shared an unregister token.
2026-04-21 18:09:29 +02:00
Undefine
e39a8719fd Meta: Move most dependency checks to check_for_dependencies.cmake
This file was here for quite a long while now. Let's finally move most
of the dependency checks to one centralized place.
2026-04-20 16:41:29 -06:00
Andreas Kling
0317007ee1 AK: Make short ASCII string literals compile-time constants
Make the _string, _fly_string, _utf16, and _utf16_fly_string UDL
operators constexpr, with a fast path for short (<= 7 byte) ASCII
literals that folds directly into an inline ShortString. Previously,
every "foo"_fly_string (and friends) involved an out-of-line call
into the string factory, even though the result is entirely known
at compile time.
2026-04-17 16:22:56 +02:00
Zaggy1024
3844edaaed AK: Avoid overflow in Duration::to_time_units() with fraction near 1
With numerators or denominators approaching NumericLimits<u32>::max(),
we could overflow in the sum of the remainder and the rounding
contribution. Instead, divide them separately and sum them afterward.
2026-04-16 15:08:27 -05:00
Zaggy1024
affbe61da0 AK: Simplify Duration::from_time_units and handle remainder overflow
Overflow could happen in the multiplication of the remainder seconds
back into time units. Instead, take a remainder of the time units from
the division and use that for the nanoseconds.
2026-04-16 15:08:27 -05:00
Andreas Kling
54f14609f4 LibWebView: Add a SQL history store
Add a HistoryStore abstraction with transient and persisted backends,
normalize recorded URLs, and skip non-browsable schemes.

Cover lookup and persistence in TestHistoryStore so history-driven
features can share one backend.
2026-04-16 21:01:28 +02:00
Andreas Kling
b23aa38546 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.
2026-04-08 09:57:53 +02:00
Tim Ledbetter
39585b1a00 AK: Don't convert encode_base64_impl() input to StringView
Since e47cdc6b, converting `ReadonlyBytes` to a `StringView` will crash
if the `ReadonlyBytes` given us empty. This caused a crash when calling
`btoa("")`, which called encode_base64() with an empty `ReadonlyBytes`.
We now don't convert the input from `ReadonlyBytes` to
`StringView`, which avoids this problem.
2026-03-31 18:14:28 +01:00
Sam Atkins
7781f1d131 AK: Allow creating a StringView from an empty ReadonlyBytes
An empty Span (and so ReadonlyBytes) can be created with a null data
pointer, which is no longer allowed for StringView. Detect that case
and use an empty string instead.
2026-03-31 19:01:10 +02:00
Shannon Booth
e47cdc6b63 AK: Remove public null state from StringView
Now that there are no callers of is_null left, Make default constructed
StringViews represent the empty string and disallow null pointers in the
public constructors, matching ByteString and String.

Keep a private null sentinel only for Optional<StringView>.
2026-03-31 13:48:50 +01:00
Shannon Booth
7ab9454f51 AK: Remove null state from Utf16View
The default constructor now initializes to an empty ASCII string rather
than a null pointer.

Also add a VERIFY in the utf16 constructor to assert the pointer is
non null, and remove the now unneeded is_null() method.
2026-03-31 13:48:50 +01:00
Undefine
9292c7bca9 AK: Move generating the Debug.h header to AK's CMakeLists 2026-03-29 13:59:11 -06:00
RubenKelevra
14a0f00400 AK: Guard JSON parser against deep nesting
Add a maximum nesting depth check in JsonParser so deeply nested
arrays/objects from untrusted input cannot blow the call stack.

Add regression tests for excessive nesting rejection and
reasonable nesting acceptance.
2026-03-27 14:29:43 +00:00
kalenikaliaksandr
70a1a9e82f AK: Apply empty base optimization to Variant on Windows
On the MSVC ABI (used by clang-cl), each empty base class is given a
unique address with 1 byte of padding by default. Variant inherits from
a deep chain of empty base classes (InheritFromPacks ->
InheritFromUniqueEntries -> VariantConstructors) for its inherited
constructor mechanism. Without __declspec(empty_bases), the pointer
adjustment in VariantConstructors::internal_cast() from the
VariantConstructors subobject back to the Variant base was computed
incorrectly due to accumulated padding, causing the constructor to write
m_data and m_index at wrong offsets and corrupting the stored object.

This manifested as heap corruption (STATUS_HEAP_CORRUPTION 0xc0000374)
whenever a Variant containing a large type (e.g. ByteCode at 240 bytes)
was destroyed after being constructed through the inherited constructor
path. In practice this crashed `new RegExp('a')` in LibJS on Windows,
preventing ~880 of ~1058 LibJS runtime tests from running.
2026-03-25 00:57:49 +01:00
Timothy Flynn
58791db818 AK+LibWeb: Move generation of random UUIDs into AK
This will let us use this more outside of LibWeb more easily.

Stop handling tiny OOM while we are here.
2026-03-24 12:04:50 -04:00
Andreas Kling
eb789e790e Everywhere: Use AK::SaturatingMath and remove Checked saturating APIs
Port all callers of Checked<T>::saturating_add/sub/mul to the new
standalone functions in AK/SaturatingMath.h, and remove the old
APIs from Checked.
2026-03-21 18:20:09 -05:00
Andreas Kling
31f816a6d8 AK: Add SaturatingMath.h with branchless saturating arithmetic
Add standalone saturating_add(), saturating_sub(), and
saturating_mul() free functions for integral types.

The signed implementations are fully branchless, using
__builtin_add/sub/mul_overflow combined with bitmask selection.
2026-03-21 18:20:09 -05:00
Jelle Raaijmakers
e123d48043 AK: Add SentinelOptional
We specialize `Optional<T>` for value types that inherently support some
kind of "empty" value or whose value range allow for a unlikely to be
useful sentinel value that can mean "empty", instead of the boolean flag
a regular Optional<T> needs to store. Because of padding, this often
means saving 4 to 8 bytes per instance.

By extending the new `SentinelOptional<T, Traits>`, these
specializations are significantly simplified to just having to define
what the sentinel value is, and how to identify a sentinel value.
2026-03-20 12:03:36 +01:00
Jelle Raaijmakers
9e245b014c AK: Simplify Optional<T> by using deducing this 2026-03-20 12:03:36 +01:00
Tim Ledbetter
972bcdeebe AK: Use correct relocation for all HashTable entry types
Robin Hood displacement and `delete_bucket()` shift-up used BucketType's
implicit move operations, which bitwise-copy the `u8` storage array
instead of going through T's move constructor and destructor. This
change adds `relocate_bucket()` and `swap_buckets()` helpers that use a
fast path for trivially-relocatable types and move-construct + destroy
for others.
2026-03-19 14:21:44 +01:00
Tim Ledbetter
0eb7012b57 AK: Add TypedTransfer<T>::relocate()
This moves objects from source to destination destructively, ensuring
the destructors are called if necessary.
2026-03-19 14:21:44 +01:00
Tim Ledbetter
8dd3c20436 AK: Add IsTriviallyRelocatable type trait 2026-03-19 14:21:44 +01:00
Zaggy1024
ae9537a53c AK: Use deducing this for AK::queue::head() and tail()
This allows us to grab these as mutable.
2026-03-17 18:58:37 -05:00
Andreas Kling
a141c2c492 LibWeb+AK: Use AK::Queue for the microtask queue
The microtask queue is a pure FIFO (enqueue at back, dequeue from
front) but was using a Vector, making every dequeue O(n) due to
element shifting.

Replace it with AK::Queue which has O(1) dequeue. This makes a huge
difference when processing large numbers of microtasks, e.g. during
async-heavy JavaScript workloads where each `await` generates a
microtask.

Also add a for_each() method to AK::Queue so the GC can visit the
queued tasks.
2026-03-16 09:38:20 +01:00
Undefine
c537bdf723 LibGfx: Add debug macro to enable Vulkan validation layers
Vulkan Validation Layers provides diagnostic feedback about Vulkan API
usage while live testing Ladybird. It is possible to enable this
diagnostic output without changing the code (using the Vulkan SDK),
but having it built into the code makes it very easy to enable whenever
required.

Co-authored-by: Rocco Corsi <5201151+rcorsi@users.noreply.github.com>
2026-03-04 22:27:40 +01:00
Zaggy1024
c78a98cc9c AK: Remove error passthrough from StackUnwinder
This isn't useful in Ladybird, we don't want to worry about fallible
allocations.
2026-03-03 11:26:42 -06:00
Zaggy1024
1609eb1f7a AK: Reintroduce StackUnwinder.h
This reverts commit fe9af7c972.

We can use this for the GC stack pointer resolution.
2026-03-03 11:26:42 -06:00
Zaggy1024
75aac67adb AK: Call AtomicRefCounted::deref_base() on the subclass
This allows adding logging for a specific class without a long rebuild.
2026-03-02 17:06:39 -06:00
Jelle Raaijmakers
7eafdcd454 AK: Simplify as_if<T> when fast_is<T> is unavailable
If `fast_is<T>` was not available but `static_cast<T>` was, we would
call into `is<T>` causing a `dynamic_cast` there, throwing away the
result and return a `static_cast`ed pointer.

We can encourage better codegen by checking for the presence of
`fast_is<T>` ourselves. This does not change anything for when
`fast_is<T>` is present, but if it's unavailable we now reduce
`as_if<T>` to a simple tailcall of `dynamic_cast<T>`.

Old:

```
stp  x20, x19, [sp, #-32]!
stp  x29, x30, [sp, #16]
add  x29, sp, #16
mov  x19, x0
adrp x1, typeinfo for Base@PAGE
add  x1, x1, typeinfo for Base@PAGEOFF
adrp x2, typeinfo for WithoutFastIs@PAGE
add  x2, x2, typeinfo for WithoutFastIs@PAGEOFF
mov  x3, #0
bl   ___dynamic_cast
cmp  x0, #0
csel x0, xzr, x19, eq
ldp  x29, x30, [sp, #16]
ldp  x20, x19, [sp], #32
ret
```

New:

```
adrp x1, typeinfo for Base@PAGE
add  x1, x1, typeinfo for Base@PAGEOFF
adrp x2, typeinfo for WithoutFastIs@PAGE
add  x2, x2, typeinfo for WithoutFastIs@PAGEOFF
mov  x3, #0
b    ___dynamic_cast
```
2026-02-27 11:42:38 -05:00
Undefine
a002bf5116 AK: Implement current_thread_id for FreeBSD
This allows displaying the current thread in the logs.
2026-02-26 19:52:49 -06:00
Undefine
9b229c96e0 AK: Fix handling of getting the current thread ID being unsupported
This previously would complain about formatting of AK::Empty which
obviously doesn't make sense.
2026-02-26 19:52:49 -06:00
Jelle Raaijmakers
2b78b84979 AK+Everywhere: Add and use weak_callback()
We have a common pattern of creating a `WeakPtr<T>` from a reference and
passing that into a lambda, to then take the strong ref when the lambda
is executed. Add `weak_callback(Weakable, lambda)` that returns a lambda
that only invokes the callback if a strong ref exists, and passes it as
the first argument.
2026-02-26 08:03:50 -05:00
Jelle Raaijmakers
3d0b2349e6 AK: Remove fallible and unused WeakPtr/Weakable methods 2026-02-26 08:03:50 -05:00
aplefull
d95baf67f6 LibJS: Prevent escaped surrogates from combining in Unicode regexes
Escaped surrogate sequences should not combine with adjacent literal
surrogates in Unicode mode.

We now use `\u{XXXX}` braces instead of `\uXXXX` when escaping code
units in Unicode mode, so LibRegex treats each as a standalone code
point. Also prevent GenericLexer from combining `\uXXXX` and `\u{XXXX}`.
2026-02-26 13:50:11 +01:00
Jelle Raaijmakers
f175a00003 AK: Add and use IdentityHashTraits<Integral>
These new traits are identical to `Traits<Integral>`, except that
calling `.hash()` will return the value itself instead of hashing it.
This should be used in cases where either the value is already a proper
hash, or using the value as a hash will yield "good enough" performance
in e.g. HashTable.

Types larger than 32 bits are folded in on themselves. Collision tests
on some popular hashing algorithms show that XOR folding slightly
increases the number of collisions, but this allows `IdentityHashTraits`
not to make any assumptions on which bits are the most relevant for the
final hash.
2026-02-24 13:24:58 +01:00
Timothy Flynn
3355fb39ae AK+LibJS: Replace home-grown Ryu implementation with fmt's dragonbox
In the benchmark added here, fmt's dragonbox is ~3x faster than our own
Ryu implementation (1197ms for dragonbox vs. 3435ms for Ryu).

Daniel Lemire recently published an article about these algorithms:
https://lemire.me/blog/2026/02/01/converting-floats-to-strings-quickly/

In this article, fmt's dragonbox implementation is actually one of the
slower ones (with the caveat that some comments note that the article is
a bit out-of-date). I've gone with fmt here because:

1. It has a readily available recent version on vcpkg.
2. It provides the methods we need to actually convert a floating point
   to decimal exponential form.
3. There is an ongoing effort to replace dragonbox with a new algorithm,
   zmij, which promises to be faster.
4. It is one of the only users of AK/UFixedBigInt, so we can potentially
   remove that as well soon.
5. Bringing in fmt opens the door to replacing a bunch of AK::format
   facilities with fmt as well.
2026-02-23 18:30:40 +01:00
Timothy Flynn
ac8c16dda6 AK: Add missing include to FloatingPoint.h
This would become an error in an upcoming commit.
2026-02-23 18:30:40 +01:00
Timothy Flynn
6bc66fe786 AK+LibGfx: Prefer if consteval over is_constant_evaluated
This is a new language construct in C++23, meant to generally replace
is_constant_evaluated. See:

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1938r3.html#problems-with-status-quo
2026-02-22 13:56:12 -05:00
Ben Wiederhake
389f43c47c AK: Remove unused header in Random 2026-02-21 19:27:35 +01:00
Shannon Booth
005aa1af62 AK: Prefer Optional<StringView> for String::bijective_base_from
Removing one more user of the null StringView state.
2026-02-21 12:37:44 +01:00
Shannon Booth
08a9646f46 AK: Remove uneeded null StringView handling for IP string parsing
A null StringView can be handled in the same way as an empty
StringView, so we can remove these conditionals.
2026-02-21 12:37:44 +01:00
R-Goc
945d7eb452 AK: Use builtin macro to get cache line size
We were previously using our own defines, however those didn't cover
various systems. This change makes AK_CACHE_ALIGNED use the destructive
interference size as defined by the compiler for the target platform.
2026-02-21 11:49:42 +01:00
Callum Law
50a9a8bfcb AK: Allow comparing ValueComparingRefPtr with nullptr 2026-02-20 22:01:44 +00:00
Callum Law
4f3303b12f AK: Use AK namespace for ValueComparingRefPtr
These were moved in 0f04c6d but the namespace remained the same. We also
now forward declare these in `AK/Forward.h` rather than
`LibWeb/Forward.h` (or not at all in the case of `ValueComparingRefPtr`)
2026-02-20 22:01:44 +00:00
Jelle Raaijmakers
a18722093d AK: Use power-of-two growth in HashTable
Measurements on my device have shown this to make lookups and inserts
faster by 30-40% on average, especially for larger number of buckets.
The memory cost is significant depending on the exact number of buckets,
increasing anywhere between 10% and 100% compared to the old way of
growing our capacity. The performance benefits still make this worth it,
in my opinion.
2026-02-20 22:47:24 +01:00
Jelle Raaijmakers
2522aad8b7 AK: Reduce HashTable's load factor to 70%
Measurements on my device have shown HashTable lookups and inserts to be
faster up to ~20%, at the cost of 10-20% more memory usage depending on
the exact amount of buckets.
2026-02-20 22:47:24 +01:00