mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-06 08:10:02 +00:00
LibWeb: Make RopeString subclass so PrimitiveString can be smaller
By moving the LHS and RHS pointers used by rope strings into a RopeString subclass, we shrink PrimitiveString by 16 bytes. Most strings are not rope strings, so this ends up saving quite a bit of memory.
This commit is contained in:
parent
568531f06a
commit
152691f9eb
Notes:
github-actions[bot]
2025-03-30 06:17:46 +00:00
Author: https://github.com/awesomekling
Commit: 152691f9eb
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4149
Reviewed-by: https://github.com/Hendiadyoin1
Reviewed-by: https://github.com/tcl3 ✅
2 changed files with 56 additions and 23 deletions
|
@ -20,14 +20,17 @@
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
GC_DEFINE_ALLOCATOR(PrimitiveString);
|
GC_DEFINE_ALLOCATOR(PrimitiveString);
|
||||||
|
GC_DEFINE_ALLOCATOR(RopeString);
|
||||||
|
|
||||||
PrimitiveString::PrimitiveString(PrimitiveString& lhs, PrimitiveString& rhs)
|
RopeString::RopeString(GC::Ref<PrimitiveString> lhs, GC::Ref<PrimitiveString> rhs)
|
||||||
: m_is_rope(true)
|
: PrimitiveString(RopeTag::Rope)
|
||||||
, m_lhs(&lhs)
|
, m_lhs(lhs)
|
||||||
, m_rhs(&rhs)
|
, m_rhs(rhs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RopeString::~RopeString() = default;
|
||||||
|
|
||||||
PrimitiveString::PrimitiveString(String string)
|
PrimitiveString::PrimitiveString(String string)
|
||||||
: m_utf8_string(move(string))
|
: m_utf8_string(move(string))
|
||||||
{
|
{
|
||||||
|
@ -46,13 +49,11 @@ PrimitiveString::~PrimitiveString()
|
||||||
vm().utf16_string_cache().remove(*m_utf16_string);
|
vm().utf16_string_cache().remove(*m_utf16_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimitiveString::visit_edges(Cell::Visitor& visitor)
|
void RopeString::visit_edges(Cell::Visitor& visitor)
|
||||||
{
|
{
|
||||||
Base::visit_edges(visitor);
|
Base::visit_edges(visitor);
|
||||||
if (m_is_rope) {
|
visitor.visit(m_lhs);
|
||||||
visitor.visit(m_lhs);
|
visitor.visit(m_rhs);
|
||||||
visitor.visit(m_rhs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrimitiveString::is_empty() const
|
bool PrimitiveString::is_empty() const
|
||||||
|
@ -192,7 +193,7 @@ GC::Ref<PrimitiveString> PrimitiveString::create(VM& vm, PrimitiveString& lhs, P
|
||||||
if (rhs_empty)
|
if (rhs_empty)
|
||||||
return lhs;
|
return lhs;
|
||||||
|
|
||||||
return vm.heap().allocate<PrimitiveString>(lhs, rhs);
|
return vm.heap().allocate<RopeString>(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) const
|
void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) const
|
||||||
|
@ -200,6 +201,13 @@ void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) cons
|
||||||
if (!m_is_rope)
|
if (!m_is_rope)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto const& rope_string = static_cast<RopeString const&>(*this);
|
||||||
|
return rope_string.resolve(preference);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RopeString::resolve(EncodingPreference preference) const
|
||||||
|
{
|
||||||
|
|
||||||
// This vector will hold all the pieces of the rope that need to be assembled
|
// This vector will hold all the pieces of the rope that need to be assembled
|
||||||
// into the resolved string.
|
// into the resolved string.
|
||||||
Vector<PrimitiveString const*> pieces;
|
Vector<PrimitiveString const*> pieces;
|
||||||
|
@ -213,8 +221,9 @@ void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) cons
|
||||||
while (!stack.is_empty()) {
|
while (!stack.is_empty()) {
|
||||||
auto const* current = stack.take_last();
|
auto const* current = stack.take_last();
|
||||||
if (current->m_is_rope) {
|
if (current->m_is_rope) {
|
||||||
stack.append(current->m_rhs);
|
auto& current_rope_string = static_cast<RopeString const&>(*current);
|
||||||
stack.append(current->m_lhs);
|
stack.append(current_rope_string.m_rhs);
|
||||||
|
stack.append(current_rope_string.m_lhs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
class PrimitiveString final : public Cell {
|
class PrimitiveString : public Cell {
|
||||||
GC_CELL(PrimitiveString, Cell);
|
GC_CELL(PrimitiveString, Cell);
|
||||||
GC_DECLARE_ALLOCATOR(PrimitiveString);
|
GC_DECLARE_ALLOCATOR(PrimitiveString);
|
||||||
|
|
||||||
|
@ -47,26 +47,50 @@ public:
|
||||||
|
|
||||||
ThrowCompletionOr<Optional<Value>> get(VM&, PropertyKey const&) const;
|
ThrowCompletionOr<Optional<Value>> get(VM&, PropertyKey const&) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
explicit PrimitiveString(PrimitiveString&, PrimitiveString&);
|
enum class RopeTag { Rope };
|
||||||
explicit PrimitiveString(String);
|
explicit PrimitiveString(RopeTag)
|
||||||
explicit PrimitiveString(Utf16String);
|
: m_is_rope(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
mutable bool m_is_rope { false };
|
||||||
|
|
||||||
|
mutable Optional<String> m_utf8_string;
|
||||||
|
mutable Optional<Utf16String> m_utf16_string;
|
||||||
|
|
||||||
enum class EncodingPreference {
|
enum class EncodingPreference {
|
||||||
UTF8,
|
UTF8,
|
||||||
UTF16,
|
UTF16,
|
||||||
};
|
};
|
||||||
void resolve_rope_if_needed(EncodingPreference) const;
|
|
||||||
|
|
||||||
mutable bool m_is_rope { false };
|
private:
|
||||||
|
friend class RopeString;
|
||||||
|
|
||||||
|
explicit PrimitiveString(String);
|
||||||
|
explicit PrimitiveString(Utf16String);
|
||||||
|
|
||||||
|
void resolve_rope_if_needed(EncodingPreference) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RopeString final : public PrimitiveString {
|
||||||
|
GC_CELL(RopeString, PrimitiveString);
|
||||||
|
GC_DECLARE_ALLOCATOR(RopeString);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~RopeString() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class PrimitiveString;
|
||||||
|
|
||||||
|
explicit RopeString(GC::Ref<PrimitiveString>, GC::Ref<PrimitiveString>);
|
||||||
|
|
||||||
|
virtual void visit_edges(Visitor&) override;
|
||||||
|
|
||||||
|
void resolve(EncodingPreference) const;
|
||||||
|
|
||||||
mutable GC::Ptr<PrimitiveString> m_lhs;
|
mutable GC::Ptr<PrimitiveString> m_lhs;
|
||||||
mutable GC::Ptr<PrimitiveString> m_rhs;
|
mutable GC::Ptr<PrimitiveString> m_rhs;
|
||||||
|
|
||||||
mutable Optional<String> m_utf8_string;
|
|
||||||
mutable Optional<Utf16String> m_utf16_string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue