The Heap::uproot_cell() API was used to implement markAsGarbage() which
was used in 3 tests to forcibly destroy a value, even if it had
references on the stack or elsewhere.
This patch rewrites the 3 tests that used this mechanism to be
structured in a way that allows garbage collection to collect the values
as intended without hacks. And now that the uprooting mechanism is no
longer needed, it's uprooted as well.
This fixes 3 test-js tests in bytecode mode. :^)
Cell::heap() and Cell::vm() needed to access member functions from
HeapBlock, and wanted to be inline, so they were moved to VM.h.
That approach will no longer work with VM.h not being included in every
file (starting from the next commit), so this commit fixes that circular
import issue by introducing secondary base classes to host the
references to Heap and VM, respectively.
Since the relationship between VM and Bytecode::Interpreter is now
clear, we can have VM ask the Interpreter for roots in the GC marking
pass. This avoids having to register and unregister handles and
MarkedVectors over and over.
Since GeneratorObject can also own a RegisterWindow, we share the code
in a RegisterWindow::visit_edges() helper.
~4% speed-up on Kraken/stanford-crypto-ccm.js :^)
This is a similar strategy to what v8 does. Use the ASAN API function
__asan_addr_is_in_fake_stack to check any fake stack frames associated
with each stack address we scan. This fully allows running test-js -g
with the option detect_stack_use_after_return turned on.
That's what this class really is; in fact that's what the first line of
the comment says it is.
This commit does not rename the main files, since those will contain
other time-related classes in a little bit.
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.
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).
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.
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.
This will temporarily bloat the size of PrimitiveString as LibJS is
transitioned to use String throughout, but will make doing so piecemeal
much easier.
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.
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.
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.
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.
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.
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.
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. :^)
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#15290FixesSerenityOS/ladybird#56
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.
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.
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
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().