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<>