Title: [225857] trunk
Revision
225857
Author
mark....@apple.com
Date
2017-12-13 11:22:14 -0800 (Wed, 13 Dec 2017)

Log Message

Fill out some Poisoned APIs, fix some bugs, and add some tests.
https://bugs.webkit.org/show_bug.cgi?id=180724
<rdar://problem/36006884>

Reviewed by JF Bastien.

Source/_javascript_Core:

* runtime/StructureTransitionTable.h:

Source/WTF:

Also rename Int32Poisoned to ConstExprPoisoned.  The key it takes is actually a
uint32_t.  So, Int32 is really a misnomer.  In addition, the key needs to be a
constexpr.  So, ConstExprPoisoned is a better name for it.

* wtf/Poisoned.cpp:
(WTF::makePoison):
* wtf/Poisoned.h:
(WTF::PoisonedImplHelper::asReference):
(WTF::PoisonedImpl::PoisonedImpl):
(WTF::PoisonedImpl::clear):
(WTF::PoisonedImpl::operator* const):
(WTF::PoisonedImpl::operator-> const):
(WTF::PoisonedImpl::operator== const):
(WTF::PoisonedImpl::operator!= const):
(WTF::PoisonedImpl::operator< const):
(WTF::PoisonedImpl::operator<= const):
(WTF::PoisonedImpl::operator> const):
(WTF::PoisonedImpl::operator>= const):
(WTF::PoisonedImpl::operator=):
(WTF::PoisonedImpl::swap):
(WTF::PoisonedImpl::exchange):
(WTF::swap):
(WTF::makePoison):
(WTF::PoisonedImpl::operator==): Deleted.

Tools:

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp: Added.
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/Poisoned.cpp: Added.
(TestWebKitAPI::initializeTestPoison):
(TestWebKitAPI::TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (225856 => 225857)


--- trunk/Source/_javascript_Core/ChangeLog	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-12-13 19:22:14 UTC (rev 225857)
@@ -1,3 +1,13 @@
+2017-12-13  Mark Lam  <mark....@apple.com>
+
+        Fill out some Poisoned APIs, fix some bugs, and add some tests.
+        https://bugs.webkit.org/show_bug.cgi?id=180724
+        <rdar://problem/36006884>
+
+        Reviewed by JF Bastien.
+
+        * runtime/StructureTransitionTable.h:
+
 2017-12-13  Caio Lima  <ticaiol...@gmail.com>
 
         [ESNext][BigInt] Breking tests on Debug build and 32-bits due to missing Exception check

Modified: trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h (225856 => 225857)


--- trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h	2017-12-13 19:22:14 UTC (rev 225857)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -187,8 +187,8 @@
 
 private:
     friend class SingleSlotTransitionWeakOwner;
-    using PoisonedTransitionMapPtr = Int32Poisoned<TransitionMapPoison, TransitionMap*>;
-    using PoisonedWeakImplPtr = Int32Poisoned<WeakImplPoison, WeakImpl*>;
+    using PoisonedTransitionMapPtr = ConstExprPoisoned<TransitionMapPoison, TransitionMap*>;
+    using PoisonedWeakImplPtr = ConstExprPoisoned<WeakImplPoison, WeakImpl*>;
 
     bool isUsingSingleSlot() const
     {

Modified: trunk/Source/WTF/ChangeLog (225856 => 225857)


--- trunk/Source/WTF/ChangeLog	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Source/WTF/ChangeLog	2017-12-13 19:22:14 UTC (rev 225857)
@@ -1,3 +1,36 @@
+2017-12-13  Mark Lam  <mark....@apple.com>
+
+        Fill out some Poisoned APIs, fix some bugs, and add some tests.
+        https://bugs.webkit.org/show_bug.cgi?id=180724
+        <rdar://problem/36006884>
+
+        Reviewed by JF Bastien.
+
+        Also rename Int32Poisoned to ConstExprPoisoned.  The key it takes is actually a
+        uint32_t.  So, Int32 is really a misnomer.  In addition, the key needs to be a
+        constexpr.  So, ConstExprPoisoned is a better name for it.
+
+        * wtf/Poisoned.cpp:
+        (WTF::makePoison):
+        * wtf/Poisoned.h:
+        (WTF::PoisonedImplHelper::asReference):
+        (WTF::PoisonedImpl::PoisonedImpl):
+        (WTF::PoisonedImpl::clear):
+        (WTF::PoisonedImpl::operator* const):
+        (WTF::PoisonedImpl::operator-> const):
+        (WTF::PoisonedImpl::operator== const):
+        (WTF::PoisonedImpl::operator!= const):
+        (WTF::PoisonedImpl::operator< const):
+        (WTF::PoisonedImpl::operator<= const):
+        (WTF::PoisonedImpl::operator> const):
+        (WTF::PoisonedImpl::operator>= const):
+        (WTF::PoisonedImpl::operator=):
+        (WTF::PoisonedImpl::swap):
+        (WTF::PoisonedImpl::exchange):
+        (WTF::swap):
+        (WTF::makePoison):
+        (WTF::PoisonedImpl::operator==): Deleted.
+
 2017-12-12  Yusuke Suzuki  <utatane....@gmail.com>
 
         [JSC] Implement optimized WeakMap and WeakSet

Modified: trunk/Source/WTF/wtf/Poisoned.cpp (225856 => 225857)


--- trunk/Source/WTF/wtf/Poisoned.cpp	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Source/WTF/wtf/Poisoned.cpp	2017-12-13 19:22:14 UTC (rev 225857)
@@ -33,7 +33,7 @@
 uintptr_t makePoison()
 {
     uintptr_t key = cryptographicallyRandomNumber();
-#if USE(JSVALUE64) && !OS(WINDOWS)
+#if ENABLE(POISON)
     key = (key << 32) ^ (static_cast<uintptr_t>(cryptographicallyRandomNumber()) << 3);
     // Ensure that the poisoned bits (pointer ^ key) do not make a valid pointer and
     // cannot be 0. We ensure that it is zero so that the poisoned bits can also be
@@ -51,4 +51,3 @@
 }
 
 } // namespace WTF
-

Modified: trunk/Source/WTF/wtf/Poisoned.h (225856 => 225857)


--- trunk/Source/WTF/wtf/Poisoned.h	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Source/WTF/wtf/Poisoned.h	2017-12-13 19:22:14 UTC (rev 225857)
@@ -27,11 +27,36 @@
 
 #include <wtf/Assertions.h>
 
+#define ENABLE_POISON 1
 #define ENABLE_POISON_ASSERTS 0
 
+// Older versions of gcc and clang have a bug which results in build failures
+// when using template methods that take an argument of PoisonedImpl<K2, k2, T2>
+// when the KeyType is a uintptr_t (i.e. when we're using the Poisoned variant
+// of PoisonedImpl). This bug does not manifest for the ConstExprPoisoned variant.
+// In practice, we will likely only use these methods for instantiations of the
+// ConstExprPoisoned variant. Hence. this bug is not a show stopper.
+// That said, we'll define ENABLE_MIXED_POISON accordingly so that we can use
+// it to disable the affected tests when building with old compilers.
+
+#if OS(DARWIN)
+#define ENABLE_MIXED_POISON (__clang_major__ >= 9)
+#elif defined(__clang_major__)
+#define ENABLE_MIXED_POISON (__clang_major__ >= 4)
+#elif defined(__GNUC__)
+#include <features.h>
+#define ENABLE_MIXED_POISON (__GNUC_PREREQ(7, 2))
+#endif // !defined(__GNUC__)
+
+#ifndef ENABLE_MIXED_POISON
+#define ENABLE_MIXED_POISON 0 // Disable for everything else.
+#endif
+
 // Not currently supported for 32-bit or OS(WINDOWS) builds (because of missing llint support).
 // Make sure it's disabled.
 #if USE(JSVALUE32_64) || OS(WINDOWS)
+#undef ENABLE_POISON
+#define ENABLE_POISON 0
 #undef ENABLE_POISON_ASSERTS
 #define ENABLE_POISON_ASSERTS 0
 #endif
@@ -40,17 +65,47 @@
 
 using PoisonedBits = uintptr_t;
 
+namespace PoisonedImplHelper {
+
+template<typename T>
+struct isFunctionPointer : std::integral_constant<bool, std::is_function<typename std::remove_pointer<T>::type>::value> { };
+
+template<typename T>
+struct isVoidPointer : std::integral_constant<bool, std::is_void<typename std::remove_pointer<T>::type>::value> { };
+
+template<typename T>
+struct isConvertibleToReference : std::integral_constant<bool, !isFunctionPointer<T>::value && !isVoidPointer<T>::value> { };
+
+template<typename T>
+typename std::enable_if_t<!isConvertibleToReference<T>::value, int>&
+asReference(T) { RELEASE_ASSERT_NOT_REACHED(); }
+
+template<typename T>
+typename std::enable_if_t<isConvertibleToReference<T>::value, typename std::remove_pointer<T>::type>&
+asReference(T ptr) { return *ptr; }
+
+} // namespace PoisonedImplHelper
+
 template<typename KeyType, KeyType key, typename T, typename = std::enable_if_t<std::is_pointer<T>::value>>
 class PoisonedImpl {
 public:
     PoisonedImpl() { }
 
-    explicit PoisonedImpl(T ptr)
+    PoisonedImpl(T ptr)
         : m_poisonedBits(poison(ptr))
     { }
 
     PoisonedImpl(const PoisonedImpl&) = default;
 
+    template<typename K2, K2 k2, typename T2>
+    PoisonedImpl(const PoisonedImpl<K2, k2, T2>& other)
+        : m_poisonedBits(poison<T>(other.unpoisoned()))
+    { }
+
+    PoisonedImpl(PoisonedImpl&& other)
+        : m_poisonedBits(WTFMove(other.m_poisonedBits))
+    { }
+
     explicit PoisonedImpl(PoisonedBits poisonedBits)
         : m_poisonedBits(poisonedBits)
     { }
@@ -72,8 +127,11 @@
     template<typename U = T>
     U unpoisoned() const { return unpoison<U>(m_poisonedBits); }
 
-    ALWAYS_INLINE T operator->() const { return unpoison<T>(m_poisonedBits); }
+    void clear() { m_poisonedBits = 0; }
 
+    auto& operator*() const { ASSERT(m_poisonedBits); return PoisonedImplHelper::asReference(unpoison(m_poisonedBits)); }
+    ALWAYS_INLINE T operator->() const { return unpoison(m_poisonedBits); }
+
     template<typename U = PoisonedBits>
     U bits() const { return bitwise_cast<U>(m_poisonedBits); }
 
@@ -80,16 +138,19 @@
     bool operator!() const { return !m_poisonedBits; }
     explicit operator bool() const { return !!m_poisonedBits; }
 
-    bool operator==(const PoisonedImpl& b) const
-    {
-        return m_poisonedBits == b.m_poisonedBits;
-    }
+    bool operator==(const PoisonedImpl& b) const { return m_poisonedBits == b.m_poisonedBits; }
+    bool operator!=(const PoisonedImpl& b) const { return m_poisonedBits != b.m_poisonedBits; }
+    bool operator<(const PoisonedImpl& b) const { return m_poisonedBits < b.m_poisonedBits; }
+    bool operator<=(const PoisonedImpl& b) const { return m_poisonedBits <= b.m_poisonedBits; }
+    bool operator>(const PoisonedImpl& b) const { return m_poisonedBits > b.m_poisonedBits; }
+    bool operator>=(const PoisonedImpl& b) const { return m_poisonedBits >= b.m_poisonedBits; }
 
-    template<typename PtrType = void*, typename = typename std::enable_if<std::is_pointer<PtrType>::value>::type>
-    bool operator==(const PtrType b)
-    {
-        return unpoisoned<PtrType>() == b;
-    }
+    template<typename U> bool operator==(U b) const { return unpoisoned<U>() == b; }
+    template<typename U> bool operator!=(U b) const { return unpoisoned<U>() != b; }
+    template<typename U> bool operator<(U b) const { return unpoisoned<U>() < b; }
+    template<typename U> bool operator<=(U b) const { return unpoisoned<U>() <= b; }
+    template<typename U> bool operator>(U b) const { return unpoisoned<U>() > b; }
+    template<typename U> bool operator>=(U b) const { return unpoisoned<U>() >= b; }
 
     PoisonedImpl& operator=(T ptr)
     {
@@ -98,16 +159,46 @@
     }
     PoisonedImpl& operator=(const PoisonedImpl&) = default;
 
+    template<typename K2, K2 k2, typename T2>
+    PoisonedImpl& operator=(const PoisonedImpl<K2, k2, T2>& other)
+    {
+        m_poisonedBits = poison<T>(other.unpoisoned());
+        return *this;
+    }
+
+    void swap(PoisonedImpl& o)
+    {
+        std::swap(m_poisonedBits, o.m_poisonedBits);
+    }
+
+    template<typename K2, K2 k2, typename T2>
+    void swap(PoisonedImpl<K2, k2, T2>& o)
+    {
+        T t1 = this->unpoisoned();
+        T2 t2 = o.unpoisoned();
+        std::swap(t1, t2);
+        m_poisonedBits = poison(t1);
+        o = t2;
+    }
+
+    template<class U>
+    T exchange(U&& newValue)
+    {
+        T oldValue = unpoisoned();
+        m_poisonedBits = poison(std::forward<U>(newValue));
+        return oldValue;
+    }
+
 private:
-#if USE(JSVALUE64)
+#if ENABLE(POISON)
     template<typename U>
     ALWAYS_INLINE static PoisonedBits poison(U ptr) { return ptr ? bitwise_cast<PoisonedBits>(ptr) ^ key : 0; }
-    template<typename U>
+    template<typename U = T>
     ALWAYS_INLINE static U unpoison(PoisonedBits poisonedBits) { return poisonedBits ? bitwise_cast<U>(poisonedBits ^ key) : bitwise_cast<U>(0ll); }
 #else
     template<typename U>
     ALWAYS_INLINE static PoisonedBits poison(U ptr) { return bitwise_cast<PoisonedBits>(ptr); }
-    template<typename U>
+    template<typename U = T>
     ALWAYS_INLINE static U unpoison(PoisonedBits poisonedBits) { return bitwise_cast<U>(poisonedBits); }
 #endif
 
@@ -114,22 +205,32 @@
     PoisonedBits m_poisonedBits { 0 };
 };
 
+template<typename K1, K1 k1, typename T1, typename K2, K2 k2, typename T2>
+inline void swap(PoisonedImpl<K1, k1, T1>& a, PoisonedImpl<K2, k2, T2>& b)
+{
+    a.swap(b);
+}
+
+WTF_EXPORT_PRIVATE uintptr_t makePoison();
+
+inline constexpr uintptr_t makePoison(uint32_t key)
+{
+#if ENABLE(POISON)
+    return static_cast<uintptr_t>(0x80000000 | key) << 32;
+#else
+    return (void)key, 0;
+#endif
+}
+
 template<uintptr_t& key, typename T>
 using Poisoned = PoisonedImpl<uintptr_t&, key, T>;
 
-#if USE(JSVALUE64)
 template<uint32_t key, typename T>
-using Int32Poisoned = PoisonedImpl<uintptr_t, static_cast<uintptr_t>(key) << 32, T>;
-#else
-template<uint32_t, typename T>
-using Int32Poisoned = PoisonedImpl<uintptr_t, 0, T>;
-#endif
+using ConstExprPoisoned = PoisonedImpl<uintptr_t, makePoison(key), T>;
 
-WTF_EXPORT_PRIVATE uintptr_t makePoison();
-
 } // namespace WTF
 
-using WTF::Int32Poisoned;
+using WTF::ConstExprPoisoned;
 using WTF::Poisoned;
 using WTF::PoisonedBits;
 using WTF::makePoison;

Modified: trunk/Tools/ChangeLog (225856 => 225857)


--- trunk/Tools/ChangeLog	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Tools/ChangeLog	2017-12-13 19:22:14 UTC (rev 225857)
@@ -1,3 +1,19 @@
+2017-12-13  Mark Lam  <mark....@apple.com>
+
+        Fill out some Poisoned APIs, fix some bugs, and add some tests.
+        https://bugs.webkit.org/show_bug.cgi?id=180724
+        <rdar://problem/36006884>
+
+        Reviewed by JF Bastien.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp: Added.
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WTF/Poisoned.cpp: Added.
+        (TestWebKitAPI::initializeTestPoison):
+        (TestWebKitAPI::TEST):
+
 2017-12-13  Jonathan Bedard  <jbed...@apple.com>
 
         webkitpy: Better name-version mapping (Part 2)

Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (225856 => 225857)


--- trunk/Tools/TestWebKitAPI/CMakeLists.txt	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt	2017-12-13 19:22:14 UTC (rev 225857)
@@ -95,6 +95,7 @@
     ${TESTWEBKITAPI_DIR}/Tests/WTF/CheckedArithmeticOperations.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/ConcurrentPtrHashSet.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Condition.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WTF/ConstExprPoisoned.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/CrossThreadTask.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
@@ -122,6 +123,7 @@
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Optional.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/OptionSet.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/ParkingLot.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WTF/Poisoned.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/PriorityQueue.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WTF/Ref.cpp

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (225856 => 225857)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-12-13 19:04:04 UTC (rev 225856)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-12-13 19:22:14 UTC (rev 225857)
@@ -756,6 +756,8 @@
 		F6B7BE9717469B96008A3445 /* associate-form-controls.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F6B7BE9617469B7E008A3445 /* associate-form-controls.html */; };
 		F6F49C6B15545CA70007F39D /* DOMWindowExtensionNoCache_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6F49C6615545C8D0007F39D /* DOMWindowExtensionNoCache_Bundle.cpp */; };
 		F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F6FDDDD514241C48004F1729 /* push-state.html */; };
+		FE05FAEF1FE0645B00093230 /* Poisoned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAEE1FE0643D00093230 /* Poisoned.cpp */; };
+		FE05FAF11FE08CD400093230 /* ConstExprPoisoned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE05FAF01FE08CCD00093230 /* ConstExprPoisoned.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -1857,6 +1859,8 @@
 		F6F49C6715545C8D0007F39D /* DOMWindowExtensionNoCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionNoCache.cpp; sourceTree = "<group>"; };
 		F6FDDDD214241AD4004F1729 /* PrivateBrowsingPushStateNoHistoryCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrivateBrowsingPushStateNoHistoryCallback.cpp; sourceTree = "<group>"; };
 		F6FDDDD514241C48004F1729 /* push-state.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "push-state.html"; sourceTree = "<group>"; };
+		FE05FAEE1FE0643D00093230 /* Poisoned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Poisoned.cpp; sourceTree = "<group>"; };
+		FE05FAF01FE08CCD00093230 /* ConstExprPoisoned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstExprPoisoned.cpp; sourceTree = "<group>"; };
 		FEB6F74E1B2BA44E009E4922 /* NakedPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NakedPtr.cpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -2613,6 +2617,7 @@
 				A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
 				0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */,
 				0FEAE3671B7D19CB00CE17F2 /* Condition.cpp */,
+				FE05FAF01FE08CCD00093230 /* ConstExprPoisoned.cpp */,
 				51714EB91D087416004723C4 /* CrossThreadTask.cpp */,
 				26A2C72E15E2E73C005B1A14 /* CString.cpp */,
 				7AA021BA1AB09EA70052953F /* DateMath.cpp */,
@@ -2646,6 +2651,7 @@
 				1AFDE6541953B2C000C48FFA /* Optional.cpp */,
 				CE50D8C81C8665CE0072EA5A /* OptionSet.cpp */,
 				0FE447971B76F1E3009498EB /* ParkingLot.cpp */,
+				FE05FAEE1FE0643D00093230 /* Poisoned.cpp */,
 				53EC253F1E96BC80000831B9 /* PriorityQueue.cpp */,
 				0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
 				93A427AA180DA26400CD24D7 /* Ref.cpp */,
@@ -3190,6 +3196,7 @@
 				7C83DF1D1D0A590C00FEBCF3 /* Lock.cpp in Sources */,
 				A57D54F61F3395D000A97AA7 /* Logger.cpp in Sources */,
 				7C83DEED1D0A590C00FEBCF3 /* MathExtras.cpp in Sources */,
+				FE05FAF11FE08CD400093230 /* ConstExprPoisoned.cpp in Sources */,
 				7C83DEEF1D0A590C00FEBCF3 /* MD5.cpp in Sources */,
 				7C83DEF11D0A590C00FEBCF3 /* MediaTime.cpp in Sources */,
 				7C83DEF61D0A590C00FEBCF3 /* MetaAllocator.cpp in Sources */,
@@ -3210,6 +3217,7 @@
 				7C83DF051D0A590C00FEBCF3 /* RunLoop.cpp in Sources */,
 				7C83DF261D0A590C00FEBCF3 /* SaturatedArithmeticOperations.cpp in Sources */,
 				1A3524AE1D63A4FB0031729B /* Scope.cpp in Sources */,
+				FE05FAEF1FE0645B00093230 /* Poisoned.cpp in Sources */,
 				7C83DF121D0A590C00FEBCF3 /* ScopedLambda.cpp in Sources */,
 				7C83DF3D1D0A590C00FEBCF3 /* SetForScope.cpp in Sources */,
 				7C83DF2A1D0A590C00FEBCF3 /* SHA1.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp (0 => 225857)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/ConstExprPoisoned.cpp	2017-12-13 19:22:14 UTC (rev 225857)
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include <mutex>
+#include <wtf/Poisoned.h>
+
+namespace TestWebKitAPI {
+
+static const uint32_t PoisonA = 0xaaaa;
+static const uint32_t PoisonB = 0xbbbb;
+
+// For these tests, we need a base class and a derived class. For this purpose,
+// we reuse the RefLogger and DerivedRefLogger classes.
+
+TEST(WTF_ConstExprPoisoned, Basic)
+{
+    DerivedRefLogger a("a");
+
+    ConstExprPoisoned<PoisonA, RefLogger*> empty;
+    ASSERT_EQ(nullptr, empty.unpoisoned());
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ASSERT_EQ(&a, &*ptr);
+        ASSERT_EQ(&a.name, &ptr->name);
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr = &a;
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(p1);
+        ConstExprPoisoned<PoisonB, RefLogger*> p3(p1);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_EQ(&a, p3.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2 = p1;
+        ConstExprPoisoned<PoisonB, RefLogger*> p3 = p1;
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_EQ(&a, p3.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2 = WTFMove(p1);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3 = &a;
+        ConstExprPoisoned<PoisonB, RefLogger*> p4 = WTFMove(p3);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(WTFMove(p1));
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3 = &a;
+        ConstExprPoisoned<PoisonB, RefLogger*> p4(WTFMove(p3));
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, DerivedRefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2 = p1;
+        ConstExprPoisoned<PoisonB, RefLogger*> p3 = p1;
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_EQ(&a, p3.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, DerivedRefLogger*> p1 = &a;
+        ConstExprPoisoned<PoisonA, RefLogger*> p2 = WTFMove(p1);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, DerivedRefLogger*> p3 = &a;
+        ConstExprPoisoned<PoisonB, RefLogger*> p4 = WTFMove(p3);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr.clear();
+        ASSERT_EQ(nullptr, ptr.unpoisoned());
+    }
+}
+
+TEST(WTF_ConstExprPoisoned, Assignment)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1 = p2;
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3 = p4;
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = &b;
+        ASSERT_EQ(&b, ptr.unpoisoned());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = nullptr;
+        ASSERT_EQ(nullptr, ptr.unpoisoned());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1 = WTFMove(p2);
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3 = WTFMove(p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, DerivedRefLogger*> p2(&c);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        p1 = p2;
+        ASSERT_EQ(&c, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, DerivedRefLogger*> p4(&c);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        p3 = p4;
+        ASSERT_EQ(&c, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = &c;
+        ASSERT_EQ(&c, ptr.unpoisoned());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, DerivedRefLogger*> p2(&c);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        p1 = WTFMove(p2);
+        ASSERT_EQ(&c, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, DerivedRefLogger*> p4(&c);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        p3 = WTFMove(p4);
+        ASSERT_EQ(&c, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() == p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = ptr;
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+        ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+}
+
+TEST(WTF_ConstExprPoisoned, Swap)
+{
+    RefLogger a("a");
+    RefLogger b("b");
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1.swap(p2);
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3.swap(p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() != p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+        ASSERT_TRUE(p1.bits() == p3.bits());
+        ASSERT_TRUE(p2.bits() != p4.bits());
+    }
+
+    {
+        ConstExprPoisoned<PoisonA, RefLogger*> p1(&a);
+        ConstExprPoisoned<PoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        swap(p1, p2);
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ConstExprPoisoned<PoisonA, RefLogger*> p3(&a);
+        ConstExprPoisoned<PoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        swap(p3, p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() != p2.bits());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+        ASSERT_TRUE(p1.bits() == p3.bits());
+        ASSERT_TRUE(p2.bits() != p4.bits());
+    }
+}
+
+static ConstExprPoisoned<PoisonA, RefLogger*> poisonedPtrFoo(RefLogger& logger)
+{
+    return ConstExprPoisoned<PoisonA, RefLogger*>(&logger);
+}
+
+TEST(WTF_ConstExprPoisoned, ReturnValue)
+{
+    DerivedRefLogger a("a");
+
+    {
+        auto ptr = poisonedPtrFoo(a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ASSERT_EQ(&a, &*ptr);
+        ASSERT_EQ(&a.name, &ptr->name);
+    }
+}
+
+} // namespace TestWebKitAPI
+

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/Poisoned.cpp (0 => 225857)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/Poisoned.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/Poisoned.cpp	2017-12-13 19:22:14 UTC (rev 225857)
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include <mutex>
+#include <wtf/Poisoned.h>
+
+namespace TestWebKitAPI {
+
+uintptr_t g_testPoisonA;
+uintptr_t g_testPoisonB;
+
+static void initializeTestPoison()
+{
+    static std::once_flag initializeOnceFlag;
+    std::call_once(initializeOnceFlag, [] {
+        // Make sure we get 2 different poison values.
+        g_testPoisonA = makePoison();
+        while (!g_testPoisonB || g_testPoisonB == g_testPoisonA)
+            g_testPoisonB = makePoison();
+    });
+}
+
+// For these tests, we need a base class and a derived class. For this purpose,
+// we reuse the RefLogger and DerivedRefLogger classes.
+
+TEST(WTF_Poisoned, Basic)
+{
+    initializeTestPoison();
+    DerivedRefLogger a("a");
+
+    Poisoned<g_testPoisonA, RefLogger*> empty;
+    ASSERT_EQ(nullptr, empty.unpoisoned());
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ASSERT_EQ(&a, &*ptr);
+        ASSERT_EQ(&a.name, &ptr->name);
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr = &a;
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2(p1);
+
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonB, RefLogger*> p3(p1);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+#endif
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2 = p1;
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonB, RefLogger*> p3 = p1;
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+#endif
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2 = WTFMove(p1);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3 = &a;
+        Poisoned<g_testPoisonB, RefLogger*> p4 = WTFMove(p3);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+#endif
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2(WTFMove(p1));
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3 = &a;
+        Poisoned<g_testPoisonB, RefLogger*> p4(WTFMove(p3));
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+#endif
+    }
+
+#if ENABLE(MIXED_POISON)
+    {
+        Poisoned<g_testPoisonA, DerivedRefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2 = p1;
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+        Poisoned<g_testPoisonB, RefLogger*> p3 = p1;
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_TRUE(p1.bits() != p3.bits());
+    }
+#endif
+
+#if ENABLE(MIXED_POISON)
+    {
+        Poisoned<g_testPoisonA, DerivedRefLogger*> p1 = &a;
+        Poisoned<g_testPoisonA, RefLogger*> p2 = WTFMove(p1);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+        Poisoned<g_testPoisonA, DerivedRefLogger*> p3 = &a;
+        Poisoned<g_testPoisonB, RefLogger*> p4 = WTFMove(p3);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+#endif
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr.clear();
+        ASSERT_EQ(nullptr, ptr.unpoisoned());
+    }
+}
+
+TEST(WTF_Poisoned, Assignment)
+{
+    initializeTestPoison();
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1 = p2;
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3 = p4;
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+#endif
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = &b;
+        ASSERT_EQ(&b, ptr.unpoisoned());
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = nullptr;
+        ASSERT_EQ(nullptr, ptr.unpoisoned());
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1 = WTFMove(p2);
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3 = WTFMove(p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+#endif
+    }
+
+#if ENABLE(MIXED_POISON)
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, DerivedRefLogger*> p2(&c);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        p1 = p2;
+        ASSERT_EQ(&c, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, DerivedRefLogger*> p4(&c);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        p3 = p4;
+        ASSERT_EQ(&c, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+#endif
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = &c;
+        ASSERT_EQ(&c, ptr.unpoisoned());
+    }
+
+#if ENABLE(MIXED_POISON)
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, DerivedRefLogger*> p2(&c);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        p1 = WTFMove(p2);
+        ASSERT_EQ(&c, p1.unpoisoned());
+        ASSERT_EQ(&c, p2.unpoisoned());
+        ASSERT_TRUE(p1.bits() == p2.bits());
+
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, DerivedRefLogger*> p4(&c);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        p3 = WTFMove(p4);
+        ASSERT_EQ(&c, p3.unpoisoned());
+        ASSERT_EQ(&c, p4.unpoisoned());
+        ASSERT_TRUE(p3.bits() != p4.bits());
+    }
+#endif
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ptr = ptr;
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> ptr(&a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+        ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        ASSERT_EQ(&a, ptr.unpoisoned());
+    }
+}
+
+TEST(WTF_Poisoned, Swap)
+{
+    initializeTestPoison();
+    RefLogger a("a");
+    RefLogger b("b");
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+        p1.swap(p2);
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() != p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        p3.swap(p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p3.bits() != p4.bits());
+        ASSERT_TRUE(p1.bits() == p3.bits());
+        ASSERT_TRUE(p2.bits() != p4.bits());
+#endif
+    }
+
+    {
+        Poisoned<g_testPoisonA, RefLogger*> p1(&a);
+        Poisoned<g_testPoisonA, RefLogger*> p2(&b);
+        ASSERT_EQ(&a, p1.unpoisoned());
+        ASSERT_EQ(&b, p2.unpoisoned());
+#if ENABLE(MIXED_POISON)
+        swap(p1, p2);
+#else
+        std::swap(p1, p2);
+#endif
+        ASSERT_EQ(&b, p1.unpoisoned());
+        ASSERT_EQ(&a, p2.unpoisoned());
+
+        ASSERT_TRUE(p1.bits() != p2.bits());
+
+#if ENABLE(MIXED_POISON)
+        Poisoned<g_testPoisonA, RefLogger*> p3(&a);
+        Poisoned<g_testPoisonB, RefLogger*> p4(&b);
+        ASSERT_EQ(&a, p3.unpoisoned());
+        ASSERT_EQ(&b, p4.unpoisoned());
+        swap(p3, p4);
+        ASSERT_EQ(&b, p3.unpoisoned());
+        ASSERT_EQ(&a, p4.unpoisoned());
+
+        ASSERT_TRUE(p3.bits() != p4.bits());
+        ASSERT_TRUE(p1.bits() == p3.bits());
+        ASSERT_TRUE(p2.bits() != p4.bits());
+#endif
+    }
+}
+
+static Poisoned<g_testPoisonA, RefLogger*> poisonedPtrFoo(RefLogger& logger)
+{
+    return Poisoned<g_testPoisonA, RefLogger*>(&logger);
+}
+
+TEST(WTF_Poisoned, ReturnValue)
+{
+    initializeTestPoison();
+    DerivedRefLogger a("a");
+
+    {
+        auto ptr = poisonedPtrFoo(a);
+        ASSERT_EQ(&a, ptr.unpoisoned());
+        ASSERT_EQ(&a, &*ptr);
+        ASSERT_EQ(&a.name, &ptr->name);
+    }
+}
+
+} // namespace TestWebKitAPI
+
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to