LibGC+Everywhere: Factor out a LibGC from LibJS

Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
This commit is contained in:
Shannon Booth 2024-11-15 04:01:23 +13:00 committed by Andreas Kling
commit f87041bf3a
Notes: github-actions[bot] 2024-11-15 13:50:17 +00:00
1722 changed files with 9939 additions and 9906 deletions

View file

@ -18,11 +18,11 @@
#include <AK/SourceLocation.h>
#include <AK/String.h>
#include <AK/Types.h>
#include <LibGC/NanBoxedValue.h>
#include <LibGC/Ptr.h>
#include <LibGC/Root.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Heap/Handle.h>
#include <LibJS/Heap/NanBoxedValue.h>
#include <math.h>
namespace JS {
@ -33,26 +33,26 @@ static constexpr double MAX_ARRAY_LIKE_INDEX = 9007199254740991.0;
static constexpr u64 NEGATIVE_ZERO_BITS = ((u64)1 << 63);
// This leaves us 3 bits to tag the type of pointer:
static constexpr u64 OBJECT_TAG = 0b001 | IS_CELL_BIT;
static constexpr u64 STRING_TAG = 0b010 | IS_CELL_BIT;
static constexpr u64 SYMBOL_TAG = 0b011 | IS_CELL_BIT;
static constexpr u64 ACCESSOR_TAG = 0b100 | IS_CELL_BIT;
static constexpr u64 BIGINT_TAG = 0b101 | IS_CELL_BIT;
static constexpr u64 OBJECT_TAG = 0b001 | GC::IS_CELL_BIT;
static constexpr u64 STRING_TAG = 0b010 | GC::IS_CELL_BIT;
static constexpr u64 SYMBOL_TAG = 0b011 | GC::IS_CELL_BIT;
static constexpr u64 ACCESSOR_TAG = 0b100 | GC::IS_CELL_BIT;
static constexpr u64 BIGINT_TAG = 0b101 | GC::IS_CELL_BIT;
// We can then by extracting the top 13 bits quickly check if a Value is
// pointer backed.
static_assert((OBJECT_TAG & IS_CELL_PATTERN) == IS_CELL_PATTERN);
static_assert((STRING_TAG & IS_CELL_PATTERN) == IS_CELL_PATTERN);
static_assert((CANON_NAN_BITS & IS_CELL_PATTERN) != IS_CELL_PATTERN);
static_assert((NEGATIVE_INFINITY_BITS & IS_CELL_PATTERN) != IS_CELL_PATTERN);
static_assert((OBJECT_TAG & GC::IS_CELL_PATTERN) == GC::IS_CELL_PATTERN);
static_assert((STRING_TAG & GC::IS_CELL_PATTERN) == GC::IS_CELL_PATTERN);
static_assert((GC::CANON_NAN_BITS & GC::IS_CELL_PATTERN) != GC::IS_CELL_PATTERN);
static_assert((GC::NEGATIVE_INFINITY_BITS & GC::IS_CELL_PATTERN) != GC::IS_CELL_PATTERN);
// Then for the non pointer backed types we don't set the sign bit and use the
// three lower bits for tagging as well.
static constexpr u64 UNDEFINED_TAG = 0b110 | BASE_TAG;
static constexpr u64 NULL_TAG = 0b111 | BASE_TAG;
static constexpr u64 BOOLEAN_TAG = 0b001 | BASE_TAG;
static constexpr u64 INT32_TAG = 0b010 | BASE_TAG;
static constexpr u64 EMPTY_TAG = 0b011 | BASE_TAG;
static constexpr u64 UNDEFINED_TAG = 0b110 | GC::BASE_TAG;
static constexpr u64 NULL_TAG = 0b111 | GC::BASE_TAG;
static constexpr u64 BOOLEAN_TAG = 0b001 | GC::BASE_TAG;
static constexpr u64 INT32_TAG = 0b010 | GC::BASE_TAG;
static constexpr u64 EMPTY_TAG = 0b011 | GC::BASE_TAG;
// Notice how only undefined and null have the top bit set, this mean we can
// quickly check for nullish values by checking if the top and bottom bits are set
// but the middle one isn't.
@ -67,8 +67,8 @@ static_assert((EMPTY_TAG & IS_NULLISH_EXTRACT_PATTERN) != IS_NULLISH_PATTERN);
// values are not valid anywhere else we can use this "value" to our advantage
// in Optional<Value> to represent the empty optional.
static constexpr u64 SHIFTED_BOOLEAN_TAG = BOOLEAN_TAG << TAG_SHIFT;
static constexpr u64 SHIFTED_INT32_TAG = INT32_TAG << TAG_SHIFT;
static constexpr u64 SHIFTED_BOOLEAN_TAG = BOOLEAN_TAG << GC::TAG_SHIFT;
static constexpr u64 SHIFTED_INT32_TAG = INT32_TAG << GC::TAG_SHIFT;
// Summary:
// To pack all the different value in to doubles we use the following schema:
@ -85,7 +85,7 @@ static constexpr u64 SHIFTED_INT32_TAG = INT32_TAG << TAG_SHIFT;
// options from 8 tags to 15 but since we currently only use 5 for both sign bits
// this is not needed.
class Value : public NanBoxedValue {
class Value : public GC::NanBoxedValue {
public:
enum class PreferredType {
Default,
@ -114,18 +114,18 @@ public:
bool is_infinity() const
{
static_assert(NEGATIVE_INFINITY_BITS == (0x1ULL << 63 | POSITIVE_INFINITY_BITS));
return (0x1ULL << 63 | m_value.encoded) == NEGATIVE_INFINITY_BITS;
static_assert(GC::NEGATIVE_INFINITY_BITS == (0x1ULL << 63 | GC::POSITIVE_INFINITY_BITS));
return (0x1ULL << 63 | m_value.encoded) == GC::NEGATIVE_INFINITY_BITS;
}
bool is_positive_infinity() const
{
return m_value.encoded == POSITIVE_INFINITY_BITS;
return m_value.encoded == GC::POSITIVE_INFINITY_BITS;
}
bool is_negative_infinity() const
{
return m_value.encoded == NEGATIVE_INFINITY_BITS;
return m_value.encoded == GC::NEGATIVE_INFINITY_BITS;
}
bool is_positive_zero() const
@ -155,13 +155,13 @@ public:
}
Value()
: Value(EMPTY_TAG << TAG_SHIFT, (u64)0)
: Value(EMPTY_TAG << GC::TAG_SHIFT, (u64)0)
{
}
template<typename T>
requires(IsSameIgnoringCV<T, bool>) explicit Value(T value)
: Value(BOOLEAN_TAG << TAG_SHIFT, (u64)value)
: Value(BOOLEAN_TAG << GC::TAG_SHIFT, (u64)value)
{
}
@ -173,7 +173,7 @@ public:
m_value.encoded = SHIFTED_INT32_TAG | (static_cast<i32>(value) & 0xFFFFFFFFul);
} else {
if (isnan(value)) [[unlikely]]
m_value.encoded = CANON_NAN_BITS;
m_value.encoded = GC::CANON_NAN_BITS;
else
m_value.as_double = value;
}
@ -215,44 +215,44 @@ public:
}
Value(Object const* object)
: Value(OBJECT_TAG << TAG_SHIFT, reinterpret_cast<void const*>(object))
: Value(OBJECT_TAG << GC::TAG_SHIFT, reinterpret_cast<void const*>(object))
{
}
Value(PrimitiveString const* string)
: Value(STRING_TAG << TAG_SHIFT, reinterpret_cast<void const*>(string))
: Value(STRING_TAG << GC::TAG_SHIFT, reinterpret_cast<void const*>(string))
{
}
Value(Symbol const* symbol)
: Value(SYMBOL_TAG << TAG_SHIFT, reinterpret_cast<void const*>(symbol))
: Value(SYMBOL_TAG << GC::TAG_SHIFT, reinterpret_cast<void const*>(symbol))
{
}
Value(Accessor const* accessor)
: Value(ACCESSOR_TAG << TAG_SHIFT, reinterpret_cast<void const*>(accessor))
: Value(ACCESSOR_TAG << GC::TAG_SHIFT, reinterpret_cast<void const*>(accessor))
{
}
Value(BigInt const* bigint)
: Value(BIGINT_TAG << TAG_SHIFT, reinterpret_cast<void const*>(bigint))
: Value(BIGINT_TAG << GC::TAG_SHIFT, reinterpret_cast<void const*>(bigint))
{
}
template<typename T>
Value(GCPtr<T> ptr)
Value(GC::Ptr<T> ptr)
: Value(ptr.ptr())
{
}
template<typename T>
Value(NonnullGCPtr<T> ptr)
Value(GC::Ref<T> ptr)
: Value(ptr.ptr())
{
}
template<typename T>
Value(Handle<T> const& ptr)
Value(GC::Root<T> const& ptr)
: Value(ptr.ptr())
{
}
@ -347,12 +347,12 @@ public:
ThrowCompletionOr<ByteString> to_byte_string(VM&) const;
ThrowCompletionOr<Utf16String> to_utf16_string(VM&) const;
ThrowCompletionOr<String> to_well_formed_string(VM&) const;
ThrowCompletionOr<NonnullGCPtr<PrimitiveString>> to_primitive_string(VM&);
ThrowCompletionOr<GC::Ref<PrimitiveString>> to_primitive_string(VM&);
ThrowCompletionOr<Value> to_primitive(VM&, PreferredType preferred_type = PreferredType::Default) const;
ThrowCompletionOr<NonnullGCPtr<Object>> to_object(VM&) const;
ThrowCompletionOr<GC::Ref<Object>> to_object(VM&) const;
ThrowCompletionOr<Value> to_numeric(VM&) const;
ThrowCompletionOr<Value> to_number(VM&) const;
ThrowCompletionOr<NonnullGCPtr<BigInt>> to_bigint(VM&) const;
ThrowCompletionOr<GC::Ref<BigInt>> to_bigint(VM&) const;
ThrowCompletionOr<i64> to_bigint_int64(VM&) const;
ThrowCompletionOr<u64> to_bigint_uint64(VM&) const;
ThrowCompletionOr<double> to_double(VM&) const;
@ -370,7 +370,7 @@ public:
bool to_boolean() const;
ThrowCompletionOr<Value> get(VM&, PropertyKey const&) const;
ThrowCompletionOr<GCPtr<FunctionObject>> get_method(VM&, PropertyKey const&) const;
ThrowCompletionOr<GC::Ptr<FunctionObject>> get_method(VM&, PropertyKey const&) const;
[[nodiscard]] String to_string_without_side_effects() const;
@ -381,7 +381,7 @@ public:
return *this;
}
[[nodiscard]] NonnullGCPtr<PrimitiveString> typeof_(VM&) const;
[[nodiscard]] GC::Ref<PrimitiveString> typeof_(VM&) const;
bool operator==(Value const&) const;
@ -390,7 +390,7 @@ public:
// A double is any Value which does not have the full exponent and top mantissa bit set or has
// exactly only those bits set.
bool is_double() const { return (m_value.encoded & CANON_NAN_BITS) != CANON_NAN_BITS || (m_value.encoded == CANON_NAN_BITS); }
bool is_double() const { return (m_value.encoded & GC::CANON_NAN_BITS) != GC::CANON_NAN_BITS || (m_value.encoded == GC::CANON_NAN_BITS); }
bool is_int32() const { return m_value.tag == INT32_TAG; }
i32 as_i32() const
@ -449,7 +449,7 @@ private:
}
}
[[nodiscard]] ThrowCompletionOr<Value> invoke_internal(VM&, PropertyKey const&, Optional<MarkedVector<Value>> arguments);
[[nodiscard]] ThrowCompletionOr<Value> invoke_internal(VM&, PropertyKey const&, Optional<GC::MarkedVector<Value>> arguments);
ThrowCompletionOr<i32> to_i32_slow_case(VM&) const;
@ -465,12 +465,12 @@ private:
inline Value js_undefined()
{
return Value(UNDEFINED_TAG << TAG_SHIFT, (u64)0);
return Value(UNDEFINED_TAG << GC::TAG_SHIFT, (u64)0);
}
inline Value js_null()
{
return Value(NULL_TAG << TAG_SHIFT, (u64)0);
return Value(NULL_TAG << GC::TAG_SHIFT, (u64)0);
}
inline Value js_nan()
@ -646,18 +646,18 @@ private:
}
namespace JS {
namespace GC {
template<>
class Handle<Value> {
class Root<JS::Value> {
public:
Handle() = default;
Root() = default;
static Handle create(Value value, SourceLocation location)
static Root create(JS::Value value, SourceLocation location)
{
if (value.is_cell())
return Handle(value, &value.as_cell(), location);
return Handle(value);
return Root(value, &value.as_cell(), location);
return Root(value);
}
auto cell() { return m_handle.cell(); }
@ -665,28 +665,28 @@ public:
auto value() const { return *m_value; }
bool is_null() const { return m_handle.is_null() && !m_value.has_value(); }
bool operator==(Value const& value) const { return value == m_value; }
bool operator==(Handle<Value> const& other) const { return other.m_value == this->m_value; }
bool operator==(JS::Value const& value) const { return value == m_value; }
bool operator==(Root<JS::Value> const& other) const { return other.m_value == this->m_value; }
private:
explicit Handle(Value value)
explicit Root(JS::Value value)
: m_value(value)
{
}
explicit Handle(Value value, CellImpl* cell, SourceLocation location)
explicit Root(JS::Value value, Cell* cell, SourceLocation location)
: m_value(value)
, m_handle(Handle<CellImpl>::create(cell, location))
, m_handle(Root<Cell>::create(cell, location))
{
}
Optional<Value> m_value;
Handle<CellImpl> m_handle;
Optional<JS::Value> m_value;
Root<Cell> m_handle;
};
inline Handle<Value> make_handle(Value value, SourceLocation location = SourceLocation::current())
inline Root<JS::Value> make_root(JS::Value value, SourceLocation location = SourceLocation::current())
{
return Handle<Value>::create(value, location);
return Root<JS::Value>::create(value, location);
}
}
@ -710,8 +710,8 @@ struct Traits<JS::Value> : DefaultTraits<JS::Value> {
};
template<>
struct Traits<JS::Handle<JS::Value>> : public DefaultTraits<JS::Handle<JS::Value>> {
static unsigned hash(JS::Handle<JS::Value> const& handle) { return Traits<JS::Value>::hash(handle.value()); }
struct Traits<GC::Root<JS::Value>> : public DefaultTraits<GC::Root<JS::Value>> {
static unsigned hash(GC::Root<JS::Value> const& handle) { return Traits<JS::Value>::hash(handle.value()); }
};
}