1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-15 10:04:59 +00:00
Commit graph

5099 commits

Author SHA1 Message Date
Andreas Kling
3d92c26445 LibJS: Stop making shapes unique
We previously had a concept of unique shapes, which meant that they
couldn't be shared between multiple objects.

Object shapes became unique in three situations:

- They were the shape of the global object.
- They had more than 100 properties added to them.
- They had one or more properties deleted from them.

Unfortunately, unique shapes presented an annoying problem for inline
caches, and we added a "unique shape serial number" for being able to
tell that a unique shape had been mutated.

This patch gets rid of the concept of unique shapes, simplifying all
the caching code, since inline caches can now simply perform a shape
check and then we're good.

To make this possible, we now have the concept of delete transitions,
which occur when a property is deleted from a shape.

Note that this patch by itself introduces a performance regression in
some situtations, since we now create a lot more shapes, and marking
their property keys can be very heavy. This will be addressed in a
subsequent patch.
2023-12-11 20:36:15 +01:00
Andreas Kling
ef86cf4646 LibJS: Mark forward shape transition keys
These should really be weakly held by the Shape, but we don't have a
mechanism for weak hashmap keys at the moment, so let's just mark
these for now so they don't go stale.
2023-12-11 20:36:15 +01:00
Aliaksandr Kalenik
6ac43274b2 LibWeb+LibJS: Use JS::GCPtr for pointers to GC-allocated objects
Fixes warnings found by LibJSGCVerifier
2023-12-11 16:55:25 +01:00
Andreas Kling
37b5c05ec5 LibJS: Add fast path for Uint8ClampedArray Get/Put
These are just like Uint8Array, except Put values have to be clamped
in the 0..255 range.

Takes CPU usage from 40% to 30% on the "Canvas Cycle" demo at
http://www.effectgames.com/demos/canvascycle/ :^)
2023-12-10 13:49:00 +01:00
Andreas Kling
463931384d LibJS: Don't use Handle<Value> for JS::Object private fields
There's no reason to use handles here, we can just mark private element
values from objects that store them.
2023-12-10 09:44:26 +01:00
Andreas Kling
d8be9ebc16 LibJS: Add fast path in ArrayIteratorPrototype::next()
When iterating over vanilla objects/arrays with normal property storage,
we can skip the generic Get mechanism in favor of looking directly at
property storage. This is essentially what we do in the bytecode path.
2023-12-09 00:20:25 +01:00
Andreas Kling
373ec387c1 LibJS: Add fast_is<ArrayIterator>() 2023-12-09 00:20:25 +01:00
Andreas Kling
73ceb475b9 LibJS: Add fast path for magical "length" property in LengthOfArrayLike
For Array objects, we can avoid a generic Get here since we know it has
magical "length" behavior anyway.
2023-12-09 00:20:25 +01:00
Andreas Kling
f47a14b9d6 LibJS: Use a premade shape when creating iterator result objects
Instead of going through the steps of creating an empty new object,
and adding two properties ("value" and "done") to it, we can pre-bake
a shape object and cache the property offsets.

This makes creating iterator result objects in the runtime much faster.

47% speedup on this microbenchmark:

    function go(a) {
        for (const p of a) {
        }
    }
    const a = [];
    a.length = 1_000_000;
    go(a);
2023-12-08 00:54:05 +01:00
Jesús (gsus) Lapastora
706710fa13 LibJS/JIT: Make generating GDB images opt-in
Since generating GDB image can be expensive, it is disabled by default
and can be activated by setting the `LIBJS_JIT_GDB` environment
variable.
2023-12-07 15:34:38 -07:00
Jesús (gsus) Lapastora
f0b984567a LibJS/JIT: Produce & register an ELF image for GDB JIT Interface
Using the code that it has just produced, the JIT::Compiler can build an
ELF image so that we can attach meaningful symbols to JITted code, and
thus enable GDB to display more information about the code that we're
running.
2023-12-07 15:34:38 -07:00
Dan Klishch
96d44b1572 Userland: Make bit-fields compatible with MSVC C++ ABI 2023-12-07 10:28:19 -07:00
Andreas Kling
350e6c54d7 LibJS: Remove dedicated iterator result instructions in favor of GetById
When iterating over an iterable, we get back a JS object with the fields
"value" and "done".

Before this change, we've had two dedicated instructions for retrieving
the two fields: IteratorResultValue and IteratorResultDone. These had no
fast path whatsoever and just did a generic [[Get]] access to fetch the
corresponding property values.

By replacing the instructions with GetById("value") and GetById("done"),
they instantly get caching and JIT fast paths for free, making iterating
over iterables much faster. :^)

26% speed-up on this microbenchmark:

    function go(a) {
        for (const p of a) {
        }
    }
    const a = [];
    a.length = 1_000_000;
    go(a);
2023-12-07 18:12:24 +01:00
Andreas Kling
4699c81fc1 LibJS: Stop converting between Object <-> IteratorRecord all the time
This patch makes IteratorRecord an Object. Although it's not exposed to
author code, this does allow us to store it in a VM register.

Now that we can store it in a VM register, we don't need to convert it
back and forth between IteratorRecord and Object when accessing it from
bytecode.

The big win here is avoiding 3 [[Get]] accesses on every iteration step
of for..of loops. There are also a bunch of smaller efficiencies gained.

20% speed-up on this microbenchmark:

    function go(a) {
        for (const p of a) {
        }
    }
    const a = [];
    a.length = 1_000_000;
    go(a);
2023-12-07 14:06:34 +01:00
Andreas Kling
c9f0f0fc70 LibJS: Elide empty lexical environment in for..in/of blocks
When all the variables in a for..in/of block's lexical scope have been
turned into locals, we don't need to create and immediately abandon an
empty environment for them.

This avoid environment allocation in cases like this:

    function foo(a) {
        for (const x of a) {
        }
    }
2023-12-07 10:52:57 +01:00
Andreas Kling
a2c3db8367 LibJS: Add basic support for module code with top-level await
For now, we handle this by creating a synthetic async function to wrap
the top-level module code. This allows us to piggyback on the async
function driver wrapper mechanism.
2023-12-06 12:58:04 +01:00
Andreas Kling
26c21fba8e LibJS: Use LoadRequestedModules in the ad-hoc module loading path
This ensures that modules go through the expected state transitions,
fixing hundreds of test262 tests.
2023-12-06 12:58:04 +01:00
Andreas Kling
d7005be768 LibJS: Update CyclicModule to match current spec
Just some minor comment tweaks and an updated assertion.
2023-12-06 12:58:04 +01:00
Andreas Kling
58294db294 LibJS: Add successfully loaded modules to the VM's stored module list
This ensures that repeated loads of the same module succeed. (There is a
specific criteria where the same exact module object has to be returned
for multiple loads of the same referrer + specifier.)

Note that we don't check the referrer at the moment, that's a FIXME.
2023-12-03 20:46:55 +01:00
Andreas Kling
99106df834 LibJS: Update import referrer's [[LoadedModules]] in place
We were previously updating a copy of the list, which meant loading
could not proceed even after a module was loaded.
2023-12-03 20:46:55 +01:00
Andreas Kling
5e67853b49 LibJS: Fix logic typo in ContinueModuleLoading 2023-12-03 20:46:55 +01:00
Andreas Kling
fc31a0d506 LibJS: Support LoadRequestedModule AO on SyntheticModule records
This allows test-js to run all the module tests in the new world.
2023-12-03 20:46:55 +01:00
Andreas Kling
4b1053e327 LibJS: Fix logic typo in CyclicModule::inner_module_linking()
The comment was right, but the code didn't match.
2023-12-03 20:46:55 +01:00
Andreas Kling
8b7d27b349 LibJS+LibWeb: More bringing module loading closer to spec
In particular, this patch removes three host hooks on JS::VM in favor
of the new JS-side module loading stuff.
2023-12-03 20:46:55 +01:00
Andreas Kling
07f567cd9f LibJS+LibWeb: Another round of bringing module loading closer to spec
In particular, this patch focuses on:
- Updating the old "import assertions" to the new "import attributes"
- Allowing realms as module import referrer
2023-12-03 20:46:55 +01:00
Andreas Kling
82977ab44b LibJS: Implement GetImportedModule and call it where appropriate
This breaks module loading temporarily while transitioning.
2023-12-03 20:46:55 +01:00
Andreas Kling
a24c543921 LibJS: Update spec steps & add missing assertions in ResolveExport 2023-12-03 20:46:55 +01:00
Andreas Kling
40d2560a93 LibJS: Update spec steps & add missing assertions in GetExportedNames 2023-12-03 20:46:55 +01:00
Andreas Kling
467a5ceb18 LibJS: Split big VERIFY conditions into smaller ones in CyclicModule
This makes assertion failures here more informative.
2023-12-03 20:46:55 +01:00
Andreas Kling
0817d8bda6 LibJS+LibWeb: Make CyclicModule & GraphLoadingState GC-allocated
This allows them to participate in the ownership graph and fixes a
lifetime issue in module loading found by ASAN.

Co-Authored-By: networkException <networkexception@serenityos.org>
2023-12-03 20:46:55 +01:00
Andreas Kling
aa7501a66a LibJS: Set initial state of CyclicModule.[[Status]] to NEW
This is what the specification tells us to do:
https://tc39.es/ecma262/#cyclic-module-record

Co-Authored-By: networkException <networkexception@serenityos.org>
2023-12-03 20:46:55 +01:00
Todderod
e335354b30 LibJS: Call builtins directly in the bytecode interpreter
Allows the bytecode interpreter to call the builtins c++
implementation directly without making a javascript call
just as the JIT.

Kraken test speedups: imaging-gaussian-blur.js (1.5x) and
audio-oscillator.js (1.2x)
2023-12-01 13:01:26 +01:00
Timothy Flynn
026363024f LibJS: Stub out Atomics.notify
We don't have the facilities to implement this method fully (namely, a
fully realized SharedArrayBuffer). But we can implement enough to
validate the values passed in by the user.
2023-11-30 09:51:46 -05:00
Timothy Flynn
78edaad97d LibJS: Stub out Atomics.wait and Atomics.waitAsync
We don't have the facilities to implement these methods fully (namely, a
fully realized SharedArrayBuffer). But we can implement enough to
validate the values passed in by the user.
2023-11-30 09:51:46 -05:00
Timothy Flynn
a7073c3f1f LibJS: Skip test262 tests with the CanBlockIsFalse flag
From test262 documentation, this flag means:

    The test file should only be run when the [[CanBlock]] property of
    the Agent Record executing the file is `false`.

This patch stubs out the accessor for that internal slot and skips tests
with the CanBlockIsFalse if that internal slot is true.
2023-11-30 09:51:46 -05:00
Andreas Kling
be8952b89d LibJS: Remove pointless Vector copy in FDI 2023-11-29 09:48:18 +01:00
Andreas Kling
aaa7b50f06 LibJS: Skip lexical declaration traversal in FDI if there are none 2023-11-29 09:48:18 +01:00
Andreas Kling
3b6785245f LibJS: Don't call shrink_to_fit() on same environment twice in FDI 2023-11-29 09:48:18 +01:00
Andreas Kling
3fc0333ee6 LibJS: Put Bytecode::CallFrame + register slots in a single allocation
The number of registers in a call frame never changes, so we can
allocate it at the end of the CallFrame object and save ourselves the
cost of allocating separate Vector storage for every call frame.
2023-11-29 09:48:18 +01:00
Andreas Kling
3dc5f467a8 LibJS: Always allocate ExecutionContext objects on the malloc heap
Instead of allocating these in a mixture of ways, we now always put
them on the malloc heap, and keep an intrusive linked list of them
that we can iterate for GC marking purposes.
2023-11-29 09:48:18 +01:00
Andreas Kling
845da3901d LibJS: Make ExecutionContext::function_name a GCPtr<PrimitiveString>
This required setting things up so that all function objects can plop
a PrimitiveString there instead of an AK string.

This is a step towards making ExecutionContext easier to allocate.
2023-11-29 09:48:18 +01:00
Andreas Kling
eda2a6d9f7 LibJS: Don't die when making PrimitiveString from "" DeprecatedFlyString 2023-11-29 09:48:18 +01:00
Andreas Kling
ecfcc9aef3 LibJS: Make Bytecode::Executable GC-allocated
This is a step towards making ExecutionContext easier to allocate.
2023-11-29 09:48:18 +01:00
Andreas Kling
ece961f882 LibJS: Pass call/construct argument lists as ReadonlySpan<Value>
(Instead of MarkedVector<Value>.) This is a step towards not storing
argument lists in MarkedVector<Value> at all. Note that they still end
up in MarkedVectors since that's what ExecutionContext has.
2023-11-29 09:48:18 +01:00
Andreas Kling
b2a1f39400 LibJS/JIT: Add fast path for JumpConditional where accumulator is Int32 2023-11-26 19:32:51 +01:00
Andreas Kling
cb46a7fd65 LibJS: Add specialized fast paths for 8/16/32-bit integer TypedArrays
By checking a few conditions up front, we can do a very specialized
direct access into the underlying byte storage for 8/16/32-bit typed
arrays. This relies on the fact that typed arrays are guaranteed to
be type-appropriately aligned within the underlying array buffer.
2023-11-26 19:32:51 +01:00
Andreas Kling
4cce181ece LibJS: Devirtualize Object::is_typed_array() 2023-11-26 19:32:51 +01:00
Andreas Kling
d154a758fa LibJS: Devirtualize TypedArrayBase::kind()
Let's put this in a member variable to avoid the virtual call.
2023-11-26 19:32:51 +01:00
Andreas Kling
abcf71a8ca LibJS: Remove unnecessary ThrowCompletionOr return types in TypedArray
We used to need these because we worried about tiny OOM errors.

Work towards #20449
2023-11-26 10:33:56 +01:00
Andreas Kling
1bc58333f8 LibJS: Add common fast path for GetByValue from TypedArray
Same exact idea as the previous commit, just for GetByValue. :^)
2023-11-26 10:14:55 +01:00