Title: [254881] trunk
Revision
254881
Author
[email protected]
Date
2020-01-21 14:05:43 -0800 (Tue, 21 Jan 2020)

Log Message

[WTF] AtomStringTable should be small
https://bugs.webkit.org/show_bug.cgi?id=206400

Reviewed by Sam Weinig.

Source/WebCore:

* dom/GCReachableRef.h:
(WebCore::GCReachableRef::GCReachableRef):
* dom/QualifiedName.h:
(WebCore::QualifiedName::hashTableDeletedValue):

Source/WTF:

AtomStringTable is the largest hashtable typically. It takes more
than 256KB per WebProcess (sometimes, it took 1MB or more).
This patch leverages PackedPtr to compact it from 8 bytes per entry
to 6 bytes per entry.

While this is still large, we should investigate how to compact C++
pointers in 4 bytes[1] to shrink memory footprint, since WebKit
memory is used by Vector and HashTable fulfilled with pointers.

[1]: https://bugs.webkit.org/show_bug.cgi?id=206469

* wtf/DumbPtrTraits.h:
(WTF::DumbPtrTraits::hashTableDeletedValue):
(WTF::DumbPtrTraits::isHashTableDeletedValue):
* wtf/Forward.h:
* wtf/HashTraits.h:
* wtf/Packed.h:
(WTF::Packed<T::Packed):
(WTF::Packed<T::isHashTableDeletedValue const):
(WTF::GetPtrHelper<PackedPtr<T>>::getPtr):
(WTF::PackedPtrTraits::hashTableDeletedValue):
(WTF::PackedPtrTraits::isHashTableDeletedValue):
(WTF::alignof): Deleted.
* wtf/Ref.h:
(WTF::Ref::Ref):
(WTF::Ref::isHashTableDeletedValue const):
(WTF::Ref::hashTableDeletedValue): Deleted.
* wtf/RefPtr.h:
(WTF::RefPtr::RefPtr):
(WTF::RefPtr::isHashTableDeletedValue const):
(WTF::RefPtr::hashTableDeletedValue): Deleted.
* wtf/text/AtomStringImpl.cpp:
(WTF::addToStringTable):
(WTF::CStringTranslator::equal):
(WTF::CStringTranslator::translate):
(WTF::UCharBufferTranslator::equal):
(WTF::UCharBufferTranslator::translate):
(WTF::HashAndUTF8CharactersTranslator::equal):
(WTF::HashAndUTF8CharactersTranslator::translate):
(WTF::SubstringTranslator::translate):
(WTF::SubstringTranslator8::equal):
(WTF::SubstringTranslator16::equal):
(WTF::LCharBufferTranslator::equal):
(WTF::LCharBufferTranslator::translate):
(WTF::BufferFromStaticDataTranslator::equal):
(WTF::BufferFromStaticDataTranslator::translate):
(WTF::AtomStringImpl::addSlowCase):
(WTF::AtomStringImpl::remove):
(WTF::AtomStringImpl::lookUpSlowCase):
(WTF::AtomStringImpl::lookUp):
* wtf/text/AtomStringTable.cpp:
(WTF::AtomStringTable::~AtomStringTable):
* wtf/text/AtomStringTable.h:
(WTF::AtomStringTable::table):
(): Deleted.
* wtf/text/StringHash.h:
(WTF::StringHash::hash):
(WTF::StringHash::equal):
(WTF::ASCIICaseInsensitiveHash::hash):
(WTF::ASCIICaseInsensitiveHash::equal):
* wtf/text/StringImpl.h:

Tools:

* TestWebKitAPI/Tests/WTF/HashMap.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/HashSet.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/Packed.cpp:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (254880 => 254881)


--- trunk/Source/WTF/ChangeLog	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/ChangeLog	2020-01-21 22:05:43 UTC (rev 254881)
@@ -1,3 +1,72 @@
+2020-01-21  Yusuke Suzuki  <[email protected]>
+
+        [WTF] AtomStringTable should be small
+        https://bugs.webkit.org/show_bug.cgi?id=206400
+
+        Reviewed by Sam Weinig.
+
+        AtomStringTable is the largest hashtable typically. It takes more
+        than 256KB per WebProcess (sometimes, it took 1MB or more).
+        This patch leverages PackedPtr to compact it from 8 bytes per entry
+        to 6 bytes per entry.
+
+        While this is still large, we should investigate how to compact C++
+        pointers in 4 bytes[1] to shrink memory footprint, since WebKit
+        memory is used by Vector and HashTable fulfilled with pointers.
+
+        [1]: https://bugs.webkit.org/show_bug.cgi?id=206469
+
+        * wtf/DumbPtrTraits.h:
+        (WTF::DumbPtrTraits::hashTableDeletedValue):
+        (WTF::DumbPtrTraits::isHashTableDeletedValue):
+        * wtf/Forward.h:
+        * wtf/HashTraits.h:
+        * wtf/Packed.h:
+        (WTF::Packed<T::Packed):
+        (WTF::Packed<T::isHashTableDeletedValue const):
+        (WTF::GetPtrHelper<PackedPtr<T>>::getPtr):
+        (WTF::PackedPtrTraits::hashTableDeletedValue):
+        (WTF::PackedPtrTraits::isHashTableDeletedValue):
+        (WTF::alignof): Deleted.
+        * wtf/Ref.h:
+        (WTF::Ref::Ref):
+        (WTF::Ref::isHashTableDeletedValue const):
+        (WTF::Ref::hashTableDeletedValue): Deleted.
+        * wtf/RefPtr.h:
+        (WTF::RefPtr::RefPtr):
+        (WTF::RefPtr::isHashTableDeletedValue const):
+        (WTF::RefPtr::hashTableDeletedValue): Deleted.
+        * wtf/text/AtomStringImpl.cpp:
+        (WTF::addToStringTable):
+        (WTF::CStringTranslator::equal):
+        (WTF::CStringTranslator::translate):
+        (WTF::UCharBufferTranslator::equal):
+        (WTF::UCharBufferTranslator::translate):
+        (WTF::HashAndUTF8CharactersTranslator::equal):
+        (WTF::HashAndUTF8CharactersTranslator::translate):
+        (WTF::SubstringTranslator::translate):
+        (WTF::SubstringTranslator8::equal):
+        (WTF::SubstringTranslator16::equal):
+        (WTF::LCharBufferTranslator::equal):
+        (WTF::LCharBufferTranslator::translate):
+        (WTF::BufferFromStaticDataTranslator::equal):
+        (WTF::BufferFromStaticDataTranslator::translate):
+        (WTF::AtomStringImpl::addSlowCase):
+        (WTF::AtomStringImpl::remove):
+        (WTF::AtomStringImpl::lookUpSlowCase):
+        (WTF::AtomStringImpl::lookUp):
+        * wtf/text/AtomStringTable.cpp:
+        (WTF::AtomStringTable::~AtomStringTable):
+        * wtf/text/AtomStringTable.h:
+        (WTF::AtomStringTable::table):
+        (): Deleted.
+        * wtf/text/StringHash.h:
+        (WTF::StringHash::hash):
+        (WTF::StringHash::equal):
+        (WTF::ASCIICaseInsensitiveHash::hash):
+        (WTF::ASCIICaseInsensitiveHash::equal):
+        * wtf/text/StringImpl.h:
+
 2020-01-17  Sam Weinig  <[email protected]>
 
         Platform.h is out of control Part 8: Macros are used inconsistently

Modified: trunk/Source/WTF/wtf/DumbPtrTraits.h (254880 => 254881)


--- trunk/Source/WTF/wtf/DumbPtrTraits.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/DumbPtrTraits.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -41,6 +41,9 @@
 
     static ALWAYS_INLINE void swap(StorageType& a, StorageType& b) { std::swap(a, b); }
     static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr; }
+
+    static StorageType hashTableDeletedValue() { return bitwise_cast<StorageType>(static_cast<uintptr_t>(-1)); }
+    static ALWAYS_INLINE bool isHashTableDeletedValue(const StorageType& ptr) { return ptr == hashTableDeletedValue(); }
 };
 
 } // namespace WTF

Modified: trunk/Source/WTF/wtf/Forward.h (254880 => 254881)


--- trunk/Source/WTF/wtf/Forward.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/Forward.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -62,6 +62,8 @@
 template<typename> class NeverDestroyed;
 template<typename> class OptionSet;
 template<typename> class Optional;
+template<typename T> class Packed;
+template<typename T, size_t = alignof(T)> class PackedAlignedPtr;
 template<typename T, typename = DumbPtrTraits<T>> class Ref;
 template<typename T, typename = DumbPtrTraits<T>> class RefPtr;
 template<typename> class StringBuffer;

Modified: trunk/Source/WTF/wtf/HashTraits.h (254880 => 254881)


--- trunk/Source/WTF/wtf/HashTraits.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/HashTraits.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -220,6 +220,19 @@
 
 template<typename P> struct HashTraits<Ref<P>> : RefHashTraits<P> { };
 
+template<typename P> struct HashTraits<Packed<P*>> : SimpleClassHashTraits<Packed<P*>> {
+    static constexpr bool hasIsEmptyValueFunction = true;
+    using TargetType = Packed<P*>;
+    static_assert(TargetType::alignment < 4 * KB, "The first page is always unmapped since it includes nullptr.");
+
+    static Packed<P*> emptyValue() { return nullptr; }
+    static bool isEmptyValue(const TargetType& value) { return value.get() == nullptr; }
+
+    using PeekType = P*;
+    static PeekType peek(const TargetType& value) { return value.get(); }
+    static PeekType peek(P* value) { return value; }
+};
+
 template<> struct HashTraits<String> : SimpleClassHashTraits<String> {
     static constexpr bool hasIsEmptyValueFunction = true;
     static bool isEmptyValue(const String&);

Modified: trunk/Source/WTF/wtf/Packed.h (254880 => 254881)


--- trunk/Source/WTF/wtf/Packed.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/Packed.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -26,6 +26,9 @@
 #pragma once
 
 #include <array>
+#include <wtf/Forward.h>
+#include <wtf/GetPtr.h>
+#include <wtf/HashFunctions.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/UnalignedAccess.h>
@@ -100,11 +103,12 @@
 // PackedAlignedPtr can take alignment parameter too. PackedAlignedPtr only uses this alignment information if it is profitable: we use
 // alignment information only when we can reduce the size of the storage. Since the pointer width is 36 bits and JSCells are aligned to 16 bytes,
 // we can use 4 bits in Darwin ARM64, we can compact cell pointer into 4 bytes (32 bits).
-template<typename T, size_t alignment = alignof(T)>
+template<typename T, size_t passedAlignment>
 class PackedAlignedPtr {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static_assert(hasOneBitSet(alignment), "Alignment needs to be power-of-two");
+    static_assert(hasOneBitSet(passedAlignment), "Alignment needs to be power-of-two");
+    static constexpr size_t alignment = passedAlignment;
     static constexpr bool isPackedType = true;
     static constexpr unsigned alignmentShiftSizeIfProfitable = getLSBSetConstexpr(alignment);
     static constexpr unsigned storageSizeWithoutAlignmentShift = roundUpToMultipleOf<8>(OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH)) / 8;
@@ -215,11 +219,26 @@
 public:
     using Base = PackedAlignedPtr<T, 1>;
     using Base::Base;
+
+    // Hash table deleted values, which are only constructed and never copied or destroyed.
+    Packed(HashTableDeletedValueType) : Base(bitwise_cast<T*>(static_cast<uintptr_t>(Base::alignment))) { }
+    bool isHashTableDeletedValue() const { return Base::get() == bitwise_cast<T*>(static_cast<uintptr_t>(Base::alignment)); }
 };
 
 template<typename T>
 using PackedPtr = Packed<T*>;
 
+template <typename T>
+struct GetPtrHelper<PackedPtr<T>> {
+    using PtrType = T*;
+    static T* getPtr(const PackedPtr<T>& p) { return const_cast<T*>(p.get()); }
+};
+
+template <typename T>
+struct IsSmartPtr<PackedPtr<T>> {
+    static constexpr bool value = true;
+};
+
 template<typename T>
 struct PackedPtrTraits {
     template<typename U> using RebindTraits = PackedPtrTraits<U>;
@@ -231,8 +250,16 @@
     template<typename Other> static ALWAYS_INLINE void swap(PackedPtr<T>& a, Other& b) { a.swap(b); }
 
     static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr.get(); }
+
+    // We assume that,
+    // 1. The alignment is < 4KB. (It is tested by HashTraits).
+    // 2. The first page (including nullptr) is never mapped.
+    static StorageType hashTableDeletedValue() { return StorageType { bitwise_cast<T*>(static_cast<uintptr_t>(StorageType::alignment)) }; }
+    static ALWAYS_INLINE bool isHashTableDeletedValue(const StorageType& ptr) { return ptr.get() == bitwise_cast<T*>(static_cast<uintptr_t>(StorageType::alignment)); }
 };
 
+template<typename P> struct DefaultHash<PackedPtr<P>> { using Hash = PtrHash<PackedPtr<P>>; };
+
 } // namespace WTF
 
 using WTF::Packed;

Modified: trunk/Source/WTF/wtf/Ref.h (254880 => 254881)


--- trunk/Source/WTF/wtf/Ref.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/Ref.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -45,9 +45,10 @@
 template<typename T, typename PtrTraits> class Ref;
 template<typename T, typename PtrTraits = DumbPtrTraits<T>> Ref<T, PtrTraits> adoptRef(T&);
 
-template<typename T, typename PtrTraits>
+template<typename T, typename Traits>
 class Ref {
 public:
+    using PtrTraits = Traits;
     static constexpr bool isRef = true;
 
     ~Ref()
@@ -94,9 +95,8 @@
     template<typename X, typename Y> void swap(Ref<X, Y>&);
 
     // Hash table deleted values, which are only constructed and never copied or destroyed.
-    Ref(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
-    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+    Ref(HashTableDeletedValueType) : m_ptr(PtrTraits::hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
 
     Ref(HashTableEmptyValueType) : m_ptr(hashTableEmptyValue()) { }
     bool isHashTableEmptyValue() const { return m_ptr == hashTableEmptyValue(); }

Modified: trunk/Source/WTF/wtf/RefPtr.h (254880 => 254881)


--- trunk/Source/WTF/wtf/RefPtr.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/RefPtr.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -44,10 +44,11 @@
         ptr->deref();
 }
 
-template<typename T, typename PtrTraits>
+template<typename T, typename Traits>
 class RefPtr {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    using PtrTraits = Traits;
     typedef T ValueType;
     typedef ValueType* PtrType;
 
@@ -63,8 +64,8 @@
     template<typename X, typename Y> RefPtr(Ref<X, Y>&&);
 
     // Hash table deleted values, which are only constructed and never copied or destroyed.
-    RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
-    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+    RefPtr(HashTableDeletedValueType) : m_ptr(PtrTraits::hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
 
     ALWAYS_INLINE ~RefPtr() { derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
 
@@ -96,8 +97,6 @@
 
     template<typename X, typename Y> void swap(RefPtr<X, Y>&);
 
-    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
-
     RefPtr copyRef() && = delete;
     RefPtr copyRef() const & WARN_UNUSED_RETURN { return RefPtr(m_ptr); }
 

Modified: trunk/Source/WTF/wtf/text/AtomStringImpl.cpp (254880 => 254881)


--- trunk/Source/WTF/wtf/text/AtomStringImpl.cpp	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/text/AtomStringImpl.cpp	2020-01-21 22:05:43 UTC (rev 254881)
@@ -67,7 +67,7 @@
 
 #endif // USE(WEB_THREAD)
 
-using StringTableImpl = HashSet<StringImpl*>;
+using StringTableImpl = HashSet<PackedPtr<StringImpl>>;
 
 static ALWAYS_INLINE StringTableImpl& stringTable()
 {
@@ -82,8 +82,8 @@
     // If the string is newly-translated, then we need to adopt it.
     // The boolean in the pair tells us if that is so.
     if (addResult.isNewEntry)
-        return adoptRef(static_cast<AtomStringImpl&>(**addResult.iterator));
-    return *static_cast<AtomStringImpl*>(*addResult.iterator);
+        return adoptRef(static_cast<AtomStringImpl&>(*addResult.iterator->get()));
+    return *static_cast<AtomStringImpl*>(addResult.iterator->get());
 }
 
 template<typename T, typename HashTranslator>
@@ -99,16 +99,17 @@
         return StringHasher::computeHashAndMaskTop8Bits(characters);
     }
 
-    static inline bool equal(StringImpl* str, const LChar* characters)
+    static inline bool equal(PackedPtr<StringImpl> str, const LChar* characters)
     {
-        return WTF::equal(str, characters);
+        return WTF::equal(str.get(), characters);
     }
 
-    static void translate(StringImpl*& location, const LChar* const& characters, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const LChar* const& characters, unsigned hash)
     {
-        location = &StringImpl::create(characters).leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &StringImpl::create(characters).leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -150,16 +151,17 @@
         return buf.hash;
     }
 
-    static bool equal(StringImpl* const& str, const UCharBuffer& buf)
+    static bool equal(PackedPtr<StringImpl> const& str, const UCharBuffer& buf)
     {
-        return WTF::equal(str, buf.characters, buf.length);
+        return WTF::equal(str.get(), buf.characters, buf.length);
     }
 
-    static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const UCharBuffer& buf, unsigned hash)
     {
-        location = &StringImpl::create8BitIfPossible(buf.characters, buf.length).leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &StringImpl::create8BitIfPossible(buf.characters, buf.length).leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -176,8 +178,9 @@
         return buffer.hash;
     }
 
-    static bool equal(StringImpl* const& string, const HashAndUTF8Characters& buffer)
+    static bool equal(PackedPtr<StringImpl> const& passedString, const HashAndUTF8Characters& buffer)
     {
+        auto* string = passedString.get();
         if (buffer.utf16Length != string->length())
             return false;
 
@@ -212,7 +215,7 @@
         return true;
     }
 
-    static void translate(StringImpl*& location, const HashAndUTF8Characters& buffer, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const HashAndUTF8Characters& buffer, unsigned hash)
     {
         UChar* target;
         auto newString = StringImpl::createUninitialized(buffer.utf16Length, target);
@@ -225,9 +228,10 @@
         if (isAllASCII)
             newString = StringImpl::create(buffer.characters, buffer.length);
 
-        location = &newString.leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &newString.leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -266,11 +270,12 @@
 };
 
 struct SubstringTranslator {
-    static void translate(StringImpl*& location, const SubstringLocation& buffer, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const SubstringLocation& buffer, unsigned hash)
     {
-        location = &StringImpl::createSubstringSharingImpl(*buffer.baseString, buffer.start, buffer.length).leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &StringImpl::createSubstringSharingImpl(*buffer.baseString, buffer.start, buffer.length).leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -280,9 +285,9 @@
         return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->characters8() + buffer.start, buffer.length);
     }
 
-    static bool equal(StringImpl* const& string, const SubstringLocation& buffer)
+    static bool equal(PackedPtr<StringImpl> const& string, const SubstringLocation& buffer)
     {
-        return WTF::equal(string, buffer.baseString->characters8() + buffer.start, buffer.length);
+        return WTF::equal(string.get(), buffer.baseString->characters8() + buffer.start, buffer.length);
     }
 };
 
@@ -292,9 +297,9 @@
         return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->characters16() + buffer.start, buffer.length);
     }
 
-    static bool equal(StringImpl* const& string, const SubstringLocation& buffer)
+    static bool equal(PackedPtr<StringImpl> const& string, const SubstringLocation& buffer)
     {
-        return WTF::equal(string, buffer.baseString->characters16() + buffer.start, buffer.length);
+        return WTF::equal(string.get(), buffer.baseString->characters16() + buffer.start, buffer.length);
     }
 };
 
@@ -326,16 +331,17 @@
         return buf.hash;
     }
 
-    static bool equal(StringImpl* const& str, const LCharBuffer& buf)
+    static bool equal(PackedPtr<StringImpl> const& str, const LCharBuffer& buf)
     {
-        return WTF::equal(str, buf.characters, buf.length);
+        return WTF::equal(str.get(), buf.characters, buf.length);
     }
 
-    static void translate(StringImpl*& location, const LCharBuffer& buf, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const LCharBuffer& buf, unsigned hash)
     {
-        location = &StringImpl::create(buf.characters, buf.length).leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &StringImpl::create(buf.characters, buf.length).leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -347,16 +353,17 @@
         return buf.hash;
     }
 
-    static bool equal(StringImpl* const& str, const Buffer& buf)
+    static bool equal(PackedPtr<StringImpl> const& str, const Buffer& buf)
     {
-        return WTF::equal(str, buf.characters, buf.length);
+        return WTF::equal(str.get(), buf.characters, buf.length);
     }
 
-    static void translate(StringImpl*& location, const Buffer& buf, unsigned hash)
+    static void translate(PackedPtr<StringImpl>& location, const Buffer& buf, unsigned hash)
     {
-        location = &StringImpl::createWithoutCopying(buf.characters, buf.length).leakRef();
-        location->setHash(hash);
-        location->setIsAtom(true);
+        auto* pointer = &StringImpl::createWithoutCopying(buf.characters, buf.length).leakRef();
+        pointer->setHash(hash);
+        pointer->setIsAtom(true);
+        location = pointer;
     }
 };
 
@@ -443,11 +450,11 @@
     auto addResult = stringTable().add(&string);
 
     if (addResult.isNewEntry) {
-        ASSERT(*addResult.iterator == &string);
+        ASSERT(addResult.iterator->get() == &string);
         string.setIsAtom(true);
     }
 
-    return *static_cast<AtomStringImpl*>(*addResult.iterator);
+    return *static_cast<AtomStringImpl*>(addResult.iterator->get());
 }
 
 Ref<AtomStringImpl> AtomStringImpl::addSlowCase(AtomStringTable& stringTable, StringImpl& string)
@@ -473,11 +480,11 @@
     auto addResult = stringTable.table().add(&string);
 
     if (addResult.isNewEntry) {
-        ASSERT(*addResult.iterator == &string);
+        ASSERT(addResult.iterator->get() == &string);
         string.setIsAtom(true);
     }
 
-    return *static_cast<AtomStringImpl*>(*addResult.iterator);
+    return *static_cast<AtomStringImpl*>(addResult.iterator->get());
 }
 
 void AtomStringImpl::remove(AtomStringImpl* string)
@@ -487,7 +494,7 @@
     auto& atomStringTable = stringTable();
     auto iterator = atomStringTable.find(string);
     ASSERT_WITH_MESSAGE(iterator != atomStringTable.end(), "The string being removed is an atom in the string table of an other thread!");
-    ASSERT(string == *iterator);
+    ASSERT(string == iterator->get());
     atomStringTable.remove(iterator);
 }
 
@@ -502,7 +509,7 @@
     auto& atomStringTable = stringTable();
     auto iterator = atomStringTable.find(&string);
     if (iterator != atomStringTable.end())
-        return static_cast<AtomStringImpl*>(*iterator);
+        return static_cast<AtomStringImpl*>(iterator->get());
     return nullptr;
 }
 
@@ -526,7 +533,7 @@
     LCharBuffer buffer = { characters, length };
     auto iterator = table.find<LCharBufferTranslator>(buffer);
     if (iterator != table.end())
-        return static_cast<AtomStringImpl*>(*iterator);
+        return static_cast<AtomStringImpl*>(iterator->get());
     return nullptr;
 }
 
@@ -538,7 +545,7 @@
     UCharBuffer buffer { characters, length };
     auto iterator = table.find<UCharBufferTranslator>(buffer);
     if (iterator != table.end())
-        return static_cast<AtomStringImpl*>(*iterator);
+        return static_cast<AtomStringImpl*>(iterator->get());
     return nullptr;
 }
 

Modified: trunk/Source/WTF/wtf/text/AtomStringTable.cpp (254880 => 254881)


--- trunk/Source/WTF/wtf/text/AtomStringTable.cpp	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/text/AtomStringTable.cpp	2020-01-21 22:05:43 UTC (rev 254881)
@@ -31,7 +31,7 @@
 
 AtomStringTable::~AtomStringTable()
 {
-    for (auto* string : m_table)
+    for (const PackedPtr<StringImpl>& string : m_table)
         string->setIsAtom(false);
 }
 

Modified: trunk/Source/WTF/wtf/text/AtomStringTable.h (254880 => 254881)


--- trunk/Source/WTF/wtf/text/AtomStringTable.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/text/AtomStringTable.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -23,6 +23,7 @@
 #pragma once
 
 #include <wtf/HashSet.h>
+#include <wtf/Packed.h>
 #include <wtf/text/StringImpl.h>
 
 namespace WTF {
@@ -34,10 +35,10 @@
 public:
     WTF_EXPORT_PRIVATE ~AtomStringTable();
 
-    HashSet<StringImpl*>& table() { return m_table; }
+    HashSet<PackedPtr<StringImpl>>& table() { return m_table; }
 
 private:
-    HashSet<StringImpl*> m_table;
+    HashSet<PackedPtr<StringImpl>> m_table;
 };
 
 }

Modified: trunk/Source/WTF/wtf/text/StringHash.h (254880 => 254881)


--- trunk/Source/WTF/wtf/text/StringHash.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/text/StringHash.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -56,6 +56,7 @@
         }
 
         static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }
+        static unsigned hash(const PackedPtr<StringImpl>& key) { return key->hash(); }
         static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
         {
             return equal(a.get(), b.get());
@@ -69,6 +70,19 @@
             return equal(a, b.get());
         }
 
+        static bool equal(const PackedPtr<StringImpl>& a, const PackedPtr<StringImpl>& b)
+        {
+            return equal(a.get(), b.get());
+        }
+        static bool equal(const PackedPtr<StringImpl>& a, const StringImpl* b)
+        {
+            return equal(a.get(), b);
+        }
+        static bool equal(const StringImpl* a, const PackedPtr<StringImpl>& b)
+        {
+            return equal(a, b.get());
+        }
+
         static unsigned hash(const String& key) { return key.impl()->hash(); }
         static bool equal(const String& a, const String& b)
         {
@@ -135,6 +149,16 @@
             return equal(a.get(), b.get());
         }
 
+        static unsigned hash(const PackedPtr<StringImpl>& key) 
+        {
+            return hash(key.get());
+        }
+
+        static bool equal(const PackedPtr<StringImpl>& a, const PackedPtr<StringImpl>& b)
+        {
+            return equal(a.get(), b.get());
+        }
+
         static unsigned hash(const String& key)
         {
             return hash(key.impl());

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (254880 => 254881)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -29,6 +29,7 @@
 #include <wtf/DebugHeap.h>
 #include <wtf/Expected.h>
 #include <wtf/MathExtras.h>
+#include <wtf/Packed.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/text/ASCIIFastPath.h>
@@ -598,6 +599,9 @@
 template<> struct DefaultHash<RefPtr<StringImpl>> {
     typedef StringHash Hash;
 };
+template<> struct DefaultHash<PackedPtr<StringImpl>> {
+    using Hash = StringHash;
+};
 
 #define MAKE_STATIC_STRING_IMPL(characters) ([] { \
         static StaticStringImpl impl(characters); \

Modified: trunk/Source/WebCore/ChangeLog (254880 => 254881)


--- trunk/Source/WebCore/ChangeLog	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WebCore/ChangeLog	2020-01-21 22:05:43 UTC (rev 254881)
@@ -1,3 +1,15 @@
+2020-01-21  Yusuke Suzuki  <[email protected]>
+
+        [WTF] AtomStringTable should be small
+        https://bugs.webkit.org/show_bug.cgi?id=206400
+
+        Reviewed by Sam Weinig.
+
+        * dom/GCReachableRef.h:
+        (WebCore::GCReachableRef::GCReachableRef):
+        * dom/QualifiedName.h:
+        (WebCore::QualifiedName::hashTableDeletedValue):
+
 2020-01-21  Jer Noble  <[email protected]>
 
         [iPad] YouTube does not automatically AirPlay when a route is selected from Control Center

Modified: trunk/Source/WebCore/dom/GCReachableRef.h (254880 => 254881)


--- trunk/Source/WebCore/dom/GCReachableRef.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WebCore/dom/GCReachableRef.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -74,7 +74,7 @@
 
     // Hash table deleted values, which are only constructed and never copied or destroyed.
     GCReachableRef(WTF::HashTableDeletedValueType)
-        : m_ptr(RefPtr<T>::hashTableDeletedValue())
+        : m_ptr(RefPtr<T>::PtrTraits::hashTableDeletedValue())
     { }
     bool isHashTableDeletedValue() const { return m_ptr.isHashTableDeletedValue(); }
 

Modified: trunk/Source/WebCore/dom/QualifiedName.h (254880 => 254881)


--- trunk/Source/WebCore/dom/QualifiedName.h	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Source/WebCore/dom/QualifiedName.h	2020-01-21 22:05:43 UTC (rev 254881)
@@ -104,7 +104,7 @@
     WEBCORE_EXPORT static void init();
 
 private:
-    static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); }
+    static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::PtrTraits::hashTableDeletedValue(); }
     
     RefPtr<QualifiedNameImpl> m_impl;
 };

Modified: trunk/Tools/ChangeLog (254880 => 254881)


--- trunk/Tools/ChangeLog	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Tools/ChangeLog	2020-01-21 22:05:43 UTC (rev 254881)
@@ -1,3 +1,17 @@
+2020-01-21  Yusuke Suzuki  <[email protected]>
+
+        [WTF] AtomStringTable should be small
+        https://bugs.webkit.org/show_bug.cgi?id=206400
+
+        Reviewed by Sam Weinig.
+
+        * TestWebKitAPI/Tests/WTF/HashMap.cpp:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WTF/HashSet.cpp:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WTF/Packed.cpp:
+        (TestWebKitAPI::TEST):
+
 2020-01-21  Alex Christensen  <[email protected]>
 
         Add SPI on WKURLSchemeTask to access WKFrameInfo of originating frame

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp (254880 => 254881)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp	2020-01-21 22:05:43 UTC (rev 254881)
@@ -716,7 +716,7 @@
     // value.
     // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
     // call.
-    EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+    EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::PtrTraits::hashTableDeletedValue());
     EXPECT_EQ(observer->count, 0u);
 }
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp (254880 => 254881)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp	2020-01-21 22:05:43 UTC (rev 254881)
@@ -315,7 +315,7 @@
     // value.
     // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
     // call.
-    EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+    EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::PtrTraits::hashTableDeletedValue());
     EXPECT_EQ(observer->count, 0u);
 }
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp (254880 => 254881)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp	2020-01-21 22:04:13 UTC (rev 254880)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp	2020-01-21 22:05:43 UTC (rev 254881)
@@ -26,6 +26,8 @@
 #include "config.h"
 
 #include <wtf/Packed.h>
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
 
 namespace TestWebKitAPI {
 
@@ -82,4 +84,25 @@
     }
 }
 
+struct PackingTarget {
+    unsigned m_value { 0 };
+};
+TEST(WTF_Packed, HashMap)
+{
+    Vector<PackingTarget> vector;
+    HashMap<PackedPtr<PackingTarget>, unsigned> map;
+    vector.reserveCapacity(10000);
+    for (unsigned i = 0; i < 10000; ++i)
+        vector.uncheckedAppend(PackingTarget { i });
+
+    for (auto& target : vector)
+        map.add(&target, target.m_value);
+
+    for (auto& target : vector) {
+        EXPECT_TRUE(map.contains(&target));
+        EXPECT_EQ(map.get(&target), target.m_value);
+    }
+}
+
+
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to