diff --git a/Source/WebCore/dom/ElementIdentifier.h b/Source/WebCore/dom/ElementIdentifier.h index 2ed378242a4c..5cea026d9362 100644 --- a/Source/WebCore/dom/ElementIdentifier.h +++ b/Source/WebCore/dom/ElementIdentifier.h @@ -25,11 +25,150 @@ #pragma once -#include +#include +#include +#include +#include +#include +#include namespace WebCore { enum ElementIdentifierType { }; -using ElementIdentifier = ObjectIdentifier; +class ElementIdentifierBase { +protected: + WTF_EXPORT_PRIVATE static uint64_t generateIdentifierInternal(); + WTF_EXPORT_PRIVATE static uint64_t generateThreadSafeIdentifierInternal(); +}; + +class ElementIdentifier : private ElementIdentifierBase { +public: + static ElementIdentifier generate() + { + RELEASE_ASSERT(!m_generationProtected); + return ElementIdentifier { generateIdentifierInternal() }; + } + + static ElementIdentifier generateThreadSafe() + { + RELEASE_ASSERT(!m_generationProtected); + return ElementIdentifier { generateThreadSafeIdentifierInternal() }; + } + + static void enableGenerationProtection() + { + m_generationProtected = true; + } + + ElementIdentifier() = default; + + ElementIdentifier(WTF::HashTableDeletedValueType) : m_identifier(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_identifier == hashTableDeletedValue(); } + + template void encode(Encoder& encoder) const + { + ASSERT(isValidIdentifier(m_identifier)); + encoder << m_identifier; + } + template static Optional decode(Decoder& decoder) + { + Optional identifier; + decoder >> identifier; + if (!identifier || !isValidIdentifier(*identifier)) + return WTF::nullopt; + return ElementIdentifier { *identifier }; + } + + bool operator==(const ElementIdentifier& other) const + { + return m_identifier == other.m_identifier; + } + + bool operator!=(const ElementIdentifier& other) const + { + return m_identifier != other.m_identifier; + } + + operator uint64_t() const { return m_identifier; } + uint64_t toUInt64() const { return m_identifier; } + explicit operator bool() const { return m_identifier; } + + String loggingString() const + { + return String::number(m_identifier); + } + + struct MarkableTraits { + static bool isEmptyValue(ElementIdentifier identifier) + { + return !identifier.m_identifier; + } + + static constexpr ElementIdentifier emptyValue() + { + return ElementIdentifier(); + } + }; + +private: + friend ElementIdentifier makeElementIdentifier(uint64_t); + friend struct HashTraits; + friend struct ElementIdentifierHash; + + static uint64_t hashTableDeletedValue() { return std::numeric_limits::max(); } + static bool isValidIdentifier(uint64_t identifier) { return identifier && identifier != hashTableDeletedValue(); } + + explicit constexpr ElementIdentifier(uint64_t identifier) + : m_identifier(identifier) + { + } + + uint64_t m_identifier { 0 }; + inline static bool m_generationProtected { false }; +}; + +inline ElementIdentifier makeElementIdentifier(uint64_t identifier) +{ + return ElementIdentifier { identifier }; +} + +struct ElementIdentifierHash { + static unsigned hash(const ElementIdentifier& identifier) { return WTF::intHash(identifier.m_identifier); } + static bool equal(const ElementIdentifier& a, const ElementIdentifier& b) { return a == b; } + static constexpr bool safeToCompareToEmptyOrDeleted = true; +}; + +inline TextStream& operator<<(TextStream& ts, const ElementIdentifier& identifier) +{ + ts << identifier.toUInt64(); + return ts; +} + +inline uint64_t ElementIdentifierBase::generateIdentifierInternal() +{ + static uint64_t current; + return ++current; } + +inline uint64_t ElementIdentifierBase::generateThreadSafeIdentifierInternal() +{ + static LazyNeverDestroyed> current; + static std::once_flag initializeCurrentIdentifier; + std::call_once(initializeCurrentIdentifier, [] { + current.construct(0); + }); + return ++current.get(); +} + +} // namespace WebCore + +namespace WTF { + +template<> struct HashTraits : SimpleClassHashTraits { }; + +template<> struct DefaultHash { + typedef WebCore::ElementIdentifierHash Hash; +}; + +} // namespace WTF diff --git a/Source/WebCore/page/PageIdentifier.h b/Source/WebCore/page/PageIdentifier.h index 44d5f8d29756..07f7f2750af2 100644 --- a/Source/WebCore/page/PageIdentifier.h +++ b/Source/WebCore/page/PageIdentifier.h @@ -25,11 +25,150 @@ #pragma once -#include +#include +#include +#include +#include +#include +#include namespace WebCore { enum PageIdentifierType { }; -using PageIdentifier = ObjectIdentifier; +class PageIdentifierBase { +protected: + WTF_EXPORT_PRIVATE static uint64_t generateIdentifierInternal(); + WTF_EXPORT_PRIVATE static uint64_t generateThreadSafeIdentifierInternal(); +}; + +class PageIdentifier : private PageIdentifierBase { +public: + static PageIdentifier generate() + { + RELEASE_ASSERT(!m_generationProtected); + return PageIdentifier { generateIdentifierInternal() }; + } + + static PageIdentifier generateThreadSafe() + { + RELEASE_ASSERT(!m_generationProtected); + return PageIdentifier { generateThreadSafeIdentifierInternal() }; + } + + static void enableGenerationProtection() + { + m_generationProtected = true; + } + + PageIdentifier() = default; + + PageIdentifier(WTF::HashTableDeletedValueType) : m_identifier(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_identifier == hashTableDeletedValue(); } + + template void encode(Encoder& encoder) const + { + ASSERT(isValidIdentifier(m_identifier)); + encoder << m_identifier; + } + template static Optional decode(Decoder& decoder) + { + Optional identifier; + decoder >> identifier; + if (!identifier || !isValidIdentifier(*identifier)) + return WTF::nullopt; + return PageIdentifier { *identifier }; + } + + bool operator==(const PageIdentifier& other) const + { + return m_identifier == other.m_identifier; + } + + bool operator!=(const PageIdentifier& other) const + { + return m_identifier != other.m_identifier; + } + + operator uint64_t() const { return m_identifier; } + uint64_t toUInt64() const { return m_identifier; } + explicit operator bool() const { return m_identifier; } + + String loggingString() const + { + return String::number(m_identifier); + } + + struct MarkableTraits { + static bool isEmptyValue(PageIdentifier identifier) + { + return !identifier.m_identifier; + } + + static constexpr PageIdentifier emptyValue() + { + return PageIdentifier(); + } + }; + +private: + friend PageIdentifier makePageIdentifier(uint64_t); + friend struct HashTraits; + friend struct PageIdentifierHash; + + static uint64_t hashTableDeletedValue() { return std::numeric_limits::max(); } + static bool isValidIdentifier(uint64_t identifier) { return identifier && identifier != hashTableDeletedValue(); } + + explicit constexpr PageIdentifier(uint64_t identifier) + : m_identifier(identifier) + { + } + + uint64_t m_identifier { 0 }; + inline static bool m_generationProtected { false }; +}; + +inline PageIdentifier makePageIdentifier(uint64_t identifier) +{ + return PageIdentifier { identifier }; +} + +struct PageIdentifierHash { + static unsigned hash(const PageIdentifier& identifier) { return WTF::intHash(identifier.m_identifier); } + static bool equal(const PageIdentifier& a, const PageIdentifier& b) { return a == b; } + static constexpr bool safeToCompareToEmptyOrDeleted = true; +}; + +inline TextStream& operator<<(TextStream& ts, const PageIdentifier& identifier) +{ + ts << identifier.toUInt64(); + return ts; +} + +inline uint64_t PageIdentifierBase::generateIdentifierInternal() +{ + static uint64_t current; + return ++current; } + +inline uint64_t PageIdentifierBase::generateThreadSafeIdentifierInternal() +{ + static LazyNeverDestroyed> current; + static std::once_flag initializeCurrentIdentifier; + std::call_once(initializeCurrentIdentifier, [] { + current.construct(0); + }); + return ++current.get(); +} + +} // namespace WebCore + +namespace WTF { + +template<> struct HashTraits : SimpleClassHashTraits { }; + +template<> struct DefaultHash { + typedef WebCore::PageIdentifierHash Hash; +}; + +} // namespace WTF diff --git a/Source/WebKit/NetworkProcess/cache/NetworkCache.h b/Source/WebKit/NetworkProcess/cache/NetworkCache.h index 04d7d6af73bc..d7bfee11b030 100644 --- a/Source/WebKit/NetworkProcess/cache/NetworkCache.h +++ b/Source/WebKit/NetworkProcess/cache/NetworkCache.h @@ -225,7 +225,7 @@ struct GlobalFrameIDHash { template<> struct HashTraits : GenericHashTraits { static WebKit::NetworkCache::GlobalFrameID emptyValue() { return { }; } - static void constructDeletedValue(WebKit::NetworkCache::GlobalFrameID& slot) { slot.webPageID = makeObjectIdentifier(std::numeric_limits::max()); } + static void constructDeletedValue(WebKit::NetworkCache::GlobalFrameID& slot) { slot.webPageID = WebCore::makePageIdentifier(std::numeric_limits::max()); } static bool isDeletedValue(const WebKit::NetworkCache::GlobalFrameID& slot) { return slot.webPageID.toUInt64() == std::numeric_limits::max(); } }; diff --git a/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp b/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp index b34d13b865c5..26083eda5486 100644 --- a/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp +++ b/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp @@ -388,7 +388,7 @@ static const struct wl_webkitgtk_interface webkitgtkInterface = { return; auto* compositor = static_cast(wl_resource_get_user_data(resource)); - compositor->bindSurfaceToWebPage(surface, makeObjectIdentifier(pageID)); + compositor->bindSurfaceToWebPage(surface, WebCore::makePageIdentifier(pageID)); } }; diff --git a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp index 5f3cca93e3ac..b52c36838dcd 100644 --- a/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp +++ b/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp @@ -98,7 +98,7 @@ void NetworkProcessConnection::didReceiveMessage(IPC::Connection& connection, IP return; } if (decoder.messageReceiverName() == Messages::WebPage::messageReceiverName()) { - if (auto* webPage = WebProcess::singleton().webPage(makeObjectIdentifier(decoder.destinationID()))) + if (auto* webPage = WebProcess::singleton().webPage(WebCore::makePageIdentifier(decoder.destinationID()))) webPage->didReceiveWebPageMessage(connection, decoder); return; } @@ -152,7 +152,7 @@ void NetworkProcessConnection::didReceiveMessage(IPC::Connection& connection, IP #if ENABLE(APPLE_PAY_REMOTE_UI) if (decoder.messageReceiverName() == Messages::WebPaymentCoordinator::messageReceiverName()) { - if (auto webPage = WebProcess::singleton().webPage(makeObjectIdentifier(decoder.destinationID()))) + if (auto webPage = WebProcess::singleton().webPage(WebCore::makePageIdentifier(decoder.destinationID()))) webPage->paymentCoordinator()->didReceiveMessage(connection, decoder); return; } @@ -174,7 +174,7 @@ void NetworkProcessConnection::didReceiveSyncMessage(IPC::Connection& connection #if ENABLE(APPLE_PAY_REMOTE_UI) if (decoder.messageReceiverName() == Messages::WebPaymentCoordinator::messageReceiverName()) { - if (auto webPage = WebProcess::singleton().webPage(makeObjectIdentifier(decoder.destinationID()))) + if (auto webPage = WebProcess::singleton().webPage(WebCore::makePageIdentifier(decoder.destinationID()))) webPage->paymentCoordinator()->didReceiveSyncMessage(connection, decoder, replyEncoder); return; }