forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LibWeb: Share QualifiedName data between identical instances
Adopt the same pattern as AK::FlyString, reducing sizeof(QualifiedName) to the size of a pointer. This reduces the size of DOM::Element by 24 bytes.
- Loading branch information
1 parent
4b900bc
commit cf5eeb9
Showing
3 changed files
with
92 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Copyright (c) 2022, Andreas Kling <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
||
#include <AK/HashTable.h> | ||
#include <LibWeb/DOM/QualifiedName.h> | ||
|
||
namespace Web::DOM { | ||
|
||
struct ImplTraits : public Traits<QualifiedName::Impl*> { | ||
static unsigned hash(QualifiedName::Impl* impl) | ||
{ | ||
return pair_int_hash(impl->local_name.hash(), pair_int_hash(impl->prefix.hash(), impl->namespace_.hash())); | ||
} | ||
|
||
static bool equals(QualifiedName::Impl* a, QualifiedName::Impl* b) | ||
{ | ||
return a->local_name == b->local_name | ||
&& a->prefix == b->prefix | ||
&& a->namespace_ == b->namespace_; | ||
} | ||
}; | ||
|
||
static HashTable<QualifiedName::Impl*, ImplTraits> impls; | ||
|
||
static NonnullRefPtr<QualifiedName::Impl> ensure_impl(FlyString const& local_name, FlyString const& prefix, FlyString const& namespace_) | ||
{ | ||
auto hash = pair_int_hash(local_name.hash(), pair_int_hash(prefix.hash(), namespace_.hash())); | ||
auto it = impls.find(hash, [&](QualifiedName::Impl* entry) { | ||
return entry->local_name == local_name | ||
&& entry->prefix == prefix | ||
&& entry->namespace_ == namespace_; | ||
}); | ||
if (it != impls.end()) | ||
return *(*it); | ||
return adopt_ref(*new QualifiedName::Impl(local_name, prefix, namespace_)); | ||
} | ||
|
||
QualifiedName::QualifiedName(FlyString const& local_name, FlyString const& prefix, FlyString const& namespace_) | ||
: m_impl(ensure_impl(local_name, prefix, namespace_)) | ||
{ | ||
} | ||
|
||
QualifiedName::Impl::Impl(FlyString const& a_local_name, FlyString const& a_prefix, FlyString const& a_namespace) | ||
: local_name(a_local_name) | ||
, prefix(a_prefix) | ||
, namespace_(a_namespace) | ||
{ | ||
impls.set(this); | ||
make_internal_string(); | ||
} | ||
|
||
QualifiedName::Impl::~Impl() | ||
{ | ||
impls.remove(this); | ||
} | ||
|
||
// https://dom.spec.whatwg.org/#concept-attribute-qualified-name | ||
// https://dom.spec.whatwg.org/#concept-element-qualified-name | ||
void QualifiedName::Impl::make_internal_string() | ||
{ | ||
// This is possible to do according to the spec: "User agents could have this as an internal slot as an optimization." | ||
if (prefix.is_null()) { | ||
as_string = local_name; | ||
return; | ||
} | ||
|
||
as_string = String::formatted("{}:{}", prefix, local_name); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (c) 2020, the SerenityOS developers. | ||
* Copyright (c) 2022, Andreas Kling <[email protected]> | ||
* | ||
* SPDX-License-Identifier: BSD-2-Clause | ||
*/ | ||
|
@@ -12,38 +13,27 @@ namespace Web::DOM { | |
|
||
class QualifiedName { | ||
public: | ||
QualifiedName(const FlyString& local_name, const FlyString& prefix, const FlyString& namespace_) | ||
: m_local_name(local_name) | ||
, m_prefix(prefix) | ||
, m_namespace(namespace_) | ||
{ | ||
make_internal_string(); | ||
} | ||
QualifiedName(FlyString const& local_name, FlyString const& prefix, FlyString const& namespace_); | ||
|
||
const FlyString& local_name() const { return m_local_name; } | ||
const FlyString& prefix() const { return m_prefix; } | ||
const FlyString& namespace_() const { return m_namespace; } | ||
FlyString const& local_name() const { return m_impl->local_name; } | ||
FlyString const& prefix() const { return m_impl->prefix; } | ||
FlyString const& namespace_() const { return m_impl->namespace_; } | ||
|
||
const String& as_string() const { return m_as_string; } | ||
String const& as_string() const { return m_impl->as_string; } | ||
|
||
struct Impl : public RefCounted<Impl> { | ||
Impl(FlyString const& local_name, FlyString const& prefix, FlyString const& namespace_); | ||
~Impl(); | ||
|
||
void make_internal_string(); | ||
FlyString local_name; | ||
FlyString prefix; | ||
FlyString namespace_; | ||
String as_string; | ||
}; | ||
|
||
private: | ||
FlyString m_local_name; | ||
FlyString m_prefix; | ||
FlyString m_namespace; | ||
String m_as_string; | ||
|
||
// https://dom.spec.whatwg.org/#concept-attribute-qualified-name | ||
// https://dom.spec.whatwg.org/#concept-element-qualified-name | ||
void make_internal_string() | ||
{ | ||
// This is possible to do according to the spec: "User agents could have this as an internal slot as an optimization." | ||
if (m_prefix.is_null()) { | ||
m_as_string = m_local_name; | ||
return; | ||
} | ||
|
||
m_as_string = String::formatted("{}:{}", m_prefix, m_local_name); | ||
} | ||
NonnullRefPtr<Impl> m_impl; | ||
}; | ||
|
||
} |