From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Source/WTF/wtf/Ref.h | 184 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 170 insertions(+), 14 deletions(-) (limited to 'Source/WTF/wtf/Ref.h') diff --git a/Source/WTF/wtf/Ref.h b/Source/WTF/wtf/Ref.h index 6ff7c8223..e955352df 100644 --- a/Source/WTF/wtf/Ref.h +++ b/Source/WTF/wtf/Ref.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,55 +26,211 @@ #ifndef WTF_Ref_h #define WTF_Ref_h -#include "Noncopyable.h" +#include +#include +#include +#include +#include + +#if ASAN_ENABLED +extern "C" void __asan_poison_memory_region(void const volatile *addr, size_t size); +extern "C" void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +extern "C" bool __asan_address_is_poisoned(void const volatile *addr); +#endif namespace WTF { -template class PassRef; +inline void adopted(const void*) { } + +template class Ref; +template Ref adoptRef(T&); template class Ref { - WTF_MAKE_NONCOPYABLE(Ref) public: - Ref(T& object) : m_ptr(&object) { m_ptr->ref(); } - template Ref(PassRef reference) : m_ptr(&reference.leakRef()) { } + static constexpr bool isRef = true; + + ~Ref() + { +#if ASAN_ENABLED + if (__asan_address_is_poisoned(this)) + __asan_unpoison_memory_region(this, sizeof(*this)); +#endif + if (m_ptr) + m_ptr->deref(); + } + + Ref(T& object) + : m_ptr(&object) + { + m_ptr->ref(); + } - ~Ref() { m_ptr->deref(); } + // Use copyRef() instead. + Ref(const Ref& other) = delete; + template Ref(const Ref& other) = delete; + + Ref(Ref&& other) + : m_ptr(&other.leakRef()) + { + ASSERT(m_ptr); + } + + template + Ref(Ref&& other) + : m_ptr(&other.leakRef()) + { + ASSERT(m_ptr); + } Ref& operator=(T& object) { + ASSERT(m_ptr); object.ref(); m_ptr->deref(); m_ptr = &object; + ASSERT(m_ptr); return *this; } - template Ref& operator=(PassRef reference) + + // Use copyRef() and the move assignment operators instead. + Ref& operator=(const Ref& reference) = delete; + template Ref& operator=(const Ref& reference) = delete; + + Ref& operator=(Ref&& reference) { + ASSERT(m_ptr); m_ptr->deref(); m_ptr = &reference.leakRef(); + ASSERT(m_ptr); return *this; } - const T* operator->() const { return m_ptr; } - T* operator->() { return m_ptr; } + template Ref& operator=(Ref&& reference) + { + ASSERT(m_ptr); + m_ptr->deref(); + m_ptr = &reference.leakRef(); + ASSERT(m_ptr); + return *this; + } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + Ref(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } + static T* hashTableDeletedValue() { return reinterpret_cast(-1); } + + Ref(HashTableEmptyValueType) : m_ptr(hashTableEmptyValue()) { } + bool isHashTableEmptyValue() const { return m_ptr == hashTableEmptyValue(); } + static T* hashTableEmptyValue() { return nullptr; } + + const T* ptrAllowingHashTableEmptyValue() const { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr; } + T* ptrAllowingHashTableEmptyValue() { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr; } + + void assignToHashTableEmptyValue(Ref&& reference) + { + ASSERT(m_ptr == hashTableEmptyValue()); + m_ptr = &reference.leakRef(); + ASSERT(m_ptr); + } + + T* operator->() const { ASSERT(m_ptr); return m_ptr; } + T* ptr() const { ASSERT(m_ptr); return m_ptr; } + T& get() const { ASSERT(m_ptr); return *m_ptr; } + operator T&() const { ASSERT(m_ptr); return *m_ptr; } + + template Ref replace(Ref&&) WARN_UNUSED_RETURN; + +#if COMPILER_SUPPORTS(CXX_REFERENCE_QUALIFIED_FUNCTIONS) + Ref copyRef() && = delete; + Ref copyRef() const & WARN_UNUSED_RETURN { return Ref(*m_ptr); } +#else + Ref copyRef() const WARN_UNUSED_RETURN { return Ref(*m_ptr); } +#endif - const T& get() const { return *m_ptr; } - T& get() { return *m_ptr; } + T& leakRef() WARN_UNUSED_RETURN + { + ASSERT(m_ptr); - template PassRef replace(PassRef) WARN_UNUSED_RETURN; + T& result = *std::exchange(m_ptr, nullptr); +#if ASAN_ENABLED + __asan_poison_memory_region(this, sizeof(*this)); +#endif + return result; + } private: + friend Ref adoptRef(T&); + + enum AdoptTag { Adopt }; + Ref(T& object, AdoptTag) + : m_ptr(&object) + { + } + T* m_ptr; }; -template template inline PassRef Ref::replace(PassRef reference) +template template inline Ref Ref::replace(Ref&& reference) { auto oldReference = adoptRef(*m_ptr); m_ptr = &reference.leakRef(); return oldReference; } +template inline Ref static_reference_cast(Ref& reference) +{ + return Ref(static_cast(reference.get())); +} + +template inline Ref static_reference_cast(Ref&& reference) +{ + return adoptRef(static_cast(reference.leakRef())); +} + +template inline Ref static_reference_cast(const Ref& reference) +{ + return Ref(static_cast(reference.copyRef().get())); +} + +template +struct GetPtrHelper> { + typedef T* PtrType; + static T* getPtr(const Ref& p) { return const_cast(p.ptr()); } +}; + +template +struct IsSmartPtr> { + static const bool value = true; +}; + +template +inline Ref adoptRef(T& reference) +{ + adopted(&reference); + return Ref(reference, Ref::Adopt); +} + +template +inline Ref makeRef(T& reference) +{ + return Ref(reference); +} + +template inline bool is(Ref& source) +{ + return is(source.get()); +} + +template inline bool is(const Ref& source) +{ + return is(source.get()); +} + } // namespace WTF using WTF::Ref; +using WTF::adoptRef; +using WTF::makeRef; +using WTF::static_reference_cast; #endif // WTF_Ref_h -- cgit v1.2.1