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
+