From 4e37ddff43784a5a784beb4b62ea3f3136e1634b Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 18 Mar 2013 22:27:41 -0700 Subject: [PATCH] Fix a crasher with RefBase debugging and vectors of wp<> background: we have some code to fix-up the IDs of references when using RefBase's DEBUG_REFS when those refs are managed by arrays wp<> or sp<> (this is because wp<> / sp<> don't have a trivial ctor when DEBUG_REFS is enabled, and Vector treats them as trivial for obvious performance reasons) this is complicated by the fact that we don't want to have to recompile everything when enabling DEBUG_REFs (i.e.: the Vector code cannot know wheter it's enabled or not for its template stuff). problem: there was a bug in the fix-up code for wp<> which was trying to access the weakref_impl from the RefBase* however, this was moronic since RefBase could have been destroyed if there wasn't any more strong refs -- and this happned. Instead we need to get the weakref_impl directly from the wp<> Change-Id: Ie16e334204205fdbff142acb9faff8479a78450b --- include/utils/RefBase.h | 95 ++++++++++++++++++++++++----------------- libs/utils/RefBase.cpp | 24 +++++++---- 2 files changed, 71 insertions(+), 48 deletions(-) diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index 0a8e10a47..033fe67f8 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -52,12 +52,16 @@ inline bool operator _op_ (const U* o) const { \ } // --------------------------------------------------------------------------- -class ReferenceMover; -class ReferenceConverterBase { + +class ReferenceRenamer { +protected: + // destructor is purposedly not virtual so we avoid code overhead from + // subclasses; we have to make it protected to guarantee that it + // cannot be called from this base class (and to make strict compilers + // happy). + ~ReferenceRenamer() { } public: - virtual size_t getReferenceTypeSize() const = 0; - virtual void* getReferenceBase(void const*) const = 0; - inline virtual ~ReferenceConverterBase() { } + virtual void operator()(size_t i) const = 0; }; // --------------------------------------------------------------------------- @@ -143,11 +147,6 @@ protected: virtual bool onIncStrongAttempted(uint32_t flags, const void* id); virtual void onLastWeakRef(const void* id); -private: - friend class ReferenceMover; - static void moveReferences(void* d, void const* s, size_t n, - const ReferenceConverterBase& caster); - private: friend class weakref_type; class weakref_impl; @@ -155,6 +154,17 @@ private: RefBase(const RefBase& o); RefBase& operator=(const RefBase& o); +private: + friend class ReferenceMover; + + static void renameRefs(size_t n, const ReferenceRenamer& renamer); + + static void renameRefId(weakref_type* ref, + const void* old_id, const void* new_id); + + static void renameRefId(RefBase* ref, + const void* old_id, const void* new_id); + weakref_impl* const mRefs; }; @@ -185,8 +195,9 @@ protected: private: friend class ReferenceMover; - inline static void moveReferences(void* d, void const* s, size_t n, - const ReferenceConverterBase& caster) { } + inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { } + inline static void renameRefId(T* ref, + const void* old_id, const void* new_id) { } private: mutable volatile int32_t mCount; @@ -455,42 +466,48 @@ inline TextOutput& operator<<(TextOutput& to, const wp& val) // this class just serves as a namespace so TYPE::moveReferences can stay // private. - class ReferenceMover { - // StrongReferenceCast and WeakReferenceCast do the impedance matching - // between the generic (void*) implementation in Refbase and the strongly typed - // template specializations below. - - template - struct StrongReferenceCast : public ReferenceConverterBase { - virtual size_t getReferenceTypeSize() const { return sizeof( sp ); } - virtual void* getReferenceBase(void const* p) const { - sp const* sptr(reinterpret_cast const*>(p)); - return static_cast(sptr->get()); - } - }; - - template - struct WeakReferenceCast : public ReferenceConverterBase { - virtual size_t getReferenceTypeSize() const { return sizeof( wp ); } - virtual void* getReferenceBase(void const* p) const { - wp const* sptr(reinterpret_cast const*>(p)); - return static_cast(sptr->unsafe_get()); - } - }; - public: + // it would be nice if we could make sure no extra code is generated + // for sp or wp when TYPE is a descendant of RefBase: + // Using a sp override doesn't work; it's a bit like we wanted + // a template template... + template static inline void move_references(sp* d, sp const* s, size_t n) { + + class Renamer : public ReferenceRenamer { + sp* d; + sp const* s; + virtual void operator()(size_t i) const { + // The id are known to be the sp<>'s this pointer + TYPE::renameRefId(d[i].get(), &s[i], &d[i]); + } + public: + Renamer(sp* d, sp const* s) : s(s), d(d) { } + }; + memmove(d, s, n*sizeof(sp)); - StrongReferenceCast caster; - TYPE::moveReferences(d, s, n, caster); + TYPE::renameRefs(n, Renamer(d, s)); } + + template static inline void move_references(wp* d, wp const* s, size_t n) { + + class Renamer : public ReferenceRenamer { + wp* d; + wp const* s; + virtual void operator()(size_t i) const { + // The id are known to be the wp<>'s this pointer + TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]); + } + public: + Renamer(wp* d, wp const* s) : s(s), d(d) { } + }; + memmove(d, s, n*sizeof(wp)); - WeakReferenceCast caster; - TYPE::moveReferences(d, s, n, caster); + TYPE::renameRefs(n, Renamer(d, s)); } }; diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp index ef87131ad..abaf3c0ca 100644 --- a/libs/utils/RefBase.cpp +++ b/libs/utils/RefBase.cpp @@ -631,21 +631,27 @@ void RefBase::onLastWeakRef(const void* /*id*/) // --------------------------------------------------------------------------- -void RefBase::moveReferences(void* dst, void const* src, size_t n, - const ReferenceConverterBase& caster) -{ +void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) { #if DEBUG_REFS - const size_t itemSize = caster.getReferenceTypeSize(); for (size_t i=0 ; i(intptr_t(dst) + i*itemSize); - void const* s = reinterpret_cast(intptr_t(src) + i*itemSize); - RefBase* ref(reinterpret_cast(caster.getReferenceBase(d))); - ref->mRefs->renameStrongRefId(s, d); - ref->mRefs->renameWeakRefId(s, d); + renamer(i); } #endif } +void RefBase::renameRefId(weakref_type* ref, + const void* old_id, const void* new_id) { + weakref_impl* const impl = static_cast(ref); + impl->renameStrongRefId(old_id, new_id); + impl->renameWeakRefId(old_id, new_id); +} + +void RefBase::renameRefId(RefBase* ref, + const void* old_id, const void* new_id) { + ref->mRefs->renameStrongRefId(old_id, new_id); + ref->mRefs->renameWeakRefId(old_id, new_id); +} + // --------------------------------------------------------------------------- TextOutput& printStrongPointer(TextOutput& to, const void* val)