Commit graph

1793 commits

Author SHA1 Message Date
Luke Wilde
d0ef1aad2d LibJS/Bytecode: Merge adjacent exception handlers
For example, this:
```
Exception handlers:
    from  678 to  698 handler  658 finalizer    0
    from  698 to  6f8 handler  658 finalizer    0
    from  6f8 to  708 handler  658 finalizer    0
    from  708 to  750 handler  658 finalizer    0
    from  750 to  788 handler  658 finalizer    0
    from  788 to  7a0 handler  658 finalizer    0
    from  7a0 to  7a8 handler  658 finalizer    0
```

Becomes:
```
Exception handlers:
    from  678 to  7a8 handler  658 finalizer    0
```
2025-11-07 09:57:06 +01:00
Timothy Flynn
aff642053a LibJS: Set day field in CalendarYearMonthFromFields before resolution
This is an editorial change in the Temporal proposal. See:
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
4bcb34d7a0 Revert "LibJS: Allocate callee execution contexts in call instruction handler"
This reverts commit cdcbbcf48b.

It made MicroBench/call-*-args.js faster, but some of the macro
benchmarks got significantly slower on macOS, so let's revert until we
understand it better.
2025-11-01 13:07:53 +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
3ef55f8859 LibJS: Only assign initial "accumulator" value if actually provided 2025-11-01 08:40:32 +01:00
Andreas Kling
6f9d297c3c LibJS: Coerce empty completion to "undefined" early in Interpreter
Instead of always checking if we're about to return an empty completion
value in Interpreter::run_executable(), we now coerce empty completions
to the undefined value earlier instead.

This simplifies the most common path through run_executable(), giving us
a small speedup.
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
13e1881bf7 LibJS: Store length of Call instructions in a member variable
This means we don't have to do a bunch of math to find the next
instruction boundary, and gives us a small speedup.
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
Timothy Flynn
583164e412 Meta: Upgrade prettier to version 3.6.2
This version is installed by default nowadays and has slight differences
from 3.3.3.
2025-10-31 19:55:50 -04:00
Timothy Flynn
019c529c07 Meta: Increase the line length enforced by prettier to 120
This matches our coding style recommendation in CodingStyle.md, and
matches our python formatting.
2025-10-31 19:55:50 -04: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
1796089f29 LibJS: Demote a VERIFY in run_executable() to ASSERT 2025-10-31 08:56:02 +01:00
Andreas Kling
62781f4818 LibJS: Use return_value register for "last completion" return values
This simplifies the epilogue in run_executable().
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
Andreas Kling
6671cbef41 LibJS: Precompute the number of regs/constants/locals in Executable
Instead of doing it again on every call. Minor bump in call performance.
2025-10-30 08:54:45 +01:00
Andreas Kling
cdcbbcf48b LibJS: Allocate callee execution contexts in call instruction handler
By handling call instructions in an inline (C++) function, we were
breaking the alloca() optimization and adding stack overhead. We fix
this by using a macro instead. It looks awful but it works.

1.07x speedup on MicroBench/call-00-args.js
2025-10-30 08:54:45 +01:00
Andreas Kling
667354fd12 LibJS: Always assume module bindings access is in strict mode
Modules are always in strict mode anyway, no need to look at the
strictness flag here.
2025-10-30 08:54:45 +01:00
Andreas Kling
9dae1acc31 LibJS: Pass ExecutionContext to Interpreter::run_executable()
This avoids having to get it from the VM's context stack, since most
callers already have it on hand.
2025-10-29 21:20:10 +01:00
Andreas Kling
a7d13b107e LibJS: Move all per-frame state from Interpreter to ExecutionContext
This simplifies function entry/exit and lets us just walk away from the
used ExecutionContext instead of resetting a bunch of its state when
returning control to the caller.
2025-10-29 21:20:10 +01:00
Andreas Kling
59ce6c9b41 LibJS: Shrink two u64 fields in ExecutionContext to u32
To shrink ExecutionContext, these two fields are made 32-bit:

- skip_when_determining_incumbent_counter
- program_counter
2025-10-29 21:20:10 +01:00
Andreas Kling
4c7ffc0552 LibJS: Remove ExecutionContext::function_name field
Instead of having ExecutionContext track function names separately,
we give FunctionObject a virtual function that returns an appropriate
name string for use in call stacks.
2025-10-29 21:20:10 +01:00
Andreas Kling
e967631763 LibJS: Remove ExecutionContext::arguments_offset and just compute it 2025-10-29 21:20:10 +01:00
Andreas Kling
fdb85a330e LibJS: Stop tracking whether execution context is strict mode or not
This was only used for basic testing, and forced us to plumb this flag
flag in a bunch of places.
2025-10-29 21:20:10 +01:00
Andreas Kling
fb05063dde LibJS: Let bytecode instructions know whether they are in strict mode
This commits puts the strict mode flag in the header of every bytecode
instruction. This allows us to check for strict mode without looking at
the currently running execution context.
2025-10-29 21:20:10 +01:00
Andreas Kling
3fb678b376 LibGC: Delete operators ! and bool from GC::Ref
The GC::Ref smart pointer is always non-null, so there's no need for it
to be convertible to bool.

This exposed a small number of unnecessary null checks which we remove.
2025-10-29 21:20:10 +01:00
Andreas Kling
9312a9f86f LibJS: Move InstantiateOrdinaryFunctionExpression into interpreter
This is execution time stuff and doesn't belong in the AST.
2025-10-27 21:14:33 +01:00
Andreas Kling
44fa9566a8 LibJS: Generate bytecode for the BlockDeclarationInstantiation AO
This necessitated adding some new instructions for creating mutable and
immutable bindings.
2025-10-27 21:14:33 +01:00
Andreas Kling
892c7d980e LibJS: Let JS::Script remember whether its code is strict mode
We don't want to rely on having the AST node just to answer the question
"is this script strict mode?"
2025-10-27 21:14:33 +01:00
Andreas Kling
b712caf855 LibJS: Move bytecode executable cache to SharedFunctionInstanceData
This shrinks every Statement and ECMAScriptFunctionObject by one
pointer, and puts the bytecode cache in the only place that actually
makes use of it anyway: functions.
2025-10-27 21:14:33 +01:00
Andreas Kling
3a38040c82 LibJS: Make SharedFunctionInstanceData GC-allocated 2025-10-27 21:14:33 +01:00
aplefull
5632a52531 LibRegex: Properly track code units in u-v modes
Previously, both string_position and view_index used code unit offsets
regardless of mode. Now in unicode mode, these variables track code
point positions while string_position_in_code_units is properly
updated to reflect code unit offsets.
2025-10-24 21:23:06 +02:00
aplefull
cd4ac4f30f LibJS: Escape line terminators in regex source 2025-10-24 13:24:55 -04:00
aplefull
7ce4abe330 LibRegex+LibUnicode: Add unicode string properties 2025-10-24 13:24:55 -04:00
Luke Wilde
d4deafe5fe LibJS: Track current shape dictionary generation in PropertyLookupCache
When an object becomes too big (currently 64 properties or more), we
change its shape to a dictionary and don't do any further transitions.

However, this means the Shape of the object no longer changes, so the
cache invalidation check of `current_shape != cache.shape` is no longer
a valid check.

This fixes that by keeping track of a generation number for the Shape
both on the Shape object and in the cache, allowing that to be checked
instead of the Shape identity. The generation is incremented whenever
the dictionary is mutated.

Fixes stale cache lookups on Gmail preventing emails from being
displayed.

I was not able to produce a reproduction for this, plus the generation
count was over the 20k mark on Gmail.
2025-10-24 15:35:04 +02:00
Luke Wilde
a21d247b0e LibJS: Actually mark uncacheable dictionary shapes as uncacheable 2025-10-24 15:35:04 +02:00
caztanj
e93f44112d LibJS: Do not verify cycle root's status is linked in CyclicModule
This VERIFY is both incorrect and redundant. The VERIFY at step 2
verifies the status when evaluate is called on m_cycle_root.
2025-10-22 11:54:56 +02:00
Feng Yu
61c36e2865 LibJS: Sync additional Import Attributes spec changes
Some steps were not updated with tc39/ecma262#3057. This patch
syncs the remaining changes.
2025-10-22 10:58:19 +02:00
Andreas Kling
7ee8645b9c LibJS: Avoid redundant GC::Weak checks in hot inline cache code paths
By copying out pointees to a temporary, we can avoid some redundant
pointer chasing inside GC::Weak when hitting our inline caches.
2025-10-17 17:22:16 +02:00
Andreas Kling
dfa796a4e4 LibJS+LibWeb: Use GC::Weak instead of AK::WeakPtr for GC-allocated types
This makes some common types like JS::Object smaller (by 8 bytes) and
yields a minor speed improvement on many benchmarks.
2025-10-17 17:22:16 +02:00
aplefull
4b989b8efd LibRegex: Add support for forward references to named capture groups
This commit implements support for forward references to named capture
groups. We now allow patterns like \k<name>(?<name>x) and
self-references like (?<name>\k<name>x).
2025-10-16 16:37:54 +02:00