From 761d16141d807a051f7fdd00e3d04154a34b1bb4 Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Mon, 22 Jan 2024 16:10:45 -0500 Subject: [PATCH] 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. --- .../Libraries/LibJS/Runtime/StringOrSymbol.h | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/StringOrSymbol.h b/Userland/Libraries/LibJS/Runtime/StringOrSymbol.h index d2d23aa999..728eb7ded0 100644 --- a/Userland/Libraries/LibJS/Runtime/StringOrSymbol.h +++ b/Userland/Libraries/LibJS/Runtime/StringOrSymbol.h @@ -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(bits() & ~1ul); + return reinterpret_cast(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,48 +115,44 @@ 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(m_ptr); - } - ALWAYS_INLINE void set_symbol_flag() { - m_ptr = reinterpret_cast(bits() | 1ul); + m_bits |= 2; } - ALWAYS_INLINE StringImpl const& as_string_impl() const - { - VERIFY(is_string()); - return *reinterpret_cast(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)); + } template<>