mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 20:29:18 +00:00
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:
parent
ce23efc5f6
commit
f87041bf3a
Notes:
github-actions[bot]
2024-11-15 13:50:17 +00:00
Author: https://github.com/shannonbooth
Commit: f87041bf3a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2345
1722 changed files with 9939 additions and 9906 deletions
|
@ -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()); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue