From 8e571669b3c8d4ac8236d0aed7a960bf88ad2bd1 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 2 Jun 2021 11:37:45 -0700 Subject: Fix cyclic reference in `ExtendedTypeLayout`. (#1868) --- source/core/slang-smart-pointer.h | 66 ++++++++++++++++++++++++++++++++++- source/slang/slang-reflection-api.cpp | 1 + source/slang/slang-type-layout.cpp | 2 +- source/slang/slang-type-layout.h | 2 +- 4 files changed, 68 insertions(+), 3 deletions(-) (limited to 'source') diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h index eb9fe7be5..2e5821ffd 100644 --- a/source/core/slang-smart-pointer.h +++ b/source/core/slang-smart-pointer.h @@ -272,6 +272,70 @@ namespace Slang private: T* m_ptr; }; -} + // A pointer that can be transformed to hold either a weak reference or a strong reference. + template + class TransformablePtr + { + private: + T* m_weakPtr = nullptr; + RefPtr m_strongPtr; + + public: + TransformablePtr() = default; + TransformablePtr(T* ptr) { *this = ptr; } + TransformablePtr(RefPtr ptr) { *this = ptr; } + TransformablePtr(const TransformablePtr& ptr) = default; + + void promoteToStrongReference() { m_strongPtr = m_weakPtr; } + void demoteToWeakReference() { m_strongPtr = nullptr; } + bool isStrongReference() const { return m_strongPtr != nullptr; } + + T& operator*() const { return *m_weakPtr; } + + T* operator->() const { return m_weakPtr; } + + T* Ptr() const { return m_weakPtr; } + T* get() const { return m_weakPtr; } + + operator T*() const { return m_weakPtr; } + operator RefPtr() const { return m_weakPtr; } + + + TransformablePtr& operator=(T* ptr) + { + m_weakPtr = ptr; + m_strongPtr = ptr; + return *this; + } + template + TransformablePtr& operator=(const RefPtr& ptr) + { + m_weakPtr = ptr.Ptr(); + m_strongPtr = ptr; + return *this; + } + + HashCode getHashCode() const + { + // Note: We need a `RefPtr` to hash the same as a `T*`, + // so that a `T*` can be used as a key in a dictionary with + // `RefPtr` keys, and vice versa. + // + return Slang::getHashCode(m_weakPtr); + } + + bool operator==(const T* ptr) const { return m_weakPtr == ptr; } + + bool operator!=(const T* ptr) const { return m_weakPtr != ptr; } + + bool operator==(RefPtr const& ptr) const { return m_weakPtr == ptr.Ptr(); } + + bool operator!=(RefPtr const& ptr) const { return m_weakPtr != ptr.Ptr(); } + + bool operator==(TransformablePtr const& ptr) const { return m_weakPtr == ptr.m_weakPtr; } + + bool operator!=(TransformablePtr const& ptr) const { return m_weakPtr != ptr.m_weakPtr; } + }; +} #endif diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index 22f34a41a..059de0be8 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -1405,6 +1405,7 @@ namespace Slang RefPtr varLayout = new VarLayout(); varLayout->typeLayout = typeLayout; + varLayout->typeLayout.demoteToWeakReference(); for(auto typeResInfo : typeLayout->resourceInfos) { diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index f2869886e..42a93f3f0 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -2819,7 +2819,7 @@ static RefPtr maybeAdjustLayoutForArrayElementType( // If nothing needed to be changed on the inner element type, // then we are done. - if(adjustedInnerElementTypeLayout == originalInnerElementTypeLayout) + if (originalInnerElementTypeLayout == adjustedInnerElementTypeLayout) return originalTypeLayout; // TODO: actually adjust the element type, and create all the required bits and diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index 52b575787..be7ccdf8f 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -467,7 +467,7 @@ public: Name* getName() { return getVariable()->getName(); } // The result of laying out the variable's type - RefPtr typeLayout; + TransformablePtr typeLayout; TypeLayout* getTypeLayout() { return typeLayout.Ptr(); } // Additional flags -- cgit v1.2.3