Commit graph

14 commits

Author SHA1 Message Date
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
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
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
Andreas Kling
53d0dd4a2e LibJS+LibWeb: Use new Cell::Visitor helpers to avoid manual iteration 2024-04-16 07:40:01 +02: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
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
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
1c06111cbd LibJS: Add file & line number to bytecode VM stack traces :^)
This works by adding source start/end offset to every bytecode
instruction. In the future we can make this more efficient by keeping
a map of bytecode ranges to source ranges in the Executable instead,
but let's just get traces working first.

Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
2023-09-02 15:37:53 +02:00
Hediadyoin1
50bf303edd LibJS: Capture UnrealizedSourceRanges in ExecutionContext, not ASTNodes
This loosens the connection to the AST interpreter and will allow us to
generate SourceRanges for the Bytecode interpreter in the future as well

Moves UnrealizedSourceRanges from TracebackFrame to the JS namespace for
this
2023-08-05 06:39:06 +02:00
Aliaksandr Kalenik
0daff637e2 LibJS: Add vector of local variables in ExecutionContext
Now ExecutionContext has vector of values that will represent values
of local variables.

This vector is initialized in ECMAScriptFunctionObject::internal_call()
or ECMAScriptFunctionObject::internal_const() using number of local
variables provided to ECMAScriptFunctionObject by the parser.
2023-07-05 21:03:01 +02:00
Luke Wilde
6431dd7904 LibJS: Make it possible to visit the edges of an ExecutionContext 2022-12-12 13:58:32 +00:00
Luke Wilde
40cc38869e LibJS: Move ExecutionContext function implementations out of line 2022-12-12 13:58:32 +00:00