1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 03:47:35 +00:00

LibJS: Store DFS instead of opaque StringImpl inside StringOrSymbol

Additionally, use the second bit (instead of the first) to differentiate
between strings and symbols there. This will allow transparent
conversion of DFS to StringBase in the future.
This commit is contained in:
Dan Klishch 2024-01-22 16:10:45 -05:00 committed by Andrew Kaster
parent a53911717f
commit 761d16141d

View file

@ -15,7 +15,10 @@ namespace JS {
class StringOrSymbol {
public:
StringOrSymbol() = default;
StringOrSymbol()
: m_bits(0)
{
}
StringOrSymbol(char const* chars)
: StringOrSymbol(DeprecatedFlyString(chars))
@ -28,50 +31,53 @@ public:
}
StringOrSymbol(DeprecatedFlyString const& string)
: m_ptr(string.impl())
: m_string(string)
{
VERIFY(!string.is_null());
as_string_impl().ref();
}
~StringOrSymbol()
{
if (is_string())
as_string_impl().unref();
m_string.~DeprecatedFlyString();
}
StringOrSymbol(Symbol const* symbol)
: m_ptr(symbol)
: m_symbol_with_tag(symbol)
{
set_symbol_flag();
}
StringOrSymbol(StringOrSymbol const& other)
{
m_ptr = other.m_ptr;
if (is_string())
as_string_impl().ref();
if (other.is_string())
new (&m_string) DeprecatedFlyString(other.m_string);
else
m_bits = other.m_bits;
}
StringOrSymbol(StringOrSymbol&& other)
{
m_ptr = exchange(other.m_ptr, nullptr);
if (other.is_string())
new (&m_string) DeprecatedFlyString(move(other.m_string));
else
m_bits = exchange(other.m_bits, 0);
}
ALWAYS_INLINE bool is_valid() const { return m_ptr != nullptr; }
ALWAYS_INLINE bool is_symbol() const { return is_valid() && (bits() & 1ul); }
ALWAYS_INLINE bool is_string() const { return is_valid() && !(bits() & 1ul); }
ALWAYS_INLINE bool is_valid() const { return m_bits != 0; }
ALWAYS_INLINE bool is_symbol() const { return is_valid() && (m_bits & 2); }
ALWAYS_INLINE bool is_string() const { return is_valid() && !(m_bits & 2); }
ALWAYS_INLINE DeprecatedFlyString as_string() const
{
VERIFY(is_string());
return DeprecatedFlyString::from_fly_impl(as_string_impl());
return m_string;
}
ALWAYS_INLINE Symbol const* as_symbol() const
{
VERIFY(is_symbol());
return reinterpret_cast<Symbol const*>(bits() & ~1ul);
return reinterpret_cast<Symbol const*>(m_bits & ~2ULL);
}
ByteString to_display_string() const
@ -101,7 +107,7 @@ public:
ALWAYS_INLINE bool operator==(StringOrSymbol const& other) const
{
if (is_string())
return other.is_string() && &as_string_impl() == &other.as_string_impl();
return other.is_string() && m_string == other.m_string;
if (is_symbol())
return other.is_symbol() && as_symbol() == other.as_symbol();
return true;
@ -109,47 +115,43 @@ public:
StringOrSymbol& operator=(StringOrSymbol const& other)
{
if (this == &other)
return *this;
m_ptr = other.m_ptr;
if (is_string())
as_string_impl().ref();
if (this != &other) {
this->~StringOrSymbol();
new (this) StringOrSymbol(other);
}
return *this;
}
StringOrSymbol& operator=(StringOrSymbol&& other)
{
if (this != &other)
m_ptr = exchange(other.m_ptr, nullptr);
if (this != &other) {
this->~StringOrSymbol();
new (this) StringOrSymbol(move(other));
}
return *this;
}
unsigned hash() const
{
if (is_string())
return as_string_impl().hash();
return m_string.hash();
return ptr_hash(as_symbol());
}
private:
ALWAYS_INLINE u64 bits() const
{
return reinterpret_cast<uintptr_t>(m_ptr);
}
ALWAYS_INLINE void set_symbol_flag()
{
m_ptr = reinterpret_cast<void const*>(bits() | 1ul);
m_bits |= 2;
}
ALWAYS_INLINE StringImpl const& as_string_impl() const
{
VERIFY(is_string());
return *reinterpret_cast<StringImpl const*>(m_ptr);
}
void const* m_ptr { nullptr };
union {
DeprecatedFlyString m_string;
Symbol const* m_symbol_with_tag;
uintptr_t m_bits;
};
};
static_assert(sizeof(StringOrSymbol) == sizeof(uintptr_t));
}