LibJS+LibWeb: Adopt RootHashTable for unrooted GC-pointer storage

This commit is contained in:
Luke Wilde 2026-05-19 14:41:17 +01:00 committed by Shannon Booth
parent 5bed7f6d73
commit 52bf9c5fcb
11 changed files with 64 additions and 59 deletions

View file

@ -10,6 +10,7 @@
#include <AK/NumericLimits.h>
#include <AK/TemporaryChange.h>
#include <LibGC/RootHashMap.h>
#include <LibGC/RootHashTable.h>
#include <LibJS/Bytecode/AsmInterpreter/AsmInterpreter.h>
#include <LibJS/Bytecode/BasicBlock.h>
#include <LibJS/Bytecode/Builtins.h>
@ -1571,7 +1572,7 @@ static ThrowCompletionOr<Optional<FastPropertyNameIteratorData>> try_get_fast_pr
result.receiver_has_magical_length_property = object.has_magical_length_property();
result.shape = &object.shape();
HashTable<GC::Ref<Object>> seen_objects;
GC::RootHashTable<GC::Ref<Object>> seen_objects(vm.heap());
size_t estimated_properties_count = 0;
bool prototype_chain_has_enumerable_named_properties = false;
for (auto object_to_check = GC::Ptr { &object }; object_to_check && !seen_objects.contains(*object_to_check); object_to_check = TRY(object_to_check->internal_get_prototype_of())) {
@ -1725,7 +1726,7 @@ inline ThrowCompletionOr<GC::Ref<PropertyNameIterator>> get_object_property_iter
}
size_t estimated_properties_count = 0;
HashTable<GC::Ref<Object>> seen_objects;
GC::RootHashTable<GC::Ref<Object>> seen_objects(vm.heap());
for (auto object_to_check = GC::Ptr { object.ptr() }; object_to_check && !seen_objects.contains(*object_to_check); object_to_check = TRY(object_to_check->internal_get_prototype_of())) {
seen_objects.set(*object_to_check);
estimated_properties_count += object_to_check->own_properties_count();

View file

@ -7,6 +7,7 @@
*/
#include <AK/GenericShorthands.h>
#include <LibGC/RootHashTable.h>
#include <LibJS/CyclicModule.h>
#include <LibJS/Module.h>
#include <LibJS/Runtime/ExternalMemory.h>
@ -186,7 +187,7 @@ GC::Ref<Object> Module::get_module_namespace(VM& vm)
Vector<Utf16FlyString> Module::get_exported_names(VM& vm)
{
HashTable<Module const*> export_star_set;
GC::RootHashTable<GC::Ref<Module const>> export_star_set(vm.heap());
return get_exported_names(vm, export_star_set);
}

View file

@ -113,7 +113,7 @@ public:
virtual ThrowCompletionOr<GC::Ref<PromiseCapability>> evaluate(VM& vm) = 0;
Vector<Utf16FlyString> get_exported_names(VM& vm);
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) = 0;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, GC::RootHashTable<GC::Ref<Module const>>& export_star_set) = 0;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) = 0;

View file

@ -94,10 +94,10 @@ static ErrorOr<String> escape_for_string_literal(StringView string)
return builder.to_string();
}
ErrorOr<void> print_value(JS::PrintContext&, JS::Value value, HashTable<JS::Object*>& seen_objects);
ErrorOr<void> print_value(JS::PrintContext&, JS::Value value, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects);
template<typename T>
ErrorOr<void> print_value(JS::PrintContext& print_context, JS::ThrowCompletionOr<T> value_or_error, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_value(JS::PrintContext& print_context, JS::ThrowCompletionOr<T> value_or_error, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
if (value_or_error.is_error()) {
auto error = value_or_error.release_error();
@ -158,7 +158,7 @@ ErrorOr<void> print_separator(JS::PrintContext& print_context, bool& first)
return {};
}
ErrorOr<void> print_array(JS::PrintContext& print_context, JS::Array const& array, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_array(JS::PrintContext& print_context, JS::Array const& array, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(js_out(print_context, "["));
bool first = true;
@ -186,7 +186,7 @@ ErrorOr<void> print_array(JS::PrintContext& print_context, JS::Array const& arra
return {};
}
ErrorOr<void> print_object(JS::PrintContext& print_context, JS::Object const& object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_object(JS::PrintContext& print_context, JS::Object const& object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(js_out(print_context, "{}{{", object.class_name()));
bool first = true;
@ -234,7 +234,7 @@ ErrorOr<void> print_object(JS::PrintContext& print_context, JS::Object const& ob
return {};
}
ErrorOr<void> print_function(JS::PrintContext& print_context, JS::FunctionObject const& function_object, HashTable<JS::Object*>&)
ErrorOr<void> print_function(JS::PrintContext& print_context, JS::FunctionObject const& function_object, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
if (is<JS::ECMAScriptFunctionObject>(function_object)) {
auto const& ecmascript_function_object = static_cast<JS::ECMAScriptFunctionObject const&>(function_object);
@ -264,14 +264,14 @@ ErrorOr<void> print_function(JS::PrintContext& print_context, JS::FunctionObject
return {};
}
ErrorOr<void> print_date(JS::PrintContext& print_context, JS::Date const& date, HashTable<JS::Object*>&)
ErrorOr<void> print_date(JS::PrintContext& print_context, JS::Date const& date, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "Date"sv));
TRY(js_out(print_context, " \033[34;1m{}\033[0m", JS::to_date_string(date.date_value())));
return {};
}
ErrorOr<void> print_error(JS::PrintContext& print_context, JS::Object const& object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_error(JS::PrintContext& print_context, JS::Object const& object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
auto name = object.get_without_side_effects(print_context.vm.names.name);
auto message = object.get_without_side_effects(print_context.vm.names.message);
@ -287,14 +287,14 @@ ErrorOr<void> print_error(JS::PrintContext& print_context, JS::Object const& obj
return {};
}
ErrorOr<void> print_regexp_object(JS::PrintContext& print_context, JS::RegExpObject const& regexp_object, HashTable<JS::Object*>&)
ErrorOr<void> print_regexp_object(JS::PrintContext& print_context, JS::RegExpObject const& regexp_object, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "RegExp"sv));
TRY(js_out(print_context, " \033[34;1m/{}/{}\033[0m", regexp_object.escape_regexp_pattern(), regexp_object.flags()));
return {};
}
ErrorOr<void> print_proxy_object(JS::PrintContext& print_context, JS::ProxyObject const& proxy_object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_proxy_object(JS::PrintContext& print_context, JS::ProxyObject const& proxy_object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Proxy"sv));
TRY(js_out(print_context, "\n target: "));
@ -304,7 +304,7 @@ ErrorOr<void> print_proxy_object(JS::PrintContext& print_context, JS::ProxyObjec
return {};
}
ErrorOr<void> print_map(JS::PrintContext& print_context, JS::Map const& map, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_map(JS::PrintContext& print_context, JS::Map const& map, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Map"sv));
TRY(js_out(print_context, " {{"));
@ -321,7 +321,7 @@ ErrorOr<void> print_map(JS::PrintContext& print_context, JS::Map const& map, Has
return {};
}
ErrorOr<void> print_set(JS::PrintContext& print_context, JS::Set const& set, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_set(JS::PrintContext& print_context, JS::Set const& set, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Set"sv));
TRY(js_out(print_context, " {{"));
@ -336,7 +336,7 @@ ErrorOr<void> print_set(JS::PrintContext& print_context, JS::Set const& set, Has
return {};
}
ErrorOr<void> print_weak_map(JS::PrintContext& print_context, JS::WeakMap const& weak_map, HashTable<JS::Object*>&)
ErrorOr<void> print_weak_map(JS::PrintContext& print_context, JS::WeakMap const& weak_map, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "WeakMap"sv));
TRY(js_out(print_context, " ({})", weak_map.weak_map_size()));
@ -344,7 +344,7 @@ ErrorOr<void> print_weak_map(JS::PrintContext& print_context, JS::WeakMap const&
return {};
}
ErrorOr<void> print_weak_set(JS::PrintContext& print_context, JS::WeakSet const& weak_set, HashTable<JS::Object*>&)
ErrorOr<void> print_weak_set(JS::PrintContext& print_context, JS::WeakSet const& weak_set, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "WeakSet"sv));
TRY(js_out(print_context, " ({})", weak_set.weak_set_size()));
@ -352,7 +352,7 @@ ErrorOr<void> print_weak_set(JS::PrintContext& print_context, JS::WeakSet const&
return {};
}
ErrorOr<void> print_weak_ref(JS::PrintContext& print_context, JS::WeakRef const& weak_ref, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_weak_ref(JS::PrintContext& print_context, JS::WeakRef const& weak_ref, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "WeakRef"sv));
TRY(js_out(print_context, " "));
@ -360,7 +360,7 @@ ErrorOr<void> print_weak_ref(JS::PrintContext& print_context, JS::WeakRef const&
return {};
}
ErrorOr<void> print_promise(JS::PrintContext& print_context, JS::Promise const& promise, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_promise(JS::PrintContext& print_context, JS::Promise const& promise, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Promise"sv));
switch (promise.state()) {
@ -386,7 +386,7 @@ ErrorOr<void> print_promise(JS::PrintContext& print_context, JS::Promise const&
return {};
}
ErrorOr<void> print_array_buffer(JS::PrintContext& print_context, JS::ArrayBuffer const& array_buffer, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_array_buffer(JS::PrintContext& print_context, JS::ArrayBuffer const& array_buffer, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "ArrayBuffer"sv));
@ -418,13 +418,13 @@ ErrorOr<void> print_array_buffer(JS::PrintContext& print_context, JS::ArrayBuffe
return {};
}
ErrorOr<void> print_generator(JS::PrintContext& print_context, JS::GeneratorObject const& generator, HashTable<JS::Object*>&)
ErrorOr<void> print_generator(JS::PrintContext& print_context, JS::GeneratorObject const& generator, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, generator.class_name()));
return {};
}
ErrorOr<void> print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const& generator, HashTable<JS::Object*>&)
ErrorOr<void> print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const& generator, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, generator.class_name()));
return {};
@ -439,7 +439,7 @@ ErrorOr<void> print_number(JS::PrintContext& print_context, T number)
return {};
}
ErrorOr<void> print_typed_array(JS::PrintContext& print_context, JS::TypedArrayBase const& typed_array_base, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_typed_array(JS::PrintContext& print_context, JS::TypedArrayBase const& typed_array_base, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
auto& array_buffer = *typed_array_base.viewed_array_buffer();
@ -488,7 +488,7 @@ ErrorOr<void> print_typed_array(JS::PrintContext& print_context, JS::TypedArrayB
VERIFY_NOT_REACHED();
}
ErrorOr<void> print_data_view(JS::PrintContext& print_context, JS::DataView const& data_view, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_data_view(JS::PrintContext& print_context, JS::DataView const& data_view, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
auto view_record = JS::make_data_view_with_buffer_witness_record(data_view, JS::ArrayBuffer::Order::SeqCst);
TRY(print_type(print_context, "DataView"sv));
@ -509,7 +509,7 @@ ErrorOr<void> print_data_view(JS::PrintContext& print_context, JS::DataView cons
return {};
}
ErrorOr<void> print_intl_display_names(JS::PrintContext& print_context, JS::Intl::DisplayNames const& display_names, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_display_names(JS::PrintContext& print_context, JS::Intl::DisplayNames const& display_names, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.DisplayNames"sv));
TRY(js_out(print_context, "\n locale: "));
@ -527,7 +527,7 @@ ErrorOr<void> print_intl_display_names(JS::PrintContext& print_context, JS::Intl
return {};
}
ErrorOr<void> print_intl_locale(JS::PrintContext& print_context, JS::Intl::Locale const& locale, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_locale(JS::PrintContext& print_context, JS::Intl::Locale const& locale, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.Locale"sv));
TRY(js_out(print_context, "\n locale: "));
@ -557,7 +557,7 @@ ErrorOr<void> print_intl_locale(JS::PrintContext& print_context, JS::Intl::Local
return {};
}
ErrorOr<void> print_intl_list_format(JS::PrintContext& print_context, JS::Intl::ListFormat const& list_format, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_list_format(JS::PrintContext& print_context, JS::Intl::ListFormat const& list_format, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.ListFormat"sv));
TRY(js_out(print_context, "\n locale: "));
@ -569,7 +569,7 @@ ErrorOr<void> print_intl_list_format(JS::PrintContext& print_context, JS::Intl::
return {};
}
ErrorOr<void> print_intl_number_format(JS::PrintContext& print_context, JS::Intl::NumberFormat const& number_format, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_number_format(JS::PrintContext& print_context, JS::Intl::NumberFormat const& number_format, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.NumberFormat"sv));
TRY(js_out(print_context, "\n locale: "));
@ -637,7 +637,7 @@ ErrorOr<void> print_intl_number_format(JS::PrintContext& print_context, JS::Intl
return {};
}
ErrorOr<void> print_intl_date_time_format(JS::PrintContext& print_context, JS::Intl::DateTimeFormat& date_time_format, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_date_time_format(JS::PrintContext& print_context, JS::Intl::DateTimeFormat& date_time_format, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.DateTimeFormat"sv));
TRY(js_out(print_context, "\n locale: "));
@ -690,7 +690,7 @@ ErrorOr<void> print_intl_date_time_format(JS::PrintContext& print_context, JS::I
return {};
}
ErrorOr<void> print_intl_relative_time_format(JS::PrintContext& print_context, JS::Intl::RelativeTimeFormat const& date_time_format, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_relative_time_format(JS::PrintContext& print_context, JS::Intl::RelativeTimeFormat const& date_time_format, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.RelativeTimeFormat"sv));
TRY(js_out(print_context, "\n locale: "));
@ -704,7 +704,7 @@ ErrorOr<void> print_intl_relative_time_format(JS::PrintContext& print_context, J
return {};
}
ErrorOr<void> print_intl_plural_rules(JS::PrintContext& print_context, JS::Intl::PluralRules const& plural_rules, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_plural_rules(JS::PrintContext& print_context, JS::Intl::PluralRules const& plural_rules, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.PluralRules"sv));
TRY(js_out(print_context, "\n locale: "));
@ -736,7 +736,7 @@ ErrorOr<void> print_intl_plural_rules(JS::PrintContext& print_context, JS::Intl:
return {};
}
ErrorOr<void> print_intl_collator(JS::PrintContext& print_context, JS::Intl::Collator const& collator, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_collator(JS::PrintContext& print_context, JS::Intl::Collator const& collator, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.Collator"sv));
TRY(js_out(print_context, "\n locale: "));
@ -756,7 +756,7 @@ ErrorOr<void> print_intl_collator(JS::PrintContext& print_context, JS::Intl::Col
return {};
}
ErrorOr<void> print_intl_segmenter(JS::PrintContext& print_context, JS::Intl::Segmenter const& segmenter, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_segmenter(JS::PrintContext& print_context, JS::Intl::Segmenter const& segmenter, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Intl.Segmenter"sv));
TRY(js_out(print_context, "\n locale: "));
@ -766,7 +766,7 @@ ErrorOr<void> print_intl_segmenter(JS::PrintContext& print_context, JS::Intl::Se
return {};
}
ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Segments"sv));
TRY(js_out(print_context, "\n string: "));
@ -774,7 +774,7 @@ ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Seg
return {};
}
ErrorOr<void> print_intl_duration_format(JS::PrintContext& print_context, JS::Intl::DurationFormat const& duration_format, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_intl_duration_format(JS::PrintContext& print_context, JS::Intl::DurationFormat const& duration_format, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
auto print_style_and_display = [&](StringView style_name, StringView display_name, JS::Intl::DurationFormat::DurationUnitOptions options) -> ErrorOr<void> {
auto style = JS::Intl::DurationFormat::value_style_to_string(options.style);
@ -815,14 +815,14 @@ ErrorOr<void> print_intl_duration_format(JS::PrintContext& print_context, JS::In
return {};
}
ErrorOr<void> print_temporal_duration(JS::PrintContext& print_context, JS::Temporal::Duration const& duration, HashTable<JS::Object*>&)
ErrorOr<void> print_temporal_duration(JS::PrintContext& print_context, JS::Temporal::Duration const& duration, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "Temporal.Duration"sv));
TRY(js_out(print_context, " \033[34;1m{} y, {} M, {} w, {} d, {} h, {} m, {} s, {} ms, {} us, {} ns\033[0m", duration.years(), duration.months(), duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds(), duration.milliseconds(), duration.microseconds(), duration.nanoseconds()));
return {};
}
ErrorOr<void> print_temporal_instant(JS::PrintContext& print_context, JS::Temporal::Instant const& instant, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_instant(JS::PrintContext& print_context, JS::Temporal::Instant const& instant, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.Instant"sv));
TRY(js_out(print_context, " "));
@ -830,7 +830,7 @@ ErrorOr<void> print_temporal_instant(JS::PrintContext& print_context, JS::Tempor
return {};
}
ErrorOr<void> print_temporal_plain_date(JS::PrintContext& print_context, JS::Temporal::PlainDate const& plain_date, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_plain_date(JS::PrintContext& print_context, JS::Temporal::PlainDate const& plain_date, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.PlainDate"sv));
TRY(js_out(print_context, " \033[34;1m{:04}-{:02}-{:02}\033[0m", plain_date.iso_date().year, plain_date.iso_date().month, plain_date.iso_date().day));
@ -839,7 +839,7 @@ ErrorOr<void> print_temporal_plain_date(JS::PrintContext& print_context, JS::Tem
return {};
}
ErrorOr<void> print_temporal_plain_date_time(JS::PrintContext& print_context, JS::Temporal::PlainDateTime const& plain_date_time, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_plain_date_time(JS::PrintContext& print_context, JS::Temporal::PlainDateTime const& plain_date_time, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.PlainDateTime"sv));
TRY(js_out(print_context, " \033[34;1m{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_date_time.iso_date_time().iso_date.year, plain_date_time.iso_date_time().iso_date.month, plain_date_time.iso_date_time().iso_date.day, plain_date_time.iso_date_time().time.hour, plain_date_time.iso_date_time().time.minute, plain_date_time.iso_date_time().time.second, plain_date_time.iso_date_time().time.millisecond, plain_date_time.iso_date_time().time.microsecond, plain_date_time.iso_date_time().time.nanosecond));
@ -848,7 +848,7 @@ ErrorOr<void> print_temporal_plain_date_time(JS::PrintContext& print_context, JS
return {};
}
ErrorOr<void> print_temporal_plain_month_day(JS::PrintContext& print_context, JS::Temporal::PlainMonthDay const& plain_month_day, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_plain_month_day(JS::PrintContext& print_context, JS::Temporal::PlainMonthDay const& plain_month_day, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.PlainMonthDay"sv));
TRY(js_out(print_context, " \033[34;1m{:02}-{:02}\033[0m", plain_month_day.iso_date().month, plain_month_day.iso_date().day));
@ -857,14 +857,14 @@ ErrorOr<void> print_temporal_plain_month_day(JS::PrintContext& print_context, JS
return {};
}
ErrorOr<void> print_temporal_plain_time(JS::PrintContext& print_context, JS::Temporal::PlainTime const& plain_time, HashTable<JS::Object*>&)
ErrorOr<void> print_temporal_plain_time(JS::PrintContext& print_context, JS::Temporal::PlainTime const& plain_time, GC::RootHashTable<GC::Ref<JS::Object>>&)
{
TRY(print_type(print_context, "Temporal.PlainTime"sv));
TRY(js_out(print_context, " \033[34;1m{:02}:{:02}:{:02}.{:03}{:03}{:03}\033[0m", plain_time.time().hour, plain_time.time().minute, plain_time.time().second, plain_time.time().millisecond, plain_time.time().microsecond, plain_time.time().nanosecond));
return {};
}
ErrorOr<void> print_temporal_plain_year_month(JS::PrintContext& print_context, JS::Temporal::PlainYearMonth const& plain_year_month, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_plain_year_month(JS::PrintContext& print_context, JS::Temporal::PlainYearMonth const& plain_year_month, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.PlainYearMonth"sv));
TRY(js_out(print_context, " \033[34;1m{:04}-{:02}\033[0m", plain_year_month.iso_date().year, plain_year_month.iso_date().month));
@ -873,7 +873,7 @@ ErrorOr<void> print_temporal_plain_year_month(JS::PrintContext& print_context, J
return {};
}
ErrorOr<void> print_temporal_zoned_date_time(JS::PrintContext& print_context, JS::Temporal::ZonedDateTime const& zoned_date_time, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_temporal_zoned_date_time(JS::PrintContext& print_context, JS::Temporal::ZonedDateTime const& zoned_date_time, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Temporal.ZonedDateTime"sv));
TRY(js_out(print_context, "\n epochNanoseconds: "));
@ -885,7 +885,7 @@ ErrorOr<void> print_temporal_zoned_date_time(JS::PrintContext& print_context, JS
return {};
}
ErrorOr<void> print_boolean_object(JS::PrintContext& print_context, JS::BooleanObject const& boolean_object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_boolean_object(JS::PrintContext& print_context, JS::BooleanObject const& boolean_object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Boolean"sv));
TRY(js_out(print_context, " "));
@ -893,7 +893,7 @@ ErrorOr<void> print_boolean_object(JS::PrintContext& print_context, JS::BooleanO
return {};
}
ErrorOr<void> print_number_object(JS::PrintContext& print_context, JS::NumberObject const& number_object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_number_object(JS::PrintContext& print_context, JS::NumberObject const& number_object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "Number"sv));
TRY(js_out(print_context, " "));
@ -901,7 +901,7 @@ ErrorOr<void> print_number_object(JS::PrintContext& print_context, JS::NumberObj
return {};
}
ErrorOr<void> print_string_object(JS::PrintContext& print_context, JS::StringObject const& string_object, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_string_object(JS::PrintContext& print_context, JS::StringObject const& string_object, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
TRY(print_type(print_context, "String"sv));
TRY(js_out(print_context, " "));
@ -909,7 +909,7 @@ ErrorOr<void> print_string_object(JS::PrintContext& print_context, JS::StringObj
return {};
}
ErrorOr<void> print_value(JS::PrintContext& print_context, JS::Value value, HashTable<JS::Object*>& seen_objects)
ErrorOr<void> print_value(JS::PrintContext& print_context, JS::Value value, GC::RootHashTable<GC::Ref<JS::Object>>& seen_objects)
{
if (value.is_special_empty_value()) {
TRY(js_out(print_context, "\033[34;1m<empty>\033[0m"));
@ -917,13 +917,13 @@ ErrorOr<void> print_value(JS::PrintContext& print_context, JS::Value value, Hash
}
if (value.is_object()) {
if (seen_objects.contains(&value.as_object())) {
if (seen_objects.contains(value.as_object())) {
// FIXME: Maybe we should only do this for circular references,
// not for all reoccurring objects.
TRY(js_out(print_context, "<already printed Object {}>", &value.as_object()));
return {};
}
seen_objects.set(&value.as_object());
seen_objects.set(value.as_object());
}
if (value.is_object()) {
@ -1051,7 +1051,7 @@ namespace JS {
ErrorOr<void> print(JS::Value value, PrintContext& print_context)
{
HashTable<JS::Object*> seen_objects;
GC::RootHashTable<GC::Ref<JS::Object>> seen_objects { print_context.vm.heap() };
return print_value(print_context, value, seen_objects);
}

View file

@ -6,6 +6,7 @@
*/
#include <LibGC/DeferGC.h>
#include <LibGC/RootHashTable.h>
#include <LibJS/Runtime/DescriptorArray.h>
#include <LibJS/Runtime/ExternalMemory.h>
#include <LibJS/Runtime/Realm.h>
@ -533,7 +534,7 @@ void Shape::invalidate_all_prototype_chains_leading_to_this()
if (!m_child_prototype_shapes || m_child_prototype_shapes->is_empty())
return;
HashTable<Shape*> shapes_to_invalidate;
GC::RootHashTable<Shape*> shapes_to_invalidate(heap());
Vector<Shape*> worklist;
auto enqueue_children_of = [&](Shape& shape) {
if (!shape.m_child_prototype_shapes)

View file

@ -7,6 +7,7 @@
#include <AK/Debug.h>
#include <AK/QuickSort.h>
#include <LibGC/RootHashTable.h>
#include <LibJS/Bytecode/Executable.h>
#include <LibJS/Runtime/AsyncFunctionDriverWrapper.h>
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
@ -201,7 +202,7 @@ Result<GC::Ref<SourceTextModule>, Vector<ParserError>> SourceTextModule::parse(S
}
// 16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] ), https://tc39.es/ecma262/#sec-getexportednames
Vector<Utf16FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Module const*>& export_star_set)
Vector<Utf16FlyString> SourceTextModule::get_exported_names(VM& vm, GC::RootHashTable<GC::Ref<Module const>>& export_star_set)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] get_export_names of {}", filename());
@ -212,7 +213,7 @@ Vector<Utf16FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Mo
// NOTE: This is done by Module.
// 3. If exportStarSet contains module, then
if (export_star_set.contains(this)) {
if (export_star_set.contains(GC::Ref<Module const>(*this))) {
// a. Assert: We've reached the starting point of an export * circularity.
// FIXME: How do we check that?
@ -221,7 +222,7 @@ Vector<Utf16FlyString> SourceTextModule::get_exported_names(VM& vm, HashTable<Mo
}
// 4. Append module to exportStarSet.
export_star_set.set(this);
export_star_set.set(GC::Ref<Module const>(*this));
// 5. Let exportedNames be a new empty List.
Vector<Utf16FlyString> exported_names;

View file

@ -36,7 +36,7 @@ public:
static Result<GC::Ref<SourceTextModule>, Vector<ParserError>> parse_from_pre_compiled(FFI::CompiledProgram* compiled, NonnullRefPtr<SourceCode const> source_code, Realm&, Script::HostDefined* host_defined = nullptr);
static Result<GC::Ref<SourceTextModule>, Vector<ParserError>> parse_from_bytecode_cache(FFI::DecodedBytecodeCacheBlob*, NonnullRefPtr<SourceCode const> source_code, Realm&, Script::HostDefined* host_defined = nullptr);
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, GC::RootHashTable<GC::Ref<Module const>>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set = {}) override;
Object* import_meta() { return m_import_meta; }

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/RootHashTable.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/ExternalMemory.h>
@ -105,7 +106,7 @@ PromiseCapability& SyntheticModule::load_requested_modules(GC::Ptr<GraphLoadingS
}
// 16.2.1.8.4.2 GetExportedNames ( ), https://tc39.es/ecma262/#sec-smr-getexportednames
Vector<Utf16FlyString> SyntheticModule::get_exported_names(VM&, HashTable<Module const*>&)
Vector<Utf16FlyString> SyntheticModule::get_exported_names(VM&, GC::RootHashTable<GC::Ref<Module const>>&)
{
// 1. Return module.[[ExportNames]].
return m_export_names;

View file

@ -25,7 +25,7 @@ public:
ThrowCompletionOr<void> set_synthetic_module_export(Utf16FlyString const& export_name, Value export_value);
virtual PromiseCapability& load_requested_modules(GC::Ptr<GraphLoadingState::HostDefined>) override;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, HashTable<Module const*>& export_star_set) override;
virtual Vector<Utf16FlyString> get_exported_names(VM& vm, GC::RootHashTable<GC::Ref<Module const>>& export_star_set) override;
virtual ResolvedBinding resolve_export(VM& vm, Utf16FlyString const& export_name, Vector<ResolvedBinding> resolve_set) override;
virtual ThrowCompletionOr<void> link(VM& vm) override;
virtual ThrowCompletionOr<GC::Ref<PromiseCapability>> evaluate(VM& vm) override;

View file

@ -140,7 +140,7 @@ Vector<Utf16FlyString> WebAssemblyModule::export_name_list()
}
// https://webassembly.github.io/esm-integration/js-api/index.html#get-exported-names
Vector<Utf16FlyString> WebAssemblyModule::get_exported_names(JS::VM&, HashTable<Module const*>&)
Vector<Utf16FlyString> WebAssemblyModule::get_exported_names(JS::VM&, GC::RootHashTable<GC::Ref<Module const>>&)
{
// 1. Let record be this WebAssembly Module Record.
auto* record = this;

View file

@ -25,7 +25,7 @@ public:
Vector<Utf16FlyString> export_name_list();
virtual Vector<Utf16FlyString> get_exported_names(JS::VM& vm, HashTable<Module const*>& export_star_set) override;
virtual Vector<Utf16FlyString> get_exported_names(JS::VM& vm, GC::RootHashTable<GC::Ref<Module const>>& export_star_set) override;
virtual JS::ResolvedBinding resolve_export(JS::VM& vm, Utf16FlyString const& export_name, Vector<JS::ResolvedBinding> resolve_set = {}) override;
protected: