Commit graph

131 commits

Author SHA1 Message Date
Matthew Olsson
7c0c1c8f49 LibJS+LibWeb: Wrap raw JS::Cell*/& fields in GCPtr/NonnullGCPtr 2023-03-15 08:48:49 +01:00
Matthew Olsson
1df3652e27 LibJS: Allow constructing a Handle<T> from a {Nonnull,}GCPtr<T> 2023-03-15 08:48:49 +01:00
Matthew Olsson
5094dcf615 LibJS: Allow constructing a GCPtr from another GCPtr of convertible type 2023-03-15 08:48:49 +01:00
Matthew Olsson
93a5a54927 LibJS: Allow GCPtr and NonnullGCPtr to be hashed 2023-03-15 08:48:49 +01:00
Andreas Kling
d21d1d99bd LibJS: Don't skip CPU registers when gathering conservative roots
We were accidentally skipping over most of the CPU registers by
incrementing the register index by sizeof(FlatPtr) instead of 1.

This fixes a long-standing issue where live objects could still get
garbage-collected if they were only pointed to by an unlucky register.
2023-03-13 20:50:38 +01:00
Matthew Olsson
176beeb08e LibJS: Enforce proper const-propogation with {Nonnull,}GCPtr 2023-03-06 13:05:43 +00:00
Matthew Olsson
70a2ca7fc0 LibJS: Handle both const and non-const Ts in Handle<T>::create()
Again, the const-ness only really involves Heap-internal metadata, so
the callers shouldn't care about mutations here.
2023-03-06 13:05:43 +00:00
Matthew Olsson
5f0ccfb499 LibJS: Accept const GCPtrs in Cell::Visitor
The const_cast in these methods should be fine since the object really
only needs to be mutable so it's Heap-internal metadata can be altered.
2023-03-06 13:05:43 +00:00
Matthew Olsson
17a528c49e LibJS: Temporarily disambiguate const-ness of GCPtr constructors
Without this change, using {Nonnull,}GCPtr<T const> would complain that
there are multiple constructors which resolve to the same type (T& and
T const&). This removes that disambiguation and allows us to slowly fix
all of the constness issues surrounding GCPtrs. This change will not be
necessary in the future as we will be able to remove all of the const
qualifiers from the Ptr classes (they'll be in the template type
instead).
2023-03-06 13:05:43 +00:00
Timothy Flynn
b75b7f0c0d LibJS+Everywhere: Propagate Cell::initialize errors from Heap::allocate
Callers that are already in a fallible context will now TRY to allocate
cells. Callers in infallible contexts get a FIXME.
2023-01-29 00:02:45 +00:00
Timothy Flynn
2692db8699 LibJS+Everywhere: Allow Cell::initialize overrides to throw OOM errors
Note that as of this commit, there aren't any such throwers, and the
call site in Heap::allocate will drop exceptions on the floor. This
commit only serves to change the declaration of the overrides, make sure
they return an empty value, and to propagate OOM errors frm their base
initialize invocations.
2023-01-29 00:02:45 +00:00
Timothy Flynn
1c1b902a6a LibJS+LibWeb: Move headers around to allow including Value from Cell
The goal here is to allow Cell::initialize to return a ThrowCompletion,
to handle OOM for example. Cell.h will then need to include Completion.h
which must include Value.h. This currently can't happen because Value.h
includes BigInt.h, which in turn includes Cell.h. So we would have an
include cycle.

This removes BigInt.h from Value.h, as it is forward-declarable (it is
only referred to with a reference or pointer). Then the Value overload
for Cell::Visitor::visit is moved to Cell.h, and missing BigInt.h
includes as peppered as needed.
2023-01-29 00:02:45 +00:00
Timothy Flynn
8f5bdce8e7 LibJS: Add initial support for creating PrimitiveStrings with AK::String
This will temporarily bloat the size of PrimitiveString as LibJS is
transitioned to use String throughout, but will make doing so piecemeal
much easier.
2023-01-15 01:00:20 +00:00
Timothy Flynn
ca655f5e7d LibJS: Rename VM::string_cache to deprecated_string_cache
And rename the member variable from m_string_cache to
m_deprecated_string_cache to match.
2023-01-15 01:00:20 +00:00
Andreas Kling
7826cb2556 LibJS: Use a work queue instead of the C++ stack for the GC mark phase
This fixes an issue where we'd run out of C++ stack while traversing
large GC heap graphs.
2023-01-10 15:30:07 -05:00
Andrew Kaster
4e7bdcfeea LibJS: Only start ElapsedTimer for GC metrics when printing is enabled
We don't need to be checking the current time unconditionally when we
only observe the results if we're going to dump the GC stats.

This saves two trips to clock_gettime at the cost of an extra branch.
2023-01-07 14:51:04 +01:00
Linus Groh
22089436ed LibJS: Convert Heap::allocate{,_without_realm}() to NonnullGCPtr 2022-12-15 06:56:37 -05:00
Linus Groh
2a66fc6cae LibJS: Add make_handle({Nonnull,}GCPtr<T>) overloads 2022-12-15 06:56:37 -05:00
Andreas Kling
d5ed07fdc4 LibJS+LibWeb: Remove NonnullGCPtr<T>::operator=(GCPtr<T>) footgun
GCPtr can be null so it's not safe to assign it to a NonnullGCPtr unless
you know it to be non-null.

This exposed a number of wrong uses in LibWeb which had to be fixed as
part of this change.
2022-12-14 15:21:15 +01:00
Ali Mohammad Pur
f96a3c002a Everywhere: Stop shoving things into ::std and mentioning them as such
Note that this still keeps the old behaviour of putting things in std by
default on serenity so the tools can be happy, but if USING_AK_GLOBALLY
is unset, AK behaves like a good citizen and doesn't try to put things
in the ::std namespace.

std::nothrow_t and its friends get to stay because I'm being told that
compilers assume things about them and I can't yeet them into a
different namespace...for now.
2022-12-14 11:44:32 +01:00
Timothy Flynn
0ec433edce LibJS: Explictly assert that a null GCPtr is not dereferenced 2022-12-14 09:59:35 +00:00
Linus Groh
d26aabff04 Everywhere: Run clang-format 2022-12-03 23:52:23 +00:00
MacDue
66a428ae03 LibJS+LibWeb: Return non-const types from Ptr class operators
Even if the pointer value is const, the value they point to is not
necessarily const, so these functions should not add the qualifier.

This also removes the redundant non-const implementations of these
operators.
2022-11-19 14:37:31 +00:00
Andreas Kling
0e232b1c8d LibJS: Only use 1 bit for Cell boolean flag 2022-10-24 19:37:36 +02:00
Andreas Kling
51579810bd LibJS: Add Cell::must_survive_garbage_collection() mechanism
This allows cells to prevent themselves from being garbage collected,
even when there are no references to them.
2022-10-24 18:06:55 +02:00
Andreas Kling
07a36c8f80 LibJS: Add a finalization pass to the garbage collector
Doing things in the destructor of a GC-allocated object isn't always
safe, in case it involves accessing other GC-allocated objects.
If they were already swept by GC, we'd be poking into freed memory.

This patch adds a separate finalization pass where GC calls finalize()
on every unmarked cell that's about to be deleted.

It's safe to access other GC objects in finalize(), even if they're
also unmarked.
2022-10-20 19:36:59 +02:00
Andreas Kling
738e770fce LibJS: Remove unnecessary operator==() for ({Nonnull,}GCPtr<T>, T*)
These aren't necessary in the first place since {Nonnull,}GCPtr has
operator T*()
2022-10-20 15:16:23 +02:00
Andrew Kaster
828441852f Everywhere: Replace uses of __serenity__ with AK_OS_SERENITY
Now that we have OS macros for essentially every supported OS, let's try
to use them everywhere.
2022-10-10 12:23:12 +02:00
Linus Groh
0585029c30 LibJS: Add Visitor::visit(GCPtr<T>) and Visitor::visit(NonnullGCPtr<T>)
Let's avoid reaching for ptr() as much as possible.
2022-10-02 23:02:27 +01:00
Idan Horowitz
4aade74b91 LibJS: Include Environment.h directly in ClassFieldDefinition.h
This was previously indirectly forcing Heap/Handle.h to include it
instead. This will let us include Handle.h from PropertyKey, which will
allow us to solve a different issue.
2022-10-01 15:36:20 +01:00
Andreas Kling
131c3f50de LibJS: Add JS::SafeFunction, like Function but protects captures from GC
SafeFunction automatically registers its closure memory area in a place
where the JS garbage collector can find it.

This means that you can capture JS::Value and arbitrary pointers into
the GC heap in closures, as long as you're using a SafeFunction, and the
GC will not zap those values!

There's probably some performance impact from this, and there's a lot of
things that could be nicer/smarter about it, but let's build something
that ensures safety first, and we can worry about performance later. :^)
2022-09-24 12:23:29 +02:00
Daniel Bertalan
2b69af2dfe AK+LibJS: Handle NaN-boxing pointers on AArch64
JS::Value stores 48 bit pointers to separately allocated objects in its
payload. On x86-64, canonical addresses have their top 16 bits set to
the same value as bit 47, effectively meaning that the value has to be
sign-extended to get the pointer. AArch64, however, expects the topmost
bits to be all zeros.

This commit gates sign extension behind `#if ARCH(X86_64)`, and adds an
`#error` for unsupported architectures, so that we do not forget to
think about pointer handling when porting to a new architecture.

Fixes #15290
Fixes SerenityOS/ladybird#56
2022-09-21 11:55:57 +02:00
Andreas Kling
6f433c8656 LibWeb+LibJS: Make the EventTarget hierarchy (incl. DOM) GC-allocated
This is a monster patch that turns all EventTargets into GC-allocated
PlatformObjects. Their C++ wrapper classes are removed, and the LibJS
garbage collector is now responsible for their lifetimes.

There's a fair amount of hacks and band-aids in this patch, and we'll
have a lot of cleanup to do after this.
2022-09-06 00:27:09 +02:00
Andreas Kling
63cc2650e3 LibJS: Make Handle<T> more user-friendly
Allow *handle, !handle, handle.ptr(), assignment from compatible
pointer types, etc. This is in preparation for using Handles in
more generated code.
2022-09-03 00:36:26 +02:00
Andreas Kling
01828edd37 LibJS: Add Cell::Visitor::visit(Cell&) 2022-09-03 00:36:26 +02:00
Andreas Kling
e34e21367e LibJS: Add GCPtr and NonnullGCPtr
These are two new smart pointers that are really just raw pointers under
the hood. The initial benefit is all in the names, they allow us to
declare that we're pointing at something in the GC heap.

Later we may also find ways to add debugging logic or static analysis to
these types.
2022-09-03 00:36:26 +02:00
Andreas Kling
d54ba587f3 LibJS: Make Heap a friend of everyone who uses JS_CELL
This will allow Heap to invoke non-public constructors when allocating
new cells.
2022-08-29 03:24:54 +02:00
Andreas Kling
6e973ce69b LibJS: Add JS_CELL macro and use it in all JS::Cell subclasses
This is similar to what we already had with JS_OBJECT (and also
JS_ENVIRONMENT) but sits at the top of the Cell inheritance hierarchy.
2022-08-29 03:24:54 +02:00
Linus Groh
f3117d46dc LibJS: Remove GlobalObject from VM::throw_completion()
This is a continuation of the previous five commits.

A first big step into the direction of no longer having to pass a realm
(or currently, a global object) trough layers upon layers of AOs!
Unlike the create() APIs we can safely assume that this is only ever
called when a running execution context and therefore current realm
exists. If not, you can always manually allocate the Error and put it in
a Completion :^)

In the spec, throw exceptions implicitly use the current realm's
intrinsics as well: https://tc39.es/ecma262/#sec-throw-an-exception
2022-08-23 13:58:30 +01:00
Linus Groh
e992a9f469 LibJS+LibWeb: Replace GlobalObject with Realm in Heap::allocate<T>()
This is a continuation of the previous three commits.

Now that create() receives the allocating realm, we can simply forward
that to allocate(), which accounts for the majority of these changes.
Additionally, we can get rid of the realm_from_global_object() in one
place, with one more remaining in VM::throw_completion().
2022-08-23 13:58:30 +01:00
Linus Groh
b99cc7d050 LibJS+LibWeb: Replace GlobalObject with Realm in create() functions
This is a continuation of the previous two commits.

As allocating a JS cell already primarily involves a realm instead of a
global object, and we'll need to pass one to the allocate() function
itself eventually (it's bridged via the global object right now), the
create() functions need to receive a realm as well.
The plan is for this to be the highest-level function that actually
receives a realm and passes it around, AOs on an even higher level will
use the "current realm" concept via VM::current_realm() as that's what
the spec assumes; passing around realms (or global objects, for that
matter) on higher AO levels is pointless and unlike for allocating
individual objects, which may happen outside of regular JS execution, we
don't need control over the specific realm that is being used there.
2022-08-23 13:58:30 +01:00
Linus Groh
5dd5896588 LibJS+LibWeb: Replace GlobalObject with Realm in initialize() functions
This is a continuation of the previous commit.

Calling initialize() is the first thing that's done after allocating a
cell on the JS heap - and in the common case of allocating an object,
that's where properties are assigned and intrinsics occasionally
accessed.
Since those are supposed to live on the realm eventually, this is
another step into that direction.
2022-08-23 13:58:30 +01:00
davidot
e746360b9a LibJS: Use NaN boxing to decrease the memory size of Values
Using the fact that there are 2^52-2 NaN representations we can
"NaN-box" all the Values possible. This means that Value no longer has
an explicit "Type" but that information is now stored in the bits of a
double. This is done by "tagging" the top two bytes of the double.
For a full explanation see the large comment with asserts at the top of
Value.

We can also use the exact representation of the tags to make checking
properties like nullish, or is_cell quicker. But the largest gains are
in the fact that the size of a Value is now halved.

The SunSpider and other benchmarks have been ran to confirm that there
are no regressions in performance compared to the previous
implementation. The tests never performed worse and in some cases
performed better. But the biggest differences can be seen in memory
usage when large arrays are allocated. A simple test which allocates a
1000 arrays of size 100000 has roughly half the memory usage.

There is also space in the representations for future expansions such as
tuples and records.

To ensure that Values on the stack and registers are not lost during
garbage collection we also have to add a check to the Heap to check for
any of the cell tags and extracting the canonical form of the pointer
if it matches.
2022-08-15 17:11:25 +02:00
sin-ack
7456904a39 Meta+Userland: Simplify some formatters
These are mostly minor mistakes I've encountered while working on the
removal of StringView(char const*). The usage of builder.put_string over
Format<FormatString>::format is preferrable as it will avoid the
indirection altogether when there's no formatting to be done. Similarly,
there is no need to do format(builder, "{}", number) when
builder.put_u64(number) works equally well.

Additionally a few Strings where only constant strings were used are
replaced with StringViews.
2022-07-12 23:11:35 +02:00
Ali Mohammad Pur
5407fe8fcf LibJS: Make Handle<Value>::is_null() also consider the contained value
Previously this would've said `make_handle(Value(1234))` is null, as it
did not contain a cell (but rather a plain Value), which made throwing
primitives spin forever in BC mode.
2022-04-05 11:46:48 +02:00
Idan Horowitz
086969277e Everywhere: Run clang-format 2022-04-01 21:24:45 +01:00
Andreas Kling
7047a5ca59 LibJS: Allow JS::make_handle(T*) to be called with nullptr
Instead of asserting, just return an empty Handle.
2022-03-31 18:25:06 +02:00
Lenny Maiorani
a0367aa43b DevTools+LibJS+LibWeb: Change class_name to use StringView
This helps make the overall codebase consistent. `class_name()` in
`Kernel` is always `StringView`, but not elsewhere.

Additionally, this results in the `strlen` (which needs to be done
when printing or other operations) always being computed at
compile-time.
2022-03-19 00:20:46 +00:00
Lenny Maiorani
d00b79568f Libraries: Use default constructors/destructors in LibJS
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-03-16 16:19:40 +00:00
Linus Groh
7676b1b925 LibJS: Remove MarkedValueList in favor of MarkedVector<Value> :^) 2022-02-09 12:25:27 +00:00