Title: [290705] trunk
Revision
290705
Author
hironori.fu...@sony.com
Date
2022-03-01 15:51:26 -0800 (Tue, 01 Mar 2022)

Log Message

WTF::SentinelLinkedList::iterator should have operator++ for range-for loop
https://bugs.webkit.org/show_bug.cgi?id=237265

Reviewed by Yusuke Suzuki.

Source/_javascript_Core:

SentinelLinkedList::iterator isn't a pointer of node now, it
should be deferenced before comparing with a pointer.

* bytecode/Watchpoint.cpp:
(JSC::WatchpointSet::fireAllWatchpoints):
* heap/HandleSet.cpp:
(JSC::HandleSet::visitStrongHandles):
(JSC::HandleSet::protectedGlobalObjectCount):
* heap/HandleSet.h:
(JSC::HandleSet::forEachStrongHandle):
* heap/IsoSubspace.cpp:
(JSC::IsoSubspace::tryAllocateFromLowerTier):
* heap/SubspaceInlines.h:
(JSC::Subspace::forEachPreciseAllocation):
* jsc.cpp:
(Workers::broadcast):

Source/WTF:

SentinelLinkedList had three problems.
1. Even though it has begin() and end(), using SentinelLinkedList
   with range-for loop resulted in a broken node because
   iterator::operator++ didn't work as expected.
2. If I used a SentinelLinkedList in a movable type, the sentinel
   pointer gets stale after moving the object. move-ctor should be deleted.
3. It didn't have const_iterator.

* wtf/OrderMaker.h:
(WTF::OrderMaker::iterator::iterator):
(WTF::OrderMaker::iterator::operator*):
(WTF::OrderMaker::iterator::operator++):
(WTF::OrderMaker::iterator::operator== const):
* wtf/SentinelLinkedList.h:
(WTF::BasicRawSentinelNode::prev const):
(WTF::BasicRawSentinelNode::next const):
(WTF::SentinelLinkedList::BaseIterator::BaseIterator):
(WTF::SentinelLinkedList::BaseIterator::operator* const):
(WTF::SentinelLinkedList::BaseIterator::operator-> const):
(WTF::SentinelLinkedList::BaseIterator::operator++):
(WTF::SentinelLinkedList::BaseIterator::operator--):
(WTF::SentinelLinkedList::BaseIterator::operator== const):
(WTF::SentinelLinkedList::BaseIterator::operator!= const):
(WTF::SentinelLinkedList::forEach):
(WTF::RawNode>::begin):
(WTF::RawNode>::end):
(WTF::RawNode>::begin const):
(WTF::RawNode>::end const):
(WTF::BasicRawSentinelNode::prev): Deleted.
(WTF::BasicRawSentinelNode::next): Deleted.

Tools:

* TestWebKitAPI/Tests/WTF/SentinelLinkedList.cpp:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (290704 => 290705)


--- trunk/Source/_javascript_Core/ChangeLog	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-03-01 23:51:26 UTC (rev 290705)
@@ -1,3 +1,27 @@
+2022-03-01  Fujii Hironori  <hironori.fu...@sony.com>
+
+        WTF::SentinelLinkedList::iterator should have operator++ for range-for loop
+        https://bugs.webkit.org/show_bug.cgi?id=237265
+
+        Reviewed by Yusuke Suzuki.
+
+        SentinelLinkedList::iterator isn't a pointer of node now, it
+        should be deferenced before comparing with a pointer.
+
+        * bytecode/Watchpoint.cpp:
+        (JSC::WatchpointSet::fireAllWatchpoints):
+        * heap/HandleSet.cpp:
+        (JSC::HandleSet::visitStrongHandles):
+        (JSC::HandleSet::protectedGlobalObjectCount):
+        * heap/HandleSet.h:
+        (JSC::HandleSet::forEachStrongHandle):
+        * heap/IsoSubspace.cpp:
+        (JSC::IsoSubspace::tryAllocateFromLowerTier):
+        * heap/SubspaceInlines.h:
+        (JSC::Subspace::forEachPreciseAllocation):
+        * jsc.cpp:
+        (Workers::broadcast):
+
 2022-03-01  Michael Catanzaro  <mcatanz...@gnome.org>
 
         Misc compiler warnings, late Feb 2022 edition

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp (290704 => 290705)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2022-03-01 23:51:26 UTC (rev 290705)
@@ -138,8 +138,8 @@
     DeferGCForAWhile deferGC(vm);
     
     while (!m_set.isEmpty()) {
-        Watchpoint* watchpoint = m_set.begin();
-        ASSERT(watchpoint->isOnList());
+        Watchpoint& watchpoint = *m_set.begin();
+        ASSERT(watchpoint.isOnList());
         
         // Removing the Watchpoint before firing it makes it possible to implement watchpoints
         // that add themselves to a different set when they fire. This kind of "adaptive"
@@ -150,11 +150,11 @@
         // So, before the watchpoint decides to invalidate any code, it can check if it is
         // possible to add itself to the transition watchpoint set of the singleton object's new
         // Structure.
-        watchpoint->remove();
-        ASSERT(m_set.begin() != watchpoint);
-        ASSERT(!watchpoint->isOnList());
+        watchpoint.remove();
+        ASSERT(&*m_set.begin() != &watchpoint);
+        ASSERT(!watchpoint.isOnList());
         
-        watchpoint->fire(vm, detail);
+        watchpoint.fire(vm, detail);
         // After we fire the watchpoint, the watchpoint pointer may be a dangling pointer. That's
         // fine, because we have no use for the pointer anymore.
     }

Modified: trunk/Source/_javascript_Core/heap/HandleSet.cpp (290704 => 290705)


--- trunk/Source/_javascript_Core/heap/HandleSet.cpp	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/heap/HandleSet.cpp	2022-03-01 23:51:26 UTC (rev 290705)
@@ -59,12 +59,11 @@
 template<typename Visitor>
 void HandleSet::visitStrongHandles(Visitor& visitor)
 {
-    Node* end = m_strongList.end();
-    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+    for (Node& node : m_strongList) {
 #if ENABLE(GC_VALIDATION)
-        RELEASE_ASSERT(isLiveNode(node));
+        RELEASE_ASSERT(isLiveNode(&node));
 #endif
-        visitor.appendUnbarriered(*node->slot());
+        visitor.appendUnbarriered(*node.slot());
     }
 }
 
@@ -95,9 +94,8 @@
 unsigned HandleSet::protectedGlobalObjectCount()
 {
     unsigned count = 0;
-    Node* end = m_strongList.end();
-    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
-        JSValue value = *node->slot();
+    for (Node& node : m_strongList) {
+        JSValue value = *node.slot();
         if (value.isObject() && asObject(value.asCell())->isGlobalObject())
             count++;
     }

Modified: trunk/Source/_javascript_Core/heap/HandleSet.h (290704 => 290705)


--- trunk/Source/_javascript_Core/heap/HandleSet.h	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/heap/HandleSet.h	2022-03-01 23:51:26 UTC (rev 290705)
@@ -181,9 +181,8 @@
 
 template<typename Functor> void HandleSet::forEachStrongHandle(const Functor& functor, const HashCountedSet<JSCell*>& skipSet)
 {
-    HandleSet::Node* end = m_strongList.end();
-    for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) {
-        JSValue value = *node->slot();
+    for (Node& node : m_strongList) {
+        JSValue value = *node.slot();
         if (!value || !value.isCell())
             continue;
         if (skipSet.contains(value.asCell()))

Modified: trunk/Source/_javascript_Core/heap/IsoSubspace.cpp (290704 => 290705)


--- trunk/Source/_javascript_Core/heap/IsoSubspace.cpp	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/heap/IsoSubspace.cpp	2022-03-01 23:51:26 UTC (rev 290705)
@@ -93,7 +93,7 @@
     };
 
     if (!m_lowerTierFreeList.isEmpty()) {
-        PreciseAllocation* allocation = m_lowerTierFreeList.begin();
+        PreciseAllocation* allocation = &*m_lowerTierFreeList.begin();
         allocation->remove();
         return revive(allocation);
     }

Modified: trunk/Source/_javascript_Core/heap/SubspaceInlines.h (290704 => 290705)


--- trunk/Source/_javascript_Core/heap/SubspaceInlines.h	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/heap/SubspaceInlines.h	2022-03-01 23:51:26 UTC (rev 290705)
@@ -62,8 +62,8 @@
 template<typename Func>
 void Subspace::forEachPreciseAllocation(const Func& func)
 {
-    for (PreciseAllocation* allocation = m_preciseAllocations.begin(); allocation != m_preciseAllocations.end(); allocation = allocation->next())
-        func(allocation);
+    for (PreciseAllocation& allocation : m_preciseAllocations)
+        func(&allocation);
 }
 
 template<typename Func>

Modified: trunk/Source/_javascript_Core/jsc.cpp (290704 => 290705)


--- trunk/Source/_javascript_Core/jsc.cpp	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/_javascript_Core/jsc.cpp	2022-03-01 23:51:26 UTC (rev 290705)
@@ -1984,9 +1984,9 @@
 void Workers::broadcast(const Func& func)
 {
     Locker locker { m_lock };
-    for (Worker* worker = m_workers.begin(); worker != m_workers.end(); worker = worker->next()) {
-        if (worker != &Worker::current())
-            func(locker, *worker);
+    for (Worker& worker : m_workers) {
+        if (&worker != &Worker::current())
+            func(locker, worker);
     }
     m_condition.notifyAll();
 }

Modified: trunk/Source/WTF/ChangeLog (290704 => 290705)


--- trunk/Source/WTF/ChangeLog	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/WTF/ChangeLog	2022-03-01 23:51:26 UTC (rev 290705)
@@ -1,3 +1,41 @@
+2022-03-01  Fujii Hironori  <hironori.fu...@sony.com>
+
+        WTF::SentinelLinkedList::iterator should have operator++ for range-for loop
+        https://bugs.webkit.org/show_bug.cgi?id=237265
+
+        Reviewed by Yusuke Suzuki.
+
+        SentinelLinkedList had three problems.
+        1. Even though it has begin() and end(), using SentinelLinkedList
+           with range-for loop resulted in a broken node because
+           iterator::operator++ didn't work as expected.
+        2. If I used a SentinelLinkedList in a movable type, the sentinel
+           pointer gets stale after moving the object. move-ctor should be deleted.
+        3. It didn't have const_iterator.
+
+        * wtf/OrderMaker.h:
+        (WTF::OrderMaker::iterator::iterator):
+        (WTF::OrderMaker::iterator::operator*):
+        (WTF::OrderMaker::iterator::operator++):
+        (WTF::OrderMaker::iterator::operator== const):
+        * wtf/SentinelLinkedList.h:
+        (WTF::BasicRawSentinelNode::prev const):
+        (WTF::BasicRawSentinelNode::next const):
+        (WTF::SentinelLinkedList::BaseIterator::BaseIterator):
+        (WTF::SentinelLinkedList::BaseIterator::operator* const):
+        (WTF::SentinelLinkedList::BaseIterator::operator-> const):
+        (WTF::SentinelLinkedList::BaseIterator::operator++):
+        (WTF::SentinelLinkedList::BaseIterator::operator--):
+        (WTF::SentinelLinkedList::BaseIterator::operator== const):
+        (WTF::SentinelLinkedList::BaseIterator::operator!= const):
+        (WTF::SentinelLinkedList::forEach):
+        (WTF::RawNode>::begin):
+        (WTF::RawNode>::end):
+        (WTF::RawNode>::begin const):
+        (WTF::RawNode>::end const):
+        (WTF::BasicRawSentinelNode::prev): Deleted.
+        (WTF::BasicRawSentinelNode::next): Deleted.
+
 2022-03-01  Youenn Fablet  <you...@apple.com>
 
         Enable WebRTCRemoteVideoFrameEnabled by default on Cocoa ports

Modified: trunk/Source/WTF/wtf/OrderMaker.h (290704 => 290705)


--- trunk/Source/WTF/wtf/OrderMaker.h	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/WTF/wtf/OrderMaker.h	2022-03-01 23:51:26 UTC (rev 290705)
@@ -88,25 +88,25 @@
         {
         }
 
-        iterator(Node* node)
-            : m_node(node)
+        iterator(typename SentinelLinkedList<Node>::iterator iter)
+            : m_iter(iter)
         {
         }
 
         const T& operator*()
         {
-            return m_node->payload;
+            return m_iter->payload;
         }
 
         iterator& operator++()
         {
-            m_node = m_node->next();
+            ++m_iter;
             return *this;
         }
 
         bool operator==(const iterator& other) const
         {
-            return m_node == other.m_node;
+            return m_iter == other.m_iter;
         }
 
         bool operator!=(const iterator& other) const
@@ -115,7 +115,7 @@
         }
         
     private:
-        Node* m_node { nullptr };
+        typename SentinelLinkedList<Node>::iterator m_iter;
     };
 
     iterator begin() const { return iterator(const_cast<SentinelLinkedList<Node>&>(m_list).begin()); }

Modified: trunk/Source/WTF/wtf/SentinelLinkedList.h (290704 => 290705)


--- trunk/Source/WTF/wtf/SentinelLinkedList.h	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Source/WTF/wtf/SentinelLinkedList.h	2022-03-01 23:51:26 UTC (rev 290705)
@@ -30,12 +30,15 @@
 //    Requires: Node is a concrete class with:
 //        Node(SentinelTag);
 //        void setPrev(Node*);
-//        Node* prev();
+//        Node* prev() const;
 //        void setNext(Node*);
-//        Node* next();
+//        Node* next() const;
 
 #pragma once
 
+#include <iterator>
+#include <wtf/Noncopyable.h>
+#include <wtf/Nonmovable.h>
 #include <wtf/Packed.h>
 
 namespace WTF {
@@ -57,8 +60,8 @@
     void setPrev(BasicRawSentinelNode* prev) { m_prev = prev; }
     void setNext(BasicRawSentinelNode* next) { m_next = next; }
     
-    T* prev() { return static_cast<T*>(PtrTraits::unwrap(m_prev)); }
-    T* next() { return static_cast<T*>(PtrTraits::unwrap(m_next)); }
+    T* prev() const { return static_cast<T*>(PtrTraits::unwrap(m_prev)); }
+    T* next() const { return static_cast<T*>(PtrTraits::unwrap(m_next)); }
     
     bool isOnList() const
     {
@@ -77,9 +80,50 @@
 };
 
 template <typename T, typename RawNode = T> class SentinelLinkedList {
+    WTF_MAKE_NONCOPYABLE(SentinelLinkedList);
+    WTF_MAKE_NONMOVABLE(SentinelLinkedList);
 public:
-    typedef T* iterator;
+    template<typename RawNodeType, typename NodeType> class BaseIterator {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        explicit BaseIterator(RawNodeType* node)
+            : m_node(node)
+        {
+        }
+        
+        auto& operator*() const { return static_cast<NodeType&>(*m_node); }
 
+        auto* operator->() const { return static_cast<NodeType*>(m_node); }
+
+        BaseIterator& operator++()
+        {
+            m_node = m_node->next();
+            return *this;
+        }
+        
+        BaseIterator& operator--()
+        {
+            m_node = m_node->prev();
+            return *this;
+        }
+        
+        bool operator==(const BaseIterator& other) const
+        {
+            return m_node == other.m_node;
+        }
+
+        bool operator!=(const BaseIterator& other) const
+        {
+            return !(*this == other);
+        }
+
+    private:
+        RawNodeType* m_node;
+    };
+
+    using iterator = BaseIterator<RawNode, T>;
+    using const_iterator = BaseIterator<const RawNode, const T>;
+
     SentinelLinkedList()
         : m_sentinel(Sentinel)
     {
@@ -101,6 +145,8 @@
 
     iterator begin();
     iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
     
     bool isEmpty() { return begin() == end(); }
     
@@ -108,8 +154,9 @@
     void forEach(const Func& func)
     {
         for (iterator iter = begin(); iter != end();) {
-            iterator next = iter->next();
-            func(iter);
+            iterator next = iter;
+            ++next;
+            func(&*iter);
             iter = next;
         }
     }
@@ -139,14 +186,24 @@
 
 template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::iterator SentinelLinkedList<T, RawNode>::begin()
 {
-    return static_cast<T*>(m_sentinel.next());
+    return iterator { m_sentinel.next() };
 }
 
 template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::iterator SentinelLinkedList<T, RawNode>::end()
 {
-    return static_cast<T*>(&m_sentinel);
+    return iterator { &m_sentinel };
 }
 
+template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::const_iterator SentinelLinkedList<T, RawNode>::begin() const
+{
+    return const_iterator { m_sentinel.next() };
+}
+
+template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::const_iterator SentinelLinkedList<T, RawNode>::end() const
+{
+    return const_iterator { &m_sentinel };
+}
+
 template <typename T, typename RawNode> inline void SentinelLinkedList<T, RawNode>::push(T* node)
 {
     ASSERT(node);

Modified: trunk/Tools/ChangeLog (290704 => 290705)


--- trunk/Tools/ChangeLog	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Tools/ChangeLog	2022-03-01 23:51:26 UTC (rev 290705)
@@ -1,5 +1,15 @@
 2022-03-01  Fujii Hironori  <hironori.fu...@sony.com>
 
+        WTF::SentinelLinkedList::iterator should have operator++ for range-for loop
+        https://bugs.webkit.org/show_bug.cgi?id=237265
+
+        Reviewed by Yusuke Suzuki.
+
+        * TestWebKitAPI/Tests/WTF/SentinelLinkedList.cpp:
+        (TestWebKitAPI::TEST):
+
+2022-03-01  Fujii Hironori  <hironori.fu...@sony.com>
+
         [WinCairo][pywebsocket3] UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 640: character maps to <undefined>
         https://bugs.webkit.org/show_bug.cgi?id=237339
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/SentinelLinkedList.cpp (290704 => 290705)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/SentinelLinkedList.cpp	2022-03-01 23:50:13 UTC (rev 290704)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/SentinelLinkedList.cpp	2022-03-01 23:51:26 UTC (rev 290705)
@@ -51,30 +51,30 @@
 
     auto* first = bag.add(0);
     list.push(first);
-    EXPECT_EQ(first, list.begin());
+    EXPECT_EQ(first, &*list.begin());
     EXPECT_EQ(0, list.begin()->value());
 
     auto* second = bag.add(1);
     list.push(second);
-    EXPECT_EQ(second, list.begin());
+    EXPECT_EQ(second, &*list.begin());
     EXPECT_EQ(1, list.begin()->value());
     EXPECT_EQ(first, list.begin()->next());
     EXPECT_EQ(0, list.begin()->next()->value());
-    EXPECT_EQ(list.end(), list.begin()->next()->next());
+    EXPECT_EQ(&*list.end(), list.begin()->next()->next());
 
     auto* third = bag.add(2);
     first->prepend(third);
-    EXPECT_EQ(second, list.begin());
+    EXPECT_EQ(second, &*list.begin());
     EXPECT_EQ(1, list.begin()->value());
     EXPECT_EQ(third, list.begin()->next());
     EXPECT_EQ(2, list.begin()->next()->value());
     EXPECT_EQ(first, list.begin()->next()->next());
     EXPECT_EQ(0, list.begin()->next()->next()->value());
-    EXPECT_EQ(list.end(), list.begin()->next()->next()->next());
+    EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next());
 
     auto* fourth = bag.add(3);
     first->append(fourth);
-    EXPECT_EQ(second, list.begin());
+    EXPECT_EQ(second, &*list.begin());
     EXPECT_EQ(1, list.begin()->value());
     EXPECT_EQ(third, list.begin()->next());
     EXPECT_EQ(2, list.begin()->next()->value());
@@ -82,7 +82,7 @@
     EXPECT_EQ(0, list.begin()->next()->next()->value());
     EXPECT_EQ(fourth, list.begin()->next()->next()->next());
     EXPECT_EQ(3, list.begin()->next()->next()->next()->value());
-    EXPECT_EQ(list.end(), list.begin()->next()->next()->next()->next());
+    EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next()->next());
 
     EXPECT_TRUE(first->isOnList());
     EXPECT_TRUE(second->isOnList());
@@ -113,9 +113,9 @@
 
     int i = 0;
     while (!list.isEmpty()) {
-        auto* node = list.begin();
-        EXPECT_EQ(i++, node->value());
-        node->remove();
+        auto& node = *list.begin();
+        EXPECT_EQ(i++, node.value());
+        node.remove();
     }
     EXPECT_EQ(10, i);
 }
@@ -147,7 +147,7 @@
     EXPECT_EQ(0, list.begin()->value());
     EXPECT_EQ(1, list.begin()->next()->value());
     EXPECT_EQ(2, list.begin()->next()->next()->value());
-    EXPECT_EQ(list.end(), list.begin()->next()->next()->next());
+    EXPECT_EQ(&*list.end(), list.begin()->next()->next()->next());
 }
 
 TEST(WTF_SentinelLinkedList, ForEach)
@@ -172,4 +172,18 @@
     EXPECT_EQ(10, i);
 }
 
+TEST(WTF_SentinelLinkedList, Const)
+{
+    Bag<TestNode> bag;
+    SentinelLinkedList<TestNode> nonConstList;
+    for (int i = 0; i < 10; ++i)
+        nonConstList.append(bag.add(i));
+
+    const SentinelLinkedList<TestNode>& constList = nonConstList;
+    int i = 0;
+    for (auto& node : constList)
+        EXPECT_EQ(i++, node.value());
+    EXPECT_EQ(10, i);
+}
+
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to