Commit Graph

121 Commits

Author SHA1 Message Date
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
Linus Groh
bc183dbbcb LibJS: Replace uses of MarkedValueList with MarkedVector<Value>
This is effectively a drop-in replacement.
2022-02-09 12:25:27 +00:00
Linus Groh
a863363b06 LibJS: Let MarkedVector<T> inherit from Vector and handle Cell* + Value
Note: MarkedVector is still relatively new and has zero users right now,
so these changes don't affect any code other than the class itself.

Reasons for this are the rather limited API:

- Despite the name and unlike MarkedValueList, MarkedVector isn't
  actually a Vector, it *wraps* a Vector. This means that plenty of
  convenient APIs are unavailable and have to be exported on the class
  separately and forwarded to the internal Vector, or need to go through
  the exposed Span - both not great options.
- Exposing append(Cell*) and prepend(Cell*) on the base class means that
  it was possible to append any Cell type, not just T! All the strong
  typing guarantees are basically gone, and MarkedVector doesn't do much
  more than casting Cells to the appropriate type through the exposed
  Span.

All of this combined means that MarkedVector - in its current form -
doesn't provide much value over MarkedValueList, and that we have to
maintain two separate, yet almost identical classes.

Let's fix this!

The updated MarkedVector steals various concepts from the existing
MarkedValueList, especially the ability to copy. On the other hand, it
remains generic enough to handle both Cell* and Value for T, making
MarkedValueList effectively redundant :^)

Additionally, by inheriting from Vector we get all the current and
future APIs without having to select and expose them separately.

MarkedVectorBase remains and takes care of communicating creation and
destruction of the class to the heap. Visiting the contained values is
handled via a pure virtual method gather_roots(), which is being called
by the Heap's function of the same name; much like the VM has one.
From there, values are added to the roots HashTable if they are cells
for T = Value, and unconditionally for any other T.

As a small additional improvement the template now also takes an
inline_capacity parameter, defaulting to 32, and forwards it to the
Vector template; allowing for possible future optimizations of current
uses of MarkedValueList, which hard-codes it to 32.
2022-02-09 12:25:27 +00:00
Andreas Kling
54d10d8dda LibJS: Add missing include to Handle.h 2022-02-07 21:05:30 +01:00
davidot
8da6c01d8f LibJS: Remove the JS_TRACK_ZOMBIE_CELLS option
This feature had bitrotted somewhat and would trigger errors because
PrimitiveStrings were "destroyed" but because of this mode they were not
removed from the string cache. Even fixing that case running test-js
with the options still failed in more places.
2022-02-05 11:52:51 +01:00
Andreas Kling
6b5f6d6c0e LibJS: Add a 96-byte CellAllocator
Two of our most frequently allocated objects are Shape (88 bytes)
and DeclarativeEnvironment (80 bytes). Putting these into 128-byte
cells was quite wasteful, so let's add a more suitable allocator
for them.
2022-01-31 16:19:23 +01:00
kleines Filmröllchen
145eeb57ab Userland: Remove a bunch of unnecessary Vector imports
How silly :^)
2022-01-28 23:40:25 +01:00
Luke Wilde
c97244d3a5 LibJS: Add Handle specialisation for Value
This allows you to keep an arbitrary JS::Value alive without having to
hook visit_edges somewhere, e.g. by being a NativeFunction that
overrides visit_edges.

For example, this allows you to store JS::Handle<JS::Value> as the key
of a HashMap. This will be used to keep arbitrary Values alive in
the key of a temporary HashMap in Array.prototype.groupByToMap.

Co-authored-by: Ali Mohammad Pur <mpfard@serenityos.org>
2022-01-05 11:21:38 +01:00
Andreas Kling
c175cea32d LibJS: Fix typo in MarkedVector::end() 2021-12-18 11:30:10 +01:00
Andreas Kling
8bb9fe63b7 LibJS: Add MarkedVector<T>
This abstracts a vector of Cell* with a strongly typed span() accessor
that gives you Span<T*> instead of Span<Cell*>.

It is intended to replace MarkedValueList in situations where you only
need to store pointers to Cell (or an even more specific type of Cell).

The API can definitely be improved, it's just the bare basics for now.
2021-12-16 22:48:17 +01:00
Andreas Kling
c26b58bc53 LibJS: Add JS::make_handle(T&)
I'm not sure why we only had a T* variant of this.
2021-12-16 22:48:17 +01:00