Commit graph

5131 commits

Author SHA1 Message Date
Shannon Booth
f95117f75d LibJS: Use TimeZoneMethods in GetOffsetNanosecondsFor
Update to the latest version of the spec which was refactored to use
time zone methods record. This requires updating a whole bunch of
callers to pass through a record too.

This also ends up improving exceptions on a missing
getOffsetNanosecondsFor method.
2024-03-02 12:27:20 +01:00
Shannon Booth
230ffc022c LibJS: Update Temporal's GetPossibleInstantsFor to latest spec
The most noteworthy change is that we now pass through a Time Zone
Methods Record to this function instead of a raw object.
2024-03-02 12:27:20 +01:00
Shannon Booth
aa9cdc2205 LibJS: Make DisambiguatePossibleInstants take a vector of NonullGCPtr
Instead of a raw pointer. Then deal with the fallout of making that
change.
2024-03-02 12:27:20 +01:00
Andreas Kling
bc21ed151e LibJS/Bytecode: Handle awkward initialization case for duplicate var
`var` declarations can have duplicates, but duplicate `let` or `const`
bindings are a syntax error.

Because of this, we can sink `let` and `const` directly into the
preferred_dst if available. This is not safe for `var` since the
preferred_dst may be used in the initializer.

This patch fixes the issue by simply skipping the preferred_dst
optimization for `var` declarations.
2024-03-01 14:51:08 +01:00
Timothy Flynn
d878975f95 AK+LibJS: Remove OFFSET_OF and its users
With the LibJS JIT removed, let's not expose pointers to internal
members.
2024-02-29 09:00:00 +01:00
Andreas Kling
953573565c LibJS/Bytecode: Cache realm, global object, and more in interpreter
Instead of looking these up in the VM execution context stack whenever
we need them, we now just cache them in the interpreter when entering
a new call frame.
2024-02-28 21:09:09 +01:00
Andreas Kling
01e9eee7dd LibJS/Bytecode: Avoid Value==Value in Call built-in fast path
Comparing two Values has to call the generic same_value() helper,
and we can avoid this by simply using a stronger type for built-in
native function handlers.
2024-02-28 21:09:09 +01:00
Andreas Kling
1060c63bd8 LibJS: Mark ThrowCompletionOr member functions as ALWAYS_INLINE
Some of them stood out in a profile, and they have no business doing so.
2024-02-28 21:09:09 +01:00
Timothy Flynn
3d2794d062 LibJS: Add a fast path for setting valid u32 values in Uint32TypedArray
The exisiting fast path only permits for valid i32 values.

On https://cyxx.github.io/another_js, this eliminates the runtime of
typed_array_set_element, and reduces the runtime of put_by_value from
11.1% to 7.7%.
2024-02-28 19:41:11 +01:00
Timothy Flynn
d0d22304e4 Revert "LibJS: Add fast path for getting the TA length of valid TAs"
This reverts commit 9c943f36ed.

This optimization is superseded by optimizing IsValidIntegerIndex for
TypedArrays with non-resizable ArrayBuffers. Reverting this commit has
no impact on test-js, test262, or live website performance.
2024-02-28 19:41:11 +01:00
Timothy Flynn
98552bf4c9 Revert "LibJS: Add fast path for checking if attached TAs are OOB"
This reverts commit 5fd53652b7.

This optimization is superseded by optimizing IsValidIntegerIndex for
TypedArrays with non-resizable ArrayBuffers. Reverting this commit has
no impact on test-js, test262, or live website performance.
2024-02-28 19:41:11 +01:00
Timothy Flynn
d8eb297b95 Revert "LibJS: Add fast path for creating a TA record for attached TAs"
This reverts commit 72cee4c88b.

This optimization is superseded by optimizing IsValidIntegerIndex for
TypedArrays with non-resizable ArrayBuffers. Reverting this commit has
no impact on test-js, test262, or live website performance.
2024-02-28 19:41:11 +01:00
Timothy Flynn
08ad2d774e LibJS: Optimize IsValidIntegerIndex for TAs with non-resizable buffers
If we know the TA does not have a resizable ArrayBuffer, we can avoid
most of the heavy lifting that IsValidIntegerIndex performs.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 7.1% to 3.7%.
2024-02-28 19:41:11 +01:00
Timothy Flynn
c7c4987967 LibJS: Store a TypeArray's element size upon construction
This avoids a virtual dispatch upon invoking the element size getter.
The size is static, so we could make TypedArrayBase templated with a
NTTP for the size, but let's not undergo such a wide-spread refactor.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 8.9% to 7.1%.
2024-02-27 20:02:07 +01:00
Timothy Flynn
17e2f751c5 LibJS: Add an explicit DataBlock::size method
This avoids visiting the underlying buffer twice from ArrayBuffer's
byte_length.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 9.9% to 8.9%.
2024-02-27 20:02:07 +01:00
Timothy Flynn
72cee4c88b LibJS: Add a fast path for creating a TA witness record for attached TAs
In IsValidIntegerIndex, we check if the TA is detached before invoking
MakeTypedArrayWithBufferWitnessRecord. There's no need to check it
again.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 10.7% to 9.9%.
2024-02-27 20:02:07 +01:00
Timothy Flynn
5fd53652b7 LibJS: Add a fast path for checking if attached TAs are out of bounds
In IsValidIntegerIndex, we check if the TA is detached before invoking
IsTypedArrayOutOfBounds. There's no need to check it again.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 11.5% to 10.7%.
2024-02-27 20:02:07 +01:00
Timothy Flynn
84936c9ab6 LibJS: Inline the ArrayBufferByteLength implementation
Note: When we better support SharedArrayBuffer, that part of this AO
might not be inlined, as it looks a bit expensive.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 12.5% to 11.5%.
2024-02-27 20:02:07 +01:00
Timothy Flynn
9c943f36ed LibJS: Add a fast path for getting the TA length of known valid TAs
In IsValidIntegerIndex, we check IsTypedArrayOutOfBounds before invoking
TypedArrayLength. There's no need to check it again.

On https://cyxx.github.io/another_js, this reduces the runtime of
IsValidIntegerIndex from 16% to 12.5%.
2024-02-27 20:02:07 +01:00
Andreas Kling
55dc69625a LibJS/Bytecode: Fix formatting of operand lists in bytecode dumps
There was an unterminated color escape sequence which caused "args"
to look like "rgs" when dumping Call instructions.
2024-02-27 07:44:18 +01:00
Shannon Booth
92a7fd77f4 LibJS: Crash on allocation failure in DurationPrototype
The String::from_utf8 calls here are also guaranteed to be given a valid
UTF-8 string.
2024-02-25 07:51:28 -05:00
Shannon Booth
c063bf39a9 LibJS: Make ToRelativeTemporalObject return a RelativeTo struct
This follows a change in the spec which refactored this function and its
callers to make use of a record instead of stuffing all of the possible
return values into a single Value.

As always in temporal land, this AO remains out of date, as well of all
its callers. Update all of these callers to the new API where possible,
and use an ad-hoc function to convert this struct back to a JS::Value
for APIs that have not been updated yet.
2024-02-25 07:51:28 -05:00
Shannon Booth
fa692ae3f6 LibJS: Implement Temporal's Time Zone Methods Record
Similar to 'Calendar Methods Record', this is part of a refactor to the
temporal spec which will need much work for all of the corresponding AOs
to be updated to use.

Put in a new header file to prevent circular include problems when using
this new record.
2024-02-25 07:51:28 -05:00
Shannon Booth
15977ea42f LibJS: Put roundTo argument into a variable
Following the pattern we have in other protoypes to avoid a magic
number index into the zeroth argument.
2024-02-25 07:51:28 -05:00
Dan Klishch
8ac0e3f0e5 AK+LibJS: Remove null state from DeprecatedFlyString :^) 2024-02-24 15:06:52 -07:00
Dan Klishch
026c1caba0 LibJS: Don't use null DFS for binding_name parameters in ClassExpression 2024-02-24 15:06:52 -07:00
Dan Klishch
d558468d03 LibJS: Don't differentiate between empty and null DFS in CatchClause 2024-02-24 15:06:52 -07:00
Dan Klishch
fb2c929310 LibJS: Don't use null DFS in {Import,Export}Entry 2024-02-24 15:06:52 -07:00
Dan Klishch
78491204d9 LibJS: Don't use null DFS for break/continue statements without a label 2024-02-24 15:06:52 -07:00
Dan Klishch
761d16141d LibJS: Store DFS instead of opaque StringImpl inside StringOrSymbol
Additionally, use the second bit (instead of the first) to differentiate
between strings and symbols there. This will allow transparent
conversion of DFS to StringBase in the future.
2024-02-24 15:06:52 -07:00
Dan Klishch
a53911717f LibJS: Remove DeprecatedFlyString::impl use in PrimitiveString 2024-02-24 15:06:52 -07:00
Andreas Kling
6402ad29a6 LibJS/Bytecode: Don't clobber dst when assigning from object expression
When compiling code like this:

    x = { foo: x }

We don't want to put a new JS::Object in `x` until *after* we've
evaluated `x` for the `foo` field.

This fixes an issue when loading https://puter.com/ :^)
2024-02-23 14:34:00 +01:00
Andreas Kling
883b2268c0 LibJS: Protect private elements from GC during class construction
Fixes an issue caught by test-js -g + UBSAN.
2024-02-22 16:44:54 +01:00
Andreas Kling
4bbb0a5c35 LibJS: Add ConservativeVector<T>
This works very similarly to MarkedVector<T>, but instead of expecting
T to be Value or a GC-allocated pointer type, T can be anything.
Every pointer-sized value in the vector's storage will be checked during
conservative root scanning.

In other words, this allows you to put something like this in a
ConservativeVector<Foo> and it will be protected from GC:

    struct Foo {
        i64 number;
        Value some_value;
        GCPtr<Object> some_object;
    };
2024-02-22 16:44:54 +01:00
Timothy Flynn
4bdcf9a4b7 LibJS: Revert the free stack limit back to 32 KiB 2024-02-20 16:24:09 -05:00
Timothy Flynn
8eaf48888e LibJS: Remove FLATTEN attribute from Interpreter::run_bytecode
This is what caused stack usage to increase so much with the new BC.
Revert it for now so we can restore our old stack limit.
2024-02-20 16:24:09 -05:00
Andreas Kling
9a0a5a79f4 LibJS/Bytecode: Put arguments directly in the Call instruction
Instead of having Call refer to a range of VM registers, it now has
a trailing list of argument operands as part of the instruction.

This means we no longer have to shuffle every argument value into
a register before making a call, making bytecode smaller & faster. :^)
2024-02-20 21:25:18 +01:00
Andreas Kling
da107ec9fb LibJS/Bytecode: Add fast paths for many binary expression instructions
By handling common cases like Int32 arithmetic directly in the
instruction handler, we can avoid the cost of calling the generic helper
functions in Value.cpp.
2024-02-20 21:25:18 +01:00
Andreas Kling
9d9b737a58 LibJS/Bytecode: Dedicated instructions for postfix increment/decrement
Instead of splitting the postfix variants into ToNumeric + Inc/Dec,
we now have dedicated PostfixIncrement and PostfixDecrement instructions
that handle both outputs in one go.
2024-02-20 21:25:18 +01:00
Timothy Flynn
3ac4b02604 LibJS: Further increase the free stack limit to 256 KiB
128 KiB seems to not be enough for CI.
2024-02-20 12:29:27 -05:00
Shannon Booth
0b457f90e0 LibJS: Fix copy paste errors in Temporal's Calendar Methods Record
This adapts our implementation to the editorial change in the temporal
proposal: 737baf2d

The changes to CalendarMethodsRecordLookup had already been implemented,
but we had followed the typo in the spec for CalendarMethodsRecordCall.
The issue in CalendarMethodsRecordCall hasn't surfaced yet, as the AOs
using Calendar Methods Record are currently not passing through a String
to represent a Calendar builtin.

No change to test-262.
2024-02-20 06:54:32 -05:00
Andreas Kling
fb4c632309 LibJS: Throw "call stack size exceeded" exception a bit earlier
This number is pure guesswork but it appears to fix GCC builds with
both ASAN and UBSAN hitting a native stack overflow before we have
a chance to catch it on our Azure CI.
2024-02-20 10:54:52 +01:00
Andreas Kling
e46b217e42 LibJS/Bytecode: Move to a new bytecode format
This patch moves us away from the accumulator-based bytecode format to
one with explicit source and destination registers.

The new format has multiple benefits:

- ~25% faster on the Kraken and Octane benchmarks :^)
- Fewer instructions to accomplish the same thing
- Much easier for humans to read(!)

Because this change requires a fundamental shift in how bytecode is
generated, it is quite comprehensive.

Main implementation mechanism: generate_bytecode() virtual function now
takes an optional "preferred dst" operand, which allows callers to
communicate when they have an operand that would be optimal for the
result to go into. It also returns an optional "actual dst" operand,
which is where the completion value (if any) of the AST node is stored
after the node has "executed".

One thing of note that's new: because instructions can now take locals
as operands, this means we got rid of the GetLocal instruction.
A side-effect of that is we have to think about the temporal deadzone
(TDZ) a bit differently for locals (GetLocal would previously check
for empty values and interpret that as a TDZ access and throw).
We now insert special ThrowIfTDZ instructions in places where a local
access may be in the TDZ, to maintain the correct behavior.

There are a number of progressions and regressions from this test:

A number of async generator tests have been accidentally fixed while
converting the implementation to the new bytecode format. It didn't
seem useful to preserve bugs in the original code when converting it.

Some "does eval() return the correct completion value" tests have
regressed, in particular ones related to propagating the appropriate
completion after control flow statements like continue and break.
These are all fairly obscure issues, and I believe we can continue
working on them separately.

The net test262 result is a progression though. :^)
2024-02-19 21:45:27 +01:00
Andreas Kling
7f1a62a1d3 LibJS/Bytecode: Add Operand in/out to all the bytecode codegen helpers
This is pure prep work for refactoring the bytecode to use more operands
instead of only registers.

generate_bytecode() virtuals now return an Optional<Operand>, and the
idea is to return an Operand referring to the value produced by this
AST node.

They also take an Optional<Operand> "preferred_dst" input. This is
intended to communicate the caller's preference for an output operand,
if any. This will be used to elide temporaries when we can store the
result directly in a local, for example.
2024-02-19 21:45:27 +01:00
Andreas Kling
e46de4eb59 LibJS/Bytecode: Add constants table to Bytecode::Executable 2024-02-19 21:45:27 +01:00
Andreas Kling
3466771492 LibJS/Bytecode: Add Bytecode::Operand
An Operand is either a register, a local, or a constant (index into the
executable's constant table)
2024-02-19 21:45:27 +01:00
Andreas Kling
c0ec924dc9 LibJS/Bytecode: Exclude extra tables from bytecode executable dumps 2024-02-19 21:45:27 +01:00
Andreas Kling
aada76d0fb LibJS: Don't dump variables multiple times in AST dumps 2024-02-19 21:45:27 +01:00
Andreas Kling
1d29f9081f LibJS: Remove JIT compiler
The JIT compiler was an interesting experiment, but ultimately the
security & complexity cost of doing arbitrary code generation at runtime
is far too high.

In subsequent commits, the bytecode format will change drastically, and
instead of rewriting the JIT to fit the new bytecode, this patch simply
removes the JIT instead.

Other engines, JavaScriptCore in particular, have already proven that
it's possible to handle the vast majority of contemporary web content
with an interpreter. They are currently ~5x faster than us on benchmarks
when running without a JIT. We need to catch up to them before
considering performance techniques with a heavy security cost.
2024-02-19 21:45:27 +01:00
Shannon Booth
4348b484c6 LibJS: Verify valid Duraton is made in DifferenceTemporalPlainDate
It shouldn't be possible to create an invalid duration here, so follow
the spec and verify that this succeeds.
2024-02-16 12:27:23 -05:00