зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1509720 - Inline atom refcounting. r=njn
We're paying two function calls from Gecko_AddRefAtom / Gecko_ReleaseAtom for no good reason, plus it's simple enough it's probably worth to inline it anyway for C++ callers. Differential Revision: https://phabricator.services.mozilla.com/D12860 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
aba162bbb6
Коммит
b65d0757d1
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -50,9 +51,9 @@ public:
|
|||
bool IsStatic() const { return mIsStatic; }
|
||||
bool IsDynamic() const { return !IsStatic(); }
|
||||
|
||||
const nsStaticAtom* AsStatic() const;
|
||||
const nsDynamicAtom* AsDynamic() const;
|
||||
nsDynamicAtom* AsDynamic();
|
||||
inline const nsStaticAtom* AsStatic() const;
|
||||
inline const nsDynamicAtom* AsDynamic() const;
|
||||
inline nsDynamicAtom* AsDynamic();
|
||||
|
||||
char16ptr_t GetUTF16String() const;
|
||||
|
||||
|
@ -82,8 +83,8 @@ public:
|
|||
|
||||
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
||||
// of this type is special.
|
||||
MozExternalRefCountType AddRef();
|
||||
MozExternalRefCountType Release();
|
||||
inline MozExternalRefCountType AddRef();
|
||||
inline MozExternalRefCountType Release();
|
||||
|
||||
typedef mozilla::TrueType HasThreadSafeRefCnt;
|
||||
|
||||
|
@ -157,8 +158,36 @@ class nsDynamicAtom : public nsAtom
|
|||
public:
|
||||
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
||||
// of this type is special.
|
||||
MozExternalRefCountType AddRef();
|
||||
MozExternalRefCountType Release();
|
||||
MozExternalRefCountType AddRef()
|
||||
{
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
nsrefcnt count = ++mRefCnt;
|
||||
if (count == 1) {
|
||||
gUnusedAtomCount--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
MozExternalRefCountType Release()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// We set a lower GC threshold for atoms in debug builds so that we exercise
|
||||
// the GC machinery more often.
|
||||
static const int32_t kAtomGCThreshold = 20;
|
||||
#else
|
||||
static const int32_t kAtomGCThreshold = 10000;
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
|
||||
nsrefcnt count = --mRefCnt;
|
||||
if (count == 0) {
|
||||
if (++gUnusedAtomCount >= kAtomGCThreshold) {
|
||||
GCAtomTable();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
const char16_t* String() const
|
||||
{
|
||||
|
@ -173,6 +202,12 @@ public:
|
|||
private:
|
||||
friend class nsAtomTable;
|
||||
friend class nsAtomSubTable;
|
||||
friend int32_t NS_GetUnusedAtomCount();
|
||||
|
||||
static mozilla::Atomic<int32_t,
|
||||
mozilla::ReleaseAcquire,
|
||||
mozilla::recordreplay::Behavior::DontPreserve> gUnusedAtomCount;
|
||||
static void GCAtomTable();
|
||||
|
||||
// These shouldn't be used directly, even by friend classes. The
|
||||
// Create()/Destroy() methods use them.
|
||||
|
@ -187,6 +222,39 @@ private:
|
|||
// The atom's chars are stored at the end of the struct.
|
||||
};
|
||||
|
||||
const nsStaticAtom*
|
||||
nsAtom::AsStatic() const
|
||||
{
|
||||
MOZ_ASSERT(IsStatic());
|
||||
return static_cast<const nsStaticAtom*>(this);
|
||||
}
|
||||
|
||||
const nsDynamicAtom*
|
||||
nsAtom::AsDynamic() const
|
||||
{
|
||||
MOZ_ASSERT(IsDynamic());
|
||||
return static_cast<const nsDynamicAtom*>(this);
|
||||
}
|
||||
|
||||
nsDynamicAtom*
|
||||
nsAtom::AsDynamic()
|
||||
{
|
||||
MOZ_ASSERT(IsDynamic());
|
||||
return static_cast<nsDynamicAtom*>(this);
|
||||
}
|
||||
|
||||
MozExternalRefCountType
|
||||
nsAtom::AddRef()
|
||||
{
|
||||
return IsStatic() ? 2 : AsDynamic()->AddRef();
|
||||
}
|
||||
|
||||
MozExternalRefCountType
|
||||
nsAtom::Release()
|
||||
{
|
||||
return IsStatic() ? 1 : AsDynamic()->Release();
|
||||
}
|
||||
|
||||
// The four forms of NS_Atomize (for use with |RefPtr<nsAtom>|) return the
|
||||
// atom for the string given. At any given time there will always be one atom
|
||||
// representing a given string. Atoms are intended to make string comparison
|
||||
|
|
|
@ -64,7 +64,8 @@ enum class GCKind {
|
|||
// This atomic can be accessed during the GC and other places where recorded
|
||||
// events are not allowed, so its value is not preserved when recording or
|
||||
// replaying.
|
||||
static Atomic<int32_t, ReleaseAcquire, recordreplay::Behavior::DontPreserve> gUnusedAtomCount(0);
|
||||
Atomic<int32_t, ReleaseAcquire, recordreplay::Behavior::DontPreserve>
|
||||
nsDynamicAtom::gUnusedAtomCount;
|
||||
|
||||
nsDynamicAtom::nsDynamicAtom(const nsAString& aString, uint32_t aHash, bool aIsAsciiLowercase)
|
||||
: nsAtom(aString, aHash, aIsAsciiLowercase)
|
||||
|
@ -114,27 +115,6 @@ nsDynamicAtom::Destroy(nsDynamicAtom* aAtom)
|
|||
free(aAtom);
|
||||
}
|
||||
|
||||
const nsStaticAtom*
|
||||
nsAtom::AsStatic() const
|
||||
{
|
||||
MOZ_ASSERT(IsStatic());
|
||||
return static_cast<const nsStaticAtom*>(this);
|
||||
}
|
||||
|
||||
const nsDynamicAtom*
|
||||
nsAtom::AsDynamic() const
|
||||
{
|
||||
MOZ_ASSERT(IsDynamic());
|
||||
return static_cast<const nsDynamicAtom*>(this);
|
||||
}
|
||||
|
||||
nsDynamicAtom*
|
||||
nsAtom::AsDynamic()
|
||||
{
|
||||
MOZ_ASSERT(IsDynamic());
|
||||
return static_cast<nsDynamicAtom*>(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsAtom::ToString(nsAString& aString) const
|
||||
{
|
||||
|
@ -450,7 +430,7 @@ void nsAtomTable::GC(GCKind aKind)
|
|||
// so we won't try to resurrect a zero refcount atom while trying to delete
|
||||
// it.
|
||||
|
||||
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, gUnusedAtomCount == 0);
|
||||
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, nsDynamicAtom::gUnusedAtomCount == 0);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -519,11 +499,11 @@ nsAtomSubTable::GCLocked(GCKind aKind)
|
|||
NS_ASSERTION(nonZeroRefcountAtomsCount == 0, msg.get());
|
||||
}
|
||||
|
||||
gUnusedAtomCount -= removedCount;
|
||||
nsDynamicAtom::gUnusedAtomCount -= removedCount;
|
||||
}
|
||||
|
||||
static void
|
||||
GCAtomTable()
|
||||
void
|
||||
nsDynamicAtom::GCAtomTable()
|
||||
{
|
||||
MOZ_ASSERT(gAtomTable);
|
||||
if (NS_IsMainThread()) {
|
||||
|
@ -531,51 +511,6 @@ GCAtomTable()
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE MozExternalRefCountType
|
||||
nsDynamicAtom::AddRef()
|
||||
{
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
nsrefcnt count = ++mRefCnt;
|
||||
if (count == 1) {
|
||||
gUnusedAtomCount--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE MozExternalRefCountType
|
||||
nsDynamicAtom::Release()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// We set a lower GC threshold for atoms in debug builds so that we exercise
|
||||
// the GC machinery more often.
|
||||
static const int32_t kAtomGCThreshold = 20;
|
||||
#else
|
||||
static const int32_t kAtomGCThreshold = 10000;
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
|
||||
nsrefcnt count = --mRefCnt;
|
||||
if (count == 0) {
|
||||
if (++gUnusedAtomCount >= kAtomGCThreshold) {
|
||||
GCAtomTable();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
MozExternalRefCountType
|
||||
nsAtom::AddRef()
|
||||
{
|
||||
return IsStatic() ? 2 : AsDynamic()->AddRef();
|
||||
}
|
||||
|
||||
MozExternalRefCountType
|
||||
nsAtom::Release()
|
||||
{
|
||||
return IsStatic() ? 1 : AsDynamic()->Release();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Have the static atoms been inserted into the table?
|
||||
|
@ -792,7 +727,7 @@ NS_GetNumberOfAtoms(void)
|
|||
int32_t
|
||||
NS_GetUnusedAtomCount(void)
|
||||
{
|
||||
return gUnusedAtomCount;
|
||||
return nsDynamicAtom::gUnusedAtomCount;
|
||||
}
|
||||
|
||||
nsStaticAtom*
|
||||
|
|
Загрузка…
Ссылка в новой задаче