Title: [196791] trunk
Revision
196791
Author
[email protected]
Date
2016-02-18 17:14:07 -0800 (Thu, 18 Feb 2016)

Log Message

Extend HashCountedSet with a method to efficiently set the count of an entry
https://bugs.webkit.org/show_bug.cgi?id=154352

Reviewed by Geoffrey Garen.

Source/WebCore:

Tested by new TestWebKitAPI tests.

* loader/ResourceLoadStatistics.cpp:
(WebCore::decodeHashCountedSet): Update to use new HashCountedSet::add method.

Source/WTF:

Tested by new TestWebKitAPI tests.

Update the HashCountedSet class with a new 'add' method to support efficient initialization of
the count of a given key. Also provide move and pointer template specializations to expand the
types of data that can be used as 'keys' in the HashCountedSet to match the underlying HashMap
implementation.

* wtf/HashCountedSet.h:
(WTF::Traits>::add): Added new overload supporting a supplied count.

Tools:

* TestWebKitAPI/CMakeLists.txt: Add new HashCountedSet test files.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Ditto.
* TestWebKitAPI/Tests/WTF/HashCountedSet.cpp: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (196790 => 196791)


--- trunk/Source/WTF/ChangeLog	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Source/WTF/ChangeLog	2016-02-19 01:14:07 UTC (rev 196791)
@@ -1,3 +1,20 @@
+2016-02-18  Brent Fulgham  <[email protected]>
+
+        Extend HashCountedSet with a method to efficiently set the count of an entry
+        https://bugs.webkit.org/show_bug.cgi?id=154352
+
+        Reviewed by Geoffrey Garen.
+
+        Tested by new TestWebKitAPI tests.
+
+        Update the HashCountedSet class with a new 'add' method to support efficient initialization of
+        the count of a given key. Also provide move and pointer template specializations to expand the
+        types of data that can be used as 'keys' in the HashCountedSet to match the underlying HashMap
+        implementation.
+
+        * wtf/HashCountedSet.h:
+        (WTF::Traits>::add): Added new overload supporting a supplied count.
+
 2016-02-17  Filip Pizlo  <[email protected]>
 
         Remove LLVM dependencies from WebKit

Modified: trunk/Source/WTF/wtf/HashCountedSet.h (196790 => 196791)


--- trunk/Source/WTF/wtf/HashCountedSet.h	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Source/WTF/wtf/HashCountedSet.h	2016-02-19 01:14:07 UTC (rev 196791)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006, 2008, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2008, 2013, 2016 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -21,6 +21,7 @@
 #ifndef WTF_HashCountedSet_h
 #define WTF_HashCountedSet_h
 
+#include <initializer_list>
 #include <wtf/Assertions.h>
 #include <wtf/HashMap.h>
 #include <wtf/Vector.h>
@@ -37,6 +38,22 @@
         typedef typename ImplType::iterator iterator;
         typedef typename ImplType::const_iterator const_iterator;
         typedef typename ImplType::AddResult AddResult;
+
+        HashCountedSet()
+        {
+        }
+
+        HashCountedSet(std::initializer_list<typename ImplType::KeyValuePairType> initializerList)
+        {
+            for (const auto& keyValuePair : initializerList)
+                add(keyValuePair.key, keyValuePair.value);
+        }
+
+        HashCountedSet(std::initializer_list<typename ImplType::KeyType> initializerList)
+        {
+            for (const auto& value : initializerList)
+                add(value);
+        }
         
         void swap(HashCountedSet&);
         
@@ -59,7 +76,12 @@
         // The return value includes both an iterator to the value's location,
         // and an isNewEntry bool that indicates whether it is a new or existing entry.
         AddResult add(const ValueType&);
-        
+        AddResult add(ValueType&&);
+
+        // Increments the count of a value by the passed amount.
+        AddResult add(const ValueType&, unsigned);
+        AddResult add(ValueType&&, unsigned);
+
         // Decrements the count of the value, and removes it if count goes down to zero.
         // Returns true if the value is removed.
         bool remove(const ValueType&);
@@ -73,10 +95,18 @@
         // Clears the whole set.
         void clear();
 
+        // Overloads for smart pointer keys that take the raw pointer type as the parameter.
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, iterator>::type find(typename GetPtrHelper<V>::PtrType);
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, const_iterator>::type find(typename GetPtrHelper<V>::PtrType) const;
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, bool>::type contains(typename GetPtrHelper<V>::PtrType) const;
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, unsigned>::type count(typename GetPtrHelper<V>::PtrType) const;
+        template<typename V = ValueType> typename std::enable_if<IsSmartPtr<V>::value, bool>::type remove(typename GetPtrHelper<V>::PtrType);
+
     private:
         ImplType m_impl;
     };
 
+
     template<typename Value, typename HashFunctions, typename Traits>
     inline void HashCountedSet<Value, HashFunctions, Traits>::swap(HashCountedSet& other)
     {
@@ -156,8 +186,32 @@
         ++result.iterator->value;
         return result;
     }
+
+    template<typename Value, typename HashFunctions, typename Traits>
+    inline typename HashCountedSet<Value, HashFunctions, Traits>::AddResult HashCountedSet<Value, HashFunctions, Traits>::add(ValueType&& value)
+    {
+        AddResult result = m_impl.add(std::forward<Value>(value), 0);
+        ++result.iterator->value;
+        return result;
+    }
+
+    template<typename Value, typename HashFunctions, typename Traits>
+    inline typename HashCountedSet<Value, HashFunctions, Traits>::AddResult HashCountedSet<Value, HashFunctions, Traits>::add(const ValueType& value, unsigned count)
+    {
+        AddResult result = m_impl.add(value, 0);
+        result.iterator->value += count;
+        return result;
+    }
     
     template<typename Value, typename HashFunctions, typename Traits>
+    inline typename HashCountedSet<Value, HashFunctions, Traits>::AddResult HashCountedSet<Value, HashFunctions, Traits>::add(ValueType&& value, unsigned count)
+    {
+        AddResult result = m_impl.add(std::forward<Value>(value), 0);
+        result.iterator->value += count;
+        return result;
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
     inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(const ValueType& value)
     {
         return remove(find(value));
@@ -229,8 +283,42 @@
             vector[i] = (*it).key;
     }
 
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashCountedSet<Value, HashFunctions, Traits>::find(typename GetPtrHelper<V>::PtrType value) -> typename std::enable_if<IsSmartPtr<V>::value, iterator>::type
+    {
+        return m_impl.template find(value);
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashCountedSet<Value, HashFunctions, Traits>::find(typename GetPtrHelper<V>::PtrType value) const -> typename std::enable_if<IsSmartPtr<V>::value, const_iterator>::type
+    {
+        return m_impl.template find(value);
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashCountedSet<Value, HashFunctions, Traits>::contains(typename GetPtrHelper<V>::PtrType value) const -> typename std::enable_if<IsSmartPtr<V>::value, bool>::type
+    {
+        return m_impl.template contains(value);
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashCountedSet<Value, HashFunctions, Traits>::count(typename GetPtrHelper<V>::PtrType value) const -> typename std::enable_if<IsSmartPtr<V>::value, unsigned>::type
+    {
+        return m_impl.template get(value);
+    }
+    
+    template<typename Value, typename HashFunctions, typename Traits>
+    template<typename V>
+    inline auto HashCountedSet<Value, HashFunctions, Traits>::remove(typename GetPtrHelper<V>::PtrType value) -> typename std::enable_if<IsSmartPtr<V>::value, bool>::type
+    {
+        return remove(find(value));
+    }
 
-} // namespace khtml
+} // namespace WTF
 
 using WTF::HashCountedSet;
 

Modified: trunk/Source/WebCore/ChangeLog (196790 => 196791)


--- trunk/Source/WebCore/ChangeLog	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Source/WebCore/ChangeLog	2016-02-19 01:14:07 UTC (rev 196791)
@@ -1,3 +1,15 @@
+2016-02-18  Brent Fulgham  <[email protected]>
+
+        Extend HashCountedSet with a method to efficiently set the count of an entry
+        https://bugs.webkit.org/show_bug.cgi?id=154352
+
+        Reviewed by Geoffrey Garen.
+
+        Tested by new TestWebKitAPI tests.
+
+        * loader/ResourceLoadStatistics.cpp:
+        (WebCore::decodeHashCountedSet): Update to use new HashCountedSet::add method.
+
 2016-02-18  Simon Fraser  <[email protected]>
 
         Wheel event callback removing the window causes crash in WebCore.

Modified: trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp (196790 => 196791)


--- trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Source/WebCore/loader/ResourceLoadStatistics.cpp	2016-02-19 01:14:07 UTC (rev 196791)
@@ -124,10 +124,8 @@
         unsigned count;
         if (!decoderInner.decodeUInt32("count", count))
             return false;
-        
-        // FIXME: Create a HashCountedSet method to do this efficiently
-        for (unsigned i = 0; i < count; ++i)
-            hashCountedSet.add(origin);
+
+        hashCountedSet.add(origin, count);
         return true;
     });
 }

Modified: trunk/Tools/ChangeLog (196790 => 196791)


--- trunk/Tools/ChangeLog	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Tools/ChangeLog	2016-02-19 01:14:07 UTC (rev 196791)
@@ -1,3 +1,14 @@
+2016-02-18  Brent Fulgham  <[email protected]>
+
+        Extend HashCountedSet with a method to efficiently set the count of an entry
+        https://bugs.webkit.org/show_bug.cgi?id=154352
+
+        Reviewed by Geoffrey Garen.
+
+        * TestWebKitAPI/CMakeLists.txt: Add new HashCountedSet test files.
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Ditto.
+        * TestWebKitAPI/Tests/WTF/HashCountedSet.cpp: Added.
+
 2016-02-18  Anders Carlsson  <[email protected]>
 
         Get rid of the --target-web-process and --use-web-process-xpc-service options.

Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (196790 => 196791)


--- trunk/Tools/TestWebKitAPI/CMakeLists.txt	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt	2016-02-19 01:14:07 UTC (rev 196791)
@@ -47,6 +47,7 @@
     ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Functional.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WTF/HashCountedSet.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/HashMap.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/HashSet.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/IntegerToStringConversion.cpp

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (196790 => 196791)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2016-02-19 01:13:15 UTC (rev 196790)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2016-02-19 01:14:07 UTC (rev 196791)
@@ -79,6 +79,7 @@
 		76E182DD1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */; };
 		76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 76E182DE15475A8300F1FADD /* auto-submitting-form.html */; };
 		7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */; };
+		7A38D7E61C752D5F004F157D /* HashCountedSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */; };
 		7A5623111AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */; };
 		7A99D9941AD4A29D00373141 /* MenuTypesForMouseEvents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */; };
 		7AA021BB1AB09EA70052953F /* DateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AA021BA1AB09EA70052953F /* DateMath.cpp */; };
@@ -610,6 +611,7 @@
 		76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent_Bundle.cpp; sourceTree = "<group>"; };
 		76E182DE15475A8300F1FADD /* auto-submitting-form.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "auto-submitting-form.html"; sourceTree = "<group>"; };
 		7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "mouse-button-listener.html"; sourceTree = "<group>"; };
+		7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashCountedSet.cpp; sourceTree = "<group>"; };
 		7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MenuTypesForMouseEvents.cpp; sourceTree = "<group>"; };
 		7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MenuTypesForMouseEvents.mm; sourceTree = "<group>"; };
 		7AA021BA1AB09EA70052953F /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
@@ -1228,6 +1230,7 @@
 				7AA021BA1AB09EA70052953F /* DateMath.cpp */,
 				E4A757D3178AEA5B00B5D7A4 /* Deque.cpp */,
 				1AA9E55714980A9900001A8A /* Functional.cpp */,
+				7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */,
 				0BCD833414857CE400EA2003 /* HashMap.cpp */,
 				26B2DFF815BDE599004F691D /* HashSet.cpp */,
 				266FAFD215E5775200F61D5B /* IntegerToStringConversion.cpp */,
@@ -1863,6 +1866,7 @@
 				9B0786A31C58830F00D159E3 /* InjectedBundleMakeAllShadowRootsOpen.cpp in Sources */,
 				1A4F81CC1BDFFD37004E672E /* RemoteObjectRegistry.mm in Sources */,
 				51CB4AD81B3A079C00C1B1C6 /* ModalAlertsSPI.cpp in Sources */,
+				7A38D7E61C752D5F004F157D /* HashCountedSet.cpp in Sources */,
 				9B7916501BD89D0D00D50B8F /* FirstResponderScrollingPosition.mm in Sources */,
 				1CF0D3791BBF2F3D00B4EF54 /* WKRetainPtr.cpp in Sources */,
 				26F6E1F01ADC749B00DE696B /* DFAMinimizer.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp (0 => 196791)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp	2016-02-19 01:14:07 UTC (rev 196791)
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "Counters.h"
+#include "MoveOnly.h"
+#include "RefLogger.h"
+#include <string>
+#include <wtf/HashCountedSet.h>
+#include <wtf/text/StringHash.h>
+
+namespace TestWebKitAPI {
+    
+typedef WTF::HashCountedSet<int> IntHashCountedSet;
+
+TEST(WTF_HashCountedSet, HashTableIteratorComparison)
+{
+    IntHashCountedSet hashCountedSet;
+    hashCountedSet.add(1);
+    ASSERT_TRUE(hashCountedSet.begin() != hashCountedSet.end());
+    ASSERT_FALSE(hashCountedSet.begin() == hashCountedSet.end());
+    
+    IntHashCountedSet::const_iterator begin = hashCountedSet.begin();
+    ASSERT_TRUE(begin == hashCountedSet.begin());
+    ASSERT_TRUE(hashCountedSet.begin() == begin);
+    ASSERT_TRUE(begin != hashCountedSet.end());
+    ASSERT_TRUE(hashCountedSet.end() != begin);
+    ASSERT_FALSE(begin != hashCountedSet.begin());
+    ASSERT_FALSE(hashCountedSet.begin() != begin);
+    ASSERT_FALSE(begin == hashCountedSet.end());
+    ASSERT_FALSE(hashCountedSet.end() == begin);
+}
+
+struct TestDoubleHashTraits : HashTraits<double> {
+    static const int minimumTableSize = 8;
+};
+
+typedef HashCountedSet<double, DefaultHash<double>::Hash, TestDoubleHashTraits> DoubleHashCountedSet;
+
+static int bucketForKey(double key)
+{
+    return DefaultHash<double>::Hash::hash(key) & (TestDoubleHashTraits::minimumTableSize - 1);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisions)
+{
+    // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+    // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+    // fails unless the FloatHash::equals() implementation can distinguish them.
+    const double clobberKey = 6;
+    const double zeroKey = 0;
+    const double negativeZeroKey = -zeroKey;
+    
+    DoubleHashCountedSet hashCountedSet;
+    
+    hashCountedSet.add(clobberKey);
+
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+    hashCountedSet.add(zeroKey);
+    hashCountedSet.add(negativeZeroKey);
+    
+    ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 1u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+
+    hashCountedSet.add(clobberKey);
+    hashCountedSet.add(zeroKey);
+    hashCountedSet.add(negativeZeroKey);
+    
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 2u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 2u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 2u);
+
+    hashCountedSet.add(clobberKey, 12);
+    hashCountedSet.add(zeroKey, 15);
+    hashCountedSet.add(negativeZeroKey, 17);
+    
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 14u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 17u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 19u);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisionsInitialCount)
+{
+    // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+    // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+    // fails unless the FloatHash::equals() implementation can distinguish them.
+    const double clobberKey = 6;
+    const double zeroKey = 0;
+    const double negativeZeroKey = -zeroKey;
+    
+    DoubleHashCountedSet hashCountedSet;
+    
+    hashCountedSet.add(clobberKey, 5);
+    
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+    
+    hashCountedSet.add(zeroKey, 22);
+    hashCountedSet.add(negativeZeroKey, 0);
+    
+    ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 22u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+    
+    hashCountedSet.add(clobberKey);
+    hashCountedSet.add(zeroKey);
+    hashCountedSet.add(negativeZeroKey);
+    
+    ASSERT_EQ(hashCountedSet.count(clobberKey), 6u);
+    ASSERT_EQ(hashCountedSet.count(zeroKey), 23u);
+    ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+}
+
+
+TEST(WTF_HashCountedSet, MoveOnlyKeys)
+{
+    HashCountedSet<MoveOnly> moveOnlyKeys;
+    
+    for (size_t i = 0; i < 100; ++i) {
+        MoveOnly moveOnly(i + 1);
+        moveOnlyKeys.add(WTFMove(moveOnly));
+    }
+    
+    for (size_t i = 0; i < 100; ++i) {
+        auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+        ASSERT_FALSE(it == moveOnlyKeys.end());
+        ASSERT_EQ(it->value, 1u);
+    }
+    
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+    
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_TRUE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+    ASSERT_TRUE(moveOnlyKeys.isEmpty());
+}
+
+TEST(WTF_HashCountedSet, MoveOnlyKeysInitialCount)
+{
+    HashCountedSet<MoveOnly> moveOnlyKeys;
+    
+    for (size_t i = 0; i < 100; ++i) {
+        MoveOnly moveOnly(i + 1);
+        moveOnlyKeys.add(WTFMove(moveOnly), i + 1);
+    }
+    
+    for (size_t i = 0; i < 100; ++i) {
+        auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+        ASSERT_FALSE(it == moveOnlyKeys.end());
+        ASSERT_EQ(it->value, i + 1);
+    }
+    
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+    
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 2);
+    
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 1);
+}
+
+TEST(WTF_HashCountedSet, InitializerList)
+{
+    HashCountedSet<String> hashCountedSet = {
+        "one",
+        "two",
+        "three",
+        "four",
+        "four",
+        "four",
+        "four",
+    };
+    
+    EXPECT_EQ(4u, hashCountedSet.size());
+    
+    EXPECT_EQ(hashCountedSet.count("one"), 1u);
+    EXPECT_EQ(hashCountedSet.count("two"), 1u);
+    EXPECT_EQ(hashCountedSet.count("three"), 1u);
+    EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, InitializerListInitialCount)
+{
+    HashCountedSet<String> hashCountedSet = {
+        { String("one"), 1u },
+        { String("two"), 2u },
+        { String("three"), 3u },
+        { String("four"), 4u },
+    };
+    
+    EXPECT_EQ(4u, hashCountedSet.size());
+    
+    EXPECT_EQ(hashCountedSet.count("one"), 1u);
+    EXPECT_EQ(hashCountedSet.count("two"), 2u);
+    EXPECT_EQ(hashCountedSet.count("three"), 3u);
+    EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+    
+    HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+    
+    hashCountedSet.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKeyInitialCount)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+    
+    HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    hashCountedSet.add(WTFMove(uniquePtr), 12);
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+    
+    hashCountedSet.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_CustomDeleter)
+{
+    ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+    DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+    
+    HashCountedSet<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>> hashCountedSet;
+    
+    std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+    
+    EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+    
+    hashCountedSet.clear();
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+    
+    EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_FindUsingRawPointer)
+{
+    HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    auto it = hashCountedSet.find(ptr);
+    ASSERT_TRUE(it != hashCountedSet.end());
+    EXPECT_EQ(ptr, it->key.get());
+    EXPECT_EQ(1u, it->value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+    HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    EXPECT_EQ(true, hashCountedSet.contains(ptr));
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_GetUsingRawPointer)
+{
+    HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<int>(5);
+    int* ptr = uniquePtr.get();
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    int value = hashCountedSet.count(ptr);
+    EXPECT_EQ(1, value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+    ConstructorDestructorCounter::TestingScope scope;
+    
+    HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+    
+    auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+    ConstructorDestructorCounter* ptr = uniquePtr.get();
+    hashCountedSet.add(WTFMove(uniquePtr));
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+    
+    bool result = hashCountedSet.remove(ptr);
+    EXPECT_EQ(true, result);
+    
+    EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+    EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_Add)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    RefPtr<RefLogger> ptr(&a);
+    hashCountedSet.add(ptr);
+    
+    ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+    EXPECT_EQ(1U, hashCountedSet.count(ptr));
+    EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRelease)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    RefPtr<RefLogger> ptr(&a);
+    hashCountedSet.add(ptr.release());
+    
+    EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMove)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    RefPtr<RefLogger> ptr(&a);
+    hashCountedSet.add(WTFMove(ptr));
+    
+    EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRaw)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    RefPtr<RefLogger> ptr(&a);
+    hashCountedSet.add(ptr.get());
+    
+    EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+    EXPECT_EQ(1U, hashCountedSet.count(ptr));
+    EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddKeyAlreadyPresent)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    
+    {
+        RefPtr<RefLogger> ptr(&a);
+        hashCountedSet.add(ptr);
+    }
+    
+    EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+    
+    {
+        RefPtr<RefLogger> ptr2(&a);
+        auto addResult = hashCountedSet.add(ptr2);
+        EXPECT_FALSE(addResult.isNewEntry);
+    }
+    
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingReleaseKeyAlreadyPresent)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    
+    {
+        RefPtr<RefLogger> ptr(&a);
+        hashCountedSet.add(ptr);
+    }
+    
+    EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+    
+    {
+        RefPtr<RefLogger> ptr2(&a);
+        auto addResult = hashCountedSet.add(ptr2.release());
+        EXPECT_FALSE(addResult.isNewEntry);
+    }
+    
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMoveKeyAlreadyPresent)
+{
+    HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+    
+    DerivedRefLogger a("a");
+    
+    {
+        RefPtr<RefLogger> ptr(&a);
+        hashCountedSet.add(ptr);
+    }
+    
+    EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+    
+    {
+        RefPtr<RefLogger> ptr2(&a);
+        auto addResult = hashCountedSet.add(WTFMove(ptr2));
+        EXPECT_FALSE(addResult.isNewEntry);
+    }
+    
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+    
+} // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to