Commit graph

1108 commits

Author SHA1 Message Date
Andreas Kling
0e4450f4b3 LibJS: Avoid function call if @@hasInstance is default implementation
This makes the instanceof operator signficantly faster by avoiding a
generic function call to @@hasInstance unless it has been overridden.

1.15x speed-up on Octane/earley-boyer.js
2025-10-13 17:15:44 +02:00
Rocco Corsi
44d2a74eeb LibJS: Increase the stack limit when ASAN enabled
Linux, x86_64, Sanitizer, GNU runners on GitHub Action fail randomly
with a stack overflow on recursive test called:
Libraries/LibJS/Tests/runtime-error-call-stack-size.js
2025-10-13 09:07:39 -04:00
Andreas Kling
755c8d8cd6 LibJS: Sprinkle [[likely]] on the fast paths in ValueInlines.h
1.04x speed-up on JetStream/quicksort.c.js
2025-10-11 20:08:58 +02:00
Andreas Kling
38e224cd9f LibJS: Make overflowing arithmetic on 2x Int32 values faster
Instead of converting them to doubles and doing double math, just do the
arithmetic operation in i64 space instead.

This gives us a ~1.25x speed-up on this kind of micro-benchmark:

    (() => {
        let a = -2124299999;
        for (let i = 0; i < 100_000_000; ++i) {
            a + a;
        }
    })()

Same idea for Add, Sub, and Mul.

There's a fair bit of overflowing Int32 arithmetic in some of the
JetStream benchmarks, and this seems like an obvious improvement.
2025-10-07 18:28:26 +02:00
Andreas Kling
4d99f9f5d1 LibJS: Try to avoid a [[GetOwnProperty]] when setting Object property
The [[Set]] operation on objects will normally end up doing
[[GetOwnProperty]] twice, but if the object and the receiver are one on
the same, we can avoid the double work.

AFAIK this is not observable via proxies or other mechanisms.

1.10x speed-up on MicroBench/object-set-with-rope-strings.js
2025-10-07 11:34:19 +02:00
Andreas Kling
7a2fe53c65 Revert "LibJS: Use HashMap::ensure() in VM string cache helpers"
This reverts commit 5810ddf339.

Appears to have introduced flakiness on WPT.
2025-10-06 12:15:34 +02:00
Andreas Kling
5810ddf339 LibJS: Use HashMap::ensure() in VM string cache helpers
This cuts the number of hash lookups on cache hit from 2 to 1.
2025-10-05 21:44:06 +02:00
Andreas Kling
b691f4c7af LibJS: Add number-to-string cache for numbers < 1000
We are often forced to convert numbers to strings inside LibJS, e.g when
iterating over the property names of an array, but it's also just a very
common operation in general.

This patch adds a 1000-entry string cache for the numbers 0-999 since
those appear to be by far the most common ones we convert.
2025-10-05 21:44:06 +02:00
Andreas Kling
0c3f113e05 LibJS: Avoid some heap allocations in JSRopeString::resolve()
- Give piece vectors some inline capacity (for the common case of a+b)
- Pre-calculate the sum of UTF-16 code unit lengths for StringBuilder
2025-10-05 21:44:06 +02:00
Andreas Kling
15eb80cb5a LibJS: Prefer UTF-16 sources when resolving rope string to UTF-16 2025-10-05 16:39:14 +02:00
Andreas Kling
cc560a6feb LibJS: Avoid string ref-count churn in PrimitiveString::*_string_view() 2025-10-05 16:39:14 +02:00
Andreas Kling
24934ba479 LibJS: Make single-character ASCII string cache strings be Utf16String
Just another little step towards all strings being Utf16String.
2025-10-05 16:39:14 +02:00
Andreas Kling
792913e9f7 LibJS: Make PrimitiveString::create() take String/Utf16String by const&
This avoids unnecessary ref-count churn in the case where a string is
already in the VM's string cache.
2025-10-05 16:39:14 +02:00
Andreas Kling
0675c6e3cc LibJS: Make Value::to_utf16_string() avoid UTF-8 roundtrip if possible
To do this, it's not enough for to_utf16_string() to just be a wrapper
around to_string(), we have to duplicate some of the logic.
2025-10-05 16:39:14 +02:00
Timothy Flynn
400300945f LibJS: Fill all available space when TA.copyWithin shrinks the array
This is a normative change in the ECMA-262 spec. See:
d228070p
2025-10-03 09:03:40 +02:00
Timothy Flynn
a7e55f3024 LibJS: Explicitly prevent out-of-bounds access in String.lastIndexOf
This is a normative change in the ECMA-262 spec. See:
541b2f6

Note we already handled this case well, but let's update our impl to
match the latest spec text.
2025-10-03 09:03:40 +02:00
Timothy Flynn
a4991143e0 LibJS: Update spec links and steps for the U8Array base64/hex proposal
This proposal reached stage 4 and was merged into ECMA-262. See:
3dfa316
2025-10-03 09:03:40 +02:00
Timothy Flynn
a7e5fa2256 LibJS: Update spec links and steps for the Math.sumPrecise proposal
This proposal reached stage 4 and was merged into ECMA-262. See:
27172c8
2025-10-03 09:03:40 +02:00
Timothy Flynn
cb56ea7e24 LibJS: Update spec links and steps for the Error.isError proposal
This proposal reached stage 4 and was merged into ECMA-262. See:
caa0482
2025-10-03 09:03:40 +02:00
Timothy Flynn
979761ad82 LibJS: Implement WeakMap.prototype.getOrInsert[Computed]
This is part of the Upsert proposal:
https://github.com/tc39/proposal-upsert
2025-10-03 08:58:40 +02:00
Timothy Flynn
b6924309a0 LibJS: Implement Map.prototype.getOrInsert[Computed]
This is part of the Upsert proposal:
https://github.com/tc39/proposal-upsert
2025-10-03 08:58:40 +02:00
Timothy Flynn
7d4245cf8a LibJS: Remove unnecessary call to Value::to_string_without_side_effects
This is handled internally by the throw completion formatter.
2025-10-03 08:58:40 +02:00
Timothy Flynn
853e3ecf23 LibJS: Include the WeakMap key (not value) in non-weakable key errors
It is the key that cannot be held weakly, and thus the key that should
be include in the error message.
2025-10-03 08:58:40 +02:00
vedant-pandey
d082e7ec58 LibJS: Move Typed Array copyWithin optimization before index update
The optimization for non-shared ArrayBuffers operates on incorrect
values of from_byte_index and to_byte_index because they will have been
modified in the preceding steps. This causes the incorrect range to be
copied within the buffer.
2025-10-02 19:41:31 +02:00
Timothy Flynn
cb6ca85564 LibJS: Handle relativeTo ZDTs that fall within second DST wallclock time
This is a normative change in the Temporal proposal. See:
1a089eb
2025-09-28 11:33:43 -04:00
Aliaksandr Kalenik
e07bb32455 LibJS+LibWeb: Add Object::fast_is<Element>() 2025-09-26 16:21:18 +02:00
Aliaksandr Kalenik
88d8380920 LibJS: Add FunctionObject::fast_is<NativeFunction>() 2025-09-26 16:21:18 +02:00
Aliaksandr Kalenik
b549d51cdc LibJS: Add Object::fast_is<Set>() and Object::fast_is<Map>()
These are often hit by object serialization code path.
2025-09-26 16:21:18 +02:00
Aliaksandr Kalenik
aec20e032b LibJS: Add FunctionObject::fast_is<BoundFunction>() 2025-09-26 16:21:18 +02:00
Aliaksandr Kalenik
2a288f6d53 LibJS: Invalidate PrototypeChainValidity when prototype shape is a dict
Adds missing PrototypeChainValidity invalidation for add/set/delete
operations on dictionary-mode prototype shapes.
2025-09-22 18:41:23 +02:00
Aliaksandr Kalenik
451c947c3f LibJS: Fast-path own-property enumeration and reduce descriptor lookups
Before this change, PropertyNameIterator (used by for..in) and
`Object::enumerable_own_property_names()` (used by `Object.keys()`,
`Object.values()`, and `Object.entries()`) enumerated an object's own
enumerable properties exactly as the spec prescribes:
- Call `internal_own_property_keys()`, allocating a list of JS::Value
  keys.
- For each key, call internal_get_own_property() to obtain a
  descriptor and check `[[Enumerable]]`.

While that is required in the general case (e.g. for Proxy objects or
platform/exotic objects that override `[[OwnPropertyKeys]]`), it's
overkill for ordinary JS objects that store their own properties in the
shape table and indexed-properties storage.

This change introduces `for_each_own_property_with_enumerability()`,
which, for objects where
`eligible_for_own_property_enumeration_fast_path()` is `true`, lets us
read the enumerability directly from shape metadata (and from
indexed-properties storage) without a per-property descriptor lookup.
When we cannot avoid `internal_get_own_property()`, we still
benefit by skipping the temporary `Vector<Value>` of keys and avoiding
the unnecessary round-trip between PropertyKey and Value.
2025-09-21 15:06:32 +02:00
Timothy Flynn
5bd867f1dc LibJS: Revert inadvertent observable Temporal change
This is an editorial change in the Temporal proposal. See:
6274e5d
2025-09-19 11:24:02 -04:00
Jelle Raaijmakers
c31eff6a47 Everywhere: Use Optional<T>::ensure() where useful
No functional changes.
2025-09-17 12:01:18 -04:00
Aliaksandr Kalenik
d45f8a3081 LibJS: Add inline caching for adding new own properties to objects
We already had IC support in PutById for the following cases:
- Changing an existing own property
- Calling a setter located in the prototype chain

This was enough to speed up code where structurally identical objects
(same shape) are processed in a loop:
```js
const arr = [{ a: 1 }, { a: 2 }, { a: 3 }];
for (let obj of arr) {
    obj.a += 1;
}
```

However, creating structurally identical objects in a loop was still
slow:
```js
for (let i = 0; i < 10_000_000; i++) {
    const o = {};
    o.a = 1;
    o.b = 2;
    o.c = 3;
}
```

This change addresses that by adding a new IC type that caches both the
source and target shapes, allowing property additions to be fast-pathed
by directly jumping to the shape that already includes the new property.
2025-09-17 12:44:44 +02:00
Aliaksandr Kalenik
a54215c07d LibJS: Make internal_define_own_property() save added property offset
...in `PropertyDescriptor`. This is required for the upcoming change
that needs to know offset of newly added properties to set up inline
caching.
2025-09-17 12:44:44 +02:00
Aliaksandr Kalenik
85e029b2e7 LibJS+LibWeb: Inline fast path for Value::to_object()
Adds inline implementation for the most common case when `Value` is
already an object.

1.47x improvement on the following benchmark:
```js
const o = {};
for (let i = 0; i < 10_000_000; i++) {
    o.a = 1;
    o.b = 2;
    o.c = 3;
}
```
2025-09-15 12:16:58 +02:00
Ali Mohammad Pur
4462348916 Everywhere: Slap some [[clang::lifetimebound]] where appropriate
This first pass only applies to the following two cases:
- Public functions returning a view type into an object they own
- Public ctors storing a view type

This catches a grand total of one (1) issue, which is fixed in
the previous commit.
2025-09-01 11:11:38 +02:00
Andreas Kling
e5b07858a2 LibJS: Allocate Call{Construct,DirectEval,Builtin) contexts up front
We already do this for normal Call contexts, so this is just continuing
to propagate the same pattern to other instructions.

Fixes #6026
2025-08-31 15:24:37 +02:00
Luke Wilde
b17783bb10 Everywhere: Change west consts caught by clang-format-21 to east consts 2025-08-29 18:18:55 +01:00
Timothy Flynn
2fa6655dcb LibJS: Ensure NudgeToCalendarUnit is given a non-zero duration sign
Otherwise, we trip internal Temporal spec assertions.

This is an editorial change in the Temporal spec. See:
30f8575
2025-08-29 01:14:20 +02:00
Timothy Flynn
0c038bf12e LibJS: Read user options in a Temporal AO sooner
This is a normative change in the Temporal proposal. See:
9924aa4
2025-08-29 01:14:20 +02:00
Timothy Flynn
355589a89e LibJS: Read user options in some Temporal toString methods sooner
This is a normative change in the Temporal proposal. See:
3eaaadf
2025-08-29 01:14:20 +02:00
ayeteadoe
6dbb59da77 LibJS: Export symbols causing linker errors in various consumers
After LibJS had its symbol exports optimized the targets
js, test-js, test262-runner, test-wasm, and LibWeb began to get linker
errors after the work to add Windows support for test-web and ladybird
targets. These extra JS_API annotations fix all those linker errors.
2025-08-23 16:04:36 -06:00
ayeteadoe
0a699132f3 WebContent: Enable in Windows CI 2025-08-23 16:04:36 -06:00
Idan Horowitz
66bd7fa530 LibJS: Add missing visit of Realm::m_builtins 2025-08-23 21:21:04 +02:00
CountBleck
a2dc6c4bbb LibJS: Keep the lengths of ArrayBuffers with unowned ByteBuffers fixed
The relevant type of ArrayBuffer DataBlock is now a struct containing
both a ByteBuffer* and a size_t size, and not just a ByteBuffer*, with
the size being that of the ByteBuffer. This type of DataBlock is only
used for WebAssembly.Memory (see commit 4fd43a8f96), meaning this
change won't affect any other code. This change is required to pass one
WPT subtest in wasm/jsapi/memory/grow.any.html, since old fixed-length
SharedArrayBuffers after a WebAssembly.Memory growth should keep their
length, while the new buffer after the growth will have the updated
length.
2025-08-23 08:26:23 +02:00
Timothy Flynn
5ec70bd00a Revert "LibJS: Revert common error types to only hold a single string"
This reverts commit 695bbcb991.

Despite improving performance on my Linux machine, this managed to tank
performance on the Linux benchmark machine.
2025-08-18 13:42:22 +02:00
Timothy Flynn
695bbcb991 LibJS: Revert common error types to only hold a single string
Before porting to UTF-16, these instances held a String. The port to
UTF-16 changed them to hold the original string as a StringView, and
lazily allocated the UTF-16 message as needed. This somehow negatively
impacting the zlib.js benchmark in the Octane suite.
2025-08-18 01:43:45 +02:00
Tete17
08284e0ef6 LibJS: Implement console.dirxml
This function actually gets tested in WPT.
2025-08-17 07:28:56 -04:00
Timothy Flynn
e314ca5e9d LibJS: Introduce ParseMonthCode and CreateMonthCode Temporal AOs
This is an editorial change in the Temporal proposal. See:
28357ea
32f4b02
f860ac6
e6f565d
2025-08-14 11:35:28 -04:00