Commit Graph

1177 Commits

Author SHA1 Message Date
Andreas Kling
99bef81d09 LibJS: Fast path for TypedArray.slice()
We now try to do a bulk memcpy() when possible. This is significantly
faster than going byte-at-a-time.
2025-12-01 15:12:52 +01:00
Andreas Kling
4d7d8aa827 LibJS: Allow fast conversions between Uint8Array and Uint8ClampedArray
These two typed array kinds have the same exact underlying data type and
differ only in how assignment works.

We can allow them to take the fast paths for same-type conversions.
2025-12-01 15:12:52 +01:00
Callum Law
1f7fe97ac3 LibJS/AK: Move XorShift128PlusRNG to AK
This will be useful for CSS random functions so it should be in a
reusable place.

This does require us to use `AK::get_random` instead of
`Crypto::get_secure_random`, but this is fine since the latter is in the
process of being removed (see #6564).
2025-12-01 11:00:33 +00:00
Rocco Corsi
11dc254d27 LibJS: Add missing internal object string printing for debugging
When testing with JS_BYTECODE_DEBUG macro defined or using the All_Debug
profile, internal objects were not known in Value class to the function
Value::to_string_without_side_effects leading to a VERIFICATION FAILED
when running the test-js or test-web programs.

Internal objects are known in the Value class as cells, and do not have
a dedicated tag to identify them. Internal objects are detected using
is_cell function call, but only after all other types have been
checked as other types of non-internal objects can also be cells.

Both the String and Utf16String version of the function were updated.
2025-11-30 19:22:46 +01:00
Luke Wilde
0eceee0a05 LibJS: Replace Array.fromAsync with a native JavaScript implementation
This allows us to use the bytecode implementation of await, which
correctly suspends execution contexts and handles completion
injections.

This gains us 4 test262 tests around mutating Array.fromAsync's
iterable whilst it's suspended as well.

This is also one step towards removing spin_until, which the
non-bytecode implementation of await uses.

```
Duration:
     -5.98s

Summary:
    Diff Tests:
        +4     -4 

Diff Tests:
    [...]/Array/fromAsync/asyncitems-array-add-to-singleton.js  -> 
    [...]/Array/fromAsync/asyncitems-array-add.js               -> 
    [...]/Array/fromAsync/asyncitems-array-mutate.js            -> 
    [...]/Array/fromAsync/asyncitems-array-remove.js            -> 
```
2025-11-30 11:54:54 +01:00
Luke Wilde
a63b0cfaba LibJS: Introduce NativeJavaScriptBackedFunction
This hosts the ability to compile and run JavaScript to implement
native functions. This is particularly useful for any native function
that is not a normal function, for example async functions such as
Array.fromAsync, which require yielding.

These functions are not allowed to observe anything from outside their
environment. Any global identifiers will instead be assumed to be a
reference to an abstract operation or a constant. The generator will
inject the appropriate bytecode if the name of the global identifier
matches a known name. Anything else will cause a code generation error.
2025-11-30 11:54:54 +01:00
Luke Wilde
899c6ebffc LibJS: Make stored realm in NativeFunction non-null
We now always have a realm for NativeFunction, which allows removing an
old hack in internal_call and internal_construct.
2025-11-30 11:54:54 +01:00
Luke Wilde
354888640d LibJS/Bytecode: Make compilation use SharedFunctionInstanceData instead
All the data we need for compilation is in SharedFunctionInstanceData,
so we shouldn't depend on ECMAScriptFunctionObject.

Allows NativeJavaScriptBackedFunction to compile bytecode.
2025-11-30 11:54:54 +01:00
Luke Wilde
2d15326f5d LibJS: Moved SharedFunctionInstanceData into separate files
This will allow it to be reused by NativeJavaScriptBackedFunction.
2025-11-30 11:54:54 +01:00
Tim Ledbetter
166c8b116f LibJS: Avoid cast to out-of-range value in MathObject::abs() fast path 2025-11-30 11:54:02 +01:00
Andreas Kling
2d76e21cfd LibJS: Don't use GC::Root unnecessarily in Error stack traces
This was causing a fair bit of root registration churn on pages that
throw lots of errors.

Since there's no need for these pointers to float around freely, we can
just visit them during the mark phase as usual.
2025-11-30 11:53:56 +01:00
Andreas Kling
c1c24e8fd6 LibJS: Use non-copying GetUint8ArrayBytes() in Uint8Array.toBase64()
If the ArrayBuffer we're looking at is non-shared, we can simply get a
view onto the underlying bytes and pass that to the Base64 encoder.
2025-11-29 09:39:43 -05:00
Andreas Kling
124b4fc06a LibJS: Limit the length of strings we put in the VM string cache
For excessively long strings, we often end up spending a ton of time
hashing and comparing them, and it basically ruins the value of the
cache as optimization.

This commit puts a cap (256) on the length of strings we put into the
cache. The number is arbitrary and there may be value in tuning it.
2025-11-29 09:39:43 -05:00
Andreas Kling
b6ef80ff36 LibJS: Avoid options object allocation in fromBase64() and toBase64()
When no options (or undefined) are passed into these APIs, the spec has
us synthesize a temporary "options object" to read the options from.

We don't actually need these objects, so let's sidestep the allocation
if we can (and just use the default values in that case).
2025-11-29 09:39:43 -05:00
Andreas Kling
b2761b5640 LibJS: Avoid redundant ByteBuffer in Uint8Array.fromBase64()
Since we already have a ByteBuffer from decoding the Base64 data, we can
pass that when creating a new ArrayBuffer.

This avoids a buffer allocation + memory clear + memory copy.
2025-11-29 09:39:43 -05:00
Tim Ledbetter
cfce5dc970 LibJS: Add fast path for loosely comparing object and nullish values 2025-11-26 22:03:31 -05:00
Tim Ledbetter
7ce103b96a LibJS: Demote VERIFY to ASSERT in JS value casting functions
This yields a ~3% performance increase across the board in JS
benchmarks.
2025-11-26 09:38:00 +01:00
Tim Ledbetter
e20e79e7a5 LibJS: Demote VERIFY in ThrowCompletionOr() to ASSERT
This improves JetStream performance by ~16% on my machine.
2025-11-25 08:38:23 +01:00
Tim Ledbetter
999656a7d3 LibJS: Add a localCompare() fast path for ASCII strings
When comparing ASCII strings we now use our own collation tables rather
than invoking ICU.
2025-11-24 00:22:10 +01:00
Tim Ledbetter
f268458aa4 LibJS: Add a localCompare() fast path for identical strings
When identical strings use the default collator, a simple equality
check can be used.
2025-11-24 00:22:10 +01:00
Timothy Flynn
37f49d5f6d LibJS: Use nanoseconds to normalize values in IsValidDuration
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/68004cc
https://github.com/tc39/proposal-temporal/commit/a6043aa
https://github.com/tc39/proposal-temporal/commit/1962c8b

Note that we were already performing this calculation using nanoseconds.
2025-11-21 13:52:55 +01:00
Timothy Flynn
8feabc3158 LibJS: Re-order infallible operations in GetDifferenceSettings
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/c11021a
2025-11-21 13:52:55 +01:00
Timothy Flynn
54b9ddcc80 LibJS: Use relative date in NudgeToCalendarUnit when comparing durations
This is a normative change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/17e12be

The test added here would previously crash.
2025-11-20 08:28:51 -05:00
Rocco Corsi
5fb78ae455 LibJS: Correct completion_cell typo in GeneratorObject 2025-11-17 23:43:04 +01:00
Andreas Kling
04238d0f3f LibJS: Make AsyncGenerator and GeneratorObject factories infallible
These should never fail.
2025-11-17 23:42:51 +01:00
Andreas Kling
d8f5971ddf LibJS: Allow constructing generator from function with null "prototype"
Fixes 4 test262 tests and simplifies some upcoming stuff.
2025-11-17 23:42:51 +01:00
Timothy Flynn
15e4deb831 LibJS: Remove "era" from Temporal's DateTimeFormat formatting options
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/0ecf157

The test added here would previously throw:

    TypeError: Unable to determine format for Temporal.PlainDate
2025-11-16 07:59:59 -05:00
Timothy Flynn
c7e4a99219 LibJS: Handle negativity in Temporal's ApplyUnsignedRoundingMode
I don't fully understand the BigInt math here, as the computation for
d1 and d2 don't align with the spec due to BigInt logic. This was
discussed a bit in SerenityOS's Discord some years ago:

https://discord.com/channels/830522505605283862/851522357734408232/978786665306918932

But some new tests in test262 indicate that we need to handle negative
values here, instead of just throwing away the sign.
2025-11-14 06:32:49 -05:00
Psychpsyo
100f37995f Everywhere: Clean up AD-HOC and FIXME comments without colons 2025-11-13 15:56:04 +01:00
Timothy Flynn
5c0fdd371a LibJS: Mark invocation to ParseMonthCode as infallible
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/c1f7bd5

Note the related assertion here was a bit silly. It was effectively:

    if (!cond) { return; }
    VERIFY(cond);
2025-11-12 16:20:04 -05:00
Timothy Flynn
041c4f4c79 LibJS: Remove unnecessary Temporal month code check
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/9110854

This change actually exposed a bug in our validator for month codes
(which is only used by this same function). We would previously allow
"M00" as a month code, which is invalid (it must be "M00L").
2025-11-12 16:20:04 -05:00
Timothy Flynn
bf3481b301 LibJS: Explicitly state integer limits for UTC offset minutes and ns
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/1fdf09a

Note that the integer limits in the above commit are in spec headers,
which we don't copy to our implementation.
2025-11-12 16:20:04 -05:00
Timothy Flynn
462e7b0c87 LibJS: Introduce Time Zone Identifier Parse Records to Temporal
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/96bb9b0

Note that we already had a struct for this, but now that it has a proper
name and spec link, this renames it to match other Parse Records and
places it alongside them.
2025-11-12 16:20:04 -05:00
Jelle Raaijmakers
cb333c53e7 LibJS: Remove unused NativeFunction::m_name_string 2025-11-12 14:39:14 +01:00
Andreas Kling
0dacc94edd LibJS: Have JS::Lexer take a JS::SourceCode as input
This moves the responsibility of setting up a SourceCode object to the
users of JS::Lexer.

This means Lexer and Parser are free to use string views into the
SourceCode internally while working.

It also means Lexer no longer has to think about anything other than
UTF-16 (or ASCII) inputs. So the unit test for parsing various invalid
UTF-8 sequences is deleted here.
2025-11-09 12:14:03 +01:00
Timothy Flynn
aff642053a LibJS: Set day field in CalendarYearMonthFromFields before resolution
This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/a8d38c6
2025-11-06 13:47:11 -05:00
Tim Ledbetter
30d9584746 LibJS: Use TypedTransfer<T>::copy() when possible in CopyDataBlockBytes
If neither block is a Shared Data Block we can use memcpy rather than
copying one byte at a time. Currently, we are using `memcpy`
unconditionally, as Shared Data Blocks are not yet supported in this
method.
2025-11-06 11:44:43 -05:00
Tim Ledbetter
ab00a4dc1f LibJS: Skip null entries in numeric string cache when gathering roots
This caused a crash when dumping the GC graph.
2025-11-04 10:34:43 +01:00
Aliaksandr Kalenik
646457099c LibJS: Avoid IteratorRecord GC-allocation in GetIterator instruction
With this change, `GetIterator` no longer GC-allocates an
`IteratorRecord`. Instead, it stores the iterator record fields in
bytecode registers. This avoids per-iteration allocations in patterns
like: `for (let [x] of array) {}`.

`IteratorRecord` now inherits from `IteratorRecordImpl`, which holds the
iteration state. This allows the existing iteration helpers
(`iterator_next()`, `iterator_step()`, etc.) operate on both the
GC-allocated and the register-backed forms.

Microbenchmarks:
1.1x array-destructuring-assignment-rest.js
1.226x array-destructuring-assignment.js
2025-11-02 20:05:47 +01:00
Andreas Kling
55636432e9 LibJS: Make ExecutionContext constructor ALWAYS_INLINE 2025-11-01 08:40:32 +01:00
Andreas Kling
8a02acbab6 LibJS: Make ExecutionContext::identifier_table a raw pointer
We were already skipping the bounds checks on this thing anyway,
so might as well shrink ExecutionContext by 8 bytes by doing this.
2025-11-01 08:40:32 +01:00
Andreas Kling
5b9469786e LibJS: Move ExecutionContext::cached_source_range to rare data 2025-11-01 08:40:32 +01:00
Andreas Kling
75d49c4b55 LibJS: Remove effectively unused value span from ExecutionContext
Instead of using this span, we can just use the getter that calculates
the base of the register/constant/local/argument array based on the
ExecutionContext's own address.
2025-11-01 08:40:32 +01:00
Andreas Kling
e1344afff3 LibJS: Move ExecutionContext::context_owner to rare data
This is only used by ExecutionContexts owned by an HTML::ESO.
2025-11-01 08:40:32 +01:00
Andreas Kling
8b1f2e4e24 LibJS: Remove unused ExecutionContext::local(size_t) 2025-11-01 08:40:32 +01:00
Andreas Kling
cd3ef805c4 LibJS: Avoid redundant bounds check in ExecutionContext::argument() 2025-11-01 08:40:32 +01:00
Andreas Kling
1e0b56586b LibJS: Move ExecutionContext members with destructors to "rare data"
This makes ExecutionContext trivially destructible, which means less
work to do on function exit.
2025-11-01 08:40:32 +01:00
Andreas Kling
9ded35f98f LibJS: Make CachedSourceRange GC-allocated
This gets rid of a RefPtr in ExecutionContext, bringing us one step
closer to destructor-less ExecutionContext.
2025-11-01 08:40:32 +01:00
Andreas Kling
2492c07430 LibJS: Remove redundant VERIFYs in running_execution_context()
Vector::last() will already verify that the context stack is non-empty.
2025-10-31 08:56:02 +01:00
Andreas Kling
5706831328 LibJS: Make run_executable() return simple ThrowCompletionOr<Value>
We don't need to return two values; running an executable only ever
produces a throw completion, or a normal completion, i.e a Value.

This necessitated a few minor changes, such as adding a way to check
if a JS::Cell is a GeneratorResult.
2025-10-31 08:56:02 +01:00