Age | Commit message (Collapse) | Author |
|
This option is already enabled when building Lagom, so let's enable it
for the main build too. We will no longer be surprised by Lagom Clang
CI builds failing while everything compiles locally.
Furthermore, the stronger `-Wsuggest-override` warning is enabled in
this commit, which enforces the use of the `override` keyword in all
classes, not just those which already have some methods marked as
`override`. This works with both GCC and Clang.
|
|
|
|
This isn't a complete conversion to ErrorOr<void>, but a good chunk.
The end goal here is to propagate buffer allocation failures to the
caller, and allow the use of TRY() with formatting functions.
|
|
WeakContainers need to look at the Cell::State bits to know if their
weak pointees got swept by garbage collection. So we must do this before
potentially freeing one or more HeapBlocks by notifying the allocator
that a block became empty.
|
|
|
|
Let's accept keeping up to 8 MiB of HeapBlock memory cached. This allows
the GC allocator to reuse memory instead of asking the kernel for more.
|
|
Instead of iterating *all* swept cells when pruning weak containers,
only iterate the cells actually *in* the container.
Also, instead of compiling a list of all swept cells, we can simply
check the Cell::state() flag to know if something should be pruned.
|
|
Since this is a debug-only feature, let's not have it impact GC marking
performance when you don't need it.
|
|
VM now has a string cache which tracks all live PrimitiveStrings and
reuses an existing one if possible. This drastically reduces the number
of GC-allocated strings in many real-word situations.
|
|
The way that transition avoidance (foo_without_transition) was
implemented led to shapes being unshareable and caused shape explosion
instead, precisely what we were trying to avoid.
This patch removes all the attempts to avoid transitioning shapes, and
instead *adds* transitions when changing an object's prototype.
This makes transitions flow naturally, and as a result we end up with
way fewer shape objects in real-world situations.
When we run out of big problems, we can get back to avoiding transitions
as an optimization, but for now, let's avoid ballooning our processes
with a unique shape for every object.
|
|
This patch ups the max number of heap allocations between each GC
from 10'000 to 100'000. This is still relatively aggressive but already
does a good job of cutting down on time spent in GC.
|
|
Default implementations allow for more optimizations.
See: https://pvs-studio.com/en/docs/warnings/v832/
|
|
|
|
When poisoning HeapBlock::m_storage, we have to compute the storage size
by excluding the HeapBlock header.
|
|
This patch adds a `-z` option to js and test-js. When run in this mode,
garbage cells are never actually destroyed. We instead keep them around
in a special zombie state.
This allows us to validate that zombies don't get marked in future GC
scans (since there were not supposed to be any more references!) :^)
Cells get notified when they become a zombie (via did_become_zombie())
and this is used by WeakContainer cells to deregister themselves from
the heap.
|
|
Make this API take a Span<Cell*> instead of a Vector<Cell*>&.
This is behavior neutral, but stops the API looking like it wants to
do mutable things to the Vector.
|
|
This makes the user-facing type only take the node member pointer, and
lets the compiler figure out the other needed types from that.
|
|
This should fix the flaky tests of test-js.
It also fixes the tests when running with the -g flag since the values
will not be garbage collected too soon.
|
|
|
|
- Replace the misleading abuse of the m_transitions_enabled flag for the
fast path without lookup with a new m_initialized boolean that's set
either by Heap::allocate() after calling the Object's initialize(), or
by the GlobalObject in its special initialize_global_object(). This
makes it work regardless of the shape's uniqueness.
- When we're adding a new property past the initialization phase,
there's no need to do a second metadata lookup to retrieve the storage
value offset - it's known to always be the shape's property count
minus one. Also, instead of doing manual storage resizing and
assignment via indexing, just use Vector::append().
- When we didn't add a new property but are overwriting an existing one,
the property count and therefore storage value offset doesn't change,
so we don't have to retrieve it either.
As a result, Object::set_shape() is now solely responsible for updating
the m_shape pointer and is not resizing storage anymore, so I moved it
into the header.
|
|
Making userspace provide a global string ID was silly, and made the API
extremely difficult to use correctly in a global profiling context.
Instead, simply make the kernel do the string ID allocation for us.
This also allows us to convert the string storage to a Vector in the
kernel (and an array in the JSON profile data.)
|
|
|
|
|
|
Almost everything in LibJS includes Cell.h, don't force all code to
include AK/TypeCasts.h + AK/String.h. Instead include them where they
are actually used and required.
|
|
|
|
|
|
This allows us to remove a HashTable from heap and cuts down on
some of the malloc traffic when creating handles.
|
|
"Records" in the spec are basically C++ classes, so let's drop this
mouthful of a suffix.
|
|
|
|
Previously, EnvironmentRecord was a JS::Object. This was done because
GlobalObject inherited from EnvironmentRecord. Now that this is no
longer the case, we can simplify things by making EnvironmentRecord
inherit from Cell directly.
This also removes the need for environment records to have a shape,
which was awkward. This will be removed in the following patch.
|
|
These are just ignored by the BlockAllocator anyway.
|
|
This will allow us to use the same interface for other JS weak
containers like the WeakMap & WeakRef.
|
|
This is an implementation of the following optional optimization:
https://tc39.es/ecma262/#sec-weakref-execution
|
|
If we can't get a CellAllocator for the requested cell size, at least
print a debug message before dying.
|
|
Mark the entirety of a heap block's storage poisoned at construction.
Unpoison all of a Cell's memory before allocating it, and re-poison as
much as possible on deallocation. Unfortunately, the entirety of the
FreelistEntry must be kept unpoisoned in order for reallocation to work
correctly.
Decreasing the size of FreelistEntry or adding a larger redzone to Cells
would make the instrumentation even better.
|
|
Use this to avoid creating a 16 byte cell allocator on x86_64, where the
size of FreelistEntry is 24 bytes. Every JS::Cell must be at least the
size of the FreelistEntry or things start crashing, so the 16 byte
allocator was wasted on that platform.
|
|
FreelistEntries are constructed manually in deallocate() instead of
using this helper.
|
|
This is the coarsest grained ASAN instrumentation possible for the LibJS
heap. Future instrumentation could add red-zones to heap block
allocations, and poison the entire heap block and only un-poison used
cells at the CellAllocator level.
|
|
There's no need to dynamically allocate a constant sized vector :^)
|
|
Fixes #7507.
|
|
The previous VERIFY() call checked that aligned_alloc() didn't return
MAP_FAILED. When out of memory aligned_alloc() returns a null pointer
so let's check for that instead.
|
|
|
|
If we use aligned_alloc() to allocate, we have to use free() to free.
|
|
Now that we have a BlockAllocator as well, it seems appropriate to name
the allocator-that-allocates-cells something more specific to match.
|
|
This patch adds a BlockAllocator to the GC heap where we now cache up to
64 HeapBlock-sized mmap's that get recycled when allocating HeapBlocks.
This improves test-js runtime performance by ~35%, pretty cool! :^)
|
|
|
|
|
|
|
|
Passing a null cell pointer is not supported.
|
|
So far we only have two states: Live and Dead. In the future, we can
add additional states to support incremental sweeping and/or multi-
stage cell destruction.
|