зеркало из 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 "nsISupportsImpl.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
#include "mozilla/Atomics.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -50,9 +51,9 @@ public:
|
||||||
bool IsStatic() const { return mIsStatic; }
|
bool IsStatic() const { return mIsStatic; }
|
||||||
bool IsDynamic() const { return !IsStatic(); }
|
bool IsDynamic() const { return !IsStatic(); }
|
||||||
|
|
||||||
const nsStaticAtom* AsStatic() const;
|
inline const nsStaticAtom* AsStatic() const;
|
||||||
const nsDynamicAtom* AsDynamic() const;
|
inline const nsDynamicAtom* AsDynamic() const;
|
||||||
nsDynamicAtom* AsDynamic();
|
inline nsDynamicAtom* AsDynamic();
|
||||||
|
|
||||||
char16ptr_t GetUTF16String() const;
|
char16ptr_t GetUTF16String() const;
|
||||||
|
|
||||||
|
@ -82,8 +83,8 @@ public:
|
||||||
|
|
||||||
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
||||||
// of this type is special.
|
// of this type is special.
|
||||||
MozExternalRefCountType AddRef();
|
inline MozExternalRefCountType AddRef();
|
||||||
MozExternalRefCountType Release();
|
inline MozExternalRefCountType Release();
|
||||||
|
|
||||||
typedef mozilla::TrueType HasThreadSafeRefCnt;
|
typedef mozilla::TrueType HasThreadSafeRefCnt;
|
||||||
|
|
||||||
|
@ -157,8 +158,36 @@ class nsDynamicAtom : public nsAtom
|
||||||
public:
|
public:
|
||||||
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
|
||||||
// of this type is special.
|
// of this type is special.
|
||||||
MozExternalRefCountType AddRef();
|
MozExternalRefCountType AddRef()
|
||||||
MozExternalRefCountType Release();
|
{
|
||||||
|
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
|
const char16_t* String() const
|
||||||
{
|
{
|
||||||
|
@ -173,6 +202,12 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class nsAtomTable;
|
friend class nsAtomTable;
|
||||||
friend class nsAtomSubTable;
|
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
|
// These shouldn't be used directly, even by friend classes. The
|
||||||
// Create()/Destroy() methods use them.
|
// Create()/Destroy() methods use them.
|
||||||
|
@ -187,6 +222,39 @@ private:
|
||||||
// The atom's chars are stored at the end of the struct.
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// events are not allowed, so its value is not preserved when recording or
|
||||||
// replaying.
|
// 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)
|
nsDynamicAtom::nsDynamicAtom(const nsAString& aString, uint32_t aHash, bool aIsAsciiLowercase)
|
||||||
: nsAtom(aString, aHash, aIsAsciiLowercase)
|
: nsAtom(aString, aHash, aIsAsciiLowercase)
|
||||||
|
@ -114,27 +115,6 @@ nsDynamicAtom::Destroy(nsDynamicAtom* aAtom)
|
||||||
free(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
|
void
|
||||||
nsAtom::ToString(nsAString& aString) const
|
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
|
// so we won't try to resurrect a zero refcount atom while trying to delete
|
||||||
// it.
|
// it.
|
||||||
|
|
||||||
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, gUnusedAtomCount == 0);
|
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, nsDynamicAtom::gUnusedAtomCount == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -519,11 +499,11 @@ nsAtomSubTable::GCLocked(GCKind aKind)
|
||||||
NS_ASSERTION(nonZeroRefcountAtomsCount == 0, msg.get());
|
NS_ASSERTION(nonZeroRefcountAtomsCount == 0, msg.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
gUnusedAtomCount -= removedCount;
|
nsDynamicAtom::gUnusedAtomCount -= removedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
GCAtomTable()
|
nsDynamicAtom::GCAtomTable()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(gAtomTable);
|
MOZ_ASSERT(gAtomTable);
|
||||||
if (NS_IsMainThread()) {
|
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?
|
// Have the static atoms been inserted into the table?
|
||||||
|
@ -792,7 +727,7 @@ NS_GetNumberOfAtoms(void)
|
||||||
int32_t
|
int32_t
|
||||||
NS_GetUnusedAtomCount(void)
|
NS_GetUnusedAtomCount(void)
|
||||||
{
|
{
|
||||||
return gUnusedAtomCount;
|
return nsDynamicAtom::gUnusedAtomCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStaticAtom*
|
nsStaticAtom*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче