Changeset 226015 in webkit


Ignore:
Timestamp:
Dec 17, 2017, 3:22:18 PM (7 years ago)
Author:
mark.lam@apple.com
Message:

Enhance Ref and RefPtr to be able to work with smart pointers.
https://bugs.webkit.org/show_bug.cgi?id=180762
<rdar://problem/36027122>

Reviewed by JF Bastien and Darin Adler.

Source/WTF:

This is so we can use them with ConstExprPoisoned pointers to make PoisonedRef
and PoisonedRefPtr.

  • WTF.xcodeproj/project.pbxproj:
  • wtf/CMakeLists.txt:
  • wtf/DumbPtrTraits.h: Added.

(WTF::DumbPtrTraits::exchange):
(WTF::DumbPtrTraits::swap):
(WTF::DumbPtrTraits::unwrap):

  • wtf/Forward.h:
  • wtf/Poisoned.h:

(WTF::ConstExprPoisonedPtrTraits::exchange):
(WTF::ConstExprPoisonedPtrTraits::swap):
(WTF::ConstExprPoisonedPtrTraits::unwrap):

  • wtf/Ref.h:

(WTF::Ref::~Ref):
(WTF::Ref::Ref):
(WTF::Ref::ptrAllowingHashTableEmptyValue const):
(WTF::Ref::ptrAllowingHashTableEmptyValue):
(WTF::Ref::operator-> const):
(WTF::Ref::get const):
(WTF::Ref::operator T& const):
(WTF::=):
(WTF::U>::swap):
(WTF::swap):
(WTF::U>::replace):
(WTF::static_reference_cast):
(WTF::adoptRef):
(WTF::is):
(WTF::Ref<T>::swap): Deleted.
(WTF::Ref<T>::replace): Deleted.
(WTF::GetPtrHelper<Ref<T>>::getPtr): Deleted.

  • wtf/RefPtr.cpp: Added.
  • wtf/RefPtr.h:

(WTF::RefPtr::RefPtr):
(WTF::RefPtr::~RefPtr):
(WTF::RefPtr::get const):
(WTF::RefPtr::operator* const):
(WTF::RefPtr::operator-> const):
(WTF::U>::RefPtr):
(WTF::U>::leakRef):
(WTF::=):
(WTF::U>::swap):
(WTF::swap):
(WTF::operator==):
(WTF::operator!=):
(WTF::static_pointer_cast):
(WTF::adoptRef):
(WTF::is):
(WTF::RefPtr<T>::RefPtr): Deleted.
(WTF::RefPtr<T>::leakRef): Deleted.
(WTF::RefPtr<T>::swap): Deleted.

Tools:

  • TestWebKitAPI/CMakeLists.txt:
  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp:

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WTF/Poisoned.cpp:

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WTF/PoisonedRef.cpp: Added.

(TestWebKitAPI::TEST):
(TestWebKitAPI::passWithRef):
(TestWebKitAPI::PoisonedRefCheckingRefLogger::PoisonedRefCheckingRefLogger):
(TestWebKitAPI::PoisonedRefCheckingRefLogger::ref):
(TestWebKitAPI::PoisonedRefCheckingRefLogger::deref):
(TestWebKitAPI::DerivedPoisonedRefCheckingRefLogger::DerivedPoisonedRefCheckingRefLogger):

  • TestWebKitAPI/Tests/WTF/PoisonedRefPtr.cpp: Added.

(TestWebKitAPI::TEST):
(TestWebKitAPI::f1):
(TestWebKitAPI::ConstRefCounted::create):
(TestWebKitAPI::returnConstRefCountedRef):
(TestWebKitAPI::returnRefCountedRef):
(TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::PoisonedRefPtrCheckingRefLogger):
(TestWebKitAPI::loggerName):
(TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::ref):
(TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::deref):

Location:
trunk
Files:
4 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r225998 r226015  
     12017-12-17  Mark Lam  <mark.lam@apple.com>
     2
     3        Enhance Ref and RefPtr to be able to work with smart pointers.
     4        https://bugs.webkit.org/show_bug.cgi?id=180762
     5        <rdar://problem/36027122>
     6
     7        Reviewed by JF Bastien and Darin Adler.
     8
     9        This is so we can use them with ConstExprPoisoned pointers to make PoisonedRef
     10        and PoisonedRefPtr.
     11
     12        * WTF.xcodeproj/project.pbxproj:
     13        * wtf/CMakeLists.txt:
     14        * wtf/DumbPtrTraits.h: Added.
     15        (WTF::DumbPtrTraits::exchange):
     16        (WTF::DumbPtrTraits::swap):
     17        (WTF::DumbPtrTraits::unwrap):
     18        * wtf/Forward.h:
     19        * wtf/Poisoned.h:
     20        (WTF::ConstExprPoisonedPtrTraits::exchange):
     21        (WTF::ConstExprPoisonedPtrTraits::swap):
     22        (WTF::ConstExprPoisonedPtrTraits::unwrap):
     23        * wtf/Ref.h:
     24        (WTF::Ref::~Ref):
     25        (WTF::Ref::Ref):
     26        (WTF::Ref::ptrAllowingHashTableEmptyValue const):
     27        (WTF::Ref::ptrAllowingHashTableEmptyValue):
     28        (WTF::Ref::operator-> const):
     29        (WTF::Ref::get const):
     30        (WTF::Ref::operator T& const):
     31        (WTF::=):
     32        (WTF::U>::swap):
     33        (WTF::swap):
     34        (WTF::U>::replace):
     35        (WTF::static_reference_cast):
     36        (WTF::adoptRef):
     37        (WTF::is):
     38        (WTF::Ref<T>::swap): Deleted.
     39        (WTF::Ref<T>::replace): Deleted.
     40        (WTF::GetPtrHelper<Ref<T>>::getPtr): Deleted.
     41        * wtf/RefPtr.cpp: Added.
     42        * wtf/RefPtr.h:
     43        (WTF::RefPtr::RefPtr):
     44        (WTF::RefPtr::~RefPtr):
     45        (WTF::RefPtr::get const):
     46        (WTF::RefPtr::operator* const):
     47        (WTF::RefPtr::operator-> const):
     48        (WTF::U>::RefPtr):
     49        (WTF::U>::leakRef):
     50        (WTF::=):
     51        (WTF::U>::swap):
     52        (WTF::swap):
     53        (WTF::operator==):
     54        (WTF::operator!=):
     55        (WTF::static_pointer_cast):
     56        (WTF::adoptRef):
     57        (WTF::is):
     58        (WTF::RefPtr<T>::RefPtr): Deleted.
     59        (WTF::RefPtr<T>::leakRef): Deleted.
     60        (WTF::RefPtr<T>::swap): Deleted.
     61
    1622017-12-16  Yusuke Suzuki  <utatane.tea@gmail.com>
    263
  • trunk/Source/WTF/WTF.xcodeproj/project.pbxproj

    r225832 r226015  
    151151                E4A0AD391A96245500536DF6 /* WorkQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A0AD371A96245500536DF6 /* WorkQueue.cpp */; };
    152152                E4A0AD3D1A96253C00536DF6 /* WorkQueueCocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A0AD3C1A96253C00536DF6 /* WorkQueueCocoa.cpp */; };
     153                FE05FAFF1FE5007500093230 /* RefPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAFE1FE5007500093230 /* RefPtr.cpp */; };
    153154                FE85416E1FBE285D008DA5DA /* Poisoned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE85416C1FBE285B008DA5DA /* Poisoned.cpp */; };
    154155                FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDACD3B1630F83F00C69634 /* StackStats.cpp */; };
     
    617618                EF7D6CD59D8642A8A0DA86AD /* StackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackTrace.h; sourceTree = "<group>"; };
    618619                F72BBDB107FA424886178B9E /* SymbolImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolImpl.cpp; sourceTree = "<group>"; };
     620                FE05FAE61FDB214300093230 /* DumbPtrTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DumbPtrTraits.h; sourceTree = "<group>"; };
     621                FE05FAFE1FE5007500093230 /* RefPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefPtr.cpp; sourceTree = "<group>"; };
    619622                FE8225301B2A1E5B00BA68FD /* NakedPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NakedPtr.h; sourceTree = "<group>"; };
    620623                FE85416C1FBE285B008DA5DA /* Poisoned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Poisoned.cpp; sourceTree = "<group>"; };
     
    849852                                0F4570421BE5B58F0062A629 /* Dominators.h */,
    850853                                A8A47280151A825A004123FF /* DoublyLinkedList.h */,
     854                                FE05FAE61FDB214300093230 /* DumbPtrTraits.h */,
    851855                                A8A47297151A825A004123FF /* dtoa.cpp */,
    852856                                A8A47298151A825A004123FF /* dtoa.h */,
     
    10051009                                A8A47302151A825B004123FF /* RefCountedLeakCounter.h */,
    10061010                                86F46F5F1A2840EE00CCBF22 /* RefCounter.h */,
     1011                                FE05FAFE1FE5007500093230 /* RefPtr.cpp */,
    10071012                                A8A47303151A825B004123FF /* RefPtr.h */,
    10081013                                A8A47305151A825B004123FF /* RetainPtr.h */,
     
    14121417                                A8A47460151A825B004123FF /* CollatorDefault.cpp in Sources */,
    14131418                                A8A47463151A825B004123FF /* CollatorICU.cpp in Sources */,
     1419                                FE05FAFF1FE5007500093230 /* RefPtr.cpp in Sources */,
    14141420                                0F8F2B92172E0103007DBDA5 /* CompilationThread.cpp in Sources */,
    14151421                                E38C41281EB4E0680042957D /* CPUTime.cpp in Sources */,
  • trunk/Source/WTF/wtf/CMakeLists.txt

    r225832 r226015  
    3838    DisallowCType.h
    3939    DoublyLinkedList.h
     40    DumbPtrTraits.h
    4041    FastMalloc.h
    4142    FastTLS.h
     
    269270    ReadWriteLock.cpp
    270271    RefCountedLeakCounter.cpp
     272    RefPtr.cpp
    271273    RunLoop.cpp
    272274    SHA1.cpp
  • trunk/Source/WTF/wtf/Forward.h

    r225824 r226015  
    4949
    5050template<typename> class CompletionHandler;
     51template<typename T> struct DumbPtrTraits;
    5152template<typename> class Function;
    5253template<typename> class LazyNeverDestroyed;
    5354template<typename> class NeverDestroyed;
    5455template<typename> class OptionSet;
    55 template<typename> class Ref;
    56 template<typename> class RefPtr;
     56template<typename T, typename = DumbPtrTraits<T>> class Ref;
     57template<typename T, typename = DumbPtrTraits<T>> class RefPtr;
    5758template<typename> class StringBuffer;
    5859template<typename, typename = void> class StringTypeAdapter;
  • trunk/Source/WTF/wtf/Poisoned.h

    r225857 r226015  
    229229using ConstExprPoisoned = PoisonedImpl<uintptr_t, makePoison(key), T>;
    230230
     231template<uint32_t key, typename T>
     232struct ConstExprPoisonedPtrTraits {
     233    using StorageType = ConstExprPoisoned<key, T*>;
     234
     235    template<class U> static ALWAYS_INLINE T* exchange(StorageType& ptr, U&& newValue) { return ptr.exchange(newValue); }
     236
     237    template<typename K1, K1 k1, typename T1, typename K2, K2 k2, typename T2>
     238    static ALWAYS_INLINE void swap(PoisonedImpl<K1, k1, T1>& a, PoisonedImpl<K2, k2, T2>& b) { a.swap(b); }
     239
     240    static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr.unpoisoned(); }
     241};
     242
    231243} // namespace WTF
    232244
  • trunk/Source/WTF/wtf/Ref.h

    r218594 r226015  
    11/*
    2  * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include <wtf/Assertions.h>
     30#include <wtf/DumbPtrTraits.h>
     31#include <wtf/Forward.h>
    3032#include <wtf/GetPtr.h>
    3133#include <wtf/StdLibExtras.h>
     
    4244inline void adopted(const void*) { }
    4345
    44 template<typename T> class Ref;
    45 template<typename T> Ref<T> adoptRef(T&);
    46 
    47 template<typename T> class Ref {
     46template<typename T, typename PtrTraits> class Ref;
     47template<typename T, typename PtrTraits = DumbPtrTraits<T>> Ref<T, PtrTraits> adoptRef(T&);
     48
     49template<typename T, typename PtrTraits>
     50class Ref {
    4851public:
    4952    static constexpr bool isRef = true;
     
    5659#endif
    5760        if (m_ptr)
    58             m_ptr->deref();
     61            PtrTraits::unwrap(m_ptr)->deref();
    5962    }
    6063
     
    6265        : m_ptr(&object)
    6366    {
    64         m_ptr->ref();
     67        object.ref();
    6568    }
    6669
    6770    // Use copyRef() instead.
    6871    Ref(const Ref& other) = delete;
    69     template<typename U> Ref(const Ref<U>& other) = delete;
     72    template<typename X, typename Y> Ref(const Ref<X, Y>& other) = delete;
    7073
    7174    Ref(Ref&& other)
     
    7578    }
    7679
    77     template<typename U>
    78     Ref(Ref<U>&& other)
     80    template<typename X, typename Y>
     81    Ref(Ref<X, Y>&& other)
    7982        : m_ptr(&other.leakRef())
    8083    {
     
    8487    Ref& operator=(T&);
    8588    Ref& operator=(Ref&&);
    86     template<typename U> Ref& operator=(Ref<U>&&);
     89    template<typename X, typename Y> Ref& operator=(Ref<X, Y>&&);
    8790
    8891    // Use copyRef() and the move assignment operators instead.
    8992    Ref& operator=(const Ref&) = delete;
    90     template<typename U> Ref& operator=(const Ref<U>&) = delete;
    91 
    92     void swap(Ref&);
     93    template<typename X, typename Y> Ref& operator=(const Ref<X, Y>&) = delete;
     94
     95    template<typename X, typename Y> void swap(Ref<X, Y>&);
    9396
    9497    // Hash table deleted values, which are only constructed and never copied or destroyed.
     
    101104    static T* hashTableEmptyValue() { return nullptr; }
    102105
    103     const T* ptrAllowingHashTableEmptyValue() const { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr; }
    104     T* ptrAllowingHashTableEmptyValue() { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr; }
     106    const T* ptrAllowingHashTableEmptyValue() const { ASSERT(m_ptr || isHashTableEmptyValue()); return PtrTraits::unwrap(m_ptr); }
     107    T* ptrAllowingHashTableEmptyValue() { ASSERT(m_ptr || isHashTableEmptyValue()); return PtrTraits::unwrap(m_ptr); }
    105108
    106109    void assignToHashTableEmptyValue(Ref&& reference)
     
    111114    }
    112115
    113     T* operator->() const { ASSERT(m_ptr); return m_ptr; }
    114     T* ptr() const RETURNS_NONNULL { ASSERT(m_ptr); return m_ptr; }
    115     T& get() const { ASSERT(m_ptr); return *m_ptr; }
    116     operator T&() const { ASSERT(m_ptr); return *m_ptr; }
     116    T* operator->() const { ASSERT(m_ptr); return PtrTraits::unwrap(m_ptr); }
     117    T* ptr() const RETURNS_NONNULL { ASSERT(m_ptr); return PtrTraits::unwrap(m_ptr); }
     118    T& get() const { ASSERT(m_ptr); return *PtrTraits::unwrap(m_ptr); }
     119    operator T&() const { ASSERT(m_ptr); return *PtrTraits::unwrap(m_ptr); }
    117120    bool operator!() const { ASSERT(m_ptr); return !*m_ptr; }
    118121
    119     template<typename U> Ref<T> replace(Ref<U>&&) WARN_UNUSED_RETURN;
     122    template<typename X, typename Y> Ref<T, PtrTraits> replace(Ref<X, Y>&&) WARN_UNUSED_RETURN;
    120123
    121124#if COMPILER_SUPPORTS(CXX_REFERENCE_QUALIFIED_FUNCTIONS)
     
    130133        ASSERT(m_ptr);
    131134
    132         T& result = *std::exchange(m_ptr, nullptr);
     135        T& result = *PtrTraits::exchange(m_ptr, nullptr);
    133136#if ASAN_ENABLED
    134137        __asan_poison_memory_region(this, sizeof(*this));
     
    139142private:
    140143    friend Ref adoptRef<T>(T&);
     144    template<typename X, typename Y> friend class Ref;
    141145
    142146    enum AdoptTag { Adopt };
     
    146150    }
    147151
    148     T* m_ptr;
     152    typename PtrTraits::StorageType m_ptr;
    149153};
    150154
    151 template<typename T> void swap(Ref<T>&, Ref<T>&);
    152 template<typename T> Ref<T> adoptRef(T&);
     155template<typename T, typename U> Ref<T, U> adoptRef(T&);
    153156template<typename T> Ref<T> makeRef(T&);
    154157
    155 template<typename T> inline Ref<T>& Ref<T>::operator=(T& reference)
     158template<typename T, typename U>
     159inline Ref<T, U>& Ref<T, U>::operator=(T& reference)
    156160{
    157161    Ref copiedReference = reference;
     
    160164}
    161165
    162 template<typename T> inline Ref<T>& Ref<T>::operator=(Ref&& reference)
     166template<typename T, typename U>
     167inline Ref<T, U>& Ref<T, U>::operator=(Ref&& reference)
    163168{
    164169    Ref movedReference = WTFMove(reference);
     
    167172}
    168173
    169 template<typename T> template<typename U> inline Ref<T>& Ref<T>::operator=(Ref<U>&& reference)
     174template<typename T, typename U>
     175template<typename X, typename Y>
     176inline Ref<T, U>& Ref<T, U>::operator=(Ref<X, Y>&& reference)
    170177{
    171178    Ref movedReference = WTFMove(reference);
     
    174181}
    175182
    176 template<typename T> inline void Ref<T>::swap(Ref& other)
    177 {
    178     std::swap(m_ptr, other.m_ptr);
    179 }
    180 
    181 template<typename T> inline void swap(Ref<T>& a, Ref<T>& b)
     183template<typename T, typename U>
     184template<typename X, typename Y>
     185inline void Ref<T, U>::swap(Ref<X, Y>& other)
     186{
     187    U::swap(m_ptr, other.m_ptr);
     188}
     189
     190template<typename T, typename U, typename X, typename Y, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>>
     191inline void swap(Ref<T, U>& a, Ref<X, Y>& b)
    182192{
    183193    a.swap(b);
    184194}
    185195
    186 template<typename T> template<typename U> inline Ref<T> Ref<T>::replace(Ref<U>&& reference)
     196template<typename T, typename U>
     197template<typename X, typename Y>
     198inline Ref<T, U> Ref<T, U>::replace(Ref<X, Y>&& reference)
    187199{
    188200    auto oldReference = adoptRef(*m_ptr);
     
    191203}
    192204
    193 template<typename T, typename U> inline Ref<T> static_reference_cast(Ref<U>& reference)
    194 {
    195     return Ref<T>(static_cast<T&>(reference.get()));
    196 }
    197 
    198 template<typename T, typename U> inline Ref<T> static_reference_cast(Ref<U>&& reference)
     205template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>
     206inline Ref<T, U> static_reference_cast(Ref<X, Y>& reference)
     207{
     208    return Ref<T, U>(static_cast<T&>(reference.get()));
     209}
     210
     211template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>
     212inline Ref<T, U> static_reference_cast(Ref<X, Y>&& reference)
    199213{
    200214    return adoptRef(static_cast<T&>(reference.leakRef()));
    201215}
    202216
    203 template<typename T, typename U> inline Ref<T> static_reference_cast(const Ref<U>& reference)
    204 {
    205     return Ref<T>(static_cast<T&>(reference.copyRef().get()));
    206 }
    207 
    208 template <typename T>
    209 struct GetPtrHelper<Ref<T>> {
     217template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>
     218inline Ref<T, U> static_reference_cast(const Ref<X, Y>& reference)
     219{
     220    return Ref<T, U>(static_cast<T&>(reference.copyRef().get()));
     221}
     222
     223template <typename T, typename U>
     224struct GetPtrHelper<Ref<T, U>> {
    210225    typedef T* PtrType;
    211     static T* getPtr(const Ref<T>& p) { return const_cast<T*>(p.ptr()); }
     226    static T* getPtr(const Ref<T, U>& p) { return const_cast<T*>(p.ptr()); }
    212227};
    213228
    214 template <typename T>
    215 struct IsSmartPtr<Ref<T>> {
     229template <typename T, typename U>
     230struct IsSmartPtr<Ref<T, U>> {
    216231    static const bool value = true;
    217232};
    218233
    219 template<typename T>
    220 inline Ref<T> adoptRef(T& reference)
     234template<typename T, typename U>
     235inline Ref<T, U> adoptRef(T& reference)
    221236{
    222237    adopted(&reference);
    223     return Ref<T>(reference, Ref<T>::Adopt);
     238    return Ref<T, U>(reference, Ref<T, U>::Adopt);
    224239}
    225240
     
    230245}
    231246
    232 template<typename ExpectedType, typename ArgType> inline bool is(Ref<ArgType>& source)
     247template<typename ExpectedType, typename ArgType, typename PtrTraits>
     248inline bool is(Ref<ArgType, PtrTraits>& source)
    233249{
    234250    return is<ExpectedType>(source.get());
    235251}
    236252
    237 template<typename ExpectedType, typename ArgType> inline bool is(const Ref<ArgType>& source)
     253template<typename ExpectedType, typename ArgType, typename PtrTraits>
     254inline bool is(const Ref<ArgType, PtrTraits>& source)
    238255{
    239256    return is<ExpectedType>(source.get());
    240257}
    241258
     259template<uint32_t key, typename T> struct ConstExprPoisonedPtrTraits;
     260
     261template<uint32_t key, typename T>
     262using PoisonedRef = Ref<T, ConstExprPoisonedPtrTraits<key, T>>;
     263
    242264} // namespace WTF
    243265
     266using WTF::PoisonedRef;
    244267using WTF::Ref;
    245268using WTF::adoptRef;
  • trunk/Source/WTF/wtf/RefPtr.h

    r224320 r226015  
    3131namespace WTF {
    3232
    33 template<typename T> class RefPtr;
    34 template<typename T> RefPtr<T> adoptRef(T*);
     33template<typename T, typename PtrTraits> class RefPtr;
     34template<typename T, typename PtrTraits = DumbPtrTraits<T>> RefPtr<T, PtrTraits> adoptRef(T*);
    3535
    3636template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
     
    4646}
    4747
    48 template<typename T> class RefPtr {
     48template<typename T, typename PtrTraits>
     49class RefPtr {
    4950    WTF_MAKE_FAST_ALLOCATED;
    5051public:
     
    5657    ALWAYS_INLINE constexpr RefPtr() : m_ptr(nullptr) { }
    5758    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
    58     ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
    59     template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
     59    ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(PtrTraits::unwrap(m_ptr)); }
     60    template<typename X, typename Y> RefPtr(const RefPtr<X, Y>& o) : m_ptr(o.get()) { refIfNotNull(PtrTraits::unwrap(m_ptr)); }
    6061
    6162    ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.leakRef()) { }
    62     template<typename U> RefPtr(RefPtr<U>&& o) : m_ptr(o.leakRef()) { }
    63     template<typename U> RefPtr(Ref<U>&&);
     63    template<typename X, typename Y> RefPtr(RefPtr<X, Y>&& o) : m_ptr(o.leakRef()) { }
     64    template<typename X, typename Y> RefPtr(Ref<X, Y>&&);
    6465
    6566    // Hash table deleted values, which are only constructed and never copied or destroyed.
     
    6768    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
    6869
    69     ALWAYS_INLINE ~RefPtr() { derefIfNotNull(std::exchange(m_ptr, nullptr)); }
    70 
    71     T* get() const { return m_ptr; }
     70    ALWAYS_INLINE ~RefPtr() { derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
     71
     72    T* get() const { return PtrTraits::unwrap(m_ptr); }
    7273
    7374    Ref<T> releaseNonNull() { ASSERT(m_ptr); Ref<T> tmp(adoptRef(*m_ptr)); m_ptr = nullptr; return tmp; }
     
    7677    T* leakRef() WARN_UNUSED_RETURN;
    7778
    78     T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
    79     ALWAYS_INLINE T* operator->() const { return m_ptr; }
     79    T& operator*() const { ASSERT(m_ptr); return *PtrTraits::unwrap(m_ptr); }
     80    ALWAYS_INLINE T* operator->() const { return PtrTraits::unwrap(m_ptr); }
    8081
    8182    bool operator!() const { return !m_ptr; }
     
    9091    RefPtr& operator=(T*);
    9192    RefPtr& operator=(std::nullptr_t);
    92     template<typename U> RefPtr& operator=(const RefPtr<U>&);
     93    template<typename X, typename Y> RefPtr& operator=(const RefPtr<X, Y>&);
    9394    RefPtr& operator=(RefPtr&&);
    94     template<typename U> RefPtr& operator=(RefPtr<U>&&);
    95     template<typename U> RefPtr& operator=(Ref<U>&&);
    96 
    97     void swap(RefPtr&);
     95    template<typename X, typename Y> RefPtr& operator=(RefPtr<X, Y>&&);
     96    template<typename X> RefPtr& operator=(Ref<X>&&);
     97
     98    template<typename X, typename Y> void swap(RefPtr<X, Y>&);
    9899
    99100    static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
     
    107108
    108109private:
    109     friend RefPtr adoptRef<T>(T*);
     110    friend RefPtr adoptRef<T, PtrTraits>(T*);
     111    template<typename X, typename Y> friend class RefPtr;
    110112
    111113    enum AdoptTag { Adopt };
    112114    RefPtr(T* ptr, AdoptTag) : m_ptr(ptr) { }
    113115
    114     T* m_ptr;
     116    typename PtrTraits::StorageType m_ptr;
    115117};
    116118
    117 template<typename T> template<typename U> inline RefPtr<T>::RefPtr(Ref<U>&& reference)
     119template<typename T, typename U>
     120template<typename X, typename Y>
     121inline RefPtr<T, U>::RefPtr(Ref<X, Y>&& reference)
    118122    : m_ptr(&reference.leakRef())
    119123{
    120124}
    121125
    122 template<typename T>
    123 inline T* RefPtr<T>::leakRef()
    124 {
    125     return std::exchange(m_ptr, nullptr);
    126 }
    127 
    128 template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr& o)
     126template<typename T, typename U>
     127inline T* RefPtr<T, U>::leakRef()
     128{
     129    return U::exchange(m_ptr, nullptr);
     130}
     131
     132template<typename T, typename U>
     133inline RefPtr<T, U>& RefPtr<T, U>::operator=(const RefPtr& o)
    129134{
    130135    RefPtr ptr = o;
     
    133138}
    134139
    135 template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
     140template<typename T, typename U>
     141template<typename X, typename Y>
     142inline RefPtr<T, U>& RefPtr<T, U>::operator=(const RefPtr<X, Y>& o)
    136143{
    137144    RefPtr ptr = o;
     
    140147}
    141148
    142 template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
     149template<typename T, typename U>
     150inline RefPtr<T, U>& RefPtr<T, U>::operator=(T* optr)
    143151{
    144152    RefPtr ptr = optr;
     
    147155}
    148156
    149 template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(std::nullptr_t)
    150 {
    151     derefIfNotNull(std::exchange(m_ptr, nullptr));
    152     return *this;
    153 }
    154 
    155 template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr&& o)
     157template<typename T, typename U>
     158inline RefPtr<T, U>& RefPtr<T, U>::operator=(std::nullptr_t)
     159{
     160    derefIfNotNull(U::exchange(m_ptr, nullptr));
     161    return *this;
     162}
     163
     164template<typename T, typename U>
     165inline RefPtr<T, U>& RefPtr<T, U>::operator=(RefPtr&& o)
    156166{
    157167    RefPtr ptr = WTFMove(o);
     
    160170}
    161171
    162 template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(RefPtr<U>&& o)
     172template<typename T, typename U>
     173template<typename X, typename Y>
     174inline RefPtr<T, U>& RefPtr<T, U>::operator=(RefPtr<X, Y>&& o)
    163175{
    164176    RefPtr ptr = WTFMove(o);
     
    167179}
    168180
    169 template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(Ref<U>&& reference)
     181template<typename T, typename V>
     182template<typename U>
     183inline RefPtr<T, V>& RefPtr<T, V>::operator=(Ref<U>&& reference)
    170184{
    171185    RefPtr ptr = WTFMove(reference);
     
    174188}
    175189
    176 template<class T> inline void RefPtr<T>::swap(RefPtr& o)
    177 {
    178     std::swap(m_ptr, o.m_ptr);
    179 }
    180 
    181 template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
     190template<class T, typename U>
     191template<typename X, typename Y>
     192inline void RefPtr<T, U>::swap(RefPtr<X, Y>& o)
     193{
     194    U::swap(m_ptr, o.m_ptr);
     195}
     196
     197template<typename T, typename U, typename X, typename Y, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>>
     198inline void swap(RefPtr<T, U>& a, RefPtr<X, Y>& b)
    182199{
    183200    a.swap(b);
    184201}
    185202
    186 template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
    187 {
    188     return a.get() == b.get();
    189 }
    190 
    191 template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
     203template<typename T, typename U, typename X, typename Y>
     204inline bool operator==(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
     205{
     206    return a.get() == b.get();
     207}
     208
     209template<typename T, typename U, typename X>
     210inline bool operator==(const RefPtr<T, U>& a, X* b)
    192211{
    193212    return a.get() == b;
    194213}
    195214
    196 template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b)
     215template<typename T, typename X, typename Y>
     216inline bool operator==(T* a, const RefPtr<X, Y>& b)
    197217{
    198218    return a == b.get();
    199219}
    200220
    201 template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
     221template<typename T, typename U, typename X, typename Y>
     222inline bool operator!=(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
    202223{
    203224    return a.get() != b.get();
    204225}
    205226
    206 template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
     227template<typename T, typename U, typename X>
     228inline bool operator!=(const RefPtr<T, U>& a, X* b)
    207229{
    208230    return a.get() != b;
    209231}
    210232
    211 template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
     233template<typename T, typename X, typename Y>
     234inline bool operator!=(T* a, const RefPtr<X, Y>& b)
    212235{
    213236    return a != b.get();
    214237}
    215238
    216 template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
    217 {
    218     return RefPtr<T>(static_cast<T*>(p.get()));
    219 }
    220 
    221 template <typename T> struct IsSmartPtr<RefPtr<T>> {
     239template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>
     240inline RefPtr<T, U> static_pointer_cast(const RefPtr<X, Y>& p)
     241{
     242    return RefPtr<T, U>(static_cast<T*>(p.get()));
     243}
     244
     245template <typename T, typename U>
     246struct IsSmartPtr<RefPtr<T, U>> {
    222247    static const bool value = true;
    223248};
    224249
    225 template<typename T> inline RefPtr<T> adoptRef(T* p)
     250template<typename T, typename U>
     251inline RefPtr<T, U> adoptRef(T* p)
    226252{
    227253    adopted(p);
    228     return RefPtr<T>(p, RefPtr<T>::Adopt);
     254    return RefPtr<T, U>(p, RefPtr<T, U>::Adopt);
    229255}
    230256
     
    239265}
    240266
    241 template<typename ExpectedType, typename ArgType> inline bool is(RefPtr<ArgType>& source)
     267template<typename ExpectedType, typename ArgType, typename PtrTraits>
     268inline bool is(RefPtr<ArgType, PtrTraits>& source)
    242269{
    243270    return is<ExpectedType>(source.get());
    244271}
    245272
    246 template<typename ExpectedType, typename ArgType> inline bool is(const RefPtr<ArgType>& source)
     273template<typename ExpectedType, typename ArgType, typename PtrTraits>
     274inline bool is(const RefPtr<ArgType, PtrTraits>& source)
    247275{
    248276    return is<ExpectedType>(source.get());
    249277}
    250278
     279template<uint32_t key, typename T> struct ConstExprPoisonedPtrTraits;
     280
     281template<uint32_t key, typename T>
     282using PoisonedRefPtr = RefPtr<T, ConstExprPoisonedPtrTraits<key, T>>;
     283
    251284} // namespace WTF
    252285
     286using WTF::PoisonedRefPtr;
    253287using WTF::RefPtr;
    254288using WTF::adoptRef;
  • trunk/Tools/ChangeLog

    r226009 r226015  
     12017-12-17  Mark Lam  <mark.lam@apple.com>
     2
     3        Enhance Ref and RefPtr to be able to work with smart pointers.
     4        https://bugs.webkit.org/show_bug.cgi?id=180762
     5        <rdar://problem/36027122>
     6
     7        Reviewed by JF Bastien and Darin Adler.
     8
     9        * TestWebKitAPI/CMakeLists.txt:
     10        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     11        * TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp:
     12        (TestWebKitAPI::TEST):
     13        * TestWebKitAPI/Tests/WTF/Poisoned.cpp:
     14        (TestWebKitAPI::TEST):
     15        * TestWebKitAPI/Tests/WTF/PoisonedRef.cpp: Added.
     16        (TestWebKitAPI::TEST):
     17        (TestWebKitAPI::passWithRef):
     18        (TestWebKitAPI::PoisonedRefCheckingRefLogger::PoisonedRefCheckingRefLogger):
     19        (TestWebKitAPI::PoisonedRefCheckingRefLogger::ref):
     20        (TestWebKitAPI::PoisonedRefCheckingRefLogger::deref):
     21        (TestWebKitAPI::DerivedPoisonedRefCheckingRefLogger::DerivedPoisonedRefCheckingRefLogger):
     22        * TestWebKitAPI/Tests/WTF/PoisonedRefPtr.cpp: Added.
     23        (TestWebKitAPI::TEST):
     24        (TestWebKitAPI::f1):
     25        (TestWebKitAPI::ConstRefCounted::create):
     26        (TestWebKitAPI::returnConstRefCountedRef):
     27        (TestWebKitAPI::returnRefCountedRef):
     28        (TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::PoisonedRefPtrCheckingRefLogger):
     29        (TestWebKitAPI::loggerName):
     30        (TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::ref):
     31        (TestWebKitAPI::PoisonedRefPtrCheckingRefLogger::deref):
     32
    1332017-12-16  Youenn Fablet  <youenn@apple.com>
    234
  • trunk/Tools/TestWebKitAPI/CMakeLists.txt

    r225857 r226015  
    125125    ${TESTWEBKITAPI_DIR}/Tests/WTF/ParkingLot.cpp
    126126    ${TESTWEBKITAPI_DIR}/Tests/WTF/Poisoned.cpp
     127    ${TESTWEBKITAPI_DIR}/Tests/WTF/PoisonedRef.cpp
     128    ${TESTWEBKITAPI_DIR}/Tests/WTF/PoisonedRefPtr.cpp
    127129    ${TESTWEBKITAPI_DIR}/Tests/WTF/PriorityQueue.cpp
    128130    ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r226008 r226015  
    758758                F6F49C6B15545CA70007F39D /* DOMWindowExtensionNoCache_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6F49C6615545C8D0007F39D /* DOMWindowExtensionNoCache_Bundle.cpp */; };
    759759                F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F6FDDDD514241C48004F1729 /* push-state.html */; };
     760                FE05FAEC1FDB510A00093230 /* PoisonedRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAEB1FDB510200093230 /* PoisonedRef.cpp */; };
     761                FE05FAED1FDB510E00093230 /* PoisonedRefPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAEA1FDB510100093230 /* PoisonedRefPtr.cpp */; };
    760762                FE05FAEF1FE0645B00093230 /* Poisoned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAEE1FE0643D00093230 /* Poisoned.cpp */; };
    761763                FE05FAF11FE08CD400093230 /* ConstExprPoisoned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAF01FE08CCD00093230 /* ConstExprPoisoned.cpp */; };
     
    18621864                F6FDDDD214241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateBrowsingPushStateNoHistoryCallback.cpp; sourceTree = "<group>"; };
    18631865                F6FDDDD514241C48004F1729 /* push-state.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "push-state.html"; sourceTree = "<group>"; };
     1866                FE05FAEA1FDB510100093230 /* PoisonedRefPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PoisonedRefPtr.cpp; sourceTree = "<group>"; };
     1867                FE05FAEB1FDB510200093230 /* PoisonedRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PoisonedRef.cpp; sourceTree = "<group>"; };
    18641868                FE05FAEE1FE0643D00093230 /* Poisoned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Poisoned.cpp; sourceTree = "<group>"; };
    18651869                FE05FAF01FE08CCD00093230 /* ConstExprPoisoned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstExprPoisoned.cpp; sourceTree = "<group>"; };
     
    26562660                                0FE447971B76F1E3009498EB /* ParkingLot.cpp */,
    26572661                                FE05FAEE1FE0643D00093230 /* Poisoned.cpp */,
     2662                                FE05FAEB1FDB510200093230 /* PoisonedRef.cpp */,
     2663                                FE05FAEA1FDB510100093230 /* PoisonedRefPtr.cpp */,
    26582664                                53EC253F1E96BC80000831B9 /* PriorityQueue.cpp */,
    26592665                                0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
     
    31873193                                7C83DEAD1D0A590C00FEBCF3 /* Deque.cpp in Sources */,
    31883194                                1AF7B21F1D6CD14D008C126C /* EnumTraits.cpp in Sources */,
     3195                                FE05FAED1FDB510E00093230 /* PoisonedRefPtr.cpp in Sources */,
    31893196                                AD7C434D1DD2A54E0026888B /* Expected.cpp in Sources */,
    31903197                                9310CD381EF708FB0050FFE0 /* Function.cpp in Sources */,
     
    32043211                                7C83DEEF1D0A590C00FEBCF3 /* MD5.cpp in Sources */,
    32053212                                7C83DEF11D0A590C00FEBCF3 /* MediaTime.cpp in Sources */,
     3213                                FE05FAEC1FDB510A00093230 /* PoisonedRef.cpp in Sources */,
    32063214                                7C83DEF61D0A590C00FEBCF3 /* MetaAllocator.cpp in Sources */,
    32073215                                7C83DEFE1D0A590C00FEBCF3 /* NakedPtr.cpp in Sources */,
  • trunk/Tools/TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp

    r225857 r226015  
    5050        ASSERT_EQ(&a, &*ptr);
    5151        ASSERT_EQ(&a.name, &ptr->name);
     52
     53#if ENABLE(POISON)
     54        uintptr_t ptrBits;
     55        std::memcpy(&ptrBits, &ptr, sizeof(ptrBits));
     56        ASSERT_TRUE(ptrBits != bitwise_cast<uintptr_t>(&a));
     57#if ENABLE(POISON_ASSERTS)
     58        ASSERT_TRUE((ConstExprPoisoned<PoisonA, RefLogger*>::isPoisoned(ptrBits)));
     59#endif
     60#endif // ENABLE(POISON)
    5261    }
    5362
  • trunk/Tools/TestWebKitAPI/Tests/WTF/Poisoned.cpp

    r225857 r226015  
    6262        ASSERT_EQ(&a, &*ptr);
    6363        ASSERT_EQ(&a.name, &ptr->name);
     64
     65#if ENABLE(POISON)
     66        uintptr_t ptrBits;
     67        std::memcpy(&ptrBits, &ptr, sizeof(ptrBits));
     68        ASSERT_TRUE(ptrBits != bitwise_cast<uintptr_t>(&a));
     69#if ENABLE(POISON_ASSERTS)
     70        ASSERT_TRUE((Poisoned<g_testPoisonA, RefLogger*>::isPoisoned(ptrBits)));
     71#endif
     72#endif // ENABLE(POISON)
    6473    }
    6574
Note: See TracChangeset for help on using the changeset viewer.