Skip to content

Commit b65d075

Browse files
committed
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
1 parent aba162b commit b65d075

File tree

2 files changed

+82
-79
lines changed

2 files changed

+82
-79
lines changed

xpcom/ds/nsAtom.h

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "nsISupportsImpl.h"
1111
#include "nsString.h"
12+
#include "mozilla/Atomics.h"
1213
#include "mozilla/UniquePtr.h"
1314

1415
namespace mozilla {
@@ -50,9 +51,9 @@ class nsAtom
5051
bool IsStatic() const { return mIsStatic; }
5152
bool IsDynamic() const { return !IsStatic(); }
5253

53-
const nsStaticAtom* AsStatic() const;
54-
const nsDynamicAtom* AsDynamic() const;
55-
nsDynamicAtom* AsDynamic();
54+
inline const nsStaticAtom* AsStatic() const;
55+
inline const nsDynamicAtom* AsDynamic() const;
56+
inline nsDynamicAtom* AsDynamic();
5657

5758
char16ptr_t GetUTF16String() const;
5859

@@ -82,8 +83,8 @@ class nsAtom
8283

8384
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
8485
// of this type is special.
85-
MozExternalRefCountType AddRef();
86-
MozExternalRefCountType Release();
86+
inline MozExternalRefCountType AddRef();
87+
inline MozExternalRefCountType Release();
8788

8889
typedef mozilla::TrueType HasThreadSafeRefCnt;
8990

@@ -157,8 +158,36 @@ class nsDynamicAtom : public nsAtom
157158
public:
158159
// We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting
159160
// of this type is special.
160-
MozExternalRefCountType AddRef();
161-
MozExternalRefCountType Release();
161+
MozExternalRefCountType AddRef()
162+
{
163+
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
164+
nsrefcnt count = ++mRefCnt;
165+
if (count == 1) {
166+
gUnusedAtomCount--;
167+
}
168+
return count;
169+
}
170+
171+
MozExternalRefCountType Release()
172+
{
173+
#ifdef DEBUG
174+
// We set a lower GC threshold for atoms in debug builds so that we exercise
175+
// the GC machinery more often.
176+
static const int32_t kAtomGCThreshold = 20;
177+
#else
178+
static const int32_t kAtomGCThreshold = 10000;
179+
#endif
180+
181+
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
182+
nsrefcnt count = --mRefCnt;
183+
if (count == 0) {
184+
if (++gUnusedAtomCount >= kAtomGCThreshold) {
185+
GCAtomTable();
186+
}
187+
}
188+
189+
return count;
190+
}
162191

163192
const char16_t* String() const
164193
{
@@ -173,6 +202,12 @@ class nsDynamicAtom : public nsAtom
173202
private:
174203
friend class nsAtomTable;
175204
friend class nsAtomSubTable;
205+
friend int32_t NS_GetUnusedAtomCount();
206+
207+
static mozilla::Atomic<int32_t,
208+
mozilla::ReleaseAcquire,
209+
mozilla::recordreplay::Behavior::DontPreserve> gUnusedAtomCount;
210+
static void GCAtomTable();
176211

177212
// These shouldn't be used directly, even by friend classes. The
178213
// Create()/Destroy() methods use them.
@@ -187,6 +222,39 @@ class nsDynamicAtom : public nsAtom
187222
// The atom's chars are stored at the end of the struct.
188223
};
189224

225+
const nsStaticAtom*
226+
nsAtom::AsStatic() const
227+
{
228+
MOZ_ASSERT(IsStatic());
229+
return static_cast<const nsStaticAtom*>(this);
230+
}
231+
232+
const nsDynamicAtom*
233+
nsAtom::AsDynamic() const
234+
{
235+
MOZ_ASSERT(IsDynamic());
236+
return static_cast<const nsDynamicAtom*>(this);
237+
}
238+
239+
nsDynamicAtom*
240+
nsAtom::AsDynamic()
241+
{
242+
MOZ_ASSERT(IsDynamic());
243+
return static_cast<nsDynamicAtom*>(this);
244+
}
245+
246+
MozExternalRefCountType
247+
nsAtom::AddRef()
248+
{
249+
return IsStatic() ? 2 : AsDynamic()->AddRef();
250+
}
251+
252+
MozExternalRefCountType
253+
nsAtom::Release()
254+
{
255+
return IsStatic() ? 1 : AsDynamic()->Release();
256+
}
257+
190258
// The four forms of NS_Atomize (for use with |RefPtr<nsAtom>|) return the
191259
// atom for the string given. At any given time there will always be one atom
192260
// representing a given string. Atoms are intended to make string comparison

xpcom/ds/nsAtomTable.cpp

Lines changed: 7 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ enum class GCKind {
6464
// This atomic can be accessed during the GC and other places where recorded
6565
// events are not allowed, so its value is not preserved when recording or
6666
// replaying.
67-
static Atomic<int32_t, ReleaseAcquire, recordreplay::Behavior::DontPreserve> gUnusedAtomCount(0);
67+
Atomic<int32_t, ReleaseAcquire, recordreplay::Behavior::DontPreserve>
68+
nsDynamicAtom::gUnusedAtomCount;
6869

6970
nsDynamicAtom::nsDynamicAtom(const nsAString& aString, uint32_t aHash, bool aIsAsciiLowercase)
7071
: nsAtom(aString, aHash, aIsAsciiLowercase)
@@ -114,27 +115,6 @@ nsDynamicAtom::Destroy(nsDynamicAtom* aAtom)
114115
free(aAtom);
115116
}
116117

117-
const nsStaticAtom*
118-
nsAtom::AsStatic() const
119-
{
120-
MOZ_ASSERT(IsStatic());
121-
return static_cast<const nsStaticAtom*>(this);
122-
}
123-
124-
const nsDynamicAtom*
125-
nsAtom::AsDynamic() const
126-
{
127-
MOZ_ASSERT(IsDynamic());
128-
return static_cast<const nsDynamicAtom*>(this);
129-
}
130-
131-
nsDynamicAtom*
132-
nsAtom::AsDynamic()
133-
{
134-
MOZ_ASSERT(IsDynamic());
135-
return static_cast<nsDynamicAtom*>(this);
136-
}
137-
138118
void
139119
nsAtom::ToString(nsAString& aString) const
140120
{
@@ -450,7 +430,7 @@ void nsAtomTable::GC(GCKind aKind)
450430
// so we won't try to resurrect a zero refcount atom while trying to delete
451431
// it.
452432

453-
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, gUnusedAtomCount == 0);
433+
MOZ_ASSERT_IF(aKind == GCKind::Shutdown, nsDynamicAtom::gUnusedAtomCount == 0);
454434
}
455435

456436
size_t
@@ -519,63 +499,18 @@ nsAtomSubTable::GCLocked(GCKind aKind)
519499
NS_ASSERTION(nonZeroRefcountAtomsCount == 0, msg.get());
520500
}
521501

522-
gUnusedAtomCount -= removedCount;
502+
nsDynamicAtom::gUnusedAtomCount -= removedCount;
523503
}
524504

525-
static void
526-
GCAtomTable()
505+
void
506+
nsDynamicAtom::GCAtomTable()
527507
{
528508
MOZ_ASSERT(gAtomTable);
529509
if (NS_IsMainThread()) {
530510
gAtomTable->GC(GCKind::RegularOperation);
531511
}
532512
}
533513

534-
MOZ_ALWAYS_INLINE MozExternalRefCountType
535-
nsDynamicAtom::AddRef()
536-
{
537-
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
538-
nsrefcnt count = ++mRefCnt;
539-
if (count == 1) {
540-
gUnusedAtomCount--;
541-
}
542-
return count;
543-
}
544-
545-
MOZ_ALWAYS_INLINE MozExternalRefCountType
546-
nsDynamicAtom::Release()
547-
{
548-
#ifdef DEBUG
549-
// We set a lower GC threshold for atoms in debug builds so that we exercise
550-
// the GC machinery more often.
551-
static const int32_t kAtomGCThreshold = 20;
552-
#else
553-
static const int32_t kAtomGCThreshold = 10000;
554-
#endif
555-
556-
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
557-
nsrefcnt count = --mRefCnt;
558-
if (count == 0) {
559-
if (++gUnusedAtomCount >= kAtomGCThreshold) {
560-
GCAtomTable();
561-
}
562-
}
563-
564-
return count;
565-
}
566-
567-
MozExternalRefCountType
568-
nsAtom::AddRef()
569-
{
570-
return IsStatic() ? 2 : AsDynamic()->AddRef();
571-
}
572-
573-
MozExternalRefCountType
574-
nsAtom::Release()
575-
{
576-
return IsStatic() ? 1 : AsDynamic()->Release();
577-
}
578-
579514
//----------------------------------------------------------------------
580515

581516
// Have the static atoms been inserted into the table?
@@ -792,7 +727,7 @@ NS_GetNumberOfAtoms(void)
792727
int32_t
793728
NS_GetUnusedAtomCount(void)
794729
{
795-
return gUnusedAtomCount;
730+
return nsDynamicAtom::gUnusedAtomCount;
796731
}
797732

798733
nsStaticAtom*

0 commit comments

Comments
 (0)