LibGC: Default-construct ConservativeVector from the global heap

This commit is contained in:
Shannon Booth 2026-05-19 20:55:11 +02:00 committed by Shannon Booth
parent 387cd6e2e2
commit de6aec04e8
20 changed files with 51 additions and 45 deletions

View file

@ -9,6 +9,11 @@
namespace GC {
ConservativeVectorBase::ConservativeVectorBase()
: ConservativeVectorBase(Heap::the())
{
}
ConservativeVectorBase::ConservativeVectorBase(Heap& heap)
: m_heap(&heap)
{

View file

@ -19,6 +19,7 @@ public:
virtual ReadonlySpan<FlatPtr> possible_values() const = 0;
protected:
ConservativeVectorBase();
explicit ConservativeVectorBase(Heap&);
~ConservativeVectorBase();
@ -35,13 +36,13 @@ class GC_API ConservativeVector final
, public Vector<T, inline_capacity> {
public:
explicit ConservativeVector(Heap& heap)
: ConservativeVectorBase(heap)
ConservativeVector()
: ConservativeVectorBase()
{
}
ConservativeVector(Heap& heap, Vector<T, inline_capacity> const& other)
: ConservativeVectorBase(heap)
ConservativeVector(Vector<T, inline_capacity> const& other)
: ConservativeVectorBase()
, Vector<T, inline_capacity>(other)
{
}

View file

@ -868,7 +868,7 @@ GC::Ref<Module> CyclicModule::get_imported_module(ModuleRequest const& request)
{
// 1. Let records be a List consisting of each LoadedModuleRequest Record r of referrer.[[LoadedModules]]
// such that ModuleRequestsEqual(r, request) is true.
GC::ConservativeVector<LoadedModuleRequest> records(vm().heap());
GC::ConservativeVector<LoadedModuleRequest> records;
for (auto const& r : m_loaded_modules) {
if (module_requests_equal(r, request))
records.append(r);

View file

@ -126,10 +126,10 @@ ThrowCompletionOr<ECMAScriptFunctionObject*> construct_class(
using StaticElement = Variant<ClassFieldDefinition, GC::Ref<ECMAScriptFunctionObject>>;
GC::ConservativeVector<PrivateElement> static_private_methods(vm.heap());
GC::ConservativeVector<PrivateElement> instance_private_methods(vm.heap());
GC::ConservativeVector<ClassFieldDefinition> instance_fields(vm.heap());
GC::ConservativeVector<StaticElement> static_elements(vm.heap());
GC::ConservativeVector<PrivateElement> static_private_methods;
GC::ConservativeVector<PrivateElement> instance_private_methods;
GC::ConservativeVector<ClassFieldDefinition> instance_fields;
GC::ConservativeVector<StaticElement> static_elements;
for (size_t element_index = 0; element_index < blueprint.elements.size(); ++element_index) {
auto const& descriptor = blueprint.elements[element_index];

View file

@ -1467,7 +1467,7 @@ ThrowCompletionOr<void> Object::for_each_own_property_with_enumerability(Functio
PropertyKey property_key;
bool enumerable;
};
GC::ConservativeVector<OwnKey> keys { heap() };
GC::ConservativeVector<OwnKey> keys;
keys.ensure_capacity(indexed_real_size() + shape().property_count() + (has_magical_length_property() ? 1 : 0));
{

View file

@ -117,7 +117,7 @@ Result<GC::Ref<SourceTextModule>, Vector<ParserError>> SourceTextModule::parse_f
if (rust_result->is_error())
return rust_result->release_error();
auto& module_result = rust_result->value();
GC::ConservativeVector<FunctionToInitialize> functions_to_initialize(realm.heap());
GC::ConservativeVector<FunctionToInitialize> functions_to_initialize;
functions_to_initialize.ensure_capacity(module_result.functions_to_initialize.size());
for (auto& f : module_result.functions_to_initialize)
functions_to_initialize.append({ *f.shared_data, move(f.name) });
@ -187,7 +187,7 @@ Result<GC::Ref<SourceTextModule>, Vector<ParserError>> SourceTextModule::parse(S
return rust_result->release_error();
auto& module_result = rust_result->value();
GC::ConservativeVector<FunctionToInitialize> functions_to_initialize(realm.heap());
GC::ConservativeVector<FunctionToInitialize> functions_to_initialize;
functions_to_initialize.ensure_capacity(module_result.functions_to_initialize.size());
for (auto& f : module_result.functions_to_initialize)
functions_to_initialize.append({ *f.shared_data, move(f.name) });

View file

@ -1977,7 +1977,7 @@ RefPtr<StyleValue const> StyleComputer::recascade_font_size_if_needed(DOM::Abstr
// Reconstruct the line of ancestor elements we need to inherit style from, and then do the cascade again
// but only for the font-size property.
GC::ConservativeVector<DOM::AbstractElement> ancestors { heap() };
GC::ConservativeVector<DOM::AbstractElement> ancestors;
for (auto ancestor = abstract_element.element_to_inherit_style_from(); ancestor.has_value(); ancestor = ancestor->element_to_inherit_style_from())
ancestors.append(*ancestor);

View file

@ -323,7 +323,7 @@ void StyleScope::for_each_stylesheet(CascadeOrigin cascade_origin, Function<void
void StyleScope::make_rule_cache_for_cascade_origin(CascadeOrigin cascade_origin, StyleCache& style_cache)
{
GC::ConservativeVector<MatchingRule> matching_rules { m_node->heap() };
GC::ConservativeVector<MatchingRule> matching_rules;
size_t style_sheet_index = 0;
for_each_stylesheet(cascade_origin, [&](auto& sheet) {
auto& rule_caches = [&] -> RuleCaches& {

View file

@ -6484,7 +6484,7 @@ void Document::update_animations_and_send_events(double timestamp)
}
// 4. Let events to dispatch be a copy of docs pending animation event queue.
auto events_to_dispatch = GC::ConservativeVector<Document::PendingAnimationEvent> { vm().heap() };
GC::ConservativeVector<PendingAnimationEvent> events_to_dispatch;
events_to_dispatch.extend(m_pending_animation_event_queue);
// 5. Clear docs pending animation event queue.
@ -7543,7 +7543,7 @@ void Document::remove_render_blocking_element(GC::Ref<Element> element)
void Document::run_fullscreen_steps()
{
// 1. Let pendingEvents be documents list of pending fullscreen events.
auto pending_events = GC::ConservativeVector<PendingFullscreenEvent> { vm().heap() };
GC::ConservativeVector<PendingFullscreenEvent> pending_events;
pending_events.extend(m_pending_fullscreen_events);
// 2. Empty documents list of pending fullscreen events.

View file

@ -249,7 +249,7 @@ bool command_delete_action(DOM::Document& document, Utf16String const&)
// 3. Record the values of the one-node list consisting of node, and let values be the
// result.
auto values = record_the_values_of_nodes(document.heap(), { *node });
auto values = record_the_values_of_nodes({ *node });
// 4. Split the parent of the one-node list consisting of node.
split_the_parent_of_nodes({ *node });
@ -674,7 +674,7 @@ bool command_format_block_action(DOM::Document& document, Utf16String const& val
});
// 7. Record the values of node list, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), node_list);
auto values = record_the_values_of_nodes(node_list);
// 8. For each node in node list, while node is the descendant of an editable HTML element in the same editing host,
// whose local name is a formattable block name, and which is not the ancestor of a prohibited paragraph child,
@ -722,7 +722,7 @@ bool command_format_block_action(DOM::Document& document, Utf16String const& val
});
// 2. Record the values of sublist, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), sublist);
auto values = record_the_values_of_nodes(sublist);
// 3. Remove the first member of node list from its parent, preserving its descendants.
remove_node_preserving_its_descendants(node_list.first());
@ -2185,7 +2185,7 @@ bool command_outdent_action(DOM::Document& document, Utf16String const&)
sublist.append(node_list.take_first());
// 6. Record the values of sublist, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), sublist);
auto values = record_the_values_of_nodes(sublist);
// 7. Split the parent of sublist.
split_the_parent_of_nodes(sublist);

View file

@ -960,7 +960,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
}
// 9. Record the values of children, and let values be the result.
values = record_the_values_of_nodes(document.heap(), children);
values = record_the_values_of_nodes(children);
// 10. While children's first member's parent is not start block, split the parent of children.
while (children.first()->parent() != start_block)
@ -1004,7 +1004,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
nodes_to_move.append(*nodes_to_move.last()->next_sibling());
// 8. Record the values of nodes to move, and let values be the result.
values = record_the_values_of_nodes(document.heap(), nodes_to_move);
values = record_the_values_of_nodes(nodes_to_move);
// 9. For each node in nodes to move, append node as the last child of start block, preserving ranges.
auto new_position = start_block->length();
@ -1031,7 +1031,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
end_block_children.append(child);
return IterationDecision::Continue;
});
values = record_the_values_of_nodes(document.heap(), end_block_children);
values = record_the_values_of_nodes(end_block_children);
// 4. While end block has children, append the first child of end block to start block, preserving ranges.
auto new_position = start_block->length();
@ -1301,7 +1301,7 @@ void fix_disallowed_ancestors_of_node(GC::Ref<DOM::Node> node)
return IterationDecision::Continue;
// 1. Record the values of the one-node list consisting of child, and let values be the result.
auto values = record_the_values_of_nodes(child.heap(), { child });
auto values = record_the_values_of_nodes({ child });
// 2. Split the parent of the one-node list consisting of child.
split_the_parent_of_nodes({ child });
@ -1317,7 +1317,7 @@ void fix_disallowed_ancestors_of_node(GC::Ref<DOM::Node> node)
}
// 3. Record the values of the one-node list consisting of node, and let values be the result.
auto values = record_the_values_of_nodes(node->heap(), { node });
auto values = record_the_values_of_nodes({ node });
// 4. While node is not an allowed child of its parent, split the parent of the one-node list consisting of node.
while (!is_allowed_child_of_node(node, GC::Ref { *node->parent() }))
@ -3005,7 +3005,7 @@ void outdent(GC::Ref<DOM::Node> node)
// 4. Otherwise:
else {
// 1. Record the values of node's children, and let values be the result.
auto values = record_the_values_of_nodes(node->heap(), children);
auto values = record_the_values_of_nodes(children);
// 2. Remove node, preserving its descendants.
remove_node_preserving_its_descendants(node);
@ -3293,10 +3293,10 @@ Vector<RecordedOverride> record_current_states_and_values(DOM::Document const& d
}
// https://w3c.github.io/editing/docs/execCommand/#record-the-values
GC::ConservativeVector<RecordedNodeValue> record_the_values_of_nodes(GC::Heap& heap, Vector<GC::Ref<DOM::Node>> const& node_list)
GC::ConservativeVector<RecordedNodeValue> record_the_values_of_nodes(Vector<GC::Ref<DOM::Node>> const& node_list)
{
// 1. Let values be a list of (node, command, specified command value) triples, initially empty.
GC::ConservativeVector<RecordedNodeValue> values { heap };
GC::ConservativeVector<RecordedNodeValue> values;
// 2. For each node in node list, for each command in the list "subscript", "bold", "fontName",
// "fontSize", "foreColor", "hiliteColor", "italic", "strikethrough", and "underline" in that
@ -4103,7 +4103,7 @@ void toggle_lists(DOM::Document& document, FlyString const& tag_name)
});
// 2. Record the values of children, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), children);
auto values = record_the_values_of_nodes(children);
// 3. Split the parent of children.
split_the_parent_of_nodes(children);
@ -4178,7 +4178,7 @@ void toggle_lists(DOM::Document& document, FlyString const& tag_name)
sublist.append(node_list.take_first());
// 5. Record the values of sublist, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), sublist);
auto values = record_the_values_of_nodes(sublist);
// 6. Split the parent of sublist.
split_the_parent_of_nodes(sublist);
@ -4261,7 +4261,7 @@ void toggle_lists(DOM::Document& document, FlyString const& tag_name)
if (!sublist.is_empty() && is<HTML::HTMLElement>(sublist.first()->parent())
&& static_cast<DOM::Element&>(*sublist.first()->parent()).local_name() == other_tag_name) {
// 1. Record the values of sublist, and let values be the result.
auto values = record_the_values_of_nodes(document.heap(), sublist);
auto values = record_the_values_of_nodes(sublist);
// 2. Split the parent of sublist.
split_the_parent_of_nodes(sublist);

View file

@ -104,7 +104,7 @@ Optional<DOM::BoundaryPoint> previous_equivalent_point(DOM::BoundaryPoint);
void push_down_values(FlyString const&, GC::Ref<DOM::Node>, Optional<Utf16String const&>);
Vector<RecordedOverride> record_current_overrides(DOM::Document const&);
Vector<RecordedOverride> record_current_states_and_values(DOM::Document const&);
GC::ConservativeVector<RecordedNodeValue> record_the_values_of_nodes(GC::Heap&, Vector<GC::Ref<DOM::Node>> const&);
GC::ConservativeVector<RecordedNodeValue> record_the_values_of_nodes(Vector<GC::Ref<DOM::Node>> const&);
void remove_extraneous_line_breaks_at_the_end_of_node(GC::Ref<DOM::Node>);
void remove_extraneous_line_breaks_before_node(GC::Ref<DOM::Node>);
void remove_extraneous_line_breaks_from_a_node(GC::Ref<DOM::Node>);

View file

@ -381,7 +381,7 @@ MultipartParsingErrorOr<GC::ConservativeVector<XHR::FormDataEntry>> parse_multip
auto boundary = maybe_boundary.release_value();
// 3. Let entry list be an empty entry list.
GC::ConservativeVector<XHR::FormDataEntry> entry_list { realm.heap() };
GC::ConservativeVector<XHR::FormDataEntry> entry_list;
// 4. Let position be a pointer to a byte in input, initially pointing at the first byte.
GenericLexer lexer(input);

View file

@ -117,7 +117,7 @@ WebIDL::ExceptionOr<Optional<GC::ConservativeVector<XHR::FormDataEntry>>> constr
auto controls = form.get_submittable_elements();
// 4. Let entry list be a new empty entry list.
GC::ConservativeVector<XHR::FormDataEntry> entry_list { realm.heap() };
GC::ConservativeVector<XHR::FormDataEntry> entry_list;
// 5. For each element field in controls, in tree order:
for (auto const& control : controls) {

View file

@ -2063,7 +2063,7 @@ void Navigable::begin_navigation(NavigateParams params)
// 2. Let entryListForFiring be formDataEntryList if documentResource is a POST resource; otherwise, null.
auto entry_list_for_firing = [&]() -> Optional<GC::ConservativeVector<XHR::FormDataEntry>> {
if (document_resource.has<POSTResource>())
return GC::ConservativeVector { vm.heap(), params.form_data_entry_list.value() };
return GC::ConservativeVector { params.form_data_entry_list.value() };
return {};
}();

View file

@ -2027,7 +2027,7 @@ GC::Ref<JS::Array> retrieve_multiple_items_from_an_object_store(JS::Realm& realm
count = OptionalNone();
// 2. Let records an empty list.
GC::ConservativeVector<ObjectStoreRecord> records(realm.heap());
GC::ConservativeVector<ObjectStoreRecord> records;
// 3. If direction is "next" or "nextunique", set records to the first count of stores list of records whose key is in range.
if (direction == Bindings::IDBCursorDirection::Next || direction == Bindings::IDBCursorDirection::Nextunique) {
@ -2293,7 +2293,7 @@ GC::Ref<JS::Array> retrieve_multiple_items_from_an_index(JS::Realm& target_realm
count = OptionalNone();
// 2. Let records be a an empty list.
GC::ConservativeVector<IndexRecord> records(target_realm.heap());
GC::ConservativeVector<IndexRecord> records;
// 3. Switching on direction:
switch (direction) {

View file

@ -96,7 +96,7 @@ Optional<IndexRecord&> Index::first_in_range(GC::Ref<IDBKeyRange> range)
GC::ConservativeVector<IndexRecord> Index::first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
{
GC::ConservativeVector<IndexRecord> records(range->heap());
GC::ConservativeVector<IndexRecord> records;
auto record_range = record_range_for_key_range(m_records, range);
for (size_t i = record_range.start; i < record_range.end; ++i) {
records.append(m_records[i]);
@ -110,7 +110,7 @@ GC::ConservativeVector<IndexRecord> Index::first_n_in_range(GC::Ref<IDBKeyRange>
GC::ConservativeVector<IndexRecord> Index::last_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
{
GC::ConservativeVector<IndexRecord> records(range->heap());
GC::ConservativeVector<IndexRecord> records;
auto record_range = record_range_for_key_range(m_records, range);
for (size_t i = record_range.end; i > record_range.start;) {
--i;

View file

@ -181,7 +181,7 @@ void ObjectStore::possibly_update_the_key_generator(GC::Ref<Key> key)
GC::ConservativeVector<ObjectStoreRecord> ObjectStore::first_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
{
GC::ConservativeVector<ObjectStoreRecord> records(range->heap());
GC::ConservativeVector<ObjectStoreRecord> records;
auto record_range = record_range_for_key_range(m_records, range);
for (size_t i = record_range.start; i < record_range.end; ++i) {
records.append(m_records[i]);
@ -195,7 +195,7 @@ GC::ConservativeVector<ObjectStoreRecord> ObjectStore::first_n_in_range(GC::Ref<
GC::ConservativeVector<ObjectStoreRecord> ObjectStore::last_n_in_range(GC::Ref<IDBKeyRange> range, Optional<WebIDL::UnsignedLong> count)
{
GC::ConservativeVector<ObjectStoreRecord> records(range->heap());
GC::ConservativeVector<ObjectStoreRecord> records;
auto record_range = record_range_for_key_range(m_records, range);
for (size_t i = record_range.end; i > record_range.start;) {
--i;

View file

@ -22,7 +22,7 @@ GC_DEFINE_ALLOCATOR(FormData);
// https://xhr.spec.whatwg.org/#dom-formdata
WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::construct_impl(JS::Realm& realm, GC::Ptr<HTML::HTMLFormElement> form, GC::Ptr<HTML::HTMLElement> submitter)
{
GC::ConservativeVector<FormDataEntry> list { realm.heap() };
GC::ConservativeVector<FormDataEntry> list;
// 1. If form is given, then:
if (form) {
// 1. If submitter is non-null, then:
@ -62,7 +62,7 @@ WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::construct_impl(JS::Realm& realm
WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::create(JS::Realm& realm, Vector<DOMURL::QueryParam> entry_list)
{
GC::ConservativeVector<FormDataEntry> list { realm.heap() };
GC::ConservativeVector<FormDataEntry> list;
list.ensure_capacity(entry_list.size());
for (auto& entry : entry_list)
list.unchecked_append({ .name = move(entry.name), .value = move(entry.value) });
@ -185,7 +185,7 @@ WebIDL::ExceptionOr<void> FormData::set(String const& name, GC::Ref<FileAPI::Blo
GC::ConservativeVector<FormDataEntry> FormData::entry_list() const
{
return { realm().heap(), m_entry_list };
return GC::ConservativeVector<FormDataEntry> { m_entry_list };
}
// https://xhr.spec.whatwg.org/#dom-formdata-set

View file

@ -168,7 +168,7 @@ TEST_CASE(cleared_container_reports_no_roots)
TEST_CASE(conservative_vector_reports_possible_values)
{
auto& heap = test_heap();
GC::ConservativeVector<GC::Ref<TestCell>> vector(heap);
GC::ConservativeVector<GC::Ref<TestCell>> vector;
auto cell = heap.allocate<TestCell>();
vector.append(cell);