Commit graph

3889 commits

Author SHA1 Message Date
Timothy Flynn
1bcc29d0d1 LibJS+LibLocale: Replace Unicode keyword lookups with ICU
Note: All of the changes to the test files in this patch are now aligned
with both Chrome and Firefox.
2024-06-16 06:57:08 +02:00
Timothy Flynn
a1464342e1 LibJS+LibLocale: Remove unused parameter from keyword canonicalization 2024-06-16 06:57:08 +02:00
Timothy Flynn
5e2ee4447e LibJS+LibLocale: Replace plural rules selection with ICU
This uses ICU for all of the Intl.PluralRules prototypes, which lets us
remove all data from our plural rules generator.

Plural rules depend directly on internal data from the number formatter,
so rather than creating a separate Locale::PluralRules class (which will
make accessing that data awkward), this adds plural rules APIs to the
existing Locale::NumberFormat.
2024-06-15 06:57:16 +02:00
Timothy Flynn
7f9ccd39f5 LibJS+LibLocale: Replace relative time formatting with ICU
This uses ICU for all of the Intl.RelativeTimeFormat prototypes, which
lets us remove all data from our relative-time format generator.
2024-06-15 06:57:16 +02:00
Timothy Flynn
d634039c10 LibJS: Implement the latest Intl.DurationFormat proposal
The proposal has undergone quite a few normative changes since we last
synced with it. There was a time when it could not be implemented as it
was written, which is no longer the case. The resulting proposal has had
so many changes compared to our implementation, that it wouldn't make
sense to implement them commit-by-commit as we normally do. So instead,
this just implements the HEAD revision of the spec in one pass.
2024-06-14 07:59:42 +02:00
Timothy Flynn
4b3e26c583 LibJS+LibLocale: Replace calendar weekday information with ICU 2024-06-13 07:42:09 +02:00
Timothy Flynn
9cb1857dc6 LibJS+LibLocale: Replace preferred hour cycle lookups with ICU 2024-06-13 07:42:09 +02:00
Timothy Flynn
e2bffe5612 LibJS+LibLocale: Replace time zone display names with ICU 2024-06-13 07:42:09 +02:00
Timothy Flynn
273694d8de LibJS+LibLocale: Replace date-time formatting with ICU
This uses ICU for the Intl.DateTimeFormat `format` `formatToParts`,
`formatRange`, and `formatRangeToParts`.

This lets us remove most data from our date-time format generator. All
that remains are time zone data and locale week info, which are relied
upon still for other interfaces. So they will be removed in a future
patch.

Note: All of the changes to the test files in this patch are now aligned
with other browsers. This includes:

* Some very incorrect formatting of Japanese symbols. (Looking at the
  old results now, it's very obvious they were wrong.)
* Old FIXMEs regarding range formatting not including the start/end date
  when only time fields were requested, but the dates differ.
* Day period inconsistencies.
2024-06-13 07:42:09 +02:00
Tim Ledbetter
88d425f32b LibJS: Add the [[Unimplemented]] attribute
Properties marked with the [[Unimplemented]] attribute behave as normal
but invoke the `VM::on_unimplemented_property_access callback` when
they are accessed.
2024-06-11 16:33:30 +02:00
circl
c169e43e13 Userland: Remove some SerenityOS checks 2024-06-10 13:53:01 +02:00
Timothy Flynn
3b68bb6e73 LibJS: Store Intl mathematical values as strings when appropriate
The IntlMV is meant to be arbitrarily precise. If the user provides a
string value to be formatted, we lose precision by converting extremely
large values to a double. We were never able to address this, as support
for arbitrary precision was a big FIXME. But ICU can handle it by just
passing the raw string on through.
2024-06-10 13:51:51 +02:00
Timothy Flynn
f6bee0f5a8 LibJS+LibLocale: Replace number range formatting with ICU
This uses ICU for the Intl.NumberFormat `formatRange` and
`formatRangeToParts` prototypes.

Note: All of the changes to the test files in this patch are now aligned
with both Chrome and Safari.
2024-06-10 13:51:51 +02:00
Timothy Flynn
67f3de2320 LibJS+LibLocale: Begin replacing number formatting with ICU
This uses ICU for the Intl.NumberFormat `format` and `formatToParts`
prototypes. It does not yet port the range formatter prototypes.

Most of the new code in LibLocale/NumberFormat is simply mapping from
ECMA-402 types to ICU types. Beyond that, the only algorithmic change is
that we have to mutate the output from ICU for `formatToParts` to match
what is expected by ECMA-402. This is explained in NumberFormat.cpp in
`flatten_partitions`.

This lets us remove most data from our number format generator. All that
remains are numbering system digits and symbols, which are relied upon
still for other interfaces (e.g. Intl.DateTimeFormat). So they will be
removed in a future patch.

Note: All of the changes to the test files in this patch are now aligned
with both Chrome and Safari.
2024-06-10 13:51:51 +02:00
Timothy Flynn
5f7251fd91 LibJS+LibLocale: Replace list formatting with ICU
This also largely eliminates the need for some ECMA-402 AOs, as is it
all handled internally by ICU (which the spec is basically based on).
2024-06-09 10:47:28 +02:00
Timothy Flynn
d17d131224 LibJS+LibLocale: Replace locale character ordering with ICU 2024-06-09 10:47:28 +02:00
Timothy Flynn
e487f91388 LibJS+LibLocale: Replace locale maximization and minimization with ICU 2024-06-09 10:47:28 +02:00
Timothy Flynn
9724a25daf LibJS+LibLocale: Replace canonical locales and display names with ICU
Note: We keep locale parsing and syntactic validation as-is. ECMA-402
places additional restrictions on locales above what is required by the
Unicode spec. ICU doesn't provide methods that let us easily check those
restrictions, whereas LibLocale does. Other browsers also implement
their own validators here.

This introduces a locale cache to re-use parsed locale data and various
related structures (not doing so has a non-negligible performance impact
on Intl tests).

The existing APIs for canonicalization and display names are pretty
intertwined, so they must both be adapted at once here. The results of
canonicalization are slightly different on some edge cases. But the
changed results are actually now aligned with Chrome and Safari.
2024-06-09 10:47:28 +02:00
Andreas Kling
a48fc971c6 LibJS: Rearrange ExecutionContext members to shrink the class
Just a minor tweak to make the class 8 bytes smaller.
2024-05-31 16:31:33 +02:00
Andreas Kling
a3782782fa LibJS: Remove two unused members from ExecutionContext 2024-05-31 16:31:33 +02:00
Matthew Olsson
9ea6ab0ad4 LibJS+LibWeb: Fix a ton of JS_CELL-like macro issues 2024-05-30 09:29:20 -06:00
Matthew Olsson
3e221fbb2d IDLGenerators: Handle restricted/unrestricted floating point types 2024-05-29 08:18:24 +02:00
Andreas Kling
2aab56bf71 LibJS: Null-check current executable in VM::dump_backtrace()
If there is no current executable (because we're in a native function
call), we shouldn't try to dereference it.
2024-05-27 17:33:29 +02:00
Shannon Booth
f28bb90d9b LibJS: Remove non-spec compliant code from internal_construct
It seems that we are now spec compliant enough to be able to remove this
code block :^)

Diff Tests:
    +2     -2 
2024-05-26 12:29:41 +02:00
Aliaksandr Kalenik
63a56a77a2 LibJS: Add fast ExecutionContext allocator
...that maintains a list of allocated execution contexts so malloc()
does not have to be called every time we need to get a new one.

20% improvement in Octane/typescript.js
16% improvement in Kraken/imaging-darkroom.js
2024-05-23 13:36:02 +02:00
Aliaksandr Kalenik
f29ac8517e LibJS: Skip ordinary_call_bind_this() when possible
If during parsing it was found that function won't use `this` then
there is no need to initialise `this_value` during call.
2024-05-23 09:53:31 +02:00
Aliaksandr Kalenik
e934132442 LibJS+LibWeb: Pass function metadata collected in parsing using a struct
By using separate struct we can avoid updating AST node and
ECMAScriptFunctionObject constructors every time there is a need to
add or remove some additional information colllected during parsing.
2024-05-23 09:53:31 +02:00
Matthew Olsson
a98ad191c7 Userland: Add ESCAPING annotations to a bunch of places
This isn't comprehensive; just a result of a simple grep search.
2024-05-22 21:55:34 -06:00
Matthew Olsson
a5f4c9a632 AK+Userland: Remove NOESCAPE
See the next commit for an explanation
2024-05-22 21:55:34 -06:00
Aliaksandr Kalenik
ebb3d8025c LibJS: Get this from execution context for non-arrow functions
Allows to skip function environment allocation for non-arrow functions
if the only reason it is needed is to hold `this` binding.

The parser is changed to do following:
- If a function is an arrow function and uses `this` then all functions
  in a scope chain are marked to allocate function environment for
  `this` binding.
- If a function uses `new.target` then all functions in a scope chain
  are marked to allocate function environment.

`ordinary_call_bind_this()` is changed to put `this` value in execution
context when function environment allocation is skipped.

35% improvement in Octane/typescript.js
50% improvement in Octane/deltablue.js
19% improvement in Octane/raytrace.js
2024-05-22 18:30:13 +02:00
Aliaksandr Kalenik
4d37b9e715 LibJS: Do not count arguments as env binding when local variable is used
This is a follow up for 210a5d77dc that
actually allows to skip function environment allocation.
2024-05-21 15:49:29 +00:00
Aliaksandr Kalenik
210a5d77dc LibJS: Use a local variable for arguments object when possible
This allows us to skip allocating a function environment in cases where
it was previously impossible because the arguments object needed a
binding.

This change does not bring visible improvement in Kraken or Octane
benchmarks but seems useful to have anyway.
2024-05-21 11:24:50 +02:00
Andreas Kling
ed50eb0aaa LibJS/Bytecode: Add environment coordinate caching to SetVariable
This means that SetVariable instructions will now remember which
(relative) environment contains the targeted binding, letting it bypass
the full binding resolution machinery on subsequent accesses.
2024-05-14 06:39:27 +02:00
Aliaksandr Kalenik
d79438a2a6 LibJS: Join locals, constants and registers into single vector
Merging registers, constants and locals into single vector means:
- Better data locality
- No need to check type in Interpreter::get() and Interpreter::set()
  which are very hot functions

Performance improvement is visible in almost all Octane and Kraken
tests.
2024-05-13 19:54:11 +02:00
Andreas Kling
6f5201b759 LibJS: Add fast paths in TypedArrayPrototype.fill()
Filling a typed array with an integer shouldn't have to go through the
generic Set for every element.

This knocks a 7% item down to <1% in profiles of Another World JS at
https://cyxx.github.io/another_js/
2024-05-13 17:29:37 +02:00
Andreas Kling
8447f6f6da LibJS: Inline more of cached environment variable access in interpreter
And stop passing VM strictness to direct access, since it doesn't care
about strictness anyway.
2024-05-13 09:22:14 +02:00
Aliaksandr Kalenik
8bcaf68023 LibJS: Remove VM::execute_ast_node() 2024-05-12 19:10:25 +02:00
Aliaksandr Kalenik
6fb1d9e516 LibJS: Stop using execute_ast_node() for class property evaluation
Instead, generate bytecode to execute their AST nodes and save the
resulting operands inside the NewClass instruction.

Moving property expression evaluation to happen before NewClass
execution also moves along creation of new private environment and
its population with private members (private members should be visible
during property evaluation).

Before:
- NewClass

After:
- CreatePrivateEnvironment
- AddPrivateName
- ...
- AddPrivateName
- NewClass
- LeavePrivateEnvironment
2024-05-12 19:10:25 +02:00
Aliaksandr Kalenik
0c8e76cbd7 LibJS: Delete named_evaluation_if_anonymous_function()
This code was a leftover from AST interpreter.
2024-05-11 18:16:15 +02:00
Andreas Kling
6ad6e09be1 LibJS: Make Environment::is_declarative_environment() non-virtual
This function was moderately hot (2%) on the clusters demo, and making
it non-virtual costs us nothing.
2024-05-11 15:22:36 +02:00
Andreas Kling
239b9d8662 LibJS: Manually limit the recursion depth in Proxy
Instead of relying on native stack overflows to kick us out of circular
proxy chains, we now keep track of the recursion depth and kick
ourselves out if it exceeds 10'000.

This fixes an issue where compiler tail/sibling call optimizations would
turn infinite recursion into infinite loops, and thus never hit a stack
overflow to kick itself out.

For whatever reason, we've only seen the issue on SerenityOS with UBSAN,
but it could theoretically happen on any platform.
2024-05-11 13:00:46 +02:00
Aliaksandr Kalenik
1e361db3f3 LibJS: Remove VM::binding_initialization()
This function was used for function params initialization but no longer
used after it got replaced by emitting bytecode.
2024-05-11 11:43:05 +02:00
Aliaksandr Kalenik
a4f70986a0 LibJS: Emit bytecode for function declaration instantiation
By doing that all instructions required for instantiation are emitted
once in compilation and then reused for subsequent calls, instead of
running generic instantiation process for each call.
2024-05-11 11:43:05 +02:00
Andreas Kling
353e635535 LibJS/Bytecode: Grab at ThrowCompletionOr errors directly
The interpreter can now grab at the error value directly instead of
instantiating a temporary Completion to hold it.
2024-05-10 15:03:24 +00:00
Andreas Kling
f5efc47905 LibJS: Make ThrowCompletionOr<T> smaller
Instead of storing a full JS::Completion for the "throw completion"
case, we now store a simple JS::Value (wrapped in ErrorValue for the
type system).

This shrinks TCO<void> and TCO<Value> (the most common TCOs) by 8 bytes,
which has a non-trivial impact on performance.
2024-05-10 15:03:24 +00:00
Andreas Kling
ae11a4de1c LibJS: Remove unused target field from Completion
This shrinks Completion by 16 bytes, which has non-trivial impact
on performance.
2024-05-10 15:03:24 +00:00
Andreas Kling
55a4b0a21e LibJS: Mark Value as a trivial type for AK collection purposes
It's perfectly fine to memcpy() a bunch of JS::Values around, and if
that helps Vector<Value> go faster, let's allow it.
2024-05-09 09:12:13 +02:00
Andreas Kling
161298b5d1 LibJS/Bytecode: Inline indexed property access in GetByVal better 2024-05-09 09:12:13 +02:00
Andreas Kling
3170ad2ee3 LibJS: Avoid string trimming in GlobalObject.parseInt() when possible
In the common case, parseInt() is being called with strings that don't
have leading whitespace. By checking for that first, we can avoid the
cost of trimming and multiple malloc/GC allocations.
2024-05-09 09:12:13 +02:00
Timothy Flynn
323c9edbb9 LibJS: Increase the stack limit on macOS with ASAN enabled
The macOS 14 runners on GitHub Actions fail with a stack overflow
otherwise.
2024-05-08 14:46:39 -06:00