Title: [288807] trunk/Source
Revision
288807
Author
[email protected]
Date
2022-01-31 00:48:47 -0800 (Mon, 31 Jan 2022)

Log Message

[WTF] Add GenericHashKey
https://bugs.webkit.org/show_bug.cgi?id=235872

Reviewed by Darin Adler.

Source/_javascript_Core:

Use GenericHashKey and WTF::HashSet / WTF::HashMap.

* dfg/DFGCommonData.h:
* dfg/DFGGraph.h:
* dfg/DFGIntegerCheckCombiningPhase.cpp:
(JSC::DFG::IntegerCheckCombiningPhase::RangeKey::Hash::hash):
(JSC::DFG::IntegerCheckCombiningPhase::RangeKey::Hash::equal):
(JSC::DFG::IntegerCheckCombiningPhase::handleBlock):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::addressOfDoubleConstant):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* runtime/DeferredWorkTimer.cpp:
* runtime/FunctionHasExecutedCache.cpp:
(JSC::FunctionHasExecutedCache::hasExecutedAtOffset):
(JSC::FunctionHasExecutedCache::insertUnexecutedRange):
(JSC::FunctionHasExecutedCache::removeUnexecutedRange):
(JSC::FunctionHasExecutedCache::getFunctionRanges):
* runtime/FunctionHasExecutedCache.h:
(JSC::FunctionHasExecutedCache::FunctionRange::Hash::hash):
(JSC::FunctionHasExecutedCache::FunctionRange::Hash::equal):
* runtime/TypeLocationCache.cpp:
(JSC::TypeLocationCache::getTypeLocation):
* runtime/TypeLocationCache.h:
(JSC::TypeLocationCache::LocationKey::Hash::hash):
(JSC::TypeLocationCache::LocationKey::Hash::equal):

Source/WebCore:

No behavior change. We should use StdMap.
This should be StdMap since it requires ordered iterations by the key, so it should not be a HashMap.

* platform/graphics/avfoundation/objc/QueuedVideoOutput.h:

Source/WTF:

This patch adds GenericHashKey<T>, which can represent any HashTable's key
even if Key does not have Empty / Deleted values. Previously we were using
StdUnorderedSet / StdUnorderedMap instead. But, (1) they are doing similar
thing to GenericHashKey to keep empty or deleted values, and (2) by using
GenericHashKey we can consistently use WTF::HashMap etc. for all possible
cases.

* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/GenericHashKey.h: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (288806 => 288807)


--- trunk/Source/_javascript_Core/ChangeLog	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-01-31 08:48:47 UTC (rev 288807)
@@ -1,3 +1,37 @@
+2022-01-30  Yusuke Suzuki  <[email protected]>
+
+        [WTF] Add GenericHashKey
+        https://bugs.webkit.org/show_bug.cgi?id=235872
+
+        Reviewed by Darin Adler.
+
+        Use GenericHashKey and WTF::HashSet / WTF::HashMap.
+
+        * dfg/DFGCommonData.h:
+        * dfg/DFGGraph.h:
+        * dfg/DFGIntegerCheckCombiningPhase.cpp:
+        (JSC::DFG::IntegerCheckCombiningPhase::RangeKey::Hash::hash):
+        (JSC::DFG::IntegerCheckCombiningPhase::RangeKey::Hash::equal):
+        (JSC::DFG::IntegerCheckCombiningPhase::handleBlock):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::addressOfDoubleConstant):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        * runtime/DeferredWorkTimer.cpp:
+        * runtime/FunctionHasExecutedCache.cpp:
+        (JSC::FunctionHasExecutedCache::hasExecutedAtOffset):
+        (JSC::FunctionHasExecutedCache::insertUnexecutedRange):
+        (JSC::FunctionHasExecutedCache::removeUnexecutedRange):
+        (JSC::FunctionHasExecutedCache::getFunctionRanges):
+        * runtime/FunctionHasExecutedCache.h:
+        (JSC::FunctionHasExecutedCache::FunctionRange::Hash::hash):
+        (JSC::FunctionHasExecutedCache::FunctionRange::Hash::equal):
+        * runtime/TypeLocationCache.cpp:
+        (JSC::TypeLocationCache::getTypeLocation):
+        * runtime/TypeLocationCache.h:
+        (JSC::TypeLocationCache::LocationKey::Hash::hash):
+        (JSC::TypeLocationCache::LocationKey::Hash::equal):
+
 2022-01-28  Diego Pino Garcia  <[email protected]>
 
         [WPE] Unreviewed, fix non-unified build after r288758

Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.h (288806 => 288807)


--- trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -140,7 +140,7 @@
     bool hasVMTrapsBreakpointsInstalled { false };
     
 #if USE(JSVALUE32_64)
-    std::unique_ptr<Bag<double>> doubleConstants;
+    Bag<double> doubleConstants;
 #endif
     
     unsigned frameRegisterCount { std::numeric_limits<unsigned>::max() };

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (288806 => 288807)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -40,10 +40,10 @@
 #include "JITScannable.h"
 #include "MethodOfGettingAValueProfile.h"
 #include <wtf/BitVector.h>
+#include <wtf/GenericHashKey.h>
 #include <wtf/HashMap.h>
 #include <wtf/StackCheck.h>
 #include <wtf/StdLibExtras.h>
-#include <wtf/StdUnorderedMap.h>
 #include <wtf/Vector.h>
 
 namespace WTF {
@@ -1179,8 +1179,8 @@
     HashMap<const StringImpl*, String> m_copiedStrings;
 
 #if USE(JSVALUE32_64)
-    StdUnorderedMap<int64_t, double*> m_doubleConstantsMap;
-    std::unique_ptr<Bag<double>> m_doubleConstants;
+    HashMap<GenericHashKey<int64_t>, double*> m_doubleConstantsMap;
+    Bag<double> m_doubleConstants;
 #endif
     
     OptimizationFixpointState m_fixpointState;

Modified: trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/dfg/DFGIntegerCheckCombiningPhase.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -52,6 +52,12 @@
     };
 
     struct RangeKey {
+        struct Hash {
+            static unsigned hash(const RangeKey& key) { return key.hash(); }
+            static bool equal(const RangeKey& a, const RangeKey& b) { return a == b; }
+            static constexpr bool safeToCompareToEmptyOrDeleted = false;
+        };
+
         static RangeKey addition(Edge edge)
         {
             RangeKey result;
@@ -185,8 +191,8 @@
                 dataLog("For ", node, ": ", data, "\n");
             if (!data)
                 continue;
-            
-            Range& range = m_map[data.m_key];
+
+            Range& range = m_map.add(data.m_key, Range { }).iterator->value;
             if (DFGIntegerCheckCombiningPhaseInternal::verbose)
                 dataLog("    Range: ", range, "\n");
             if (range.m_count) {
@@ -213,7 +219,7 @@
             RangeKeyAndAddend data = ""
             if (!data)
                 continue;
-            Range range = m_map[data.m_key];
+            Range range = m_map.get(data.m_key);
             if (!isValid(data.m_key, range))
                 continue;
             
@@ -260,7 +266,7 @@
                             nodeIndex, SpecNone, CheckInBounds, node->origin,
                             Edge(minNode, Int32Use), Edge(data.m_key.m_key, Int32Use));
                     }
-                    m_map[data.m_key].m_dependency = m_insertionSet.insertNode(
+                    m_map.find(data.m_key)->value.m_dependency = m_insertionSet.insertNode(
                         nodeIndex, SpecNone, CheckInBounds, node->origin,
                         Edge(maxNode, Int32Use), Edge(data.m_key.m_key, Int32Use), Edge(minCheck, UntypedUse));
                     break;
@@ -271,7 +277,7 @@
                 }
                 
                 m_changed = true;
-                m_map[data.m_key].m_hoisted = true;
+                m_map.find(data.m_key)->value.m_hoisted = true;
             }
             
             // Do the elimination.
@@ -285,7 +291,7 @@
                 ASSERT(node->op() == CheckInBounds);
                 if (UNLIKELY(Options::validateBoundsCheckElimination()))
                     m_insertionSet.insertNode(nodeIndex, SpecNone, AssertInBounds, node->origin, node->child1(), node->child2());
-                node->convertToIdentityOn(m_map[data.m_key].m_dependency);
+                node->convertToIdentityOn(m_map.get(data.m_key).m_dependency);
                 m_changed = true;
                 break;
                 
@@ -378,7 +384,7 @@
                 nodeIndex, origin, jsNumber(addend), source.useKind()));
     }
     
-    using RangeMap = StdUnorderedMap<RangeKey, Range, HashMethod<RangeKey>>;
+    using RangeMap = HashMap<GenericHashKey<RangeKey, RangeKey::Hash>, Range>;
     RangeMap m_map;
     
     InsertionSet m_insertionSet;

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -531,17 +531,11 @@
 {
     double value = node->asNumber();
     int64_t valueBits = bitwise_cast<int64_t>(value);
-    auto it = m_graph.m_doubleConstantsMap.find(valueBits);
-    if (it != m_graph.m_doubleConstantsMap.end())
-        return it->second;
-
-    if (!m_graph.m_doubleConstants)
-        m_graph.m_doubleConstants = makeUnique<Bag<double>>();
-
-    double* addressInConstantPool = m_graph.m_doubleConstants->add();
-    *addressInConstantPool = value;
-    m_graph.m_doubleConstantsMap[valueBits] = addressInConstantPool;
-    return addressInConstantPool;
+    return m_graph.m_doubleConstantsMap.ensure(valueBits, [&]{
+        double* addressInConstantPool = m_graph.m_doubleConstants.add();
+        *addressInConstantPool = value;
+        return addressInConstantPool;
+    }).iterator->value;
 }
 #endif
 

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -101,8 +101,8 @@
 #include "YarrJITRegisters.h"
 #include <atomic>
 #include <wtf/Box.h>
+#include <wtf/GenericHashKey.h>
 #include <wtf/RecursableLambda.h>
-#include <wtf/StdUnorderedSet.h>
 
 #undef RELEASE_ASSERT
 #define RELEASE_ASSERT(assertion) do { \
@@ -17846,7 +17846,7 @@
         
         Vector<SwitchCase> cases;
         // These may be negative, or zero, or probably other stuff, too. We don't want to mess with HashSet's corner cases and we don't really care about throughput here.
-        StdUnorderedSet<int32_t> alreadyHandled;
+        HashSet<GenericHashKey<int32_t>> alreadyHandled;
         for (unsigned i = 0; i < data->cases.size(); ++i) {
             // FIXME: The fact that we're using the bytecode's switch table means that the
             // following DFG IR transformation would be invalid.
@@ -17884,7 +17884,7 @@
             DFG_ASSERT(m_graph, m_node, iter != unlinkedTable.m_offsetTable.end());
             
             // Use m_indexInTable instead of m_branchOffset to make Switch table dense.
-            if (!alreadyHandled.insert(iter->value.m_indexInTable).second)
+            if (!alreadyHandled.add(iter->value.m_indexInTable).isNewEntry)
                 continue;
 
             cases.append(SwitchCase(

Modified: trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/runtime/DeferredWorkTimer.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -34,7 +34,7 @@
 namespace JSC {
 
 namespace DeferredWorkTimerInternal {
-static const bool verbose = false;
+static constexpr bool verbose = false;
 }
 
 inline DeferredWorkTimer::TicketData::TicketData(VM& vm, JSObject* scriptExecutionOwner, Vector<Strong<JSCell>>&& dependencies)

Modified: trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -32,16 +32,17 @@
 
 bool FunctionHasExecutedCache::hasExecutedAtOffset(SourceID id, unsigned offset)
 {
-    if (m_rangeMap.find(id) == m_rangeMap.end())
+    auto iterator = m_rangeMap.find(id);
+    if (iterator == m_rangeMap.end())
         return false;
 
-    RangeMap& map = m_rangeMap.find(id)->second;
+    RangeMap& map = iterator->value;
     unsigned distance = UINT_MAX;
     bool hasExecuted = false;
     for (auto& pair : map) {
-        const FunctionRange& range = pair.first;
+        const FunctionRange& range = pair.key.key();
         if (range.m_start <= offset && offset <= range.m_end && range.m_end - range.m_start < distance) {
-            hasExecuted = pair.second;
+            hasExecuted = pair.value;
             distance = range.m_end - range.m_start;
         }
     }
@@ -51,46 +52,41 @@
 
 void FunctionHasExecutedCache::insertUnexecutedRange(SourceID id, unsigned start, unsigned end)
 {
-    if (m_rangeMap.find(id) == m_rangeMap.end()) {
-        RangeMap map;
-        m_rangeMap[id] = map;
-    }
-
-    RangeMap& map = m_rangeMap.find(id)->second;
+    RangeMap& map = m_rangeMap.add(id, RangeMap { }).iterator->value;
     FunctionRange range;
     range.m_start = start;
     range.m_end = end;
     // Only insert unexecuted ranges once for a given sourceID because we may run into a situation where an executable executes, then is GCed, and then is allocated again,
     // and tries to reinsert itself, claiming it has never run, but this is false because it indeed already executed.
-    if (map.find(range) == map.end())
-        map[range] = false;
+    map.add(range, false);
 }
 
 void FunctionHasExecutedCache::removeUnexecutedRange(SourceID id, unsigned start, unsigned end)
 {
     // FIXME: We should never have an instance where we return here, but currently do in some situations. Find out why.
-    if (m_rangeMap.find(id) == m_rangeMap.end())
+    auto iterator = m_rangeMap.find(id);
+    if (iterator == m_rangeMap.end())
         return;
 
-    RangeMap& map = m_rangeMap.find(id)->second;
+    RangeMap& map = iterator->value;
 
     FunctionRange range;
     range.m_start = start;
     range.m_end = end;
-    map[range] = true;
+    map.set(range, true);
 }
 
 Vector<std::tuple<bool, unsigned, unsigned>> FunctionHasExecutedCache::getFunctionRanges(SourceID id)
 {
     Vector<std::tuple<bool, unsigned, unsigned>> ranges(0);
-    auto findResult = m_rangeMap.find(id);
-    if (findResult == m_rangeMap.end())
+    auto iterator = m_rangeMap.find(id);
+    if (iterator == m_rangeMap.end())
         return ranges;
 
-    RangeMap& map = m_rangeMap.find(id)->second;
+    RangeMap& map = iterator->value;
     for (auto& pair : map) {
-        const FunctionRange& range = pair.first;
-        bool hasExecuted = pair.second;
+        const FunctionRange& range = pair.key.key();
+        bool hasExecuted = pair.value;
         ranges.append(std::tuple<bool, unsigned, unsigned>(hasExecuted, range.m_start, range.m_end));
     }
 

Modified: trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.h (288806 => 288807)


--- trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.h	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/runtime/FunctionHasExecutedCache.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -26,8 +26,7 @@
 #pragma once
 
 #include "SourceID.h"
-#include <wtf/HashMethod.h>
-#include <wtf/StdUnorderedMap.h>
+#include <wtf/GenericHashKey.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
@@ -35,6 +34,12 @@
 class FunctionHasExecutedCache {
 public:
     struct FunctionRange {
+        struct Hash {
+            static unsigned hash(const FunctionRange& key) { return key.hash(); }
+            static bool equal(const FunctionRange& a, const FunctionRange& b) { return a == b; }
+            static constexpr bool safeToCompareToEmptyOrDeleted = false;
+        };
+
         FunctionRange() {}
         bool operator==(const FunctionRange& other) const 
         {
@@ -55,8 +60,8 @@
     Vector<std::tuple<bool, unsigned, unsigned>> getFunctionRanges(SourceID);
 
 private:
-    using RangeMap = StdUnorderedMap<FunctionRange, bool, HashMethod<FunctionRange>>;
-    using SourceIDToRangeMap = StdUnorderedMap<intptr_t, RangeMap>;
+    using RangeMap = HashMap<GenericHashKey<FunctionRange, FunctionRange::Hash>, bool>;
+    using SourceIDToRangeMap = HashMap<GenericHashKey<intptr_t>, RangeMap>;
     SourceIDToRangeMap m_rangeMap;
 };
 

Modified: trunk/Source/_javascript_Core/runtime/TypeLocationCache.cpp (288806 => 288807)


--- trunk/Source/_javascript_Core/runtime/TypeLocationCache.cpp	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/runtime/TypeLocationCache.cpp	2022-01-31 08:48:47 UTC (rev 288807)
@@ -41,22 +41,17 @@
     key.m_start = start;
     key.m_end = end;
 
-    bool isNewLocation = false;
-    if (m_locationMap.find(key) == m_locationMap.end()) {
+    auto result = m_locationMap.ensure(key, [&]{
         ASSERT(vm->typeProfiler());
-        TypeLocation* location = vm->typeProfiler()->nextTypeLocation();
+        auto* location = vm->typeProfiler()->nextTypeLocation();
         location->m_globalVariableID = globalVariableID;
         location->m_sourceID = sourceID;
         location->m_divotStart = start;
         location->m_divotEnd = end;
         location->m_globalTypeSet = WTFMove(globalTypeSet);
-
-        m_locationMap[key] = location;
-        isNewLocation = true;
-    }
-
-    TypeLocation* location = m_locationMap.find(key)->second;
-    return std::pair<TypeLocation*, bool>(location, isNewLocation);
+        return location;
+    });
+    return std::pair { result.iterator->value, result.isNewEntry };
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/TypeLocationCache.h (288806 => 288807)


--- trunk/Source/_javascript_Core/runtime/TypeLocationCache.h	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/_javascript_Core/runtime/TypeLocationCache.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -28,8 +28,7 @@
 #include "SourceID.h"
 #include "TypeLocation.h"
 #include <wtf/FastMalloc.h>
-#include <wtf/HashMethod.h>
-#include <wtf/StdUnorderedMap.h>
+#include <wtf/GenericHashKey.h>
 
 namespace JSC {
 
@@ -38,6 +37,12 @@
 class TypeLocationCache {
 public:
     struct LocationKey {
+        struct Hash {
+            static unsigned hash(const LocationKey& key) { return key.hash(); }
+            static bool equal(const LocationKey& a, const LocationKey& b) { return a == b; }
+            static constexpr bool safeToCompareToEmptyOrDeleted = false;
+        };
+
         LocationKey() {}
         bool operator==(const LocationKey& other) const 
         {
@@ -60,7 +65,7 @@
 
     std::pair<TypeLocation*, bool> getTypeLocation(GlobalVariableID, SourceID, unsigned start, unsigned end, RefPtr<TypeSet>&&, VM*);
 private:
-    using LocationMap = StdUnorderedMap<LocationKey, TypeLocation*, HashMethod<LocationKey>>;
+    using LocationMap = HashMap<GenericHashKey<LocationKey, LocationKey::Hash>, TypeLocation*>;
     LocationMap m_locationMap;
 };
 

Modified: trunk/Source/WTF/ChangeLog (288806 => 288807)


--- trunk/Source/WTF/ChangeLog	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/WTF/ChangeLog	2022-01-31 08:48:47 UTC (rev 288807)
@@ -1,3 +1,21 @@
+2022-01-30  Yusuke Suzuki  <[email protected]>
+
+        [WTF] Add GenericHashKey
+        https://bugs.webkit.org/show_bug.cgi?id=235872
+
+        Reviewed by Darin Adler.
+
+        This patch adds GenericHashKey<T>, which can represent any HashTable's key
+        even if Key does not have Empty / Deleted values. Previously we were using
+        StdUnorderedSet / StdUnorderedMap instead. But, (1) they are doing similar
+        thing to GenericHashKey to keep empty or deleted values, and (2) by using
+        GenericHashKey we can consistently use WTF::HashMap etc. for all possible
+        cases.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/GenericHashKey.h: Added.
+
 2022-01-30  Diego Pino Garcia  <[email protected]>
 
         [WinCairo] 'fileSystemRepresentation' identifier not found in URL.cpp

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (288806 => 288807)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2022-01-31 08:48:47 UTC (rev 288807)
@@ -800,6 +800,7 @@
 		E3E158251EADA53C004A079D /* SystemFree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemFree.h; sourceTree = "<group>"; };
 		E3E64F0B22813428001E55B4 /* Nonmovable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Nonmovable.h; sourceTree = "<group>"; };
 		E3E8162F2764799300BAA45B /* RefCountedFixedVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RefCountedFixedVector.h; sourceTree = "<group>"; };
+		E3FD6D6627A1F6AD00935000 /* GenericHashKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GenericHashKey.h; sourceTree = "<group>"; };
 		E419F2E623AB9E2300B26129 /* VectorHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VectorHash.h; sourceTree = "<group>"; };
 		E431CC4A21187ADB000C8A07 /* DispatchSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchSPI.h; sourceTree = "<group>"; };
 		E4A0AD371A96245500536DF6 /* WorkQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkQueue.cpp; sourceTree = "<group>"; };
@@ -1115,6 +1116,7 @@
 				1A1D8B9D1731879800141DA4 /* FunctionDispatcher.cpp */,
 				1A1D8B9B173186CE00141DA4 /* FunctionDispatcher.h */,
 				53F1D98620477B9800EBC6BF /* FunctionTraits.h */,
+				E3FD6D6627A1F6AD00935000 /* GenericHashKey.h */,
 				E3831F922703101A00EF5EB3 /* GenericTimeMixin.h */,
 				A8A472A8151A825A004123FF /* GetPtr.h */,
 				0F5BF1741F23D49A0029D91D /* Gigacage.cpp */,
@@ -1149,9 +1151,9 @@
 				E33667492722550900259122 /* Int128.cpp */,
 				F6D67D3226F90142006E0349 /* Int128.h */,
 				33FD4811265CB38000ABE4F4 /* InterferenceGraph.h */,
-				5295B00427920C54006D746A /* IterationStatus.h */,
 				0F7EB85B1FA8FF4100F1ABCB /* IsoMalloc.h */,
 				0F7EB85C1FA8FF4200F1ABCB /* IsoMallocInlines.h */,
+				5295B00427920C54006D746A /* IterationStatus.h */,
 				7CDD7FF7186D291E007433CD /* IteratorAdaptors.h */,
 				7CDD7FF9186D2A54007433CD /* IteratorRange.h */,
 				7A05093E1FB9DCC500B33FB8 /* JSONValues.cpp */,

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (288806 => 288807)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2022-01-31 08:48:47 UTC (rev 288807)
@@ -81,6 +81,7 @@
     Function.h
     FunctionDispatcher.h
     FunctionTraits.h
+    GenericHashKey.h
     GenericTimeMixin.h
     GetPtr.h
     Gigacage.h

Added: trunk/Source/WTF/wtf/GenericHashKey.h (0 => 288807)


--- trunk/Source/WTF/wtf/GenericHashKey.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/GenericHashKey.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2022 Apple 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+#include <variant>
+#include <wtf/Forward.h>
+
+namespace WTF {
+
+template<typename Key, typename HashArg = DefaultHash<Key>>
+class GenericHashKey final {
+    WTF_MAKE_FAST_ALLOCATED;
+
+    struct EmptyKey { };
+    struct DeletedKey { };
+
+public:
+    constexpr GenericHashKey(Key&& key)
+        : m_value(std::in_place_type_t<Key>(), WTFMove(key))
+    {
+    }
+
+    template<typename K>
+    constexpr GenericHashKey(K&& key)
+        : m_value(std::in_place_type_t<Key>(), std::forward<K>(key))
+    {
+    }
+
+    constexpr GenericHashKey(HashTableEmptyValueType)
+        : m_value(EmptyKey { })
+    {
+    }
+
+    constexpr GenericHashKey(HashTableDeletedValueType)
+        : m_value(DeletedKey { })
+    {
+    }
+
+    constexpr const Key& key() const { return std::get<Key>(m_value); }
+    constexpr unsigned hash() const
+    {
+        ASSERT_UNDER_CONSTEXPR_CONTEXT(!isHashTableDeletedValue() && !isHashTableEmptyValue());
+        return HashArg::hash(key());
+    }
+
+    constexpr bool isHashTableDeletedValue() const { return std::holds_alternative<DeletedKey>(m_value); }
+    constexpr bool isHashTableEmptyValue() const { return std::holds_alternative<EmptyKey>(m_value); }
+
+    constexpr bool operator==(const GenericHashKey& other) const
+    {
+        if (m_value.index() != other.m_value.index())
+            return false;
+        if (!std::holds_alternative<Key>(m_value))
+            return true;
+        return HashArg::equal(key(), other.key());
+    }
+
+    constexpr bool operator!=(const GenericHashKey& other) const
+    {
+        return !(*this == other);
+    }
+
+private:
+    std::variant<Key, EmptyKey, DeletedKey> m_value;
+};
+
+template<typename K, typename H> struct HashTraits<GenericHashKey<K, H>> : GenericHashTraits<GenericHashKey<K, H>> {
+    static GenericHashKey<K, H> emptyValue() { return GenericHashKey<K, H> { HashTableEmptyValue }; }
+    static void constructDeletedValue(GenericHashKey<K, H>& slot) { slot = GenericHashKey<K, H> { HashTableDeletedValue }; }
+    static bool isDeletedValue(const GenericHashKey<K, H>& value) { return value.isHashTableDeletedValue(); }
+};
+
+template<typename K, typename H> struct DefaultHash<GenericHashKey<K, H>> {
+    static unsigned hash(const GenericHashKey<K, H>& key) { return key.hash(); }
+    static bool equal(const GenericHashKey<K, H>& a, const GenericHashKey<K, H>& b) { return a == b; }
+    static constexpr bool safeToCompareToEmptyOrDeleted = false;
+};
+
+}
+
+using WTF::GenericHashKey;

Modified: trunk/Source/WebCore/ChangeLog (288806 => 288807)


--- trunk/Source/WebCore/ChangeLog	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/WebCore/ChangeLog	2022-01-31 08:48:47 UTC (rev 288807)
@@ -1,3 +1,15 @@
+2022-01-30  Yusuke Suzuki  <[email protected]>
+
+        [WTF] Add GenericHashKey
+        https://bugs.webkit.org/show_bug.cgi?id=235872
+
+        Reviewed by Darin Adler.
+
+        No behavior change. We should use StdMap.
+        This should be StdMap since it requires ordered iterations by the key, so it should not be a HashMap.
+
+        * platform/graphics/avfoundation/objc/QueuedVideoOutput.h:
+
 2022-01-30  Ryosuke Niwa  <[email protected]>
 
         Delete code for keygen element

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/QueuedVideoOutput.h (288806 => 288807)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/QueuedVideoOutput.h	2022-01-31 05:47:29 UTC (rev 288806)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/QueuedVideoOutput.h	2022-01-31 08:48:47 UTC (rev 288807)
@@ -33,6 +33,7 @@
 #include <wtf/Observer.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/StdMap.h>
 #include <wtf/WeakHashSet.h>
 
 OBJC_CLASS AVPlayer;
@@ -67,7 +68,7 @@
     using CurrentImageChangedObserver = Observer<void()>;
     void addCurrentImageChangedObserver(const CurrentImageChangedObserver&);
 
-    using ImageMap = std::map<MediaTime, RetainPtr<CVPixelBufferRef>>;
+    using ImageMap = StdMap<MediaTime, RetainPtr<CVPixelBufferRef>>;
 
     void rateChanged(float);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to