2021-12-16 17:54:06 +00:00
|
|
|
/*
|
2024-10-04 11:19:50 +00:00
|
|
|
* Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
|
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 09:40:49 +00:00
|
|
|
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
2021-12-16 17:54:06 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
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 13:34:19 +00:00
|
|
|
#include <AK/HashMap.h>
|
2021-12-16 17:54:06 +00:00
|
|
|
#include <AK/IntrusiveList.h>
|
|
|
|
#include <AK/Vector.h>
|
2024-11-14 15:01:23 +00:00
|
|
|
#include <LibGC/Cell.h>
|
|
|
|
#include <LibGC/Forward.h>
|
|
|
|
#include <LibGC/HeapRoot.h>
|
2021-12-16 17:54:06 +00:00
|
|
|
|
2024-11-14 15:01:23 +00:00
|
|
|
namespace GC {
|
2021-12-16 17:54:06 +00:00
|
|
|
|
|
|
|
class MarkedVectorBase {
|
|
|
|
public:
|
2024-11-14 15:01:23 +00:00
|
|
|
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>&) const = 0;
|
2021-12-16 17:54:06 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit MarkedVectorBase(Heap&);
|
|
|
|
~MarkedVectorBase();
|
|
|
|
|
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 09:40:49 +00:00
|
|
|
MarkedVectorBase& operator=(MarkedVectorBase const&);
|
2021-12-16 17:54:06 +00:00
|
|
|
|
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 09:40:49 +00:00
|
|
|
Heap* m_heap { nullptr };
|
2021-12-16 17:54:06 +00:00
|
|
|
IntrusiveListNode<MarkedVectorBase> m_list_node;
|
|
|
|
|
|
|
|
public:
|
|
|
|
using List = IntrusiveList<&MarkedVectorBase::m_list_node>;
|
|
|
|
};
|
|
|
|
|
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 09:40:49 +00:00
|
|
|
template<typename T, size_t inline_capacity>
|
2023-08-13 10:53:46 +00:00
|
|
|
class MarkedVector final
|
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 09:40:49 +00:00
|
|
|
: public MarkedVectorBase
|
|
|
|
, public Vector<T, inline_capacity> {
|
|
|
|
|
2021-12-16 17:54:06 +00:00
|
|
|
public:
|
|
|
|
explicit MarkedVector(Heap& heap)
|
|
|
|
: MarkedVectorBase(heap)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
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 09:40:49 +00:00
|
|
|
virtual ~MarkedVector() = default;
|
2021-12-16 17:54:06 +00:00
|
|
|
|
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 09:40:49 +00:00
|
|
|
MarkedVector(MarkedVector const& other)
|
|
|
|
: MarkedVectorBase(*other.m_heap)
|
|
|
|
, Vector<T, inline_capacity>(other)
|
|
|
|
{
|
|
|
|
}
|
2021-12-16 17:54:06 +00:00
|
|
|
|
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 09:40:49 +00:00
|
|
|
MarkedVector(MarkedVector&& other)
|
|
|
|
: MarkedVectorBase(*other.m_heap)
|
|
|
|
, Vector<T, inline_capacity>(move(static_cast<Vector<T, inline_capacity>&>(other)))
|
|
|
|
{
|
|
|
|
}
|
2021-12-16 17:54:06 +00:00
|
|
|
|
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 09:40:49 +00:00
|
|
|
MarkedVector& operator=(MarkedVector const& other)
|
|
|
|
{
|
|
|
|
Vector<T, inline_capacity>::operator=(other);
|
|
|
|
MarkedVectorBase::operator=(other);
|
|
|
|
return *this;
|
|
|
|
}
|
2021-12-16 17:54:06 +00:00
|
|
|
|
2024-11-14 15:01:23 +00:00
|
|
|
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
|
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 09:40:49 +00:00
|
|
|
{
|
|
|
|
for (auto& value : *this) {
|
2024-11-14 15:01:23 +00:00
|
|
|
if constexpr (IsBaseOf<NanBoxedValue, T>) {
|
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 09:40:49 +00:00
|
|
|
if (value.is_cell())
|
2023-09-22 00:04:16 +00:00
|
|
|
roots.set(&const_cast<T&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::MarkedVector });
|
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 09:40:49 +00:00
|
|
|
} else {
|
2023-09-22 00:04:16 +00:00
|
|
|
roots.set(value, HeapRoot { .type = HeapRoot::Type::MarkedVector });
|
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 09:40:49 +00:00
|
|
|
}
|
|
|
|
}
|
2023-07-08 02:48:11 +00:00
|
|
|
}
|
2021-12-16 17:54:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|