Commit graph

194 commits

Author SHA1 Message Date
Andreas Kling
cc4b3cbacc Meta: Update my e-mail address everywhere 2024-10-04 13:19:50 +02:00
Andreas Kling
a6bf253602 LibJS: Use the system native page size as the HeapBlock::block_size
Before this change, we were hard-coding 4 KiB. This meant that systems
with a 16 KiB native page size were wasting 12 KiB per HeapBlock on
nothing, leading to worse locality and more mmap/madvise churn.

We now query the system page size on startup and use that as the
HeapBlock size.

The only downside here is that some of the pointer math for finding the
base of a HeapBlock now has to use a runtime computed value instead of a
compile time constant. But that's a small price to pay for what we get.
2024-08-29 13:56:09 +02:00
Andrew Kaster
f314f58fca LibJS+ClangPlugins: Add escape hatch for GCPtr checks 2024-07-25 18:35:57 -06:00
Andrew Kaster
f8d1a25254 LibJS: Prefix AK::Duration with AK Namespace 2024-07-18 09:43:38 +01:00
Andreas Kling
ef30f191b6 LibJS: Demote VERIFY in GCPtr to ASSERT
These were just here to create a nicer error message for debugging.
A release build will still crash in the exact same place, but now you'll
need to get a backtrace the normal way instead.
2024-07-10 07:03:20 +02:00
circl
c169e43e13 Userland: Remove some SerenityOS checks 2024-06-10 13:53:01 +02:00
Andrew Kaster
89092e98a4 LibJS: Pass -1 as fd when using MAP_ANONYMOUS with mmap
NetBSD and FreeBSD get upset when we don't set the fd to an invalid
value when using a non-shared mapping.

Reported-By: Thomas Klausner <wiz@gatalith.at>
2024-06-06 12:48:58 -06:00
Matthew Olsson
9ea6ab0ad4 LibJS+LibWeb: Fix a ton of JS_CELL-like macro issues 2024-05-30 09:29:20 -06:00
Andreas Kling
3945e1a82a LibJS: Make JS::Cell a Weakable
This makes things easier downstream of Cell, and is preparation for
using weak pointers in prototype chain property caches.
2024-05-04 21:42:59 +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
Aliaksandr Kalenik
1072d9f15d LibJS: Save min and max block addresses in CellAllocator
This allows to skip iterating through all allocated blocks in
`find_min_and_max_block_addresses()`.

With this change `collect_garbage()` in profiles of Discord goes down
from 17% to 8%.
2024-04-24 11:42:15 +02:00
Andreas Kling
e993fb53d5 LibJS: Simplify iteration in GC heap dumping code 2024-04-21 09:12:25 +02:00
Andreas Kling
1a6d025793 LibJS: Add helpers to Cell::Visitor for visiting AK collections 2024-04-16 07:40:01 +02:00
Space Meyer
f870841bee LibJS: Use toolchain agnostic NO_SANITIZE_ADDRESS 2024-04-15 21:16:22 -06:00
Matthew Olsson
edf484a5ab LibJS: Force a semicolon after JS_{DECLARE,DEFINE}_ALLOCATOR()
This matches the style of other macros, and prevents IDEs from flagging
the semicolon as unnecessary.
2024-04-09 09:13:06 +02:00
Matthew Olsson
8b8ada292e LibJS: Fix some GCVerifier warnings 2024-04-07 07:03:13 +02:00
Idan Horowitz
c84cd1d668 LibJSGCVerifier: Support marking GCPtr members as raw references
This lets us avoid false positives when a GCPtr-wrapped member is only
a weak reference which is automatically updated by the GC when the
member's gc state is updated.
2024-04-06 06:59:36 +02:00
Andreas Kling
3881717103 LibJS+AK: Register GC memory as root regions for LeakSanitizer
This should fix the gigantic list of false positives dumped by
LeakSanitizer on exit .
2024-04-03 12:41:02 +02:00
Andrew Kaster
44671d7d37 LibJS: Mark GCPtr's operator bool as explicit
This avoids the potential for unwanted implicit conversions to bool.
It doesn't prevent if (m_ptr) checks though, as that invokes an explicit
conversion to bool. This is how std::unique_ptr and std::optional work.
2024-04-02 06:40:08 -04: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
Shannon Booth
e118430648 LibJS: Allow JS::create_heap_function to accept a lambda
This helps us avoid from needing to construct a Function<T> when
invoking `create_heap_function` with a lambda.

Co-Authored-By: Ali Mohammad Pur <mpfard@serenityos.org>
2024-01-27 21:40:25 -05:00
Sergey Bugaev
c64c199ab7 LibJS: Don't use MADV_FREE / MADV_DONTNEED on GNU/Hurd
Much like on Serenity itself, these aren't implemented.
2024-01-14 14:56:33 -07:00
Andreas Kling
ee3d09f225 LibJS: Show class in SerenityOS mmap name for type-specific allocators 2023-12-31 15:35:56 +01:00
Andreas Kling
b6d4eea7ac LibJS: Never give back virtual memory once it belongs to a cell type
Instead of returning HeapBlock memory to the kernel (or a non-type
specific shared cache), we now keep a BlockAllocator per CellAllocator
and implement "deallocation" by basically informing the kernel that we
don't need the physical memory right now.

This is done with MADV_FREE or MADV_DONTNEED if available, but for other
platforms (including SerenityOS) we munmap and then re-mmap the memory
to achieve the same effect. It's definitely clunky, so I've added a
FIXME about implementing the madvise options on SerenityOS too.

The important outcome of this change is that GC types that use a
type-specific allocator become immune to use-after-free type confusion
attacks, since their virtual addresses will only ever be re-used for
the same exact type again and again.

Fixes #22274
2023-12-31 15:35:56 +01:00
Andreas Kling
6c1fcc5f7e LibJS: Actually invoke the type-isolating cell allocators
Due to a `requires` mistake, we were always using the fallback
size-based cell allocators.

Also, now that we start using them, make them NeverDestroyed so
we don't try to deallocate them on program exit.
2023-12-23 23:02:10 +01:00
Andreas Kling
11c968fa1f LibJS: Make Heap aware of all CellAllocators
Also add a link from HeapBlock to their owning CellAllocator.
This fixes an issue where the Heap would skip over non-size-based
cell allocators.
2023-12-23 23:02:10 +01:00
Ali Mohammad Pur
5e1499d104 Everywhere: Rename {Deprecated => Byte}String
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).

This commit is auto-generated:
  $ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
    Meta Ports Ladybird Tests Kernel)
  $ perl -pie 's/\bDeprecatedString\b/ByteString/g;
    s/deprecated_string/byte_string/g' $xs
  $ clang-format --style=file -i \
    $(git diff --name-only | grep \.cpp\|\.h)
  $ gn format $(git ls-files '*.gn' '*.gni')
2023-12-17 18:25:10 +03:30
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
Aliaksandr Kalenik
57e5abae92 LibJS+LibWebView+WebContent+Ladybird: Output GC-graph into a file
Instead of displaying a massive JSON in stdout, it's more practical
to save the GC-graph to a file.
2023-12-12 15:35:35 +01:00
Dan Klishch
96d44b1572 Userland: Make bit-fields compatible with MSVC C++ ABI 2023-12-07 10:28:19 -07: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
84a8ee01e1 LibJS: Lower HeapBlock size to 4 KiB
This is to prepare for making per-type allocators, since we'll have a
*lot* more HeapBlocks in that world.
2023-11-19 12:10:31 +01:00
Tim Schumacher
a2f60911fe AK: Rename GenericTraits to DefaultTraits
This feels like a more fitting name for something that provides the
default values for Traits.
2023-11-09 10:05:51 -05:00
Andreas Kling
8a727abd23 LibJS: Move Heap intrusive list manipulation inline
The functions for registering and unregistering MarkedVector, Handle,
etc. were quite prominent in benchmark profiles.

4% speed-up on the entire Kraken benchmark :^)
(including: 7% speed-up on Kraken/imaging-gaussian-blur.js, the current
slowest subtest)
2023-10-07 11:36:28 +02:00
Andreas Kling
a54e283901 LibJS: Fix two bugs in the GC fast rejection of possible pointers
- Convert to FlatPtr instead of doing pointer arithmetic on a too-large
  pointer type in find_min_and_max_block_addresses(). This makes the
  range more accurate.

- Untag possible cell pointers in add_possible_value() before doing the
  rejection. Otherwise we end up rejecting most pointers since the tags
  sit in the highest bits!

This fixes a crash when running the Speedometer benchmark.
2023-09-30 09:50:55 +02:00
Aliaksandr Kalenik
e79d4f3462 LibJS: Early reject pointers outside of allocated blocks range in GC
This change adds a check to discard pointers that are lower than the
minimum address of all allocated blocks or higher than the maximum
address of all blocks. By doing this we avoid executing plenty of set()
operations on the HashMap in the add_possible_value().

With this change gather_conservative_roots() run 10x times faster in
Speedometer React-Redux-TodoMVC test.
2023-09-30 08:07:12 +02:00
Aliaksandr Kalenik
c46ce53ce3 LibJS: Declare HeapFunction::function() with [[nodiscard]] 2023-09-26 19:42:59 +02:00
Hendiadyoin1
12c6692611 LibJS: Defer GC during cell construction
This stops us from trying to collect not fully constructed Cells,
which's vtables are not fully initialized, which would cause issues
during GC.
2023-09-25 13:19:25 +02:00
Hendiadyoin1
87e063db65 LibJS: Make GC deferral friendship based 2023-09-25 13:19:25 +02:00
Aliaksandr Kalenik
719a00df3a LibJS: Add source location for Handle nodes in GC graph dumper output
With this change JS::Handle root nodes will contain source location
where they were constructed like:
```
    "94675029575744": {
        "root": "Handle activate_event_handler \
           serenity/Userland/Libraries/LibWeb/DOM/EventTarget.cpp:564",
        "class_name": "HTMLButtonElement",
        "edges": [
            "94675025955904",
            "94675026899520",
            "94675030831168",
```
2023-09-24 14:55:32 +02:00
Andreas Kling
9220c68408 LibJS: Avoid pointless HashTable copying during GC mark phase
for_each_cell_among_possible_pointers() was taking HashTable by value
instead of by const reference for no reason.

The copying was soaking up ~4% of CPU time while loading https://x.com/
2023-09-15 12:12:54 +02:00
Andrew Kaster
96600e77c2 LibJS: Enable storing Value and Handle<Value> in HashMaps
We have the right conversions to make this work, so let's make it
possible to have a `HashMap<JS::Handle<T>, V>` and look for a specific
T inside it without having to create a temporary handle.

This involves adding some operator== implementations, and some
specializations of AK::Traits.
2023-08-22 13:08:08 +02:00
Aliaksandr Kalenik
469aea5a5b AK+LibJS: Introduce JS::HeapFunction
This change introduces HeapFunction, which is intended to be used as a
replacement for SafeFunction. The new type behaves like a regular
GC-allocated object, which means it needs to be visited from
visit_edges, and unlike SafeFunction, it does not create new roots for
captured parameters.

Co-Authored-By: Andreas Kling <kling@serenityos.org>
2023-08-19 05:03:17 +02:00
Aliaksandr Kalenik
0ff29349e6 LibJS: Add GC graph dumper
This change introduces a very basic GC graph dumper. The `dump_graph()`
function outputs JSON data that contains information about all nodes in
the graph, including their class types and edges.

Root nodes will have a property indicating their root type or source
location if the root is captured by a SafeFunction. It would be useful
to add source location for other types of roots in the future.

Output JSON dump have following format:
```json
    "4908721208": {
        "class_name": "Accessor",
        "edges": [
            "4909298232",
            "4909297976"
        ]
    },
    "4907520440": {
        "root": "SafeFunction Optional Optional.h:137",
        "class_name": "Realm",
        "edges": [
            "4908269624",
            "4924821560",
            "4908409240",
            "4908483960",
            "4924527672"
        ]
    },
    "4908251320": {
        "class_name": "CSSStyleRule",
        "edges": [
            "4908302648",
            "4925101656",
            "4908251192"
        ]
    },
```
2023-08-17 18:27:02 +02:00
Daniel Bertalan
65232b6681 LibJS: Mark classes and virtual functions final where possible
These cases were found with GCC's `-Wsuggest-final-{types,methods}`
warnings, which catch calls that could have been devirtualized had we
declared the functions `final` in the source.

To reproduce, Link Time Optimization needs to be enabled. The easiest
way to achieve this is to set the `CMAKE_INTERPROCEDURAL_OPTIMIZATION`
cache variable to `ON`. The `.incbin` directive in LibCompress' Brotli
decompressor might needs to be changed to an absolute path for this to
work.

This commit also removes a pair of unused virtual functions.
2023-08-13 18:05:09 +02:00
Andreas Kling
72c9f56c66 LibJS: Make Heap::allocate<T>() infallible
Stop worrying about tiny OOMs. Work towards #20449.

While going through these, I also changed the function signature in many
places where returning ThrowCompletionOr<T> is no longer necessary.
2023-08-13 15:38:42 +02:00
Aliaksandr Kalenik
d978c762bc LibJS: Remove usage of bytecode_interpreter_if_exists()
There is no need to check if bytecode interpreter exists after we
switched away from AST interpreter.
2023-08-12 08:46:35 +02:00
flofriday
a2abc5b824 LibJS: Improve garbage collection trigger condition
This patch triggers the collector when allocated memory doubles instead
of every 100k allocations. Which can almost half (reduce by ~48%) the
time spent on collection when loading google-maps.

This dynamic approach is inspired by some other GCs like Golang's and
Lua's and improves performance in memory heavy applications because
marking must visit old objects which will dominate the marking phase if
the GC is invoked too often.

This commit also improves the Octane Splay benchmark and almost
doubles it :^)
2023-08-09 18:32:19 +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