Title: [278344] trunk
Revision
278344
Author
rn...@webkit.org
Date
2021-06-02 01:43:13 -0700 (Wed, 02 Jun 2021)

Log Message

Add CheckedPtr
https://bugs.webkit.org/show_bug.cgi?id=226158

Reviewed by Antti Koivisto.

Source/WTF:

This patch introduces a new type of smart pointer, CheckedPtr, which behaves like RefPtr and
let each object keep track of pointers pointing to the object. Unlike CheckedPtr, the purpose of
this internal counter is to release assert that there is no outstanding pointer at the time
of destruction instead of keeping the object alive when there is one.

* WTF.xcodeproj/project.pbxproj:
* wtf/CheckedPtr.h: Added.
(WTF::CheckedPtr): Added.
(WTF::CheckedPtr::CheckedPtr): Added.
(WTF::CheckedPtr::~CheckedPtr): Added.
(WTF::CheckedPtr::isHashTableDeletedValue const): Added.
(WTF::CheckedPtr::operator UnspecifiedBoolType const): Added.
(WTF::CheckedPtr::operator! const): Added.
(WTF::CheckedPtr::get const): Added.
(WTF::CheckedPtr::get): Added.
(WTF::CheckedPtr::operator* const): Added.
(WTF::CheckedPtr::operator*): Added.
(WTF::CheckedPtr::operator-> const): Added.
(WTF::CheckedPtr::operator->): Added.
(WTF::CheckedPtr::operator== const): Added.
(WTF::CheckedPtr::operator=): Added.
(WTF::CheckedPtr::unspecifiedBoolTypeInstance const): Added.
(WTF::CheckedPtr::refIfNotNull): Added.
(WTF::CheckedPtr::derefIfNotNull): Added.
(WTF::makeCheckedPtr): Added.
(WTF::is): Added.
(WTF::CanMakeCheckedPtr): Added.
(WTF::CanMakeCheckedPtr::~CanMakeCheckedPtr): Added. Release assert that m_ptrCount is 0.
(WTF::CanMakeCheckedPtr::ptrCount const): Added.
(WTF::CanMakeCheckedPtr::incrementPtrCount): Added.
(WTF::CanMakeCheckedPtr::decrementPtrCount): Added. Note that we don't do anything when m_ptrCount
becomes 0 unlike RefPtr.
(WTF::HashTraits<CheckedPtr<P>>): Added.
(WTF::HashTraits<CheckedPtr<P>>::emptyValue): Added.
(WTF::HashTraits<CheckedPtr<P>>::peek): Added.
(WTF::HashTraits<CheckedPtr<P>>::customDeleteBucket): Added.

Tools:

Added basic tests.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/CheckedPtr.cpp: Added.
(TestWebKitAPI::CheckedObject): Added.
(TestWebKitAPI::DerivedCheckedObject): Added.
(WTF_CheckedPtr.Basic):
(WTF_CheckedPtr.DerivedClass):
(WTF_CheckedPtr.HashSet):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (278343 => 278344)


--- trunk/Source/WTF/ChangeLog	2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Source/WTF/ChangeLog	2021-06-02 08:43:13 UTC (rev 278344)
@@ -1,3 +1,47 @@
+2021-05-23  Ryosuke Niwa  <rn...@webkit.org>
+
+        Add CheckedPtr
+        https://bugs.webkit.org/show_bug.cgi?id=226158
+
+        Reviewed by Antti Koivisto.
+
+        This patch introduces a new type of smart pointer, CheckedPtr, which behaves like RefPtr and
+        let each object keep track of pointers pointing to the object. Unlike CheckedPtr, the purpose of
+        this internal counter is to release assert that there is no outstanding pointer at the time
+        of destruction instead of keeping the object alive when there is one.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CheckedPtr.h: Added.
+        (WTF::CheckedPtr): Added.
+        (WTF::CheckedPtr::CheckedPtr): Added.
+        (WTF::CheckedPtr::~CheckedPtr): Added.
+        (WTF::CheckedPtr::isHashTableDeletedValue const): Added.
+        (WTF::CheckedPtr::operator UnspecifiedBoolType const): Added.
+        (WTF::CheckedPtr::operator! const): Added.
+        (WTF::CheckedPtr::get const): Added.
+        (WTF::CheckedPtr::get): Added.
+        (WTF::CheckedPtr::operator* const): Added.
+        (WTF::CheckedPtr::operator*): Added.
+        (WTF::CheckedPtr::operator-> const): Added.
+        (WTF::CheckedPtr::operator->): Added.
+        (WTF::CheckedPtr::operator== const): Added.
+        (WTF::CheckedPtr::operator=): Added.
+        (WTF::CheckedPtr::unspecifiedBoolTypeInstance const): Added.
+        (WTF::CheckedPtr::refIfNotNull): Added.
+        (WTF::CheckedPtr::derefIfNotNull): Added.
+        (WTF::makeCheckedPtr): Added.
+        (WTF::is): Added.
+        (WTF::CanMakeCheckedPtr): Added.
+        (WTF::CanMakeCheckedPtr::~CanMakeCheckedPtr): Added. Release assert that m_ptrCount is 0.
+        (WTF::CanMakeCheckedPtr::ptrCount const): Added.
+        (WTF::CanMakeCheckedPtr::incrementPtrCount): Added.
+        (WTF::CanMakeCheckedPtr::decrementPtrCount): Added. Note that we don't do anything when m_ptrCount
+        becomes 0 unlike RefPtr.
+        (WTF::HashTraits<CheckedPtr<P>>): Added.
+        (WTF::HashTraits<CheckedPtr<P>>::emptyValue): Added.
+        (WTF::HashTraits<CheckedPtr<P>>::peek): Added.
+        (WTF::HashTraits<CheckedPtr<P>>::customDeleteBucket): Added.
+
 2021-06-01  Darin Adler  <da...@apple.com>
 
         Remove <wtf/Optional.h>

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (278343 => 278344)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2021-06-02 08:43:13 UTC (rev 278344)
@@ -507,6 +507,7 @@
 		996B17841EBA441C007E10EB /* DebugUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUtilities.h; sourceTree = "<group>"; };
 		9B67F3F12228D5310030DE9C /* WeakHashSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakHashSet.h; sourceTree = "<group>"; };
 		9B96E9B324FF77B8001756C3 /* CompactUniquePtrTuple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompactUniquePtrTuple.h; sourceTree = "<group>"; };
+		9BB91F512648EA4D00A56217 /* CheckedPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckedPtr.h; sourceTree = "<group>"; };
 		9BC70F04176C379D00101DEC /* AtomStringTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomStringTable.cpp; sourceTree = "<group>"; };
 		9BD8F40A176C2AD80002D865 /* AtomStringTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtomStringTable.h; sourceTree = "<group>"; };
 		9C67C542589348E285B49699 /* IndexedContainerIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexedContainerIterator.h; sourceTree = "<group>"; };
@@ -983,6 +984,7 @@
 				413FE8F51F8D2EAB00F6D7D7 /* CallbackAggregator.h */,
 				A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
 				A8A4726B151A825A004123FF /* CheckedBoolean.h */,
+				9BB91F512648EA4D00A56217 /* CheckedPtr.h */,
 				0F66B2801DC97BAB004A1D3F /* ClockType.cpp */,
 				0F66B2811DC97BAB004A1D3F /* ClockType.h */,
 				0FC4EDE51696149600F65041 /* CommaPrinter.h */,

Added: trunk/Source/WTF/wtf/CheckedPtr.h (0 => 278344)


--- trunk/Source/WTF/wtf/CheckedPtr.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/CheckedPtr.h	2021-06-02 08:43:13 UTC (rev 278344)
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2021 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. 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.
+ */
+
+#pragma once
+
+#include <wtf/HashTraits.h>
+#include <wtf/RawPtrTraits.h>
+
+namespace WTF {
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>>
+class CheckedPtr {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+
+    CheckedPtr()
+        : m_ptr(nullptr)
+    { }
+
+    CheckedPtr(std::nullptr_t)
+        : m_ptr(nullptr)
+    { }
+
+    ALWAYS_INLINE CheckedPtr(T* ptr)
+        : m_ptr { ptr }
+    {
+        refIfNotNull();
+    }
+
+    ALWAYS_INLINE CheckedPtr(const CheckedPtr& other)
+        : m_ptr { other.m_ptr }
+    {
+        refIfNotNull();
+    }
+
+    ALWAYS_INLINE CheckedPtr(CheckedPtr&& other)
+        : m_ptr { PtrTraits::exchange(other.m_ptr, nullptr) }
+    { }
+
+    ALWAYS_INLINE ~CheckedPtr()
+    {
+        derefIfNotNull();
+    }
+
+    template<typename OtherType, typename OtherPtrTraits> CheckedPtr(const CheckedPtr<OtherType, OtherPtrTraits>& other)
+        : m_ptr { other.m_ptr }
+    {
+        refIfNotNull();
+    }
+
+    template<typename OtherType, typename OtherPtrTraits> CheckedPtr(CheckedPtr<OtherType, OtherPtrTraits>&& other)
+        : m_ptr { PtrTraits::exchange(other.m_ptr, nullptr) }
+    { }
+
+    CheckedPtr(HashTableDeletedValueType)
+        : m_ptr(PtrTraits::hashTableDeletedValue())
+    { }
+
+    bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    using UnspecifiedBoolType = void (CheckedPtr::*)() const;
+    operator UnspecifiedBoolType() const { return m_ptr ? &CheckedPtr::unspecifiedBoolTypeInstance : nullptr; }
+
+    ALWAYS_INLINE bool operator!() const { return !PtrTraits::unwrap(m_ptr); }
+
+    ALWAYS_INLINE const T* get() const { return PtrTraits::unwrap(m_ptr); }
+    ALWAYS_INLINE T* get() { return PtrTraits::unwrap(m_ptr); }
+    ALWAYS_INLINE const T& operator*() const { ASSERT(this); return *get(); }
+    ALWAYS_INLINE T& operator*() { ASSERT(this); return *get(); }
+    ALWAYS_INLINE const T* operator->() const { return get(); }
+    ALWAYS_INLINE T* operator->() { return get(); }
+
+    bool operator==(const T* other) const { return m_ptr == other; }
+    template<typename U> bool operator==(U* other) const { return m_ptr == other; }
+
+    bool operator==(const CheckedPtr& other) const { return m_ptr == other.m_ptr; }
+
+    template<typename OtherType, typename OtherPtrTraits>
+    bool operator==(const CheckedPtr<OtherType, OtherPtrTraits>& other) const { return m_ptr == other.m_ptr; }
+
+    CheckedPtr& operator=(std::nullptr_t)
+    {
+        derefIfNotNull();
+        m_ptr = nullptr;
+        return *this;
+    }
+
+    CheckedPtr& operator=(T* ptr)
+    {
+        CheckedPtr copy { ptr };
+        PtrTraits::swap(m_ptr, copy.m_ptr);
+        return *this;
+    }
+
+    CheckedPtr& operator=(const CheckedPtr& other)
+    {
+        CheckedPtr copy { other };
+        PtrTraits::swap(m_ptr, copy.m_ptr);
+        return *this;
+    }
+
+    template<typename OtherType, typename OtherPtrTraits> CheckedPtr& operator=(const CheckedPtr<OtherType, OtherPtrTraits>& other)
+    {
+        CheckedPtr copy { other };
+        PtrTraits::swap(m_ptr, copy.m_ptr);
+        return *this;
+    }
+
+    CheckedPtr& operator=(CheckedPtr&& other)
+    {
+        CheckedPtr moved { WTFMove(other) };
+        PtrTraits::swap(m_ptr, moved.m_ptr);
+        return *this;
+    }
+
+    template<typename OtherType, typename OtherPtrTraits> CheckedPtr& operator=(CheckedPtr<OtherType, OtherPtrTraits>&& other)
+    {
+        CheckedPtr moved { WTFMove(other) };
+        PtrTraits::swap(m_ptr, moved.m_ptr);
+        return *this;
+    }
+
+private:
+    template<typename OtherType, typename OtherPtrTraits> friend class CheckedPtr;
+
+    void unspecifiedBoolTypeInstance() const { }
+
+    ALWAYS_INLINE void refIfNotNull()
+    {
+        if (T* ptr = PtrTraits::unwrap(m_ptr); LIKELY(ptr))
+            ptr->incrementPtrCount();
+    }
+
+    ALWAYS_INLINE void derefIfNotNull()
+    {
+        if (T* ptr = PtrTraits::unwrap(m_ptr); LIKELY(ptr))
+            ptr->decrementPtrCount();
+    }
+
+    typename PtrTraits::StorageType m_ptr;
+};
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>> inline CheckedPtr<T, PtrTraits> makeCheckedPtr(T* pointer)
+{
+    return pointer;
+}
+
+template<typename T, typename PtrTraits = RawPtrTraits<T>> inline CheckedPtr<T, PtrTraits> makeCheckedPtr(T& reference)
+{
+    return &reference;
+}
+
+template <typename T, typename PtrTraits>
+struct GetPtrHelper<CheckedPtr<T, PtrTraits>> {
+    typedef T* PtrType;
+    static T* getPtr(const CheckedPtr<T, PtrTraits>& p) { return const_cast<T*>(p.get()); }
+};
+
+template <typename T, typename U>
+struct IsSmartPtr<CheckedPtr<T, U>> {
+    static constexpr bool value = true;
+};
+
+template<typename ExpectedType, typename ArgType, typename ArgPtrTraits>
+inline bool is(CheckedPtr<ArgType, ArgPtrTraits>& source)
+{
+    return is<ExpectedType>(source.get());
+}
+
+template<typename ExpectedType, typename ArgType, typename ArgPtrTraits>
+inline bool is(const CheckedPtr<ArgType, ArgPtrTraits>& source)
+{
+    return is<ExpectedType>(source.get());
+}
+
+class CanMakeCheckedPtr {
+public:
+    ~CanMakeCheckedPtr() { RELEASE_ASSERT(!m_count); }
+
+    uint16_t ptrCount() const { return m_count; }
+    void incrementPtrCount() { ++m_count; }
+    void decrementPtrCount() { ASSERT(m_count); --m_count; }
+private:
+    uint16_t m_count { 0 };
+};
+
+template<typename P> struct HashTraits<CheckedPtr<P>> : SimpleClassHashTraits<CheckedPtr<P>> {
+    static P* emptyValue() { return nullptr; }
+
+    typedef P* PeekType;
+    static PeekType peek(const CheckedPtr<P>& value) { return value.get(); }
+    static PeekType peek(P* value) { return value; }
+
+    static void customDeleteBucket(CheckedPtr<P>& value)
+    {
+        // See unique_ptr's customDeleteBucket() for an explanation.
+        ASSERT(!SimpleClassHashTraits<CheckedPtr<P>>::isDeletedValue(value));
+        auto valueToBeDestroyed = WTFMove(value);
+        SimpleClassHashTraits<CheckedPtr<P>>::constructDeletedValue(value);
+    }
+};
+
+template<typename P> struct DefaultHash<CheckedPtr<P>> : PtrHash<CheckedPtr<P>> { };
+
+} // namespace WTF
+
+using WTF::CheckedPtr;
+using WTF::CanMakeCheckedPtr;
+using WTF::makeCheckedPtr;
+

Modified: trunk/Tools/ChangeLog (278343 => 278344)


--- trunk/Tools/ChangeLog	2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Tools/ChangeLog	2021-06-02 08:43:13 UTC (rev 278344)
@@ -1,3 +1,20 @@
+2021-05-23  Ryosuke Niwa  <rn...@webkit.org>
+
+        Add CheckedPtr
+        https://bugs.webkit.org/show_bug.cgi?id=226158
+
+        Reviewed by Antti Koivisto.
+
+        Added basic tests.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/CheckedPtr.cpp: Added.
+        (TestWebKitAPI::CheckedObject): Added.
+        (TestWebKitAPI::DerivedCheckedObject): Added.
+        (WTF_CheckedPtr.Basic):
+        (WTF_CheckedPtr.DerivedClass):
+        (WTF_CheckedPtr.HashSet):
+
 2021-06-01  Darin Adler  <da...@apple.com>
 
         Remove <wtf/Optional.h>

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (278343 => 278344)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-06-02 08:28:32 UTC (rev 278343)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-06-02 08:43:13 UTC (rev 278344)
@@ -903,6 +903,7 @@
 		9B9332CE2320C745002D50E8 /* cocoa-writer-markup-with-lists.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B9332CD2320C73E002D50E8 /* cocoa-writer-markup-with-lists.html */; };
 		9BAD7F3E22690F2000F8DA66 /* DeallocWebViewInEventListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BAD7F3D22690F1400F8DA66 /* DeallocWebViewInEventListener.mm */; };
 		9BAE177B22E2BBFB00DF3098 /* cocoa-writer-markup-with-system-fonts.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BAE177A22E2BB6B00DF3098 /* cocoa-writer-markup-with-system-fonts.html */; };
+		9BBCA4DF265ACA5B00DFE723 /* CheckedPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */; };
 		9BCB7C2820130600003E7C0C /* PasteHTML.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BCB7C2620130600003E7C0C /* PasteHTML.mm */; };
 		9BCD411A206DBCA3001D71BE /* mso-list-on-h4.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BCD4119206D5ED7001D71BE /* mso-list-on-h4.html */; };
 		9BD4239A1E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */; };
@@ -2616,6 +2617,7 @@
 		9B9332CD2320C73E002D50E8 /* cocoa-writer-markup-with-lists.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "cocoa-writer-markup-with-lists.html"; sourceTree = "<group>"; };
 		9BAD7F3D22690F1400F8DA66 /* DeallocWebViewInEventListener.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeallocWebViewInEventListener.mm; sourceTree = "<group>"; };
 		9BAE177A22E2BB6B00DF3098 /* cocoa-writer-markup-with-system-fonts.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "cocoa-writer-markup-with-system-fonts.html"; sourceTree = "<group>"; };
+		9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CheckedPtr.cpp; sourceTree = "<group>"; };
 		9BCB7C2620130600003E7C0C /* PasteHTML.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteHTML.mm; sourceTree = "<group>"; };
 		9BCD4119206D5ED7001D71BE /* mso-list-on-h4.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "mso-list-on-h4.html"; sourceTree = "<group>"; };
 		9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AttributedSubstringForProposedRangeWithImage.mm; sourceTree = "<group>"; };
@@ -4415,6 +4417,7 @@
 				93A427AE180DA60F00CD24D7 /* BoxPtr.cpp */,
 				0451A5A6235E438E009DF945 /* BumpPointerAllocator.cpp */,
 				A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
+				9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */,
 				E302BDA92404B92300865277 /* CompactRefPtrTuple.cpp */,
 				9B0C051824FDFB7000F2FE31 /* CompactUniquePtrTuple.cpp */,
 				0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */,
@@ -5177,6 +5180,7 @@
 				7C83DF181D0A590C00FEBCF3 /* BoxPtr.cpp in Sources */,
 				04DB2396235E43EC00328F17 /* BumpPointerAllocator.cpp in Sources */,
 				7C83DEA01D0A590C00FEBCF3 /* CheckedArithmeticOperations.cpp in Sources */,
+				9BBCA4DF265ACA5B00DFE723 /* CheckedPtr.cpp in Sources */,
 				E302BDAA2404B92400865277 /* CompactRefPtrTuple.cpp in Sources */,
 				9B0C051924FDFB7D00F2FE31 /* CompactUniquePtrTuple.cpp in Sources */,
 				0F30CB5C1FCE1796004B5323 /* ConcurrentPtrHashSet.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp (0 => 278344)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedPtr.cpp	2021-06-02 08:43:13 UTC (rev 278344)
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2021 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. 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 "Utilities.h"
+#include <wtf/CheckedPtr.h>
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace TestWebKitAPI {
+
+class CheckedObject : public CanMakeCheckedPtr {
+public:
+    int someFunction() const { return -7; }
+};
+
+class DerivedCheckedObject : public CheckedObject {
+};
+
+TEST(WTF_CheckedPtr, Basic)
+{
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+        {
+            auto ptr = makeCheckedPtr(checkedObject);
+            EXPECT_TRUE(!!ptr);
+            EXPECT_EQ(ptr.get(), &checkedObject);
+            EXPECT_EQ(ptr->someFunction(), -7);
+            EXPECT_EQ(checkedObject.ptrCount(), 1);
+        }
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+        auto ptr = makeCheckedPtr(checkedObject);
+        EXPECT_TRUE(!!ptr);
+        EXPECT_EQ(ptr.get(), &checkedObject);
+        EXPECT_EQ(ptr->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+        ptr = nullptr;
+
+        EXPECT_FALSE(!!ptr);
+        EXPECT_EQ(ptr.get(), nullptr);
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+        auto ptr1 = makeCheckedPtr(checkedObject);
+        EXPECT_TRUE(!!ptr1);
+        EXPECT_EQ(ptr1.get(), &checkedObject);
+        EXPECT_EQ(ptr1->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+        const CheckedPtr<CheckedObject> ptr2 = makeCheckedPtr(&checkedObject);
+        EXPECT_TRUE(!!ptr2);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr2->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+        CheckedPtr<CheckedObject> ptr3 = ptr2;
+        EXPECT_TRUE(!!ptr3);
+        EXPECT_EQ(ptr3.get(), &checkedObject);
+        EXPECT_EQ(checkedObject.ptrCount(), 3);
+
+        ptr1 = nullptr;
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+        EXPECT_EQ(ptr1.get(), nullptr);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr3.get(), &checkedObject);
+
+        ptr1 = WTFMove(ptr3);
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+        EXPECT_EQ(ptr1.get(), &checkedObject);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr3.get(), nullptr);
+    }
+}
+
+TEST(WTF_CheckedPtr, DerivedClass)
+{
+    {
+        DerivedCheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        DerivedCheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+        {
+            auto ptr = makeCheckedPtr(checkedObject);
+            EXPECT_TRUE(!!ptr);
+            EXPECT_EQ(ptr.get(), &checkedObject);
+            EXPECT_EQ(ptr->someFunction(), -7);
+            EXPECT_EQ(checkedObject.ptrCount(), 1);
+        }
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+        CheckedPtr<CheckedObject> ptr = makeCheckedPtr(checkedObject);
+        EXPECT_TRUE(!!ptr);
+        EXPECT_EQ(ptr.get(), &checkedObject);
+        EXPECT_EQ(ptr->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+        ptr = nullptr;
+
+        EXPECT_FALSE(!!ptr);
+        EXPECT_EQ(ptr.get(), nullptr);
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+    }
+
+    {
+        DerivedCheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+        CheckedPtr<DerivedCheckedObject> ptr1 = makeCheckedPtr(checkedObject);
+        EXPECT_TRUE(!!ptr1);
+        EXPECT_EQ(ptr1.get(), &checkedObject);
+        EXPECT_EQ(ptr1->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+        const CheckedPtr<CheckedObject> ptr2 = ptr1;
+        EXPECT_TRUE(!!ptr2);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr2->someFunction(), -7);
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+        CheckedPtr<CheckedObject> ptr3 = ptr1;
+        EXPECT_TRUE(!!ptr3);
+        EXPECT_EQ(ptr3.get(), &checkedObject);
+        EXPECT_EQ(checkedObject.ptrCount(), 3);
+
+        ptr1 = nullptr;
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+        EXPECT_EQ(ptr1.get(), nullptr);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr3.get(), &checkedObject);
+
+        CheckedPtr<CheckedObject> ptr4 = WTFMove(ptr3);
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+        EXPECT_EQ(ptr1.get(), nullptr);
+        EXPECT_EQ(ptr2.get(), &checkedObject);
+        EXPECT_EQ(ptr3.get(), nullptr);
+        EXPECT_EQ(ptr4.get(), &checkedObject);
+    }
+}
+
+TEST(WTF_CheckedPtr, HashSet)
+{
+    {
+        CheckedObject checkedObject;
+        EXPECT_EQ(checkedObject.ptrCount(), 0);
+
+        auto ptr = makeCheckedPtr(checkedObject);
+        EXPECT_EQ(ptr.get(), &checkedObject);
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+
+        HashSet<CheckedPtr<CheckedObject>> set;
+        set.add(ptr);
+        EXPECT_EQ(checkedObject.ptrCount(), 2);
+
+        ptr = nullptr;
+        EXPECT_EQ(checkedObject.ptrCount(), 1);
+    }
+
+    {
+        CheckedObject object1;
+        DerivedCheckedObject object2;
+        EXPECT_EQ(object1.ptrCount(), 0);
+        EXPECT_EQ(object2.ptrCount(), 0);
+
+        HashSet<CheckedPtr<CheckedObject>> set;
+        set.add(&object1);
+        EXPECT_EQ(object1.ptrCount(), 1);
+        EXPECT_EQ(object2.ptrCount(), 0);
+
+        set.add(&object1);
+        EXPECT_EQ(object1.ptrCount(), 1);
+        EXPECT_EQ(object2.ptrCount(), 0);
+
+        CheckedPtr<DerivedCheckedObject> ptr { &object2 };
+        set.add(ptr);
+        EXPECT_EQ(object1.ptrCount(), 1);
+        EXPECT_EQ(object2.ptrCount(), 2);
+        ptr = nullptr;
+
+        EXPECT_EQ(object1.ptrCount(), 1);
+        EXPECT_EQ(object2.ptrCount(), 1);
+
+        set.remove(&object1);
+        EXPECT_EQ(object1.ptrCount(), 0);
+        EXPECT_EQ(object2.ptrCount(), 1);
+    }
+
+    {
+        Vector<std::unique_ptr<CheckedObject>> objects;
+        objects.append(makeUniqueWithoutFastMallocCheck<CheckedObject>());
+        EXPECT_EQ(objects[0]->ptrCount(), 0);
+
+        HashSet<CheckedPtr<CheckedObject>> set;
+        set.add(objects[0].get());
+        auto initialCapacity = set.capacity();
+
+        for (unsigned i = 0; set.capacity() == initialCapacity; ++i) {
+            if (i % 2)
+                objects.append(makeUniqueWithoutFastMallocCheck<DerivedCheckedObject>());
+            else
+                objects.append(makeUniqueWithoutFastMallocCheck<CheckedObject>());
+            set.add(objects.last().get());
+        }
+
+        for (auto& object : objects)
+            EXPECT_EQ(object->ptrCount(), 1);
+
+        auto setVector = WTF::copyToVector(set);
+
+        for (auto& object : objects)
+            EXPECT_EQ(object->ptrCount(), 2);
+    }
+}
+
+} // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to