10 Commits
Author SHA1 Message Date
Lucas CHOLLET f3f6de2b27 LibJS: Prefer strict_lower_bound() over binary_search() 2025-04-13 17:42:52 -04:00
Lucas CHOLLETandNico Weber d012289263 AK+LibJS+LibWeb: Make binary_search() return the first occurrence
Given `{1, 2, 2, 2, 2, 2, 2, 3}` and the needle being `2`, the function
used to return the first matching element that it found (at index 3). It
now continues the search until it founds the first one, here at index 1.

Note that one side effect of that change is that when the binary search
fails, `nearby_index` now gives you the index right after instead of the
one before. The changes in LibJS and LibWeb are needed because of that.

Co-authored-by: Nico Weber <[email protected]>
2025-04-13 17:42:52 -04:00
Jonne Ransijn 8b68800a8d LibJS: Cache source code positions more often
The source code position cache was moved from a line based approach
to a "chunk"-based approach to improve performance on large, minified
JavaScript files with few lines, but this has had an adverse effect
on _multi-line_ source files.

Reintroduce some of the old behaviour by caching lines again, with
some added sanity limits to avoid caching empty/overly small lines.

Source code positions in files with few lines will still be cached
less often, since minified JavaScript files can be assumed to be
unusually large, and since stack traces for minified JavaScript
are less useful as well.

On WPT tests with large JavaScript dependencies like
`css/css-masking/animations/clip-interpolation.html` this reduces the
amount of time spent in `SourceCode::range_from_offsets` by as much as
99.98%, for the small small price of 80KB extra memory usage.

(cherry picked from commit 1b3f8e1e9ad14f0777188bd6eba06e42ffd98961)
2024-12-21 14:58:20 -05:00
Andreas Kling 44b2735b9e LibJS: Make line-and-column resolution fast for large minified JS
Instead of caching start-of-line offsets, we now cache byte offsets
at regular intervals. This fixes an issue where we had terrible
performance on large minified JS, since that often means one very,
VERY long line (with no line endings to cache).

My machine was spending ~35ms per stack frame when throwing errors
on some heavy minified websites, and after this patch, we now spend
<1ms per stack frame.
2023-09-12 17:21:42 +02:00
Andreas Kling bd5d8e9d35 LibJS: Make RefPtr and NonnullRefPtr usage const-correct
This mainly affected the AST, which is now const throughout.
2023-02-21 00:54:04 +01:00
Evan Smal 93674e4383 LibJS: Remove DeprecatedString usage from SourceCode
This change also requires updates to some users of the SourceCode
interface since it no longer use DeprecatedString.
2023-01-26 20:25:25 +00:00
Linus Groh 6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Andreas Kling c922d21ecb LibJS: Unbreak test262-parser-tests after source range caching changes
Turns out we have to be a little more lenient when dealing with the
slightly hostile inputs in tests262-parser-tests.

This fix papers over some problematic situations by returning a fallback
range if we can't figure out exactly where an error occurred.
I've added a FIXME about returning nicer values.
2022-11-24 18:01:52 +01:00
Andreas Kling f0482b61bf LibJS: Make Error stack trace generation faster with a line break cache
Generating Error objects got a lot slower after the introduction of
SourceCode in b0b022507b.

This was noticeable with `test-js` which generates a lot of errors,
so walking the source code over and over to compute (line, column)
was eating a ton of time.

This patch makes repeated lookups a lot faster by building a cache
of line break offsets in the source code. The cache is built on first
offset lookup, so we only pay for this in code that actually throws.

On my machine, this takes `test-js` runtime from 6.7 sec to 4.3 sec.
2022-11-24 16:06:20 +00:00
Andreas Kling b0b022507b LibJS: Reduce AST memory usage by shrink-wrapping source range info
Before this change, each AST node had a 64-byte SourceRange member.
This SourceRange had the following layout:

    filename:       StringView (16 bytes)
    start:          Position (24 bytes)
    end:            Position (24 bytes)

The Position structs have { line, column, offset }, all members size_t.

To reduce memory consumption, AST nodes now only store the following:

    source_code:    NonnullRefPtr<SourceCode> (8 bytes)
    start_offset:   u32 (4 bytes)
    end_offset:     u32 (4 bytes)

SourceCode is a new ref-counted data structure that keeps the filename
and original parsed source code in a single location, and all AST nodes
have a pointer to it.

The start_offset and end_offset can be turned into (line, column) when
necessary by calling SourceCode::range_from_offsets(). This will walk
the source code string and compute line/column numbers on the fly, so
it's not necessarily fast, but it should be rare since this information
is primarily used for diagnostics and exception stack traces.

With this, ASTNode shrinks from 80 bytes to 32 bytes. This gives us a
~23% reduction in memory usage when loading twitter.com/awesomekling
(330 MiB before, 253 MiB after!) :^)
2022-11-22 21:13:35 +01:00