Commit graph

69 commits

Author SHA1 Message Date
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Andreas Kling
cc4b3cbacc Meta: Update my e-mail address everywhere 2024-10-04 13:19:50 +02:00
Andreas Kling
0f9444fa06 LibJS: Fix mix-up when re-exporting an imported symbol with a new name
This makes https://cling.com/ load, and more of the animated elements
on https://shopify.com/ start appearing.
2024-09-02 17:14:21 +02:00
Daniel Bertalan
bf1f631f25 Everywhere: Write dtors for types with incomplete members out-of-line
These are rejected by Clang (19) trunk as a result of
https://github.com/llvm/llvm-project/pull/77753.
2024-06-16 07:19:56 -04:00
Andreas Kling
a3782782fa LibJS: Remove two unused members from ExecutionContext 2024-05-31 16:31:33 +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
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
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
f6aee2b9e8 LibJS/Bytecode: Flatten bytecode to a contiguous representation
Instead of keeping bytecode as a set of disjoint basic blocks on the
malloc heap, bytecode is now a contiguous sequence of bytes(!)

The transformation happens at the end of Bytecode::Generator::generate()
and the only really hairy part is rerouting jump labels.

This required solving a few problems:

- The interpreter execution loop had to change quite a bit, since we
  were storing BasicBlock pointers all over the place, and control
  transfer was done by redirecting the interpreter's current block.

- Exception handlers & finalizers are now stored per-bytecode-range
  in a side table in Executable.

- The interpreter now has a plain program counter instead of a stream
  iterator. This actually makes error stack generation a bit nicer
  since we just have to deal with a number instead of reaching into
  the iterator.

This yields a 25% performance improvement on this microbenchmark:

    for (let i = 0; i < 1_000_000; ++i) { }

But basically everything gets faster. :^)
2024-05-07 09:15:40 +02:00
Aliaksandr Kalenik
4d5823a5bc LibWeb+LibJS: Skip function environment allocation if possible
If a function has the following properties:
- uses only local variables and registers
- does not use `this`
- does not use `new.target`
- does not use `super`
- does not use direct eval() calls

then it is possible to entirely skip function environment allocation
because it will never be used

This change adds gathering of information whether a function needs to
access `this` from environment and updates `prepare_for_ordinary_call()`
to skip allocation when possible.

For now, this optimisation is too aggressively blocked; e.g. if `this`
is used in a function scope, then all functions in outer scopes have to
allocate an environment. It could be improved in the future, although
this implementation already allows skipping >80% of environment
allocations on Discord, GitHub and Twitter.
2024-05-04 06:48:07 +02:00
Aliaksandr Kalenik
865e651a7d LibJS: Merge CallFrame into ExecutionContext
Before this change both ExecutionContext and CallFrame were created
before executing function/module/script with a couple exceptions:
- executable created for default function argument evaluation has to
  run in function's execution context.
- `execute_ast_node()` where executable compiled for ASTNode has to be
  executed in running execution context.

This change moves all members previously owned by CallFrame into
ExecutionContext, and makes two exceptions where an executable that does
not have a corresponding execution context saves and restores registers
before running.

Now, all execution state lives in a single entity, which makes it a bit
easier to reason about and opens opportunities for optimizations, such
as moving registers and local variables into a single array.
2024-05-02 07:26:13 +02:00
Dan Klishch
fb2c929310 LibJS: Don't use null DFS in {Import,Export}Entry 2024-02-24 15:06:52 -07: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
Aliaksandr Kalenik
b108d51c5b LibJS: Only consider VM-accessible execution contexts as strong roots
Partially reverts 3dc5f467a8 to fix
GC memory leak that happens because we treated all execution contexts
as strong roots.
2023-12-13 11:19:13 +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
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
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
3c74dc9f4d LibJS: Segregate GC-allocated objects by type
This patch adds two macros to declare per-type allocators:

- JS_DECLARE_ALLOCATOR(TypeName)
- JS_DEFINE_ALLOCATOR(TypeName)

When used, they add a type-specific CellAllocator that the Heap will
delegate allocation requests to.

The result of this is that GC objects of the same type always end up
within the same HeapBlock, drastically reducing the ability to perform
type confusion attacks.

It also improves HeapBlock utilization, since each block now has cells
sized exactly to the type used within that block. (Previously we only
had a handful of block sizes available, and most GC allocations ended
up with a large amount of slack in their tails.)

There is a small performance hit from this, but I'm sure we can make
up for it elsewhere.

Note that the old size-based allocators still exist, and we fall back
to them for any type that doesn't have its own CellAllocator.
2023-11-19 12:10:31 +01:00
Andreas Kling
3ccac0cf6e LibJS: Remove unused realm parameter from run_and_return_frame() 2023-09-21 16:19:13 +02:00
Andreas Kling
2eaa528a0e LibJS: Rip out the AST interpreter :^)
This has been superseded by the bytecode VM, which is both faster
and more capable.
2023-08-08 13:07:13 +02:00
Aliaksandr Kalenik
fb94415f03 LibJS: Delete Declaration::for_each_var_declared_name
1. Replaces for_each_var_declared_name usage with more generic
for_each_var_declared_identifier.
2. Deletes for_each_var_declared_name.
2023-07-20 20:19:15 +02:00
Aliaksandr Kalenik
348e43b36d LibJS: Replace for_each_bound_name with for_each_bound_identifier
Preparation before deleting for_each_bound_name.
2023-07-20 20:19:15 +02:00
Shannon Booth
930dd2948f LibJS: Make AsyncFunctionStart and AsyncBlockStart templates
This will allow implementing a version of these functions that accepts a
JS::SafeFunction, which is needed for the implementation of
Array.fromAsync.
2023-07-16 14:56:10 +01:00
Aliaksandr Kalenik
7765ebb5f2 LibJS+LibWeb: Plumb local variables names to ECMAScriptFunctionObject
Saving vector of local variables names in ECMAScriptFunctionObject
will allow to get a name by index in case message of ReferenceError
needs to contain a variable name.
2023-07-05 21:03:01 +02:00
Andreas Kling
5d79431859 LibJS/Bytecode: Actually generate & run bytecode for SourceTextModule 2023-06-24 17:13:30 +02:00
Matthew Olsson
7c0c1c8f49 LibJS+LibWeb: Wrap raw JS::Cell*/& fields in GCPtr/NonnullGCPtr 2023-03-15 08:48:49 +01:00
Andreas Kling
8a48246ed1 Everywhere: Stop using NonnullRefPtrVector
This class had slightly confusing semantics and the added weirdness
doesn't seem worth it just so we can say "." instead of "->" when
iterating over a vector of NNRPs.

This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
2023-03-06 23:46:35 +01:00
Luke Wilde
f4be95af69 LibJS: Don't discard ThrowCompletionOr<void> from declaration iteration 2023-02-27 23:57:08 +00:00
Andreas Kling
bd5d8e9d35 LibJS: Make RefPtr and NonnullRefPtr usage const-correct
This mainly affected the AST, which is now const throughout.
2023-02-21 00:54:04 +01:00
davidot
541637e15a LibJS: Add using declaration support, RAII like operation in js
In this patch only top level and not the more complicated for loop using
statements are supported. Also, as noted in the latest meeting of tc39
async parts of the spec are not stage 3 thus not included.
2023-01-23 09:56:50 +00:00
davidot
a746739cb0 LibJS: Add an initialize binding hint to all initialize_binding methods
This will allow us to specify things like SyncDispose and perhaps
AsyncDispose in the future.
2023-01-23 09:56:50 +00:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
Ben Wiederhake
8a331d4fa0 Everywhere: Move AK/Debug.h include to using files or remove 2023-01-02 20:27:20 -05:00
Linus Groh
22089436ed LibJS: Convert Heap::allocate{,_without_realm}() to NonnullGCPtr 2022-12-15 06:56:37 -05:00
Linus Groh
73efdb1cc4 LibJS: Convert ECMAScriptFunctionObject::create() to NonnullGCPtr 2022-12-14 09:59:45 +00:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
davidot
0c4befd811 LibJS: Use the source offset to sort imports in module
Using source offsets directly means we don't have to synthesize any
SourceRanges and circumvents that SourceRange returns invalid values for
the last range of a file.
2022-11-27 00:51:36 +00:00
davidot
d87676de8a LibJS: Remove already resolved FIXME
We wouldn't want someone to be disappointed when trying to fix this :^).
2022-11-27 00:51:36 +00:00
Andreas Kling
b81816a539 LibJS+LibWeb: Make CyclicModule.h not include AST.h
This led to some fallout as many things in LibJS and LibWeb were pulling
in other things via CyclicModule.h
2022-11-23 16:05:59 +00:00
Andreas Kling
e6331031c4 LibJS: Make Parser::Error a standalone ParserError class
This allows us to forward declare it and reduce the number of things
that need to include Parser.h.
2022-11-23 16:05:59 +00:00
Andreas Kling
e0916dbb35 LibJS: Move {Import,Export}Entry out of {Import,Export}Statement
By making these be standalone instead of nested structs, we can forward
declare them. This will allow us to stop including AST.h in some places.
2022-11-23 16:05:59 +00:00
networkException
fb6de442c6 LibJS: Add [[HostDefined]] field to Modules
This patch adds the [[HostDefined]] field defined in
https://tc39.es/ecma262/#table-module-record-fields to module records.

Co-authored-by: davidot <davidot@serenityos.org>
2022-10-06 16:41:36 +02:00
Linus Groh
fc9d587e39 LibJS: Make PromiseCapability GC-allocated
A struct with three raw pointers to other GC'd types is a pretty big
liability, let's just turn this into a Cell itself.
This comes with the additional benefit of being able to capture it in
a lambda effortlessly, without having to create handles for individual
members.
2022-10-02 23:02:27 +01:00
Andreas Kling
00c8f07192 LibJS: Make Script and Module GC-allocated
This ensures that code currently in any active or saved execution stack
always stays alive.
2022-09-06 00:27:09 +02:00