Ignore:
Timestamp:
Sep 19, 2008, 1:50:13 AM (17 years ago)
Author:
[email protected]
Message:

2008-09-19 Julien Chaffraix <[email protected]>

Reviewed by Alexey Proskuryakov.

Use the template hoisting technique on the RefCounted class. This reduces the code bloat due to
non-template methods' code been copied for each instance of the template.
The patch splits RefCounted between a base class that holds non-template methods and attributes
and the template RefCounted class that keeps the same functionnality.

On my Linux with gcc 4.3 for the Gtk port, this is:

  • a ~600KB save on libwebkit.so in release.
  • a ~1.6MB save on libwebkit.so in debug.

It is a wash on Sunspider and a small win on Dromaeo (not sure it is relevant).
On the whole, it should be a small win as we reduce the compiled code size and the only
new function call should be inlined by the compiler.

  • wtf/RefCounted.h: (WTF::RefCountedBase::ref): Copied from RefCounted. (WTF::RefCountedBase::hasOneRef): Ditto. (WTF::RefCountedBase::refCount): Ditto. (WTF::RefCountedBase::RefCountedBase): Ditto. (WTF::RefCountedBase::~RefCountedBase): Ditto. (WTF::RefCountedBase::derefBase): Tweaked from the RefCounted version to remove template section. (WTF::RefCounted::RefCounted): (WTF::RefCounted::deref): Small wrapper around RefCountedBase::derefBase(). (WTF::RefCounted::~RefCounted): Keep private destructor.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/RefCounted.h

    r36425 r36663  
    2727namespace WTF {
    2828
    29 template<class T> class RefCounted : Noncopyable {
     29// This base class holds the non-template methods and attributes.
     30// The RefCounted class inherits from it reducing the template bloat
     31// generated by the compiler (technique called template hoisting).
     32class RefCountedBase : Noncopyable {
    3033public:
    31     RefCounted(int initialRefCount = 1)
    32         : m_refCount(initialRefCount)
    33 #ifndef NDEBUG
    34         , m_deletionHasBegun(false)
    35 #endif
    36     {
    37     }
    38 
    3934    void ref()
    4035    {
    4136        ASSERT(!m_deletionHasBegun);
    4237        ++m_refCount;
    43     }
    44 
    45     void deref()
    46     {
    47         ASSERT(!m_deletionHasBegun);
    48         ASSERT(m_refCount > 0);
    49         if (m_refCount == 1) {
    50 #ifndef NDEBUG
    51             m_deletionHasBegun = true;
    52 #endif
    53             delete static_cast<T*>(this);
    54         } else
    55             --m_refCount;
    5638    }
    5739
     
    6850
    6951protected:
    70     ~RefCounted() {}
     52    RefCountedBase(int initialRefCount)
     53        : m_refCount(initialRefCount)
     54#ifndef NDEBUG
     55        , m_deletionHasBegun(false)
     56#endif
     57    {
     58    }
     59
     60    ~RefCountedBase() {}
     61
     62    // Returns whether the pointer should be freed or not.
     63    bool derefBase()
     64    {
     65        ASSERT(!m_deletionHasBegun);
     66        ASSERT(m_refCount > 0);
     67        if (m_refCount == 1) {
     68#ifndef NDEBUG
     69            m_deletionHasBegun = true;
     70#endif
     71            return true;
     72        }
     73
     74        --m_refCount;
     75        return false;
     76    }
    7177
    7278private:
     
    7783};
    7884
     85
     86template<class T> class RefCounted : public RefCountedBase {
     87public:
     88    RefCounted(int initialRefCount = 1)
     89        : RefCountedBase(initialRefCount)
     90    {
     91    }
     92
     93    void deref()
     94    {
     95        if (derefBase())
     96            delete static_cast<T*>(this);
     97    }
     98
     99protected:
     100    ~RefCounted() {}
     101};
     102
    79103} // namespace WTF
    80104
Note: See TracChangeset for help on using the changeset viewer.